1 // Copyright (c) 1994 James Clark 2 // See the file COPYING for copying permission. 3 #pragma ident "%Z%%M% %I% %E% SMI" 4 5 #include "splib.h" 6 #include "Allocator.h" 7 #include "macros.h" 8 9 #ifdef SP_NAMESPACE 10 namespace SP_NAMESPACE { 11 #endif 12 Allocator(size_t maxSize,unsigned blocksPerSegment)13Allocator::Allocator(size_t maxSize, unsigned blocksPerSegment) 14 : objectSize_(maxSize), 15 blocksPerSegment_(blocksPerSegment), 16 freeList_(0), 17 segments_(0) 18 { 19 } 20 ~Allocator()21Allocator::~Allocator() 22 { 23 SegmentHeader *p = segments_; 24 while (p) { 25 SegmentHeader *tem = p->next; 26 if (p->liveCount == 0) 27 ::operator delete(p); 28 else 29 p->freeList = 0; 30 p = tem; 31 } 32 } 33 alloc(size_t sz)34void *Allocator::alloc(size_t sz) 35 { 36 if (sz > objectSize_) 37 tooBig(sz); 38 Block *tem = freeList_; 39 if (tem) { 40 tem->header.seg->liveCount += 1; 41 freeList_ = tem->next; 42 return &(tem->next); 43 } 44 else 45 return alloc1(); 46 } 47 allocSimple(size_t sz)48void *Allocator::allocSimple(size_t sz) 49 { 50 BlockHeader *p = (BlockHeader *)::operator new(sz + sizeof(BlockHeader)); 51 p->seg = 0; 52 return p + 1; 53 } 54 free(void * p)55void Allocator::free(void *p) 56 { 57 BlockHeader *b = ((BlockHeader *)p) - 1; 58 SegmentHeader *seg = b->seg; 59 if (seg == 0) 60 ::operator delete(b); 61 else { 62 Block **freeList = seg->freeList; 63 if (freeList == 0) { 64 seg->liveCount -= 1; 65 if (seg->liveCount == 0) 66 ::operator delete(seg); 67 } 68 else { 69 ((Block *)b)->next = *freeList; 70 *freeList = (Block *)b; 71 seg->liveCount -= 1; 72 } 73 } 74 } 75 alloc1()76void *Allocator::alloc1() 77 { 78 SegmentHeader *seg 79 = (SegmentHeader *)::operator new(sizeof(SegmentHeader) 80 + ((objectSize_ + sizeof(BlockHeader)) 81 * blocksPerSegment_)); 82 seg->next = segments_; 83 segments_ = seg; 84 seg->liveCount = 1; 85 seg->freeList = &freeList_; 86 char *p = (char *)(seg + 1); 87 Block *head = 0; 88 for (size_t n = blocksPerSegment_; n > 0; n--) { 89 ((Block *)p)->next = head; 90 ((Block *)p)->header.seg = seg; 91 head = (Block *)p; 92 p += sizeof(BlockHeader) + objectSize_; 93 } 94 freeList_ = head->next; 95 return &(head->next); 96 } 97 tooBig(size_t sz)98void Allocator::tooBig(size_t sz) 99 { 100 ASSERT(sz <= objectSize_); 101 } 102 103 #ifdef SP_NAMESPACE 104 } 105 #endif 106