Browse Source

cmDList.h/c/Tpl.h : Changes to support initial debugging of cmDList.

master
Kevin Larke 8 years ago
parent
commit
9bf87e175b
3 changed files with 234 additions and 129 deletions
  1. 184
    112
      cmDList.c
  2. 43
    10
      cmDList.h
  3. 7
    7
      cmDListTpl.h

+ 184
- 112
cmDList.c View File

@@ -39,10 +39,10 @@ struct cmDList_str;
39 39
 
40 40
 typedef struct cmDListIter_str
41 41
 {
42
-  struct cmDList_str*     p;
43
-  cmDListIndex_t*         x;
44
-  cmDListIndexRecd_t*     s;
45
-  struct cmDListIter_str* link;
42
+  struct cmDList_str*     p;    // pointer to the owner cmDList
43
+  cmDListIndex_t*         x;    // pointer to the index this iterator traverses
44
+  cmDListIndexRecd_t*     s;    // current record
45
+  struct cmDListIter_str* link; // p->iters list link 
46 46
 } cmDListIter_t;
47 47
 
48 48
 typedef struct cmDList_str
@@ -66,6 +66,7 @@ cmDList_t* _cmDListHandleToPtr( cmDListH_t h )
66 66
   return p;
67 67
 }
68 68
 
69
+// Given an indexId return the associated index.
69 70
 cmDListIndex_t* _cmDListIdToIndex( cmDList_t* p, unsigned indexId )
70 71
 {
71 72
   cmDListIndex_t* x = p->indexes;
@@ -76,12 +77,14 @@ cmDListIndex_t* _cmDListIdToIndex( cmDList_t* p, unsigned indexId )
76 77
   return NULL;
77 78
 }
78 79
 
80
+// Allocate 'n' new index records for the index 'x'. 
79 81
 void _cmDListIndexAllocRecds( cmDListIndex_t* x, unsigned n )
80 82
 {
81 83
   unsigned i;
82 84
   for(i=0; i<n; ++i)
83 85
   {
84 86
     cmDListIndexRecd_t* s = cmMemAllocZ(cmDListIndexRecd_t,1);
87
+
85 88
     s->prev = x->last;
86 89
     
87 90
     if( x->last != NULL )
@@ -99,82 +102,6 @@ void _cmDListIndexAllocRecds( cmDListIndex_t* x, unsigned n )
99 102
 
100 103
 }
101 104
 
102
-void _cmDListIndexUpdate( cmDList_t* p, cmDListIndex_t* x )
103
-{
104
-  cmDListIndexRecd_t* first = NULL;
105
-  cmDListIndexRecd_t* last  = NULL;
106
-  cmDListIndexRecd_t* avail = x->first;
107
-
108
-  // for each data recd
109
-  cmDListRecd_t* r = p->first;
110
-  for(; r!=NULL; r=r->next)
111
-  {
112
-    // get the next available index record
113
-    cmDListIndexRecd_t* a = avail;
114
-    
115
-    avail = avail->next;
116
-
117
-    // The count of index records and data records should always be the same.
118
-    assert( a != NULL );
119
-    a->r = r;
120
-    
121
-    cmDListIndexRecd_t* s = first;
122
-
123
-    // for each index recd that has already been sorted
124
-    for(; s!=NULL; s=s->next)
125
-      if( x->cmpFunc( x->funcArg, r->dV, r->dN, s->r->dV, s->r->dN ) < 0 )
126
-      {
127
-        // r is less than s->r
128
-        // insert 'a' prior to 's' in the index
129
-
130
-        a->next = s;
131
-        a->prev = s->prev;
132
-
133
-        // if 's' is not first
134
-        if( s->prev != NULL )
135
-          s->prev->next = a;
136
-        else
137
-        { // 's' was first - now 'a' is first
138
-          assert( s == first );
139
-          first = a;
140
-        }
141
-        
142
-        s->prev = a;
143
-                
144
-        break;
145
-      }
146
-
147
-    // No records are greater than r or the index is empty - 'a' is last in the index.
148
-    if( s == NULL )
149
-    {      
150
-      // insert 'a' after 'last'
151
-
152
-      // if the index is empty
153
-      if( last == NULL )
154
-      {
155
-        first   = a;
156
-        a->prev = NULL;
157
-      }
158
-      else // make 'a' last in the index
159
-      {
160
-        a->prev    = last;
161
-        a->next    = NULL;
162
-        assert( last->next == NULL );
163
-        last->next = a;
164
-      }
165
-
166
-      a->next = NULL;
167
-      last    = a;
168
-    }
169
-
170
-
171
-    
172
-  }
173
-
174
-  x->first = first;
175
-  x->last  = last;
176
-}
177
-
178 105
 void _cmDListRecdFree( cmDList_t* p, cmDListRecd_t* r )
179 106
 {
180 107
   if( r->prev != NULL )
@@ -202,7 +129,7 @@ void _cmDListIndexRecdFree( cmDListIndex_t* x, cmDListIndexRecd_t* s )
202 129
     s->next->prev = s->prev;
203 130
   else
204 131
     x->last = s->prev;
205
-  
132
+
206 133
   cmMemFree(s);  
207 134
 }
208 135
 
@@ -274,7 +201,7 @@ cmDlRC_t _cmDListIterFree( cmDListIter_t* e )
274 201
       else
275 202
         e0->link = e1->link;
276 203
 
277
-      cmMemFree(e0);
204
+      cmMemFree(e1);
278 205
       break;
279 206
     }
280 207
 
@@ -307,6 +234,99 @@ cmDlRC_t _cmDListFree( cmDList_t* p )
307 234
   return rc;
308 235
 }
309 236
 
237
+
238
+void _cmDListIndexUpdate( cmDList_t* p, cmDListIndex_t* x )
239
+{
240
+  cmDListIndexRecd_t* first = NULL;
241
+  cmDListIndexRecd_t* last  = NULL;
242
+
243
+  assert(  x->recdN >= p->recdN  );
244
+
245
+  // for each data recd
246
+  cmDListRecd_t* r = p->first;
247
+  for(; r!=NULL; r=r->next)
248
+  {
249
+    // get the next available index record
250
+    cmDListIndexRecd_t* a = x->first;
251
+    assert(a!=NULL);
252
+    x->first = x->first->next;
253
+    if( x->first != NULL )
254
+      x->first->prev = NULL;
255
+
256
+    // The count of index records and data records should always be the same.
257
+    assert( a != NULL );
258
+    a->r = r;
259
+    
260
+    cmDListIndexRecd_t* s = first;
261
+
262
+    // for each index recd that has already been sorted
263
+    for(; s!=NULL; s=s->next)
264
+      if( x->cmpFunc( x->funcArg, r->dV, r->dN, s->r->dV, s->r->dN ) < 0 )
265
+      {
266
+        // r is less than s->r
267
+        // insert 'a' prior to 's' in the index
268
+
269
+        a->next = s;
270
+        a->prev = s->prev;
271
+
272
+        // if 's' is not first
273
+        if( s->prev != NULL )
274
+          s->prev->next = a;
275
+        else
276
+        { // 's' was first - now 'a' is first
277
+          assert( s == first );
278
+          first = a;
279
+        }
280
+        
281
+        s->prev = a;
282
+                
283
+        break;
284
+      }
285
+
286
+    // No records are greater than r or the index is empty - 'a' is last in the index.
287
+    if( s == NULL )
288
+    {      
289
+      // insert 'a' after 'last'
290
+
291
+      // if the index is empty
292
+      if( last == NULL )
293
+      {
294
+        first   = a;
295
+        a->prev = NULL;
296
+      }
297
+      else // make 'a' last in the index
298
+      {
299
+        a->prev    = last;
300
+        a->next    = NULL;
301
+        assert( last->next == NULL );
302
+        last->next = a;
303
+      }
304
+
305
+      a->next = NULL;
306
+      last    = a;
307
+    }
308
+  }
309
+
310
+  // release any index records that are not in use
311
+  while(x->first!=NULL)
312
+  {
313
+    _cmDListIndexRecdFree(x,x->first);
314
+    x->recdN -= 1;
315
+  }
316
+    
317
+  assert( x->recdN == p->recdN );
318
+
319
+  // Invalidate all iterators which use index x.
320
+  cmDListIter_t* e = p->iters;
321
+  for(; e!=NULL; e=e->link)
322
+    if( e->x == x )
323
+      e->s = NULL;
324
+  
325
+  x->first = first;
326
+  x->last  = last;
327
+}
328
+
329
+
310 330
 cmDlRC_t _cmDListIndexAlloc( cmDList_t* p, unsigned indexId, cmDListCmpFunc_t func, void* funcArg )
311 331
 {
312 332
   cmDListIndex_t* x;
@@ -373,7 +393,8 @@ cmDlRC_t cmDListFree(   cmDListH_t* hp )
373 393
 bool     cmDListIsValid( cmDListH_t h )
374 394
 { return h.h != NULL; }
375 395
 
376
-cmDlRC_t cmDListInsert( cmDListH_t  h, const void* recd, unsigned recdByteN )
396
+
397
+cmDlRC_t cmDListInsert( cmDListH_t  h, const void* recd, unsigned recdByteN, bool resyncFl )
377 398
 {
378 399
   cmDList_t*     p  = _cmDListHandleToPtr(h);
379 400
   char*          vp = cmMemAllocZ(char,sizeof(cmDListRecd_t) + recdByteN );
@@ -383,7 +404,7 @@ cmDlRC_t cmDListInsert( cmDListH_t  h, const void* recd, unsigned recdByteN )
383 404
   r->dN = recdByteN;
384 405
   memcpy( r->dV, recd, recdByteN );
385 406
 
386
-  // Add records at the end of the list.
407
+  // Add records at the end of the data record list.
387 408
 
388 409
   // If the list is not empty
389 410
   if( p->last != NULL )
@@ -400,51 +421,88 @@ cmDlRC_t cmDListInsert( cmDListH_t  h, const void* recd, unsigned recdByteN )
400 421
   p->last   = r;
401 422
   p->recdN += 1;
402 423
 
403
-  // update the indexes
424
+  // add a record to each index
404 425
   cmDListIndex_t* x = p->indexes;
405 426
   for(; x!=NULL; x=x->link)
406 427
   {
407
-    _cmDListIndexAllocRecds(x,1);
408
-    _cmDListIndexUpdate(p,x);
428
+    if( x->recdN < p->recdN )
429
+      _cmDListIndexAllocRecds(x,1);
430
+
431
+    assert( x->recdN >= p->recdN );
432
+    
433
+    if( resyncFl )
434
+      _cmDListIndexUpdate(p,x);
409 435
   }
436
+
410 437
   
411 438
   return kOkDlRC;
412 439
 }
413 440
 
414
-cmDlRC_t cmDListDelete( cmDListH_t  h, const void* recd )
441
+cmDlRC_t cmDListDelete( cmDListH_t  h, const void* recd, bool resyncFl )
415 442
 {
416
-  cmDList_t*      p = _cmDListHandleToPtr(h);
417
-  cmDListIndex_t* x = p->indexes;
443
+  cmDList_t*          p = _cmDListHandleToPtr(h);
444
+  cmDListIndex_t*     x = p->indexes;
418 445
   cmDListIndexRecd_t* s = NULL;
419
-  cmDListRecd_t* r = NULL;
420
-  
421
-  for(; x!=NULL; x=x->link)
446
+  cmDListRecd_t*      r = NULL;
447
+
448
+  if( resyncFl==false )
422 449
   {
423
-    for(s=x->first; s!=NULL; s=s->next)
424
-      if( s->r->dV == recd )
450
+    r = p->first;
451
+    for(; r!=NULL; r=r->next)
452
+      if( r->dV == recd )
425 453
       {
426
-        if( r == NULL )
427
-          r = s->r;
428
-        else
429
-        {
430
-          // the same data record should be found for all indexes
431
-          assert( s->r == r );
432
-        }
433
-        
434
-        _cmDListIndexRecdFree(x,s);
435
-        
454
+        _cmDListRecdFree(p,r);
436 455
         break;
437 456
       }
438 457
 
439
-    if( r == NULL )
440
-      return cmErrMsg(&p->err,kDataRecdNotFoundDlRC,"The delete target data record could not be found.");
458
+  }
459
+  else
460
+  {
461
+    // for each index
462
+    for(; x!=NULL; x=x->link)
463
+    {
464
+      // for each index recd
465
+      for(s=x->first; s!=NULL; s=s->next)        
466
+        if( s->r->dV == recd )  // if this index recd points to the deletion target
467
+        {
468
+          // store a ptr to the data recd to be deleted
469
+          if( r == NULL )
470
+            r = s->r;
471
+          else
472
+          {
473
+            // the same data record should be found for all indexes
474
+            assert( s->r == r );
475
+          }
476
+
477
+          // free the index record
478
+          _cmDListIndexRecdFree(x,s);
479
+        
480
+          break;
481
+        }
482
+
483
+      // if the deletion target was not found
484
+      if( r == NULL )
485
+        goto errLabel;
441 486
     
442
-    // if the indexes are valid then the recd should always be found
443
-    assert( s!=NULL );
487
+    }
488
+
489
+    // advance any iterators that are pointing to the deleted record
490
+    cmDListIter_t* e = p->iters;
491
+    for(; e!=NULL; e=e->link)
492
+      if( e->s != NULL && e->s->r != NULL && e->s->r == r )
493
+        e->s = e->s->next;
494
+
495
+    // release the data record
496
+    _cmDListRecdFree(p,r);
497
+
444 498
   }
445 499
 
446
-  // release the data record
447
-  _cmDListRecdFree(p,r);
500
+ errLabel:
501
+  if( r == NULL )
502
+    return cmErrMsg(&p->err,kDataRecdNotFoundDlRC,"The deletion target record could not be found.");
503
+
504
+  assert( p->recdN > 0 );
505
+  p->recdN -= 1;
448 506
 
449 507
   return kOkDlRC;
450 508
   
@@ -479,6 +537,18 @@ cmDlRC_t cmDListIndexSetFreeFunc(cmDListH_t h, unsigned indexId, cmDListIndexFre
479 537
   return kOkDlRC;
480 538
 }
481 539
 
540
+cmDlRC_t cmDListIndexUpdateAll(  cmDListH_t h )
541
+{
542
+  cmDList_t*      p = _cmDListHandleToPtr(h);
543
+  cmDListIndex_t* x = p->indexes;
544
+  
545
+  for(; x!=NULL; x=x->link)
546
+    _cmDListIndexUpdate(p,x);
547
+
548
+  return kOkDlRC;
549
+}
550
+
551
+
482 552
 
483 553
 cmDListIter_t* _cmDListIterHandleToPtr( cmDListIterH_t h )
484 554
 {
@@ -557,6 +627,8 @@ const void* _cmDListIterGet(   cmDListIter_t*  e, unsigned* recdByteNRef )
557 627
     return NULL;
558 628
   }
559 629
 
630
+  assert( e->s->r != NULL );
631
+
560 632
   if( recdByteNRef != NULL )
561 633
     *recdByteNRef = e->s->r->dN;
562 634
 
@@ -585,7 +657,7 @@ const void* cmDListIterNext( cmDListIterH_t  iH, unsigned* recdByteNRef )
585 657
 {
586 658
   cmDListIter_t* e = _cmDListIterHandleToPtr(iH);
587 659
   const void*   rv = _cmDListIterGet(e,recdByteNRef);
588
-
660
+  
589 661
   if( e->s != NULL )
590 662
     e->s = e->s->next;
591 663
 

+ 43
- 10
cmDList.h View File

@@ -30,27 +30,60 @@ extern "C" {
30 30
   
31 31
   typedef void (*cmDListIndexFreeFunc_t)( unsigned indexId, void* arg );
32 32
 
33
-  // If 'f' is not NULL then a default index with an indexId==0 will be automatically created.
34
-  cmDlRC_t cmDListAlloc( cmCtx_t* ctx, cmDListH_t* hp, cmDListCmpFunc_t f, void* farg );
35
-  cmDlRC_t cmDListFree(   cmDListH_t* hp );
36
-  bool     cmDListIsValid( cmDListH_t h );
37
-  cmDlRC_t cmDListInsert( cmDListH_t  h, const void* recd, unsigned recdByteN );
38
-  cmDlRC_t cmDListDelete( cmDListH_t  h, const void* recd );
33
+  // If 'cmpFunc' is not NULL then a default index with an indexId==0 will be automatically created.
34
+  cmDlRC_t cmDListAlloc( cmCtx_t* ctx, cmDListH_t* hp, cmDListCmpFunc_t cmpFunc, void* funcArg );
35
+  cmDlRC_t cmDListFree(    cmDListH_t* hp );
36
+  bool     cmDListIsValid( cmDListH_t  h );
39 37
 
40
-  
41
-  cmDlRC_t cmDListIndexAlloc(   cmDListH_t h, unsigned indexId, cmDListCmpFunc_t f, void* farg );
42
-  cmDlRC_t cmDListIndexFree(    cmDListH_t h, unsigned indexId );
38
+  // Set resyncFl to automatically update the indexes to reflect the new record, otherwise
39
+  // cmDListIndexUpdateAll() should be called to resynchronize the data list to the indexes.
40
+  // If many inserts are to be performed with no intervening accesses to the list then it
41
+  // is more efficient to defer updating the indexes until all the inserts are completed.
42
+  cmDlRC_t cmDListInsert(  cmDListH_t  h, const void* recd, unsigned recdByteN, bool resyncFl );
43
+
44
+  // Delete a data record.
45
+  // 'recd' should be set to a value returned via one of the iterator accessors.
46
+  // If 'resyncFl' is set then the indexes and interators will be
47
+  // automatically synchronized with the data list after the deletion.
48
+  // If 'resyncFl' is not set then the client must call cmDListIndexUpdateAll()
49
+  // to resynchronize the indexes and iterators after the deletion.
50
+  // Note that if multiple records are to be deleted without intervening accesses
51
+  // to the list then it is more efficient to defer update the indexes until
52
+  // all the deletions are completed.
53
+  cmDlRC_t cmDListDelete(  cmDListH_t  h, const void* recd, bool resyncFl );
54
+
55
+  // Allocate a new index.  'indexId' is used to identify this index and must be unique among all
56
+  // previously allocated indexes.
57
+  cmDlRC_t cmDListIndexAlloc(      cmDListH_t h, unsigned indexId, cmDListCmpFunc_t cmpFunc, void* funcArg );
58
+  cmDlRC_t cmDListIndexFree(       cmDListH_t h, unsigned indexId );
59
+
60
+  // Refresh all the indexes.  This function should be called after new records are inserted
61
+  // via cmDListInsert(..,false).
62
+  cmDlRC_t cmDListIndexUpdateAll(  cmDListH_t h );
63
+
64
+  // Set a function to be called when indexes are released.  
43 65
   cmDlRC_t cmDListIndexSetFreeFunc(cmDListH_t h, unsigned indexId, cmDListIndexFreeFunc_t func );
44 66
 
45
- 
67
+  // Allocate an interator. By default the new iterator is pointing to the first record
68
+  // in the index identified by 'indexId'.
46 69
   cmDlRC_t    cmDListIterAlloc( cmDListH_t h, cmDListIterH_t* iHp, unsigned indexId );
47 70
   cmDlRC_t    cmDListIterFree(      cmDListIterH_t* iHp );
48 71
   bool        cmDListIterIsValid(   cmDListIterH_t  iH );
72
+
73
+  // Set the current iteration location to the begin/end of the index it is attached to.
49 74
   cmDlRC_t    cmDListIterSeekBegin( cmDListIterH_t  iH );
50 75
   cmDlRC_t    cmDListIterSeekEnd(   cmDListIterH_t  iH );
76
+
77
+  // Return the current record this iterator is pointing to.
51 78
   const void* cmDListIterGet(       cmDListIterH_t  iH, unsigned* recdByteNRef );
79
+
80
+  // Return the current record this iterator is pointint to and advance the iterator.
52 81
   const void* cmDListIterPrev(      cmDListIterH_t  iH, unsigned* recdByteNRef );
53 82
   const void* cmDListIterNext(      cmDListIterH_t  iH, unsigned* recdByteNRef );
83
+
84
+  // Make the record which matches 'key' the current iterator.
85
+  // The match is made by using the compare function which is assigned to the index
86
+  // which this iterator is attached to.
54 87
   const void* cmDListIterFind(      cmDListIterH_t  iH, const void* key, unsigned keyN, unsigned* recdByteNRef);
55 88
 
56 89
 

+ 7
- 7
cmDListTpl.h View File

@@ -12,8 +12,8 @@ typedef int (*cmSFX(cmDListFunc))( void* arg, const cmTYPE* v0, const cmTYPE* v1
12 12
 
13 13
 cmDlRC_t cmSFX(cmDListAlloc)( cmCtx_t* ctx, cmDListH_t* hp, cmSFX(cmDListFunc) func, void* funcArg );
14 14
 
15
-cmDlRC_t cmSFX(cmDListInsert)( cmDListH_t  h, const cmTYPE* recd );
16
-cmDlRC_t cmSFX(cmDListDelete)( cmDListH_t  h, const cmTYPE* recd );
15
+cmDlRC_t cmSFX(cmDListInsert)( cmDListH_t  h, const cmTYPE* recd, bool resyncFl );
16
+cmDlRC_t cmSFX(cmDListDelete)( cmDListH_t  h, const cmTYPE* recd, bool resyncFl );
17 17
 
18 18
 cmDlRC_t cmSFX(cmDListAllocIndex)( cmDListH_t h, unsigned indexId, cmSFX(cmDListFunc) f, void* farg );
19 19
 
@@ -43,7 +43,7 @@ void cmSFX(_cmDListIndexOnFree)( unsigned indexId, void* arg )
43 43
 // Proxy function used to cast generic compare function to the user defined compare function.
44 44
 int cmSFX(_cmDListCmp)( void* arg, const void* v0, unsigned vn0, const void* v1, unsigned vn1 )
45 45
 {
46
-  assert(vn0==vn1 && sizeof(cmTYPE)==vn0);
46
+  assert(vn0==vn1);
47 47
   cmSFX(_cmDListArg)* a = (cmSFX(_cmDListArg)*)arg;
48 48
   return a->func(a->funcArg,(const cmTYPE*)v0,(const cmTYPE*)v1);
49 49
 }
@@ -96,11 +96,11 @@ cmDlRC_t cmSFX(cmDListIndexAlloc)(   cmDListH_t h, unsigned indexId, cmSFX(cmDLi
96 96
   return rc;
97 97
 }
98 98
 
99
-cmDlRC_t cmSFX(cmDListInsert)( cmDListH_t  h, const cmTYPE* recd )
100
-{ return cmDListInsert(h,recd,sizeof(recd)); }
99
+cmDlRC_t cmSFX(cmDListInsert)( cmDListH_t  h, const cmTYPE* recd, bool resyncFl )
100
+{ return cmDListInsert(h,recd,sizeof(cmTYPE),resyncFl); }
101 101
 
102
-cmDlRC_t cmSFX(cmDListDelete)( cmDListH_t  h, const cmTYPE* recd )
103
-{ return cmDListDelete(h,recd);  }
102
+cmDlRC_t cmSFX(cmDListDelete)( cmDListH_t  h, const cmTYPE* recd, bool resyncFl )
103
+{ return cmDListDelete(h,recd,resyncFl);  }
104 104
 
105 105
 
106 106
 const cmTYPE* cmSFX(cmDListIterGet)(  cmDListIterH_t  iH )

Loading…
Cancel
Save