aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/bfc/freelist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Wasabi/bfc/freelist.cpp')
-rw-r--r--Src/Wasabi/bfc/freelist.cpp81
1 files changed, 81 insertions, 0 deletions
diff --git a/Src/Wasabi/bfc/freelist.cpp b/Src/Wasabi/bfc/freelist.cpp
new file mode 100644
index 00000000..06a9218d
--- /dev/null
+++ b/Src/Wasabi/bfc/freelist.cpp
@@ -0,0 +1,81 @@
+#include "precomp_wasabi_bfc.h"
+
+#include "freelist.h"
+
+// define this to turn off freelist behavior
+//#define FREELIST_FUCT
+
+FreelistPriv::FreelistPriv() {
+ total_allocated = 0;
+}
+
+FreelistPriv::~FreelistPriv() {
+#ifdef ASSERTS_ENABLED
+// ASSERTPR(total_allocated == 0, "didn't free entire freelist!(1)");
+// ASSERTPR(blocks.getNumItems() == 0, "didn't free entire freelist!(2)");
+ if (total_allocated != 0) DebugStringW(L"didn't free entire freelist!(1)\n");
+ if (blocks.getNumItems() != 0) DebugStringW(L"didn't free entire freelist!(2)\n");
+#endif
+}
+
+void *FreelistPriv::getRecord(int typesize, int blocksize, int initialblocksize) {
+#ifdef FREELIST_FUCT
+ return MALLOC(typesize);
+#else
+ ASSERT(typesize >= sizeof(void *));
+ FLMemBlock *mem = NULL;
+ for (int i = 0; i < blocks.getNumItems(); i++) {
+ mem = blocks[i];
+ if (mem->freelist != NULL) break;
+ mem = NULL;
+ }
+ if (mem == NULL) {
+ // figure record count for this new block
+ int siz = (blocks.getNumItems() ? blocksize : initialblocksize);
+ // allocate another block of memory
+ mem = new FLMemBlock(siz*typesize);
+ // prelink it into a freelist
+ char *record = static_cast<char *>(mem->freelist);
+ void **ptr;
+ for (int i = 0; i < siz-1; i++) {
+ ptr = reinterpret_cast<void **>(record);
+ record += typesize;
+ *ptr = static_cast<void *>(record);
+ }
+ // terminate newly made freelist
+ ptr = reinterpret_cast<void **>(record);
+ *ptr = NULL;
+ blocks.addItem(mem);
+ }
+ // get first free record
+ void *ret = mem->freelist;
+ // advance freelist *
+ mem->freelist = *(static_cast<void **>(mem->freelist));
+ mem->nallocated++;
+ total_allocated++;
+ return ret;
+#endif
+}
+
+void FreelistPriv::freeRecord(void *record) {
+#ifdef FREELIST_FUCT
+ FREE(record);
+#else
+ FLMemBlock *mem=NULL;
+ for (int i = 0; i < blocks.getNumItems(); i++) {
+ mem = blocks[i];
+ if (mem->isMine(reinterpret_cast<MBT*>(record))) break;
+ mem = NULL;
+ }
+ ASSERTPR(mem != NULL, "attempted to free record with no block");
+ // stash it back on the block's freelist
+ *reinterpret_cast<void **>(record) = mem->freelist;
+ mem->freelist = record;
+ ASSERT(mem->nallocated > 0);
+ mem->nallocated--;
+ if (mem->nallocated == 0) {
+ blocks.delItem(mem);
+ }
+ total_allocated--;
+#endif
+}