00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef cmplr_segmented_array_INCLUDED
00039 #define cmplr_segmented_array_INCLUDED
00040
00041 #ifndef __SGI_STL_ALGO_H
00042
00043 #if defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00044 #undef short // get around bogus type defs.
00045 #undef int
00046 #undef long
00047 #endif // defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00048
00049 #include <algorithm>
00050 #include <vector>
00051
00052 using std::find;
00053 using std::transform;
00054 using std::sort;
00055 using std::stable_sort;
00056 using std::rotate;
00057 using std::reverse;
00058 using std::set_union;
00059 using std::set_intersection;
00060 using std::set_difference;
00061 using std::min;
00062 using std::pair;
00063 using std::vector;
00064
00065 #endif // __SGI_STL_ALGO_H
00066
00067 #ifndef __SGI_STL_VECTOR_H
00068
00069 #if defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00070 #undef short // get around bogus type defs.
00071 #undef int
00072 #undef long
00073 #endif // defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00074
00075
00076
00077
00078 #endif // __SGI_STL_VECTOR_H
00079
00080 #ifndef __SGI_STL_SLIST_H
00081
00082 #if defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00083 #undef short // get around bogus type defs.
00084 #undef int
00085 #undef long
00086 #endif // defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00087
00088
00089 #include <list>
00090 using std::list;
00091
00092 #endif // __SGI_STL_LIST_H
00093
00094
00095 #ifndef ERRORS_INCLUDED
00096 #include "errors.h"
00097 #endif // ERRORS_INCLUDED
00098
00099 #ifndef mempool_INCLUDED
00100 #include "mempool.h"
00101 #endif // mempool_INCLUDED
00102
00103 #ifndef segmented_array_INCLUDED
00104 #include "segmented_array.h"
00105 #endif // segmented_array_INCLUDED
00106
00107 #ifndef mempool_allocator_INCLUDED
00108 #include "mempool_allocator.h"
00109 #endif
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 class growing_table {
00173 protected:
00174 UINT size;
00175
00176 private:
00177
00178 typedef std::list<growing_table *> kids_type;
00179
00180 kids_type kids;
00181
00182 virtual void Construct_new_entry(void) = 0;
00183 virtual void Construct_new_entry(UINT n) = 0;
00184 virtual void Delete_last(void) = 0;
00185 virtual void Delete_last(UINT n) = 0;
00186
00187 protected:
00188
00189
00190
00191
00192
00193 void Decrease_kids_size(void)
00194 {
00195 for (kids_type::iterator kid = kids.begin();
00196 kid != kids.end();
00197 ++kid) {
00198 (*kid)->Delete_last();
00199 }
00200 }
00201
00202 void Decrease_kids_size(UINT n)
00203 {
00204 for (kids_type::iterator kid = kids.begin();
00205 kid != kids.end();
00206 ++kid) {
00207 (*kid)->Delete_last(n);
00208 }
00209 }
00210
00211 void Increase_kids_size(void)
00212 {
00213 for (kids_type::iterator kid = kids.begin();
00214 kid != kids.end();
00215 ++kid) {
00216 (*kid)->Construct_new_entry();
00217 }
00218 }
00219
00220 void Increase_kids_size(UINT n)
00221 {
00222 for (kids_type::iterator kid = kids.begin();
00223 kid != kids.end();
00224 ++kid) {
00225 (*kid)->Construct_new_entry(n);
00226 }
00227 }
00228
00229 public:
00230 growing_table() : size(0) { }
00231 virtual ~growing_table() { }
00232
00233
00234
00235 void Register(growing_table &kid)
00236 {
00237
00238 FmtAssert(kid.size <= size,
00239 ("growing_table::Register: child must not be larger "
00240 "than parent"));
00241
00242 while (kid.size < size) {
00243 kid.Construct_new_entry();
00244 }
00245
00246
00247 kids.push_front(&kid);
00248 }
00249
00250 void Un_register(growing_table &kid)
00251 {
00252 kids_type::iterator kid_ptr = std::find(kids.begin(), kids.end(), &kid);
00253 if (kid_ptr != kids.end()) {
00254 kids.erase(kid_ptr);
00255 }
00256 else {
00257 Fail_FmtAssertion("RELATED_SEGMENTED_ARRAY: Cannot un-register "
00258 "an unregistered kid");
00259 }
00260 }
00261 };
00262
00263 template <class T, UINT block_size = 128>
00264 class RELATED_SEGMENTED_ARRAY : public growing_table {
00265 private:
00266
00267 std::vector<std::pair<T *, BOOL>, mempool_allocator<std::pair<T *,BOOL> > > map;
00268
00269 MEM_POOL *pool;
00270 UINT max_size;
00271 INT block_base;
00272
00273
00274 UINT next_block_size;
00275 T *block;
00276
00277 private:
00278
00279 typedef RELATED_SEGMENTED_ARRAY<T, block_size> self;
00280
00281 public:
00282 typedef T base_type;
00283
00284 typedef T value_type;
00285 typedef value_type* pointer;
00286 typedef const value_type* const_pointer;
00287 typedef value_type& reference;
00288 typedef const value_type& const_reference;
00289 typedef UINT size_type;
00290 typedef INT difference_type;
00291
00292 typedef SEGMENTED_ARRAY_ITERATOR<self*, T, pointer, reference>
00293 iterator;
00294 typedef SEGMENTED_ARRAY_ITERATOR<const self*, T,
00295 const_pointer, const_reference>
00296 const_iterator;
00297
00298 private:
00299
00300
00301 virtual void Construct_new_entry(void)
00302 {
00303 if (size == max_size) Allocate();
00304 Increase_kids_size();
00305 new(&block[size++ - block_base]) T();
00306
00307
00308
00309
00310 }
00311
00312 virtual void Construct_new_entry(UINT n)
00313 {
00314
00315
00316 for (; n > 0; n--) {
00317 Construct_new_entry();
00318 }
00319 }
00320
00321 UINT Round_up (UINT s) {
00322 UINT mask = block_size - 1;
00323 return (s + mask) & ~mask;
00324 }
00325
00326 void Update_Map (T *marker, UINT new_size, BOOL own_memory);
00327
00328 void Pop_Map ();
00329
00330
00331 void Allocate ();
00332
00333 T& New_entry () {
00334
00335 if (size == max_size) Allocate ();
00336 Increase_kids_size();
00337 return block[size++ - block_base];
00338 }
00339
00340
00341 void Copy (const T* x, UINT n) {
00342 std::copy(x, x + n, block + (size - block_base));
00343 size += n;
00344 Increase_kids_size(n);
00345 }
00346
00347
00348
00349 UINT next_block_idx(UINT block_idx) const {
00350 for ( ; block_idx + 1 < map.size() &&
00351 map[block_idx].first + block_size == map[block_idx + 1].first;
00352 ++block_idx)
00353 {}
00354 return block_idx + 1;
00355 }
00356
00357 public:
00358
00359 RELATED_SEGMENTED_ARRAY(MEM_POOL *m = Malloc_Mem_Pool) : map(m), pool(m) {
00360 size = max_size = next_block_size = 0;
00361 block_base = -1;
00362 block = 0;
00363 }
00364
00365 ~RELATED_SEGMENTED_ARRAY() {
00366
00367
00368 typedef typename vector<pair<T *, BOOL>, mempool_allocator<pair<T *, BOOL> > >::iterator TempIteratorType;
00369 for ( TempIteratorType entry = map.begin(); entry != map.end(); ++entry ) {
00370
00371 if (entry->second) {
00372 MEM_POOL_FREE(pool, entry->first);
00373 }
00374 }
00375 }
00376
00377 UINT Block_size () const { return block_size; }
00378
00379 UINT Size () const { return growing_table::size; }
00380
00381 T& Entry (UINT idx) {
00382 Is_True (idx < size, ("Array subscript out of bound"));
00383 return map[idx / block_size].first[idx % block_size];
00384 }
00385
00386 const T& Entry (UINT idx) const {
00387 Is_True (idx < size, ("Array subscript out of bound"));
00388 return map[idx / block_size].first[idx % block_size];
00389 }
00390
00391
00392 T& operator[] (UINT idx) { return Entry(idx); }
00393 const T& operator[] (UINT idx) const { return Entry(idx); }
00394
00395 iterator begin () {
00396 return iterator (this, map[0].first, Block_end (0), 0);
00397 }
00398
00399 iterator end () {
00400 return iterator (this, block + (size - block_base),
00401 block + (max_size - block_base), size);
00402 }
00403
00404 const_iterator begin () const {
00405 return const_iterator (this, map[0].first, Block_end (0), 0);
00406 }
00407
00408 const_iterator end () const {
00409 return const_iterator (this, block + (size - block_base),
00410 block + (max_size - block_base), size);
00411 }
00412
00413 T& New_entry (UINT& idx) { idx = size; return New_entry (); }
00414
00415 UINT Insert (const T& x);
00416
00417 virtual void Delete_last () {
00418 size--;
00419 Decrease_kids_size();
00420 if (size == (UINT)block_base)
00421 Pop_Map ();
00422 }
00423
00424 virtual void Delete_last (UINT n);
00425
00426
00427 UINT Insert (const T* x, UINT n_elemt);
00428
00429
00430 UINT Transfer (T* x, UINT n_elemt);
00431
00432
00433
00434 void Reserve (UINT n_elemt) {
00435 if (max_size - size + next_block_size < n_elemt)
00436 next_block_size = n_elemt - (max_size - size);
00437 }
00438
00439
00440 UINT Get_block_size (UINT idx) const {
00441 UINT block_idx = idx / block_size;
00442 return min(next_block_idx(block_idx) * block_size, size) - idx;
00443 }
00444
00445 UINT Block_index (UINT idx) const { return idx / block_size; }
00446
00447
00448 UINT Block_index_end () const { return map.size(); }
00449
00450 T* Block_begin (UINT block_idx) { return map[block_idx].first; }
00451 const T* Block_begin (UINT block_idx) const { return map[block_idx].first; }
00452
00453 T* Block_end(UINT block_idx) {
00454 return Block_begin(block_idx) +
00455 (next_block_idx(block_idx) - block_idx) * block_size;
00456 }
00457
00458 const T* Block_end(UINT block_idx) const {
00459 return Block_begin(block_idx) +
00460 (next_block_idx(block_idx) - block_idx) * block_size;
00461 }
00462
00463 void Clear(void);
00464 };
00465
00466 template <class T, UINT block_size>
00467 inline void
00468 RELATED_SEGMENTED_ARRAY<T,block_size>::Update_Map(T *marker,
00469 UINT new_size,
00470 BOOL own_memory)
00471 {
00472 do {
00473
00474 map.push_back(std::pair<T*, BOOL>(marker, own_memory));
00475 new_size -= block_size;
00476 marker += block_size;
00477 } while (new_size);
00478 }
00479
00480
00481
00482 template <class T, UINT block_size>
00483 void
00484 RELATED_SEGMENTED_ARRAY<T,block_size>::Pop_Map ()
00485 {
00486 next_block_size += max_size - block_base;
00487 MEM_POOL_FREE (pool, block);
00488
00489 T *last_map_entry;
00490 do {
00491 last_map_entry = (map.end() - 1)->first;
00492 map.pop_back ();
00493 } while (last_map_entry != block);
00494
00495 max_size = size;
00496 if (size > 0) {
00497 Is_True(size >= block_size,
00498 ("RELATED_SEGMENTED_ARRAY: size in limbo"));
00499 block_base = size - block_size;
00500 UINT idx = block_base / block_size;
00501 block = map[idx].first;
00502 while (idx > 0 && map[idx - 1].first + block_size == block) {
00503 block = map[--idx].first;
00504 block_base -= block_size;
00505 }
00506 }
00507 else {
00508 Is_True(map.begin() == map.end(),
00509 ("RELATED_SEGMENTED_ARRAY::Pop_Map: Map should be empty"));
00510 block_base = -1;
00511 block = NULL;
00512 }
00513 }
00514
00515
00516 template <class T, UINT block_size>
00517 void
00518 RELATED_SEGMENTED_ARRAY<T,block_size>::Allocate ()
00519 {
00520 Is_True (size == max_size, ("Invalid internal state in segmented array"));
00521
00522 UINT new_size;
00523
00524 if (next_block_size == 0)
00525 new_size = block_size;
00526 else {
00527 new_size = Round_up (next_block_size);
00528 next_block_size = 0;
00529 }
00530
00531 block = (T *) MEM_POOL_Alloc (pool, new_size * sizeof(T));
00532 max_size += new_size;
00533 block_base = size;
00534
00535 Update_Map (block, new_size, TRUE);
00536
00537 }
00538
00539
00540 template <class T, UINT block_size>
00541 void
00542 RELATED_SEGMENTED_ARRAY<T,block_size>::Delete_last (UINT n)
00543 {
00544 while (n >= size - block_base) {
00545 n -= size - block_base;
00546 size = block_base;
00547 Pop_Map ();
00548 }
00549 size -= n;
00550 Decrease_kids_size(n);
00551 }
00552
00553
00554 template <class T, UINT block_size>
00555 inline UINT
00556 RELATED_SEGMENTED_ARRAY<T,block_size>::Insert (const T& x)
00557 {
00558 UINT idx = size;
00559 T &entry = New_entry ();
00560
00561 entry = x;
00562 return idx;
00563 }
00564
00565
00566 template <class T, UINT block_size>
00567 UINT
00568 RELATED_SEGMENTED_ARRAY<T,block_size>::Insert (const T* x, UINT n_elemt)
00569 {
00570 UINT result = size;
00571 if (size + n_elemt <= max_size) {
00572 Copy (x, n_elemt);
00573 return result;
00574 }
00575
00576 UINT space_left = max_size - size;
00577 Copy (x, space_left);
00578 n_elemt -= space_left;
00579
00580 Reserve (n_elemt);
00581 Allocate ();
00582 Copy (x + space_left, n_elemt);
00583
00584 return result;
00585 }
00586
00587
00588 template <class T, UINT block_size>
00589 UINT
00590 RELATED_SEGMENTED_ARRAY<T,block_size>::Transfer (T* x, UINT n_elemt)
00591 {
00592 UINT result = size;
00593
00594 if (size + n_elemt <= max_size) {
00595 Copy (x, n_elemt);
00596 return result;
00597 }
00598
00599 UINT space_left = max_size - size;
00600 if (space_left > 0) {
00601 Copy (x, space_left);
00602 n_elemt -= space_left;
00603 x += space_left;
00604 }
00605
00606 if (n_elemt >= block_size) {
00607 UINT reused_size = n_elemt & ~(block_size - 1);
00608 block = x;
00609 Update_Map (block, reused_size, FALSE);
00610 block_base = size;
00611 size += reused_size;
00612 max_size += reused_size;
00613 n_elemt -= reused_size;
00614 x += reused_size;
00615 if (next_block_size > reused_size)
00616 next_block_size -= reused_size;
00617 else
00618 next_block_size = 0;
00619 }
00620
00621 if (n_elemt > 0) {
00622 Allocate ();
00623 Copy (x, n_elemt);
00624 }
00625
00626 return result;
00627 }
00628
00629
00630
00631 template <class T, UINT block_size>
00632 void
00633 RELATED_SEGMENTED_ARRAY<T,block_size>::Clear(void)
00634 {
00635 if (growing_table::size > 0) {
00636 Delete_last(growing_table::size);
00637 }
00638 Is_True(map.begin() == map.end(),
00639 ("RELATED_SEGMENTED_ARRAY::Clear: Map should be empty"));
00640 }
00641
00642 template <class T, UINT block_size, class OP>
00643 inline void
00644 For_all_entries (RELATED_SEGMENTED_ARRAY<T, block_size>& array,
00645 const OP &op,
00646 UINT32 first = 0)
00647 {
00648 UINT last = array.Size ();
00649
00650 while (first < last) {
00651 T *block = &array[first];
00652 UINT size = array.Get_block_size (first);
00653 for (UINT j = 0; j < size; ++j, ++block)
00654 op (first + j, block);
00655 first += size;
00656 }
00657 }
00658
00659
00660
00661
00662 #if 0
00663
00664 template <class T, UINT block_size, class OP>
00665 inline void
00666 For_all_entries (const RELATED_SEGMENTED_ARRAY<T, block_size>& array,
00667 const OP &op,
00668 UINT32 first = 0)
00669 {
00670 UINT last = array.Size ();
00671
00672 while (first < last) {
00673 const T *block = &array[first];
00674 UINT size = array.Get_block_size (first);
00675 for (UINT j = 0; j < size; ++j, ++block)
00676 op (first + j, block);
00677 first += size;
00678 }
00679 }
00680
00681 #endif
00682
00683 template <class T, UINT block_size, class OP>
00684 inline void
00685 For_all_blocks (RELATED_SEGMENTED_ARRAY<T, block_size>& array, const OP &op)
00686 {
00687 UINT max_size = array.Size ();
00688 UINT i = 0;
00689
00690 while (i < max_size) {
00691 T *block = &array[i];
00692 UINT size = array.Get_block_size (i);
00693 op (i, block, size);
00694 i += size;
00695 }
00696 }
00697
00698
00699 #define NOT_FOUND ((UINT) -1)
00700
00701 template <class T, UINT block_size, class PREDICATE>
00702 inline UINT
00703 Find_entry_if (const RELATED_SEGMENTED_ARRAY<T, block_size>& array,
00704 const PREDICATE& pred, UINT i = 0)
00705 {
00706 UINT max_size = array.Size ();
00707
00708 while (i < max_size) {
00709 const T *block = &array[i];
00710 UINT size = array.Get_block_size (i);
00711 for (UINT j = 0; j < size; ++j, ++block)
00712 if (pred (i+j, block))
00713 return i + j;
00714 i += size;
00715 }
00716
00717 return (UINT) NOT_FOUND;
00718 }
00719
00720
00721
00722
00723
00724 template <class T, UINT block_size>
00725 UINT32
00726 Copy_array_range (const RELATED_SEGMENTED_ARRAY<T, block_size>& from_array,
00727 RELATED_SEGMENTED_ARRAY<T, block_size>& to_array,
00728 UINT32 first_idx = 0, UINT32 last_idx = (UINT32) -1)
00729 {
00730 if (last_idx > from_array.Size ())
00731 last_idx = from_array.Size ();
00732
00733 Is_True (last_idx >= first_idx, ("Invalid copy range"));
00734
00735 UINT32 entries = last_idx - first_idx;
00736
00737 to_array.Reserve (entries);
00738
00739 while (first_idx < last_idx) {
00740 const T* block = &from_array[first_idx];
00741 UINT32 size = from_array.Get_block_size (first_idx);
00742 if (size > last_idx - first_idx)
00743 size = last_idx - first_idx;
00744
00745 to_array.Insert (block, size);
00746 first_idx += size;
00747 }
00748
00749 return entries;
00750 }
00751
00752 #endif // cmplr_segmented_array_INCLUDED