diff --git a/dynarrc/common.h b/dynarrc/common.h index 2cdd74a..bfdd02a 100644 --- a/dynarrc/common.h +++ b/dynarrc/common.h @@ -54,13 +54,23 @@ #define SIZE_ARR(a) ( ((a)!=NULL) ? sizeof(a) / sizeof((a)[0]) : 0) -// max nodes -#define MAXSEG MaxSeg -#define LOG_MAXSEG LogMaxSeg -#define MAXSEG_REMAINDER_BITMASK MaxSegRemainderBitMask // types #define real_t float +// helper macros + +// e.g.: structVar.member or structPtr->member +#define MEMBER(structVar, memberop, member) TOKEN_PASTE(TOKEN_PASTE(structVar, memberop), member) + + +// swap two integers, or pointers, without using temporary storage +__inline void int_swap(unsigned int *var1, unsigned int *var2) { + (*var1) = (*var1) ^ (*var2); + (*var2) = (*var1) ^ (*var2); + (*var1) = (*var1) ^ (*var2); +} + + #endif // __dynarr_common_h__ \ No newline at end of file diff --git a/dynarrc/dynarr.c b/dynarrc/dynarr.c index 0919c2a..2ed0724 100644 --- a/dynarrc/dynarr.c +++ b/dynarrc/dynarr.c @@ -17,123 +17,3 @@ EXTERN unsigned int MaxSegRemainderBitMask; SEGALLOC_USE(); -// when maximum number of segment banks is reached, -// double MaxSegBanks and -// reallocate the bookkeeping machinery -// returns 0 if bad, 1 if ok -int seg_bank_increase_max(){ - void* pVoid; - int bSuccess = 1; - int prevMaxSegBanks = MAX_SEG_BANKS; - // new limit on number of segment banks - MAX_SEG_BANKS <<= 1; - - // realloc - if (pVoid = realloc(pSegBanksArr, MaxSegBanks * sizeof(real_t*))){ - pSegBanksArr = (real_t**)pVoid; - memset(pSegBanksArr + prevMaxSegBanks, 0, (MaxSegBanks - prevMaxSegBanks) * sizeof(real_t*)); - } - else { - printf("\nFatal error: Failed to increase the Maximum number of segment banks." - "\n\tFile: %s\n\tLine: %d\n", - __FILE__, __LINE__); - return 0; - } - - if (pVoid = realloc(pSegBankSizeArr, MaxSegBanks * sizeof(int))){ - pSegBankSizeArr = (int*)pVoid; - memset(pSegBankSizeArr + prevMaxSegBanks, 0, (MaxSegBanks - prevMaxSegBanks) * sizeof(int)); - } - else { - printf("\nFatal error: Failed to increase the Maximum number of segment banks." - "\n\tFile: %s\n\tLine: %d\n", - __FILE__, __LINE__); - return 0; - } - - if (pVoid = realloc(pSegBankIndexLimitArr, MaxSegBanks * sizeof(int))){ - pSegBankIndexLimitArr = (int*)pVoid; - memset(pSegBankIndexLimitArr + prevMaxSegBanks, 0, (MaxSegBanks - prevMaxSegBanks) * sizeof(int)); - } - else { - printf("\nFatal error: Failed to increase the Maximum number of segment banks." - "\n\tFile: %s\n\tLine: %d\n", - __FILE__, __LINE__); - return 0; - } - - // ok - return 1; -} - -// -// allocate next segment bank and place iInsertPos in appropriate value -// -int seg_bank_alloc_next(){ - int numElems = MaxSeg, - round = 0, - iHypotheticalTotalSegsUptoLastActiveBank = 0; - real_t* ptr; - int bCpuGpuAllocDone = 0; - - //assert(NumSegBanks < MAX_SEG_BANKS); - if (NumSegBanks >= MAX_SEG_BANKS) { - // increase limit on the number of segment banks - if (!seg_bank_increase_max()){ - // no futher alloc possible - SegBankAllocViolation = 1; - - printf("\nFatal error: Maximum number of segment banks is reached." - "\n\tFile: %s\n\tLine: %d\n", - __FILE__, __LINE__); - return 0; - } - else{ - // great, it is possible to have more segment banks - // continue - } - } - - // ok, lets try to allocate one more segment bank - do{ - // cpu alloc - do{ - numElems >>= (round++); - assert(numElems % 4 == 0); // must be a multiple of 4 - - ptr = (real_t*)malloc(numElems * NUM_SEG_MEMBERS_IN_ARR * sizeof(real_t)); - } while (numElems > 1 && ptr == NULL); - assert(ptr != NULL); - if (ptr == NULL){ - // no futher alloc possible - SegBankAllocViolation = 1; - - printf("\nFatal error: Failed to allocate next segment bank" - "\n\tFile: %s\n\tLine: %d\n", __FILE__, __LINE__); - return 0; - } - - // ok in cpu - pSegBanksArr[NumSegBanks] = ptr; - - // update the size of the bank - // it is used when allocating bank in gpu - pSegBankSizeArr[NumSegBanks] = numElems; - - // now allocate corresponding bank in gpu - bCpuGpuAllocDone = 1; - } while (bCpuGpuAllocDone == 0); - - // great - // initialize everything to zero, this makes all segments initially null - memset(ptr, 0, numElems * NUM_SEG_MEMBERS_IN_ARR * sizeof(real_t)); - iHypotheticalTotalSegsUptoLastActiveBank = NumSegBanks * MaxSeg; - // pretend that each segment bank is of size MaxSeg - pSegBankIndexLimitArr[NumSegBanks] = (iHypotheticalTotalSegsUptoLastActiveBank - 1) + numElems; - - // finally - iInsertPos = iHypotheticalTotalSegsUptoLastActiveBank; - NumSegBanks++; - - return 1; -} diff --git a/dynarrc/dynarr.h b/dynarrc/dynarr.h index 4b0f511..088daa1 100644 --- a/dynarrc/dynarr.h +++ b/dynarrc/dynarr.h @@ -1,39 +1,55 @@ #pragma message("touching: "__FILE__) #include "common.h" +#include +#include -#define MAXSEG 5 -#define DYNARR_TYPE int -#define TYPED_NAME(name) TOKEN_PASTE(DYNARR_TYPE, name) +//#define MAXSEG 5 +//#define DYNARR_DATA_TYPE int +//#define TYPED_NAME(name) TOKEN_PASTE(DYNARR_DATA_TYPE, name) /* Assuming MAXSEG is defined. Size of each block of the dynamic array. Must be a positive integer.*/ -/* Assuming DYNARR_TYPE is defined. +/* Assuming DYNARR_DATA_TYPE is defined. The data type of the array. Must be a valid one-word type without space, *, etc. (use typedef if necessary) */ #ifndef MAXSEG -#pragma message("MAXSEG must be defined before including " __FILE__) +// #pragma message("MAXSEG must be defined before including " __FILE__) +// must be pow of 2 +#define MAXSEG 1024 #elif MAXSEG <= 0 #pragma message("MAXSEG has non positive value: " MAXSEG) -#elif !defined(DYNARR_TYPE) -#pragma message("DYNARR_TYPE must be defined before including " __FILE__) -#else +#elif !defined(DYNARR_DATA_TYPE) +#pragma message("DYNARR_DATA_TYPE must be defined before including " __FILE__) +#endif + + // everything is fine #include "dynarr_freenodelist.h" /* The segment structure. These are the nodes of the linked list */ +#define DYNARR_SEG_TYPE TYPED_NAME(Sseg) typedef struct { - DYNARR_TYPE data; + DYNARR_DATA_TYPE data; int index; // my position int nextIndex; // next node's position -}TYPED_NAME(Sseg); -const TYPED_NAME(Sseg) EMPTY_SSEG; +}DYNARR_SEG_TYPE; +//const DYNARR_SEG_STRUCT TYPED_NAME(EMPTY_SSEG); + /* The dynamic array data structure */ +#define DYNARR_STRUCT TYPED_NAME(DynArr) typedef struct{ - TYPED_NAME(Sseg)* pSegArr; + ////////// basics ////////// + //unsigned int MaxSeg; + /* Base-2 log */ + unsigned int LogMaxSeg; + /* MAXSEG-1; MAXSEG must be a power of 2 */ + unsigned int MaxSegRemainderBitMask; + + DYNARR_SEG_TYPE* pSegArr; //real_t* pSegNextArr; int iInsertPos; /////////////////// Free nodes list //////////////// @@ -42,23 +58,26 @@ typedef struct{ struct FreeSegNode* pTempFreeNode1, *pTempFreeNode2; ////////////// temporaries ////////////// int iTempIndex1, iTempIndex2; - TYPED_NAME(Sseg) tempSeg1; - const TYPED_NAME(Sseg) emptySeg; + DYNARR_SEG_TYPE tempSeg1; + const DYNARR_SEG_TYPE emptySeg; //////////// Segment banks //////////// - TYPED_NAME(Sseg)** pSegBanksArr; + DYNARR_SEG_TYPE** pSegBanksArr; int* pSegBankSizeArr; int* pSegBankIndexLimitArr; int NumSegBanks; - int NumSegBanks; int MaxSegBanks; int SegBankAllocViolation; -}TYPED_NAME(DynArr); +}DYNARR_STRUCT; // dynarr variable name; contains all state variables -#define DYNARR_VARS TOKEN_PASTE(TYPED_NAME(DynArr), Vars) +#define DYNARR_VARS TOKEN_PASTE(DYNARR_DATA_TYPE, Vars) +// create a reference +extern DYNARR_STRUCT DYNARR_VARS; /* Shortcuts to important variables */ -#define SEG_ARR DYNARR_VARS.pSegArr +#define LOGMAXSEG MEMBER(DYNARR_VARS,.,logMaxSeg) +#define MAXSEG_REMAINDER_BITMASK MEMBER(DYNARR_VARS,.,MaxSegRemainderBitMask) +#define SEG_ARR MEMBER(DYNARR_VARS,.,pSegArr) #define SEG_INSERT_POS DYNARR_VARS.iInsertPos #define FREESEG_LIST DYNARR_VARS.pFreeSegList #define FREESEG_INVALID_LIST DYNARR_VARS.pFreeSegInvalidList @@ -73,39 +92,32 @@ typedef struct{ // maximum number of segment banks // this should be a very big number // this number should never be reached -#define MAX_SEG_BANKS DYNARR_VARS.MaxSegBanks +#define MAX_SEG_BANKS MEMBER(DYNARR_VARS,.,MaxSegBanks) // array containing size (# of segments) of each segment bank -#define SEG_BANK_SIZE_ARR DYNARR_VARS.pSegBankSizeArr +#define SEG_BANK_SIZE_ARR MEMBER(DYNARR_VARS,.,pSegBankSizeArr) // array containing last valid index of each segment bank -#define SEG_BANK_INDEX_LIMIT_ARR DYNARR_VARS.pSegBankIndexLimitArr +#define SEG_BANK_INDEX_LIMIT_ARR MEMBER(DYNARR_VARS,.,pSegBankIndexLimitArr) // Number of active segment banks -#define NUM_SEG_BANKS DYNARR_VARS.NumSegBanks +#define NUM_SEG_BANKS MEMBER(DYNARR_VARS,.,NumSegBanks) #define CURRENT_SEG_BANK (NUM_SEG_BANKS - 1) // actual segment banks -#define SEG_BANKS_ARR DYNARR_VARS.pSegBanksArr +#define SEG_BANKS_ARR MEMBER(DYNARR_VARS,.,pSegBanksArr) // declarations -// swap two integers, or pointers, without using temporary storage -__inline void int_swap(unsigned int *var1, unsigned int *var2) { - (*var1) = (*var1) ^ (*var2); - (*var2) = (*var1) ^ (*var2); - (*var1) = (*var1) ^ (*var2); -} // external definitions for allocating/resizing blocks -extern int seg_bank_alloc_next(); -extern int seg_bank_increase_max(); - +int TYPED_NAME(seg_bank_alloc_next)(); +int TYPED_NAME(seg_bank_increase_max)(); +#if 0 #define EMPTY_INDEX 0 #define EMPTY_BYTE 0 -#define NULL_SEG TYPED_NAME(DynArr).emptySeg #define SEG_INSERT_POS_BEGIN 1 // Node blocks @@ -184,12 +196,10 @@ extern int seg_bank_increase_max(); /* DynArr methods*/ #define SEG_ARR_USE() \ - extern TYPED_NAME(DynArr) DYNARR_VARS; - - + extern DYNARR_STRUCT DYNARR_VARS; #define SEG_ARR_CREATE() \ - TYPED_NAME(DynArr) DYNARR_VARS;\ + DYNARR_STRUCT DYNARR_VARS; \ SEG_ARR = NULL; \ SEG_INSERT_POS = SEG_INSERT_POS_BEGIN; \ FREESEG_LIST = NULL, FREESEG_INVALID_LIST = NULL; \ @@ -200,6 +210,7 @@ extern int seg_bank_increase_max(); SEG_BANKS_CREATE(); \ + #define SEG_ARR_INIT() \ printf("maxseg: %d, offsets... fs:%d ls:%d c:%d v:%d n:%d num_seg_arr_items:%d\n", \ MAXSEG, \ @@ -291,8 +302,138 @@ extern int seg_bank_increase_max(); ) \ + #endif +// when maximum number of segment banks is reached, +// double MaxSegBanks and +// reallocate the bookkeeping machinery +// returns 0 if bad, 1 if ok +int TYPED_NAME(seg_bank_increase_max)(){ + void* pVoid; + int bSuccess = 1; + int prevMaxSegBanks = MAX_SEG_BANKS; + // new limit on number of segment banks + MAX_SEG_BANKS <<= 1; + + // realloc + if (pVoid = realloc(SEG_BANKS_ARR, MAX_SEG_BANKS * sizeof(DYNARR_SEG_TYPE*))){ + SEG_BANKS_ARR = (DYNARR_SEG_TYPE**)pVoid; + memset(SEG_BANKS_ARR + prevMaxSegBanks, 0, (MAX_SEG_BANKS - prevMaxSegBanks) * sizeof(DYNARR_SEG_TYPE*)); + } + else { + printf("\nFatal error: Failed to increase the Maximum number of segment banks." + "\n\tFile: %s\n\tLine: %d\n", + __FILE__, __LINE__); + return 0; + } + + if (pVoid = realloc(SEG_BANK_SIZE_ARR, MAX_SEG_BANKS * sizeof(int))){ + SEG_BANK_SIZE_ARR = (int*)pVoid; + memset(SEG_BANK_SIZE_ARR + prevMaxSegBanks, 0, (MAX_SEG_BANKS - prevMaxSegBanks) * sizeof(int)); + } + else { + printf("\nFatal error: Failed to increase the Maximum number of segment banks." + "\n\tFile: %s\n\tLine: %d\n", + __FILE__, __LINE__); + return 0; + } + + if (pVoid = realloc(SEG_BANK_INDEX_LIMIT_ARR, MAX_SEG_BANKS * sizeof(int))){ + SEG_BANK_INDEX_LIMIT_ARR = (int*)pVoid; + memset(SEG_BANK_INDEX_LIMIT_ARR + prevMaxSegBanks, 0, (MAX_SEG_BANKS - prevMaxSegBanks) * sizeof(int)); + } + else { + printf("\nFatal error: Failed to increase the Maximum number of segment banks." + "\n\tFile: %s\n\tLine: %d\n", + __FILE__, __LINE__); + return 0; + } + + // ok + return 1; + } + +// +// allocate next segment bank and place iInsertPos in appropriate value +// +int TYPED_NAME(seg_bank_alloc_next)(){ + // shall we also alloc gpu with cpu? + int bAllocGpu = 0; + + int numElems = MAXSEG, + round = 0, + iHypotheticalTotalSegsUptoLastActiveBank = 0; + DYNARR_SEG_TYPE* ptr; + int bCpuGpuAllocDone = 0; + + //assert(NumSegBanks < MAX_SEG_BANKS); + if (NUM_SEG_BANKS >= MAX_SEG_BANKS) { + // increase limit on the number of segment banks + if (!TYPED_NAME(seg_bank_increase_max)() ){ + // no futher alloc possible + SEG_BANK_ALLOC_VIOLATION = 1; + + printf("\nFatal error: Maximum number of segment banks is reached." + "\n\tFile: %s\n\tLine: %d\n", + __FILE__, __LINE__); + return 0; + } + else{ + // great, it is possible to have more segment banks + // continue + } + } + + // ok, lets try to allocate one more segment bank + do{ + // cpu alloc + do{ + numElems >>= (round++); + assert(numElems % 4 == 0); // must be a multiple of 4 + + ptr = (DYNARR_SEG_TYPE*)malloc(numElems * sizeof(DYNARR_SEG_TYPE)); + } while (numElems > 1 && ptr == NULL); + assert(ptr != NULL); + if (ptr == NULL){ + // no futher alloc possible + SEG_BANK_ALLOC_VIOLATION = 1; + + printf("\nFatal error: Failed to allocate next segment bank" + "\n\tFile: %s\n\tLine: %d\n", __FILE__, __LINE__); + return 0; + } + + // ok in cpu + SEG_BANKS_ARR[NUM_SEG_BANKS] = ptr; + + // update the size of the bank + // it is used when allocating bank in gpu + SEG_BANK_SIZE_ARR[NUM_SEG_BANKS] = numElems; + + // now allocate corresponding bank in gpu + bCpuGpuAllocDone = 1; + } while (bCpuGpuAllocDone == 0); + + // great + // initialize everything to zero, this makes all segments initially null + memset(ptr, 0, numElems * sizeof(DYNARR_SEG_TYPE)); + iHypotheticalTotalSegsUptoLastActiveBank = NUM_SEG_BANKS * MAXSEG; + // pretend that each segment bank is of size MaxSeg + SEG_BANK_INDEX_LIMIT_ARR[NUM_SEG_BANKS] = (iHypotheticalTotalSegsUptoLastActiveBank - 1) + numElems; + + // finally + SEG_INSERT_POS = iHypotheticalTotalSegsUptoLastActiveBank; + NUM_SEG_BANKS++; + + return 1; +} + +// done + + + + diff --git a/dynarrc/dynarrc.vcxproj b/dynarrc/dynarrc.vcxproj index ab0b92f..e31e8ad 100644 --- a/dynarrc/dynarrc.vcxproj +++ b/dynarrc/dynarrc.vcxproj @@ -69,7 +69,6 @@ - diff --git a/dynarrc/dynarrc.vcxproj.filters b/dynarrc/dynarrc.vcxproj.filters index 9e5ae37..a683cab 100644 --- a/dynarrc/dynarrc.vcxproj.filters +++ b/dynarrc/dynarrc.vcxproj.filters @@ -26,9 +26,6 @@ - - Source Files - Source Files diff --git a/dynarrc/main.c b/dynarrc/main.c index 06ac2cb..fa3722c 100644 --- a/dynarrc/main.c +++ b/dynarrc/main.c @@ -2,17 +2,21 @@ #include #include -#define MAXSEG 5 -#define DYNARR_TYPE int -#define TYPED_NAME( name ) TOKEN_PASTE(DYNARR_TYPE, name) +//#define MAXSEG 5 +#define DYNARR_DATA_TYPE int +#define TYPED_NAME( name ) TOKEN_PASTE(DYNARR_DATA_TYPE, name) #include "dynarr.h" -typedef struct TYPED_NAME(DynArr) IdArr; +typedef DYNARR_STRUCT IdArr; +#undef DYNARR_DATA_TYPE -#define DYNARR_TYPE float -#define TYPED_NAME( name ) TOKEN_PASTE(DYNARR_TYPE, name) + +#define DYNARR_DATA_TYPE float +#define TYPED_NAME( name ) TOKEN_PASTE(DYNARR_DATA_TYPE, name) #include "dynarr.h" -typedef struct TYPED_NAME(DynArr) ValueArr; +typedef DYNARR_STRUCT ValueArr; +#undef DYNARR_DATA_TYPE + int main(int argc, char** argv){