-- Copyright (C) 1986 by Xerox Corporation. All rights reserved. -- BucketAllocImpl.mesa -- MEW 2-Mar-86 12:39:45 DIRECTORY BucketAlloc, Heap; BucketAllocImpl: MONITOR IMPORTS Heap EXPORTS BucketAlloc = BEGIN BucketRec: TYPE = RECORD [ first: LONG POINTER TO LONG POINTER, size: CARDINAL, info: BucketAlloc.BucketInfo]; BucketSeq: TYPE = RECORD [SEQUENCE length: CARDINAL OF BucketRec]; BigNode: TYPE = LONG POINTER TO BigNodeRec; BigNodeRec: TYPE = RECORD [size: CARDINAL, ptr: LONG POINTER, next: BigNode]; bigList: BigNode ← NIL; zone: UNCOUNTED ZONE; b: LONG POINTER TO BucketSeq; Initialize: PUBLIC ENTRY PROCEDURE [ z: UNCOUNTED ZONE, buckets: LONG DESCRIPTOR FOR ARRAY OF BucketAlloc.BucketInfo] = BEGIN zone ← z; b ← z.NEW[BucketSeq [LENGTH[buckets]]]; FOR i: CARDINAL IN [0..LENGTH[buckets]) DO b[i] ← [first: NIL, size: 0, info: buckets[i]]; IF buckets[i].nodeSize < SIZE[LONG POINTER] THEN b[i].info.nodeSize ← SIZE[LONG POINTER]; FOR j: CARDINAL IN [0..buckets[i].initialBucketSize) DO p: LONG POINTER TO LONG POINTER; p ← Heap.MakeNode[z, buckets[i].nodeSize]; p↑ ← b[i].first; b[i].first ← p; ENDLOOP; b[i].size ← buckets[i].initialBucketSize; ENDLOOP; -- Now Sort These FOR i: CARDINAL IN [1..LENGTH[buckets]) DO current: BucketRec = b[i]; FOR j: CARDINAL DECREASING IN [0..i - 1] DO IF current.info.nodeSize >= b[j].info.nodeSize THEN { b[j + 1] ← current; EXIT}; b[j + 1] ← b[j]; ENDLOOP ENDLOOP; END; Reset: PUBLIC PROCEDURE = BEGIN FOR i: CARDINAL IN [0..b.length) DO IF b[i].size > b[i].info.initialBucketSize THEN FOR j: CARDINAL IN [0..(b[i].info.initialBucketSize - b[i].size)) DO ptr: LONG POINTER TO LONG POINTER ← b[i].first; b[i].first ← ptr↑; zone.FREE[@ptr]; ENDLOOP ELSE FOR j: CARDINAL IN [b[i].size..b[i].info.initialBucketSize) DO p: LONG POINTER TO LONG POINTER; p ← Heap.MakeNode[zone, b[i].info.nodeSize]; p↑ ← b[i].first; b[i].first ← p; ENDLOOP; b[i].size ← b[i].info.initialBucketSize; ENDLOOP END; Destroy: PUBLIC PROCEDURE = BEGIN FOR i: CARDINAL IN [0..b.length) DO p, next: LONG POINTER TO LONG POINTER; FOR p ← b[i].first, next WHILE p # NIL DO next ← p↑; zone.FREE[@p]; ENDLOOP; ENDLOOP END; Alloc: PUBLIC PROCEDURE [size: CARDINAL] RETURNS [p: LONG POINTER] = BEGIN bucket: LONG POINTER TO BucketRec ← FindBucket[size]; IF bucket.info.nodeSize < size THEN { -- bigger than the biggest bucket big: BigNode ← zone.NEW[BigNodeRec]; p ← Heap.MakeNode[zone, size]; big↑ ← [size: size, ptr: p, next: bigList]; bigList ← big; RETURN[p]}; IF bucket.first # NIL THEN { p ← bucket.first; bucket.first ← bucket.first↑; bucket.size ← bucket.size - 1; RETURN[p]} ELSE RETURN[Heap.MakeNode[zone, bucket.info.nodeSize]] END; Free: PUBLIC PROCEDURE [p: LONG POINTER TO LONG POINTER, size: CARDINAL] = BEGIN bucket: LONG POINTER TO BucketRec ← FindBucket[size]; IF bucket.info.nodeSize < size THEN { -- bigger than the biggest bucket big: BigNode; FOR big ← bigList, big.next WHILE big # NIL DO IF big.ptr = p↑ THEN { IF big # bigList THEN ERROR; -- ASSERT big = bigList bigList ← big.next; Heap.FreeNode[zone, p↑]; p↑ ← NIL; zone.FREE[@big]; RETURN}; IF big.next.ptr = p↑ THEN { big.next ← big.next.next; Heap.FreeNode[zone, p↑]; p↑ ← NIL; zone.FREE[@big]; RETURN} ENDLOOP; }; IF bucket.size >= bucket.info.maxBucketSize THEN { Heap.FreeNode[zone, p↑]; p↑ ← NIL; RETURN} ELSE { LOOPHOLE[p↑, LONG POINTER TO LONG POINTER]↑ ← bucket.first; bucket.first ← LOOPHOLE[p↑, LONG POINTER TO LONG POINTER]; bucket.size ← bucket.size + 1} END; FindBucket: PROCEDURE [size: CARDINAL] RETURNS [l: LONG POINTER TO BucketRec ← NIL] = BEGIN low, high, mid: CARDINAL; IF b[0].info.nodeSize >= size THEN RETURN[@b[0]]; IF b[b.length - 1].info.nodeSize <= size THEN RETURN[@b[b.length - 1]]; low ← 0; high ← b.length - 1; FOR mid ← (low + high) / 2, (low + high) / 2 WHILE high >= low DO IF b[mid].info.nodeSize = size THEN RETURN[@b[mid]]; IF b[mid].info.nodeSize > size THEN { IF b[mid - 1].info.nodeSize = size THEN RETURN[@b[mid - 1]]; IF b[mid - 1].info.nodeSize < size THEN RETURN[@b[mid]]; high ← mid - 1} ELSE { IF b[mid + 1].info.nodeSize >= size THEN RETURN[@b[mid + 1]]; low ← mid + 1} ENDLOOP; END; END..