yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie Hermaszewskaformatf65d756bf

master
3.5 KiB119 linesraw
1#ifndef SLANG_VIRTUAL_POOL_ALLOCATOR_H
2#define SLANG_VIRTUAL_POOL_ALLOCATOR_H
3
4namespace Slang
5{
6
7/// A virtual free-list allocater.
8/// This class doesn't actually allocates memory, instead it operates on a
9/// virtual integer space. Can be used to implement various types of object pools
10/// that needs to support contiguous allocations of more than one elements.
11class VirtualObjectPool
12{
13public:
14    struct FreeListNode
15    {
16        int Offset;
17        int Length;
18        FreeListNode* prev;
19        FreeListNode* next;
20    };
21    FreeListNode* freeListHead = nullptr;
22
23public:
24    void destroy()
25    {
26        auto list = freeListHead;
27        while (list)
28        {
29            auto next = list->next;
30            delete list;
31            list = next;
32        }
33        freeListHead = nullptr;
34    }
35
36    ~VirtualObjectPool() { destroy(); }
37
38    void initPool(int numElements)
39    {
40        freeListHead = new FreeListNode();
41        freeListHead->prev = freeListHead->next = nullptr;
42        freeListHead->Offset = 0;
43        freeListHead->Length = numElements;
44    }
45
46    int alloc(int size)
47    {
48        if (!freeListHead)
49            return -1;
50        auto freeBlock = freeListHead;
51        while (freeBlock && freeBlock->Length < size)
52            freeBlock = freeBlock->next;
53        if (!freeBlock || freeBlock->Length < size)
54            return -1;
55        int result = freeBlock->Offset;
56        freeBlock->Offset += size;
57        freeBlock->Length -= size;
58        if (freeBlock->Length == 0)
59        {
60            if (freeBlock->prev)
61                freeBlock->prev->next = freeBlock->next;
62            if (freeBlock->next)
63                freeBlock->next->prev = freeBlock->prev;
64            if (freeBlock == freeListHead)
65                freeListHead = freeBlock->next;
66            delete freeBlock;
67        }
68        return result;
69    }
70    void free(int offset, int size)
71    {
72        if (!freeListHead)
73        {
74            freeListHead = new FreeListNode();
75            freeListHead->next = freeListHead->prev = nullptr;
76            freeListHead->Length = size;
77            freeListHead->Offset = offset;
78            return;
79        }
80        auto freeListNode = freeListHead;
81        FreeListNode* prevFreeNode = nullptr;
82        while (freeListNode && freeListNode->Offset < offset + size)
83        {
84            prevFreeNode = freeListNode;
85            freeListNode = freeListNode->next;
86        }
87        FreeListNode* newNode = new FreeListNode();
88        newNode->Offset = offset;
89        newNode->Length = size;
90        newNode->prev = prevFreeNode;
91        newNode->next = freeListNode;
92        if (freeListNode)
93            freeListNode->prev = newNode;
94        if (prevFreeNode)
95            prevFreeNode->next = newNode;
96        if (freeListNode == freeListHead)
97            freeListHead = newNode;
98        if (prevFreeNode && prevFreeNode->Offset + prevFreeNode->Length == newNode->Offset)
99        {
100            prevFreeNode->Length += newNode->Length;
101            prevFreeNode->next = freeListNode;
102            if (freeListNode)
103                freeListNode->prev = prevFreeNode;
104            delete newNode;
105            newNode = prevFreeNode;
106        }
107        if (freeListNode && newNode->Offset + newNode->Length == freeListNode->Offset)
108        {
109            newNode->Length += freeListNode->Length;
110            newNode->next = freeListNode->next;
111            if (freeListNode->next)
112                freeListNode->next->prev = newNode;
113            delete freeListNode;
114        }
115    }
116};
117
118} // namespace Slang
119#endif