diff --git a/dynarrc/dynarr.h b/dynarrc/dynarr.h
index bf7ceeb..68c9467 100644
--- a/dynarrc/dynarr.h
+++ b/dynarrc/dynarr.h
@@ -26,21 +26,74 @@
// everything is fine
-#include "dynarr_freenodelist.h"
+#ifndef __dynarr_only_once__
+#define __dynarr_only_once__
+
+
+// the struct FreeSegNode will be used multiple times, so we do not want to redefine it
+struct FreeSegNode{
+ int index;
+ struct FreeSegNode* next;
+};
+typedef struct FreeSegNode FreeSegNode;
+
+
+
+#define _FreeSegNodeMalloc() \
+ ( (struct FreeSegNode*) malloc(sizeof(struct FreeSegNode)) )
+// Swaps two 32-bit intergers without using temporary variables
+#define _SEG_ARR_INT_SWAP(var1, var2) (\
+ (var1) = (FreeSegNode*) (((int) (void*) var1) ^ ((int) (void*) var2) ), \
+ (var2) = (FreeSegNode*) (((int) (void*) var1) ^ ((int) (void*) var2) ), \
+ (var1) = (FreeSegNode*) (((int) (void*) var1) ^ ((int) (void*) var2) ) )
+// Given two lists A and B, moves the head of A in front of the
+// head of B. Head of A must be non-null.
+//
+// Before:
+// A-->1-2-3-4-5
+// B-->a-b-c-d-e
+// After:
+// A-->2-3-4-5
+// B-->1-a-b-c-d-e
+//
+#define _SEG_ARR_MOVE_LIST_HEAD(listFrom, listTo) (\
+ _SEG_ARR_INT_SWAP( listFrom->next, listTo), \
+ _SEG_ARR_INT_SWAP( listFrom, listTo ) \
+ )
+
#ifndef TYPED_NAME
+// prefix the name with the type
#define TYPED_NAME(type, name ) TOKEN_PASTE(type, name)
#endif
+#if defined(_MSC_VER)
+
+// inlining
+#define INLINE _inline /* use _inline (VC++ specific) */
+// #define INLINE __forceinline /* use __forceinline (VC++ specific) */
+//#elif __GNUC__ && !__GNUC_STDC_INLINE__
+//#define INLINE inline
+#else
+#define INLINE inline /* use standard inline */
+#endif
+
+#endif // __dynarr_only_once__
+
+
/* The segment structure. These are the nodes of the linked list */
#define DYNARR_SEG_TYPE(type) TYPED_NAME(type, Sseg)
typedef struct {
- DYNARR_DATA_TYPE data;
int index; // my position
int nextIndex; // next node's position
+ DYNARR_DATA_TYPE data;
}DYNARR_SEG_TYPE(DYNARR_DATA_TYPE);
-//const DYNARR_SEG_STRUCT TYPED_NAME(EMPTY_SSEG);
+
+// true if the index is 0
+#define DYNARR_SEG_NULL(value_seg) ( (value_seg).index == EMPTY_INDEX )
+#define DYNARR_SEG_NOT_NULL(value_seg) ( (value_seg).index != EMPTY_INDEX )
+#define MAKE_DYNARR_SEG_NULL(value_seg) ( (value_seg).index = EMPTY_INDEX )
/* The dynamic array data structure */
@@ -63,7 +116,7 @@ typedef struct{
////////////// temporaries //////////////
int iTempIndex1, iTempIndex2;
DYNARR_SEG_TYPE(DYNARR_DATA_TYPE) tempSeg1;
- const DYNARR_SEG_TYPE(DYNARR_DATA_TYPE) emptySeg;
+ DYNARR_SEG_TYPE(DYNARR_DATA_TYPE) emptySeg;
//////////// Segment banks ////////////
DYNARR_SEG_TYPE(DYNARR_DATA_TYPE)** pSegBanksArr;
int* pSegBankSizeArr;
@@ -77,6 +130,18 @@ typedef struct{
// dynarr variable name; contains all state variables
#define DYNARR_VARS(type) TYPED_NAME(type, Vars)
+// create a global dynarr struct containing all state variables for given type
+#define SEG_ARR_CREATE(type) \
+ DYNARR_STATE(type) DYNARR_VARS(type);
+
+// use the global dynarr struct containing all state variables for given type
+#define SEG_ARR_USE(type) \
+ extern SEG_ARR_CREATE(type);
+
+/* Declare state variables to be used by functions below */
+SEG_ARR_USE(DYNARR_DATA_TYPE);
+
+
/* Shortcuts to important variables */
#define LOGMAXSEG(type) MEMBER(DYNARR_VARS(type),.,LogMaxSeg)
#pragma message(TO_STRING(LOGMAXSEG(DYNARR_DATA_TYPE)))
@@ -86,9 +151,9 @@ typedef struct{
#pragma message(TO_STRING(SEG_ARR(DYNARR_DATA_TYPE)))
#define SEG_INSERT_POS(type) MEMBER(DYNARR_VARS(type),.,iInsertPos)
#pragma message(TO_STRING(SEG_INSERT_POS(DYNARR_DATA_TYPE)))
-#define FREESEG_LIST(type) DYNARR_VARS(type).pFreeSegList
+#define FREESEG_LIST(type) MEMBER(DYNARR_VARS(type),.,pFreeSegList)
#pragma message(TO_STRING(FREESEG_LIST(DYNARR_DATA_TYPE)))
-#define FREESEG_INVALID_LIST(type) DYNARR_VARS(type).pFreeSegInvalidList
+#define FREESEG_INVALID_LIST(type) MEMBER(DYNARR_VARS(type),.,pFreeSegInvalidList)
#pragma message(TO_STRING(FREESEG_INVALID_LIST(DYNARR_DATA_TYPE)))
#define FREESEG_LIST_SIZE(type) DYNARR_VARS(type).iSizeOfFreeSegList
#pragma message(TO_STRING(FREESEG_LIST_SIZE(DYNARR_DATA_TYPE)))
@@ -126,11 +191,12 @@ typedef struct{
-// declarations
-// external definitions for allocating/resizing blocks
-#define SEG_ARR_ALLOC_NEXT_FUNC(type) TYPED_NAME(type, _seg_bank_alloc_next)
-#define SEG_ARR_INC_MAX_FUNC(type) TYPED_NAME(type, _seg_bank_increase_max)
-
+// external declarations for allocating/resizing blocks
+#define SEG_ARR_ALLOC_NEXT_FUNC(type) TYPED_NAME(type, _seg_bank_alloc_next)
+#define SEG_ARR_INC_MAX_FUNC(type) TYPED_NAME(type, _seg_bank_increase_max)
+// early declarations
+extern int SEG_ARR_ALLOC_NEXT_FUNC(DYNARR_DATA_TYPE)();
+extern int SEG_ARR_INC_MAX_FUNC(DYNARR_DATA_TYPE)();
#define EMPTY_INDEX 0
@@ -153,31 +219,94 @@ typedef struct{
(BANK_FROM_SEG_INDEX(type, index) + SLOT_FROM_SEG_INDEX(type, index) )
#endif
+// Free segment list methods
+#if _REGION_
+// returns index
+#define _SEG_ARR_FREE_LIST_ADD_VALIDLIST(type, value_seg) (\
+ (!FREESEG_LIST(type))\
+ ?(\
+ FREESEG_LIST(type) = _FreeSegNodeMalloc(), \
+ /*assert(FREESEG_LIST(type) != NULL );*/ \
+ FREESEG_LIST(type)->next = NULL, \
+ FREESEG_LIST(type)->index = ((value_seg).index) \
+ ) : (\
+ TEMP_FREESEGNODE_1(type) = _FreeSegNodeMalloc(), \
+ /*assert(pTempFreeNode1 != NULL );*/ \
+ TEMP_FREESEGNODE_1(type)->next = FREESEG_LIST(type); \
+ FREESEG_LIST(type) = TEMP_FREESEGNODE_1(type); \
+ FREESEG_LIST(type)->index = ((value_seg).index) \
+ ) \
+ )
+// Algorithm:
+// If (an invalid node exists) Then
+// move it to the front of valid list
+// set its index as the index of value_seg
+// Else
+// Allocate new node in the valid list
+//
+#define _SEG_ARR_FREE_LIST_ADD(type, value_seg) (\
+ ( FREESEG_INVALID_LIST(type) ) \
+ ? ( \
+ _SEG_ARR_MOVE_LIST_HEAD( FREESEG_INVALID_LIST(type), FREESEG_LIST(type) ), \
+ FREESEG_LIST(type)->index = ((value_seg).index) \
+ ) \
+ : ( _SEG_ARR_FREE_LIST_ADD_VALIDLIST_FUNC(type)(value_seg) ) \
+ )
-/* DynArr methods*/
-#if _REGION_
+#define _SEG_ARR_REMOVE_LIST_HEAD(type, list) (\
+ TEMP_FREESEGNODE_1(type) = list, \
+ list = list->next, \
+ FREE_SAFE( TEMP_FREESEGNODE_1(type) ) )\
-// create a global dynarr struct containing all state variables for given type
-#define SEG_ARR_CREATE(type) \
- DYNARR_STATE(type) DYNARR_VARS(type);
+// Algorithm:
+// If (a valid node exists) Then
+// output its index, and
+// move it to the front of invalid list
+// Else
+// output null index
+//
+#define _SEG_ARR_FREE_LIST_GRAB_INDEX(type, value_seg) (\
+ ( FREESEG_LIST(type) ) ?(\
+ (value_seg).index = FREESEG_LIST(type)->index, \
+ (value_seg).nextIndex = EMPTY_INDEX, \
+ _SEG_ARR_MOVE_LIST_HEAD( type, FREESEG_LIST(type), FREESEG_INVALID_LIST(type) ), \
+ (value_seg) \
+ ):(\
+ MAKE_DYNARR_SEG_NULL(value_seg), \
+ (value_seg) \
+ ) )\
+
+
+#define _SEG_ARR_FREE_LIST_CLEANUP(type) {\
+ while( FREESEG_LIST(type) ) {\
+ _SEG_ARR_REMOVE_LIST_HEAD(type, FREESEG_LIST(type)); \
+ } \
+ while( FREESEG_INVALID_LIST(type) ) {\
+ _SEG_ARR_REMOVE_LIST_HEAD(type, FREESEG_INVALID_LIST(type)); \
+ } \
+} \
-// use the global dynarr struct containing all state variables for given type
-#define SEG_ARR_USE(type) \
- extern SEG_ARR_CREATE(type);
+#endif
+/* DynArr methods*/
+#if _REGION_
+
+// SEG_ARR_USE() and SEG_ARR_CREATE() has already been defined
+
// 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 ); \
- /* seg-arr management */ \
memset(SEG_ARR(type), 0, sizeof(DYNARR_SEG_TYPE(type)) * MAXSEG ); \
SEG_INSERT_POS(type) = SEG_INSERT_POS_BEGIN; \
/*------------------------------------*/ \
@@ -216,67 +345,62 @@ typedef struct{
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(); \
+ SEG_BANK_ALLOC_VIOLATION(type) = 0; \
+ _SEG_ARR_FREE_LIST_CLEANUP(type); \
#endif // _REGION
//#define SEG_ARR_EXISTS() ( pSegArr != NULL )
//#define SEG_ARR_SIZE NUM_SEG_ARR_ITEMS
+#define SEG_ARR_SEG_NEXT_INDEX(type, value_seg) (PTR_SEG_FROM_INDEX(type, (value_seg).index)->nextIndex)
// segment allocation/free/access
-#if 0 //_REGION_
+#if 1 //_REGION_
/* Accessor methods */
#define SEG_ARR_GET_SEG(type, segIndex) \
( (segIndex) != EMPTY_INDEX && \
(segIndex) >= 0 && \
(segIndex) < SEG_INSERT_POS(type) )\
- ? ( (tempSeg1).index = (segIndex),\
- tempSeg1.nextIndex = \
- (int) (SEG_ARR_SEG_NEXT_INDEX(type, tempSeg1)),\
- tempSeg1.c = SEG_ARR_SEG_C(tempSeg1), \
- tempSeg1.v = SEG_ARR_SEG_V(tempSeg1), \
- tempSeg1.prev = NULL, \
- tempSeg1)\
- : NULL_SEG
-
-#define SEG_EPANET_FREE_SET(value_seg) \
- ( _SEG_ARR_FREE_LIST_ADD((value_seg)), \
+ ? ( (TEMP_SEG_1(type)).index = (segIndex),\
+ TEMP_SEG_1(type).nextIndex = \
+ (int) (SEG_ARR_SEG_NEXT_INDEX(type, TEMP_SEG_1(type))),\
+ TEMP_SEG_1(type))\
+ : NULL_SEG(type)
+
+#define SEG_ARR_FREE_SET(type, value_seg) \
+ ( _SEG_ARR_FREE_LIST_ADD(type, (value_seg)), \
/*TOTALSEGS_DECR(), */\
- SEG_ARR_SEG_NEXT_INDEX(value_seg) = (real_t) EMPTY_INDEX, \
+ SEG_ARR_SEG_NEXT_INDEX(type, (value_seg)) = EMPTY_INDEX, \
(value_seg).index = (value_seg).nextIndex = EMPTY_INDEX \
)
-#define SEG_EPANET_FREE_GET(value_seg) (\
- _SEG_ARR_FREE_LIST_GRAB_INDEX((value_seg)), \
- (SEG_EPANET_NOT_NULL(value_seg) ? TOTALSEGS_INCR() : 0), \
+#define SEG_ARR_FREE_GET(type, value_seg) (\
+ _SEG_ARR_FREE_LIST_GRAB_INDEX(type, (value_seg)), \
(value_seg) \
)
// should return NULL_SEG if alloc fails
-#define SEG_EPANET_ALLOC(type, value_seg) (\
- (SegBankAllocViolation) \
+#define SEG_ARR_ALLOC_SEG(type, value_seg) (\
+ (SEG_BANK_ALLOC_VIOLATION(type)) \
? ((value_seg).index = (value_seg).nextIndex = EMPTY_INDEX, (value_seg) ) \
: ( \
- (value_seg).index = iInsertPos, \
+ (value_seg).index = SEG_INSERT_POS(type), \
(value_seg).nextIndex = EMPTY_INDEX, \
- TOTALSEGS_INCR(), \
- (iInsertPos >= SEG_BANK_INDEX_LIMIT_ARR[NUM_SEG_BANKS-1]) \
+ (SEG_INSERT_POS(type) >= SEG_BANK_INDEX_LIMIT_ARR(type)[NUM_SEG_BANKS(type)-1]) \
? /* last index filled. allocate more banks. */ \
SEG_ARR_ALLOC_NEXT_FUNC(type) \
? /* ok */ (void) 0 \
: /* further alloc not possible */ (\
- SegBankAllocViolation = 1, \
+ SEG_BANK_ALLOC_VIOLATION(type) = 1, \
printf("\nFatal error: No more segment allocation possible." \
"\n\tSegment index: %d, Last possible index: %d " \
"NumSegBanks: %d, MaxSegBanks: %d " \
"\n\tFile: %s\n\tLine: %d\n", \
- iInsertPos, SEG_BANK_INDEX_LIMIT_ARR[CURRENT_SEG_BANK], \
- NUM_SEG_BANKS, MAX_SEG_BANKS, \
+ SEG_INSERT_POS(type), SEG_BANK_INDEX_LIMIT_ARR(type)[CURRENT_SEG_BANK(type)], \
+ NUM_SEG_BANKS(type), MAX_SEG_BANKS(type), \
__FILE__, __LINE__) \
) \
- : /* last index not filled */ iInsertPos++, \
+ : /* last index not filled */ SEG_INSERT_POS(type)++, \
(value_seg)\
) \
) \
@@ -286,21 +410,13 @@ typedef struct{
/*---------------------------------------*/
/*------- Seg banks methods -------------*/
-SEG_ARR_USE(DYNARR_DATA_TYPE);
-#if defined(_MSC_VER)
-#define INLINE _inline /* use _inline (VC++ specific) */
-// #define INLINE __forceinline /* use __forceinline (VC++ specific) */
-//#elif __GNUC__ && !__GNUC_STDC_INLINE__
-//#define INLINE inline
-#else
-#define INLINE inline /* use standard inline */
-#endif
+
// when maximum number of segment banks is reached,
// double MaxSegBanks and
// reallocate the bookkeeping machinery
// returns 0 if bad, 1 if ok
-INLINE int SEG_ARR_INC_MAX_FUNC(DYNARR_DATA_TYPE)(){
+static INLINE int SEG_ARR_INC_MAX_FUNC(DYNARR_DATA_TYPE)(){
void* pVoid;
int bSuccess = 1;
int prevMaxSegBanks = MAX_SEG_BANKS(DYNARR_DATA_TYPE);
@@ -351,7 +467,7 @@ INLINE int SEG_ARR_INC_MAX_FUNC(DYNARR_DATA_TYPE)(){
//
// allocate next segment bank and place iInsertPos in appropriate value
//
-INLINE int SEG_ARR_ALLOC_NEXT_FUNC(DYNARR_DATA_TYPE)(){
+static INLINE int SEG_ARR_ALLOC_NEXT_FUNC(DYNARR_DATA_TYPE)(){
// shall we also alloc gpu with cpu?
int bAllocGpu = 0;
diff --git a/dynarrc/dynarr_freenodelist.h b/dynarrc/dynarr_freenodelist.h
deleted file mode 100644
index 8212da8..0000000
--- a/dynarrc/dynarr_freenodelist.h
+++ /dev/null
@@ -1,102 +0,0 @@
-#ifndef __dynarr_free_node_list_h__
-#define __dynarr_free_node_list_h__
-
-// the struct FreeSegNode will be used multiple times, so we do not want to redefine it
-struct FreeSegNode{
- int index;
- struct FreeSegNode* next;
-};
-typedef struct FreeSegNode FreeSegNode;
-
-// name of variables
-#define FREESEG_LIST_NAME pFreeSegList
-#define FREESEG_INVALID_LIST_NAME pFreeSegInvalidList
-
-
-#define _FreeSegNodeMalloc() \
- ( (struct FreeSegNode*) malloc(sizeof(struct FreeSegNode)) )
-// Swaps two 32-bit intergers without using temporary variables
-#define _SEG_ARR_INT_SWAP(var1, var2) (\
- (var1) = (FreeSegNode*) (((int) (void*) var1) ^ ((int) (void*) var2) ), \
- (var2) = (FreeSegNode*) (((int) (void*) var1) ^ ((int) (void*) var2) ), \
- (var1) = (FreeSegNode*) (((int) (void*) var1) ^ ((int) (void*) var2) ) )
-// Given two lists A and B, moves the head of A in front of the
-// head of B. Head of A must be non-null.
-//
-// Before:
-// A-->1-2-3-4-5
-// B-->a-b-c-d-e
-// After:
-// A-->2-3-4-5
-// B-->1-a-b-c-d-e
-//
-#define _SEG_ARR_MOVE_LIST_HEAD(listFrom, listTo) (\
- _SEG_ARR_INT_SWAP( listFrom->next, listTo), \
- _SEG_ARR_INT_SWAP( listFrom, listTo ) \
- )
-
-
-#define _SEG_ARR_FREE_LIST_ADD_VALIDLIST(value_seg) \
- ( ( !FREESEG_LIST_NAME ) \
- ?( \
- FREESEG_LIST_NAME = _FreeSegNodeMalloc(), \
- /*assert(FREESEG_LIST_NAME != NULL ),*/ \
- FREESEG_LIST_NAME->next = NULL, \
- FREESEG_LIST_NAME->index = ((value_seg).index) \
- ) \
- :( \
- pTempFreeNode1 = _FreeSegNodeMalloc(), \
- /*assert(pTempFreeNode1 != NULL ),*/ \
- pTempFreeNode1->next = FREESEG_LIST_NAME, \
- FREESEG_LIST_NAME = pTempFreeNode1, \
- FREESEG_LIST_NAME->index = ((value_seg).index) \
- )\
- )
-
-// Algorithm:
-// If (an invalid node exists) Then
-// move it to the front of valid list
-// set its index as the index of value_seg
-// Else
-// Allocate new node in the valid list
-//
-#define _SEG_ARR_FREE_LIST_ADD(value_seg) (\
- ( FREESEG_INVALID_LIST_NAME ) \
- ? ( \
- _SEG_ARR_MOVE_LIST_HEAD( FREESEG_INVALID_LIST_NAME, FREESEG_LIST_NAME ), \
- FREESEG_LIST_NAME->index = ((value_seg).index) \
- ) \
- : ( _SEG_ARR_FREE_LIST_ADD_VALIDLIST(value_seg) ) \
- )
-
-
-#define _SEG_ARR_REMOVE_LIST_HEAD(list) (\
- pTempFreeNode1 = list, \
- list = list->next, \
- FREE_SAFE( pTempFreeNode1 ) )\
-
-// Algorithm:
-// If (a valid node exists) Then
-// output its index, and
-// move it to the front of invalid list
-// Else
-// output null index
-//
-#define _SEG_ARR_FREE_LIST_GRAB_INDEX(value_seg) (\
- ( FREESEG_LIST_NAME ) ?(\
- (value_seg).index = FREESEG_LIST_NAME->index, \
- (value_seg).nextIndex = EMPTY_INDEX, \
- _SEG_ARR_MOVE_LIST_HEAD( FREESEG_LIST_NAME, FREESEG_INVALID_LIST_NAME ), \
- (value_seg) \
- ):(\
- ( (value_seg) = NULL_SEG ) \
- ) )\
-
-
-#define _SEG_ARR_FREE_LIST_CLEANUP() {\
- while( FREESEG_LIST_NAME ) _SEG_ARR_REMOVE_LIST_HEAD(FREESEG_LIST_NAME); \
- while( FREESEG_INVALID_LIST_NAME ) _SEG_ARR_REMOVE_LIST_HEAD(FREESEG_INVALID_LIST_NAME); \
- } \
-
-
-#endif
\ No newline at end of file
diff --git a/dynarrc/dynarrc.vcxproj b/dynarrc/dynarrc.vcxproj
index e31e8ad..f1eac40 100644
--- a/dynarrc/dynarrc.vcxproj
+++ b/dynarrc/dynarrc.vcxproj
@@ -66,7 +66,6 @@
-
diff --git a/dynarrc/dynarrc.vcxproj.filters b/dynarrc/dynarrc.vcxproj.filters
index a683cab..924c3f3 100644
--- a/dynarrc/dynarrc.vcxproj.filters
+++ b/dynarrc/dynarrc.vcxproj.filters
@@ -21,9 +21,6 @@
Header Files
-
- Header Files
-
diff --git a/dynarrc/main.c b/dynarrc/main.c
index 380d54d..29e9dac 100644
--- a/dynarrc/main.c
+++ b/dynarrc/main.c
@@ -29,6 +29,8 @@ int main(int argc, char** argv){
MEM_LEAK_CATCH();
// your code here
SEG_ARR_INIT(MyStruct);
+ DYNARR_SEG_TYPE(MyStruct) seg = NULL_SEG(MyStruct);
+ SEG_ARR_ALLOC_SEG(MyStruct, seg);
SEG_ARR_CLEANUP(MyStruct);
SEG_ARR_INIT(MyStructPtr);