1// Block.h 2 3#ifndef BLOCK_H 4#define BLOCK_H 5 6class Block; 7class BlockHeader; 8class BlockReference; 9class TFreeBlock; 10 11#include <SupportDefs.h> 12 13// debugging 14//#define inline 15#define BA_DEFINE_INLINES 1 16 17// BlockHeader 18class BlockHeader { 19public: 20 inline Block *ToBlock() { return (Block*)this; } 21 inline TFreeBlock *ToFreeBlock() { return (TFreeBlock*)this; } 22 23 inline void SetPreviousBlock(Block *block); 24 inline Block *GetPreviousBlock(); 25 26 inline void SetNextBlock(Block *block); 27 inline Block *GetNextBlock(); 28 inline bool HasNextBlock() { return (fSize & HAS_NEXT_FLAG); } 29 30 inline void SetSize(size_t size, bool hasNext = false); 31 inline size_t GetSize() const; 32 static inline size_t GetUsableSizeFor(size_t size); 33 inline size_t GetUsableSize() const; 34 35 inline void *GetData(); 36 37 inline void SetFree(bool flag); 38 inline bool IsFree() const; 39 40 inline void SetReference(BlockReference *ref); 41 inline BlockReference *GetReference() const { return fReference; } 42 inline void FixReference(); 43 44 inline void SetTo(Block *previous, size_t size, bool isFree, bool hasNext, 45 BlockReference *reference = NULL); 46 47private: 48 enum { 49 FREE_FLAG = 0x80000000, 50 BACK_SKIP_MASK = 0x7fffffff, 51 }; 52 53 enum { 54 HAS_NEXT_FLAG = 0x80000000, 55 SIZE_MASK = 0x7fffffff, 56 }; 57 58private: 59 BlockHeader(); 60 ~BlockHeader(); 61 62protected: 63 size_t fBackSkip; 64 size_t fSize; 65 BlockReference *fReference; 66}; 67 68// Block 69class Block : public BlockHeader { 70public: 71 static inline Block *MakeBlock(void *address, ssize_t offset, 72 Block *previous, size_t size, bool isFree, 73 bool hasNext, 74 BlockReference *reference = NULL); 75 76private: 77 Block(); 78 ~Block(); 79}; 80 81// TFreeBlock 82class TFreeBlock : public Block { 83public: 84 85 inline void SetPreviousFreeBlock(TFreeBlock *block) { fPrevious = block; } 86 inline void SetNextFreeBlock(TFreeBlock *block) { fNext = block; } 87 inline TFreeBlock *GetPreviousFreeBlock() { return fPrevious; } 88 inline TFreeBlock *GetNextFreeBlock() { return fNext; } 89 90 inline void SetTo(Block *previous, size_t size, bool hasNext, 91 TFreeBlock *previousFree, TFreeBlock *nextFree); 92 93// static inline TFreeBlock *MakeFreeBlock(void *address, ssize_t offset, 94// Block *previous, size_t size, bool hasNext, TFreeBlock *previousFree, 95// TFreeBlock *nextFree); 96 97private: 98 TFreeBlock(); 99 ~TFreeBlock(); 100 101private: 102 TFreeBlock *fPrevious; 103 TFreeBlock *fNext; 104}; 105 106// BlockReference 107class BlockReference { 108public: 109 inline BlockReference() : fBlock(NULL) {} 110 inline BlockReference(Block *block) : fBlock(block) {} 111 112 inline void SetBlock(Block *block) { fBlock = block; } 113 inline Block *GetBlock() const { return fBlock; } 114 115 inline void *GetData() const { return fBlock->GetData(); } 116 inline void *GetDataAt(ssize_t offset) const; 117 118private: 119 Block *fBlock; 120}; 121 122 123// --------------------------------------------------------------------------- 124// inline methods 125 126// debugging 127#if BA_DEFINE_INLINES 128 129// BlockHeader 130 131// SetPreviousBlock 132inline 133void 134BlockHeader::SetPreviousBlock(Block *block) 135{ 136 size_t offset = (block ? (char*)this - (char*)block : 0); 137 fBackSkip = fBackSkip & FREE_FLAG | offset; 138} 139 140// GetPreviousBlock 141inline 142Block * 143BlockHeader::GetPreviousBlock() 144{ 145 if (fBackSkip & BACK_SKIP_MASK) 146 return (Block*)((char*)this - (fBackSkip & BACK_SKIP_MASK)); 147 return NULL; 148} 149 150// SetNextBlock 151inline 152void 153BlockHeader::SetNextBlock(Block *block) 154{ 155 if (block) 156 fSize = ((char*)block - (char*)this) | HAS_NEXT_FLAG; 157 else 158 fSize &= SIZE_MASK; 159} 160 161// GetNextBlock 162inline 163Block * 164BlockHeader::GetNextBlock() 165{ 166 if (fSize & HAS_NEXT_FLAG) 167 return (Block*)((char*)this + (SIZE_MASK & fSize)); 168 return NULL; 169} 170 171// SetSize 172inline 173void 174BlockHeader::SetSize(size_t size, bool hasNext) 175{ 176 fSize = size; 177 if (hasNext) 178 fSize |= HAS_NEXT_FLAG; 179} 180 181// GetSize 182inline 183size_t 184BlockHeader::GetSize() const 185{ 186 return (fSize & SIZE_MASK); 187} 188 189// GetUsableSizeFor 190inline 191size_t 192BlockHeader::GetUsableSizeFor(size_t size) 193{ 194 return (size - sizeof(BlockHeader)); 195} 196 197// GetUsableSize 198inline 199size_t 200BlockHeader::GetUsableSize() const 201{ 202 return GetUsableSizeFor(GetSize()); 203} 204 205// GetData 206inline 207void * 208BlockHeader::GetData() 209{ 210 return (char*)this + sizeof(BlockHeader); 211} 212 213// SetFree 214inline 215void 216BlockHeader::SetFree(bool flag) 217{ 218 if (flag) 219 fBackSkip |= FREE_FLAG; 220 else 221 fBackSkip &= ~FREE_FLAG; 222} 223 224// IsFree 225inline 226bool 227BlockHeader::IsFree() const 228{ 229 return (fBackSkip & FREE_FLAG); 230} 231 232// SetTo 233inline 234void 235BlockHeader::SetTo(Block *previous, size_t size, bool isFree, bool hasNext, 236 BlockReference *reference) 237{ 238 SetPreviousBlock(previous); 239 SetSize(size, hasNext); 240 SetFree(isFree); 241 SetReference(reference); 242} 243 244// SetReference 245inline 246void 247BlockHeader::SetReference(BlockReference *ref) 248{ 249 fReference = ref; 250 FixReference(); 251} 252 253// FixReference 254inline 255void 256BlockHeader::FixReference() 257{ 258 if (fReference) 259 fReference->SetBlock(ToBlock()); 260} 261 262 263// Block 264 265// MakeBlock 266/*inline 267Block * 268Block::MakeBlock(void *address, ssize_t offset, Block *previous, size_t size, 269 bool isFree, bool hasNext, BlockReference *reference) 270{ 271 Block *block = (Block*)((char*)address + offset); 272 block->SetTo(previous, size, isFree, hasNext, reference); 273 return block; 274}*/ 275 276 277// TFreeBlock 278 279// SetTo 280inline 281void 282TFreeBlock::SetTo(Block *previous, size_t size, bool hasNext, 283 TFreeBlock *previousFree, TFreeBlock *nextFree) 284{ 285 Block::SetTo(previous, size, true, hasNext, NULL); 286 SetPreviousFreeBlock(previousFree); 287 SetNextFreeBlock(nextFree); 288} 289 290// MakeFreeBlock 291/*inline 292TFreeBlock * 293TFreeBlock::MakeFreeBlock(void *address, ssize_t offset, Block *previous, 294 size_t size, bool hasNext, TFreeBlock *previousFree, 295 TFreeBlock *nextFree) 296{ 297 TFreeBlock *block = (TFreeBlock*)((char*)address + offset); 298 block->SetTo(previous, size, hasNext, previousFree, nextFree); 299 if (hasNext) 300 block->GetNextBlock()->SetPreviousBlock(block); 301 return block; 302}*/ 303 304 305// BlockReference 306 307// GetDataAt 308inline 309void * 310BlockReference::GetDataAt(ssize_t offset) const 311{ 312 return (char*)fBlock->GetData() + offset; 313} 314 315#endif // BA_DEFINE_INLINES 316 317#endif // BLOCK_H 318