Skip to content
Permalink
Browse files

Fixed issue 1 (multiple init) by adding a state variable.

Now including dynarr.h automatically calls SEG_ARR_CREATE() and undefs DYNARR_DATA_TYPE.
  • Loading branch information...
unknown
unknown committed Oct 8, 2014
1 parent d4c7e78 commit b5fa1b28a81de8fe21e3536a1d11f111556d5908
Showing with 100 additions and 48 deletions.
  1. +2 −0 dynarrc/CuTest.c
  2. +7 −0 dynarrc/dynarr.h
  3. +44 −36 dynarrc/dynarrc.coremethods.h
  4. +6 −0 dynarrc/dynarrc.interface.h
  5. +7 −0 dynarrc/dynarrc.vars.h
  6. +34 −12 dynarrc/test.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);
}
@@ -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
@@ -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)
@@ -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
@@ -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)
@@ -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;
}

0 comments on commit b5fa1b2

Please sign in to comment.
You can’t perform that action at this time.