summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/core/slang-virtual-object-pool.h119
1 files changed, 119 insertions, 0 deletions
diff --git a/source/core/slang-virtual-object-pool.h b/source/core/slang-virtual-object-pool.h
new file mode 100644
index 000000000..c1247acb7
--- /dev/null
+++ b/source/core/slang-virtual-object-pool.h
@@ -0,0 +1,119 @@
+#ifndef SLANG_VIRTUAL_POOL_ALLOCATOR_H
+#define SLANG_VIRTUAL_POOL_ALLOCATOR_H
+
+namespace Slang
+{
+
+ /// A virtual free-list allocater.
+ /// This class doesn't actually allocates memory, instead it operates on a
+ /// virtual integer space. Can be used to implement various types of object pools
+ /// that needs to support contiguous allocations of more than one elements.
+class VirtualObjectPool
+{
+public:
+ struct FreeListNode
+ {
+ int Offset;
+ int Length;
+ FreeListNode* prev;
+ FreeListNode* next;
+ };
+ FreeListNode* freeListHead = nullptr;
+
+public:
+ void destroy()
+ {
+ auto list = freeListHead;
+ while (list)
+ {
+ auto next = list->next;
+ delete list;
+ list = next;
+ }
+ freeListHead = nullptr;
+ }
+
+ ~VirtualObjectPool() { destroy(); }
+
+ void initPool(int numElements)
+ {
+ freeListHead = new FreeListNode();
+ freeListHead->prev = freeListHead->next = nullptr;
+ freeListHead->Offset = 0;
+ freeListHead->Length = numElements;
+ }
+
+ int alloc(int size)
+ {
+ if (!freeListHead)
+ return -1;
+ auto freeBlock = freeListHead;
+ while (freeBlock && freeBlock->Length < size)
+ freeBlock = freeBlock->next;
+ if (!freeBlock || freeBlock->Length < size)
+ return -1;
+ int result = freeBlock->Offset;
+ freeBlock->Offset += size;
+ freeBlock->Length -= size;
+ if (freeBlock->Length == 0)
+ {
+ if (freeBlock->prev)
+ freeBlock->prev->next = freeBlock->next;
+ if (freeBlock->next)
+ freeBlock->next->prev = freeBlock->prev;
+ if (freeBlock == freeListHead)
+ freeListHead = freeBlock->next;
+ delete freeBlock;
+ }
+ return result;
+ }
+ void free(int offset, int size)
+ {
+ if (!freeListHead)
+ {
+ freeListHead = new FreeListNode();
+ freeListHead->next = freeListHead->prev = nullptr;
+ freeListHead->Length = size;
+ freeListHead->Offset = offset;
+ return;
+ }
+ auto freeListNode = freeListHead;
+ FreeListNode* prevFreeNode = nullptr;
+ while (freeListNode && freeListNode->Offset < offset + size)
+ {
+ prevFreeNode = freeListNode;
+ freeListNode = freeListNode->next;
+ }
+ FreeListNode* newNode = new FreeListNode();
+ newNode->Offset = offset;
+ newNode->Length = size;
+ newNode->prev = prevFreeNode;
+ newNode->next = freeListNode;
+ if (freeListNode)
+ freeListNode->prev = newNode;
+ if (prevFreeNode)
+ prevFreeNode->next = newNode;
+ if (freeListNode == freeListHead)
+ freeListHead = newNode;
+ if (prevFreeNode && prevFreeNode->Offset + prevFreeNode->Length == newNode->Offset)
+ {
+ prevFreeNode->Length += newNode->Length;
+ prevFreeNode->next = freeListNode;
+ if (freeListNode)
+ freeListNode->prev = prevFreeNode;
+ delete newNode;
+ newNode = prevFreeNode;
+ }
+ if (freeListNode && newNode->Offset + newNode->Length == freeListNode->Offset)
+ {
+ newNode->Length += freeListNode->Length;
+ newNode->next = freeListNode->next;
+ if (freeListNode->next)
+ freeListNode->next->prev = newNode;
+ delete freeListNode;
+ }
+ }
+};
+
+} // namespace Slang
+#endif