From b5fa1b28a81de8fe21e3536a1d11f111556d5908 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Oct 2014 14:05:00 -0400 Subject: [PATCH] Fixed issue 1 (multiple init) by adding a state variable. Now including dynarr.h automatically calls SEG_ARR_CREATE() and undefs DYNARR_DATA_TYPE. --- dynarrc/CuTest.c | 2 + dynarrc/dynarr.h | 7 +++ dynarrc/dynarrc.coremethods.h | 80 +++++++++++++++++++---------------- dynarrc/dynarrc.interface.h | 6 +++ dynarrc/dynarrc.vars.h | 7 +++ dynarrc/test.c | 46 ++++++++++++++------ 6 files changed, 100 insertions(+), 48 deletions(-) diff --git a/dynarrc/CuTest.c b/dynarrc/CuTest.c index 257c1d2..f2025ba 100644 --- a/dynarrc/CuTest.c +++ b/dynarrc/CuTest.c @@ -142,6 +142,8 @@ void CuTestRun(CuTest* tc) tc->jumpBuf = &buf; if (setjmp(buf) == 0) { + // added by Saad + printf("Test: %s\n", tc->name); tc->ran = 1; (tc->function)(tc); } diff --git a/dynarrc/dynarr.h b/dynarrc/dynarr.h index 6ad5641..0594559 100644 --- a/dynarrc/dynarr.h +++ b/dynarrc/dynarr.h @@ -63,6 +63,13 @@ extern "C"{ /* Finally, the interface used by clients */ #include "dynarrc.interface.h" + /*---------------------------------*/ + // Ready to use LLArr + // create the state variables + // prepare for further use by undefining DYNARR_DATA_TYPE +createLLArr(MyStruct); // global allocator +#undef DYNARR_DATA_TYPE + #ifdef __cplusplus } // extern "C" #endif diff --git a/dynarrc/dynarrc.coremethods.h b/dynarrc/dynarrc.coremethods.h index de178c1..7c4c36f 100644 --- a/dynarrc/dynarrc.coremethods.h +++ b/dynarrc/dynarrc.coremethods.h @@ -1,4 +1,6 @@ + + // create a global dynarr struct containing all state variables for given type #define SEG_ARR_CREATE(type) \ DYNARR_STATE(type) DYNARR_VARS(type); @@ -8,54 +10,60 @@ extern SEG_ARR_CREATE(type); // initialize all state variables in the global dynarr struct for given type -#define SEG_ARR_INIT(type) \ - /*MaxSeg should be already assigned */ \ - assert(MAXSEG > 0 ); \ - LOGMAXSEG(type) = (unsigned int) (log(MAXSEG+0.0f)/log(2.0f)); \ - MAXSEG_REMAINDER_BITMASK(type) = (unsigned int) (MAXSEG - 1); \ - NULL_SEG(type).index = NULL_SEG(type).nextIndex = EMPTY_INDEX; \ - /* seg-arr management */ \ - SEG_ARR(type) = ( DYNARR_SEG_TYPE(type) *) malloc( sizeof(DYNARR_SEG_TYPE(type) ) * MAXSEG ); \ - assert(SEG_ARR(type) != NULL ); \ - memset(SEG_ARR(type), 0, sizeof(DYNARR_SEG_TYPE(type)) * MAXSEG ); \ - SEG_INSERT_POS(type) = SEG_INSERT_POS_BEGIN; \ - /*------------------------------------*/ \ - /* multiple segment banks */ \ - /* In test mode, do not initalize MaxSegBanks here so that */ \ - /* it can be initialized by other code before calling SEG_BANKS_INIT() */ \ - /*if (!TestEnabled) MAX_SEG_BANKS(type) = 1; */ \ - MAX_SEG_BANKS(type) = 1; /* Default value */ \ - TOTAL_SEGS(type) = 0; /* Default value */ \ - SEG_BANK_ALLOC_VIOLATION(type) = 0; \ - /* segment banks*/ \ - SEG_BANKS_ARR(type) = (DYNARR_SEG_TYPE(type)**)malloc(MAX_SEG_BANKS(type) * sizeof(DYNARR_SEG_TYPE(type)*)); \ - memset(SEG_BANKS_ARR(type), 0, MAX_SEG_BANKS(type) * sizeof(DYNARR_SEG_TYPE(type)*)); \ - /* segment bank sizes*/ \ - SEG_BANK_SIZE_ARR(type) = (int*)malloc(MAX_SEG_BANKS(type) * sizeof(int)); \ - memset(SEG_BANK_SIZE_ARR(type), 0, MAX_SEG_BANKS(type) * sizeof(int)); \ - /* segment bank index limits */ \ - SEG_BANK_INDEX_LIMIT_ARR(type) = (int*)malloc(MAX_SEG_BANKS(type) * sizeof(int)); \ - memset(SEG_BANK_INDEX_LIMIT_ARR(type), 0, MAX_SEG_BANKS(type) * sizeof(int)); \ - /* first segment bacnk already allocated */ \ - SEG_BANKS_ARR(type)[0] = SEG_ARR(type); \ - SEG_BANK_SIZE_ARR(type)[0] = MAXSEG; \ - SEG_BANK_INDEX_LIMIT_ARR(type)[0] = MAXSEG - 1; \ - NUM_SEG_BANKS(type) = 1; +#define SEG_ARR_INIT(type) do{\ + if(INITIALIZED_FLAG(type) == 0) { \ + /*MaxSeg should be already assigned */ \ + assert(MAXSEG > 0 ); \ + LOGMAXSEG(type) = (unsigned int) (log(MAXSEG+0.0f)/log(2.0f)); \ + MAXSEG_REMAINDER_BITMASK(type) = (unsigned int) (MAXSEG - 1); \ + NULL_SEG(type).index = NULL_SEG(type).nextIndex = EMPTY_INDEX; \ + /* seg-arr management */ \ + SEG_ARR(type) = ( DYNARR_SEG_TYPE(type) *) malloc( sizeof(DYNARR_SEG_TYPE(type) ) * MAXSEG ); \ + assert(SEG_ARR(type) != NULL ); \ + memset(SEG_ARR(type), 0, sizeof(DYNARR_SEG_TYPE(type)) * MAXSEG ); \ + SEG_INSERT_POS(type) = SEG_INSERT_POS_BEGIN; \ + /*------------------------------------*/ \ + /* multiple segment banks */ \ + /* In test mode, do not initalize MaxSegBanks here so that */ \ + /* it can be initialized by other code before calling SEG_BANKS_INIT() */ \ + /*if (!TestEnabled) MAX_SEG_BANKS(type) = 1; */ \ + MAX_SEG_BANKS(type) = 1; /* Default value */ \ + TOTAL_SEGS(type) = 0; /* Default value */ \ + SEG_BANK_ALLOC_VIOLATION(type) = 0; \ + /* segment banks*/ \ + SEG_BANKS_ARR(type) = (DYNARR_SEG_TYPE(type)**)malloc(MAX_SEG_BANKS(type) * sizeof(DYNARR_SEG_TYPE(type)*)); \ + memset(SEG_BANKS_ARR(type), 0, MAX_SEG_BANKS(type) * sizeof(DYNARR_SEG_TYPE(type)*)); \ + /* segment bank sizes*/ \ + SEG_BANK_SIZE_ARR(type) = (int*)malloc(MAX_SEG_BANKS(type) * sizeof(int)); \ + memset(SEG_BANK_SIZE_ARR(type), 0, MAX_SEG_BANKS(type) * sizeof(int)); \ + /* segment bank index limits */ \ + SEG_BANK_INDEX_LIMIT_ARR(type) = (int*)malloc(MAX_SEG_BANKS(type) * sizeof(int)); \ + memset(SEG_BANK_INDEX_LIMIT_ARR(type), 0, MAX_SEG_BANKS(type) * sizeof(int)); \ + /* first segment bacnk already allocated */ \ + SEG_BANKS_ARR(type)[0] = SEG_ARR(type); \ + SEG_BANK_SIZE_ARR(type)[0] = MAXSEG; \ + SEG_BANK_INDEX_LIMIT_ARR(type)[0] = MAXSEG - 1; \ + NUM_SEG_BANKS(type) = 1; \ + INITIALIZED_FLAG(type) = 1; \ + } \ +}while(0) // cleanup all state variables in the global dynarr struct for given type -#define SEG_ARR_CLEANUP(type) \ +#define SEG_ARR_CLEANUP(type) do{\ FREE_SAFE( SEG_ARR(type) ); \ SEG_INSERT_POS(type) = SEG_INSERT_POS_BEGIN; \ /*-------------------------------*/ \ /* multiple segment banks */ \ for(TEMP_INDEX_1(type) = 1; TEMP_INDEX_1(type) < NUM_SEG_BANKS(type); TEMP_INDEX_1(type)++){ \ FREE_SAFE(SEG_BANKS_ARR(type)[TEMP_INDEX_1(type)]); \ - } \ + } \ NUM_SEG_BANKS(type) = 0; \ FREE_SAFE(SEG_BANKS_ARR(type)); \ FREE_SAFE(SEG_BANK_SIZE_ARR(type)); \ FREE_SAFE(SEG_BANK_INDEX_LIMIT_ARR(type)); \ SEG_BANK_ALLOC_VIOLATION(type) = 0; \ _SEG_ARR_FREE_LIST_CLEANUP(type); \ - TOTAL_SEGS(type) = 0; + TOTAL_SEGS(type) = 0; \ + INITIALIZED_FLAG(type) = 0; \ +}while(0) diff --git a/dynarrc/dynarrc.interface.h b/dynarrc/dynarrc.interface.h index 0aac3a4..6f4d954 100644 --- a/dynarrc/dynarrc.interface.h +++ b/dynarrc/dynarrc.interface.h @@ -1,5 +1,11 @@ /* Main interface for array-based linked-list allocator */ +// core methods +#define createLLArr(type) SEG_ARR_CREATE(type) +#define useLLArr(type) SEG_ARR_USE(type) +#define initLLArr(type) SEG_ARR_INIT(type) +#define clearLLArr(type) SEG_ARR_CLEANUP(type) + // checks whether a segment is empty/NULL/unusable #define segNull(seg) DYNARR_SEG_NULL(seg) // checks whether a segment is not empty/NULL/unusable diff --git a/dynarrc/dynarrc.vars.h b/dynarrc/dynarrc.vars.h index 3c7b38b..8cd2b6d 100644 --- a/dynarrc/dynarrc.vars.h +++ b/dynarrc/dynarrc.vars.h @@ -16,6 +16,11 @@ typedef struct { /* The dynamic array data structure */ #define DYNARR_STATE(type) TYPED_NAME(type, DynArr) typedef struct{ + ////////// meta //////////// + + // must be 1 after init, 0 after cleanup, 0 before init + int bInitializedFlag; + ////////// basics ////////// //unsigned int MaxSeg; /* Base-2 log */ @@ -55,6 +60,8 @@ typedef struct{ /* Shortcuts to important variables */ +#define INITIALIZED_FLAG(type) MEMBER(DYNARR_VARS(type),.,bInitializedFlag) +#pragma message(TO_STRING(INITIALIZED_FLAG(DYNARR_DATA_TYPE))) #define LOGMAXSEG(type) MEMBER(DYNARR_VARS(type),.,LogMaxSeg) #pragma message(TO_STRING(LOGMAXSEG(DYNARR_DATA_TYPE))) #define MAXSEG_REMAINDER_BITMASK(type) MEMBER(DYNARR_VARS(type),.,MaxSegRemainderBitMask) diff --git a/dynarrc/test.c b/dynarrc/test.c index aefd010..ee87c78 100644 --- a/dynarrc/test.c +++ b/dynarrc/test.c @@ -14,23 +14,19 @@ typedef struct MyStruct{ // fix the type for this allocator #define DYNARR_DATA_TYPE MyStruct #include "dynarr.h" -SEG_ARR_CREATE(MyStruct); // global allocator -#undef DYNARR_DATA_TYPE /*------ Allocator for MyStruct* ------*/ typedef struct MyStruct* MyStructPtr; #define DYNARR_DATA_TYPE MyStructPtr #include "dynarr.h" -#undef DYNARR_DATA_TYPE -SEG_ARR_CREATE(MyStructPtr); // global allocator // create, init, cleanup -void testCreateInitCleanup(CuTest* tc){ +void test_createInitCleanup(CuTest* tc){ int i; // init - SEG_ARR_INIT(MyStruct); + initLLArr(MyStruct); CuAssert(tc, "LogMaxSeg not 4", 4 == LOGMAXSEG(MyStruct)); CuAssert(tc, "MaxSegRemainderBitMask not 15", 15 == MAXSEG_REMAINDER_BITMASK(MyStruct)); CuAssert(tc, "insertPos not 1", 1 == SEG_INSERT_POS(MyStruct)); @@ -49,7 +45,7 @@ void testCreateInitCleanup(CuTest* tc){ CuAssert(tc, "SEG_BANK_INDEX_LIMIT_ARR[0] not MAXSEG-1", (MAXSEG-1) == SEG_BANK_INDEX_LIMIT_ARR(MyStruct)[0]); // cleanup - SEG_ARR_CLEANUP(MyStruct); + clearLLArr(MyStruct); CuAssert(tc, "SEGARR not NULL", NULL == SEG_ARR(MyStruct)); for (i = 1; i < NUM_SEG_BANKS(MyStruct); i++){ CuAssert(tc, "SEG_BANKS_ARR[i] not NULL", NULL == SEG_BANKS_ARR(MyStruct)[i]); @@ -62,11 +58,11 @@ void testCreateInitCleanup(CuTest* tc){ } // allocate segment -void testAllocSeg(CuTest* tc){ +void test_allocSeg(CuTest* tc){ int i; DYNARR_SEG_TYPE(MyStruct) seg1, seg2, seg, tempSeg; // init - SEG_ARR_INIT(MyStruct); + initLLArr(MyStruct); /* Allocate one segment */ seg1 = allocSeg(MyStruct); @@ -153,16 +149,42 @@ void testAllocSeg(CuTest* tc){ CuAssert(tc, "new index not deleted index", i == seg1.index); // cleanup - SEG_ARR_CLEANUP(MyStruct); + clearLLArr(MyStruct); } +// prevent repeated initialization +// if it is already initialized, init() should do nothing more +void test_issue1(CuTest* tc){ + int i; + int numSegs, numSegBanks; + CuAssert(tc, "initialized flag not 0", 0 == INITIALIZED_FLAG(MyStruct)); + initLLArr(MyStruct); + CuAssert(tc, "initialized flag not 1", 1 == INITIALIZED_FLAG(MyStruct)); + // add some segments + for (i = 0; i < MAXSEG+1; i++){ + allocSeg(MyStruct); + } + numSegs = TOTAL_SEGS(MyStruct); + numSegBanks = NUM_SEG_BANKS(MyStruct); + CuAssert(tc, "numsegbanks not 2", 2 == numSegBanks); + // now init again + initLLArr(MyStruct); + // totalsegs and numsegs should stay the same + CuAssert(tc, "numsegbanks changed", numSegBanks == NUM_SEG_BANKS(MyStruct)); + CuAssert(tc, "totalsegs changed", numSegs == TOTAL_SEGS(MyStruct)); + // now cleanup + clearLLArr(MyStruct); + CuAssert(tc, "initialized flag not 0", 0 == INITIALIZED_FLAG(MyStruct)); +} + CuSuite* getBasicTestSuite(void) { CuSuite* suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, testCreateInitCleanup); - SUITE_ADD_TEST(suite, testAllocSeg); + SUITE_ADD_TEST(suite, test_createInitCleanup); + SUITE_ADD_TEST(suite, test_allocSeg); + SUITE_ADD_TEST(suite, test_issue1); return suite; }