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
00039
00040
00041
00042
00043 #ifndef segmented_array_INCLUDED
00044 #define segmented_array_INCLUDED
00045
00046 #ifndef __SGI_STL_VECTOR_H
00047
00048 #if defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00049 #undef short // get around bogus type defs.
00050 #undef int
00051 #undef long
00052 #endif // defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00053
00054 #ifndef __GNUC__
00055 #include <CC/vector>
00056 #else
00057 #include "vector"
00058 #endif
00059
00060 #endif // __SGI_STL_VECTOR_H
00061
00062 #ifndef ERRORS_INCLUDED
00063 #include "errors.h"
00064 #endif // ERRORS_INCLUDED
00065
00066 #ifndef mempool_INCLUDED
00067 #include "mempool.h"
00068 #endif // mempool_INCLUDED
00069
00070 #ifndef mempool_allocator_INCLUDED
00071 #include "mempool_allocator.h"
00072 #endif
00073
00074 #ifdef KEY // needed for building with g++ 3.2
00075 using std::pair;
00076 using std::vector;
00077 using std::forward_iterator_tag;
00078 #endif
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 template <class ARRAY_Ptr, class T, class VALUE_Ptr, class REF>
00095 class SEGMENTED_ARRAY_ITERATOR
00096 {
00097 public:
00098 typedef T value_type;
00099 typedef UINT difference_type;
00100 typedef std::forward_iterator_tag iterator_category;
00101 typedef VALUE_Ptr pointer;
00102 typedef REF reference;
00103
00104 private:
00105
00106 ARRAY_Ptr segmented_array;
00107 VALUE_Ptr ptr;
00108 VALUE_Ptr segment_last;
00109 UINT map_idx;
00110
00111 private:
00112
00113 typedef SEGMENTED_ARRAY_ITERATOR self;
00114
00115 public:
00116
00117 SEGMENTED_ARRAY_ITERATOR (ARRAY_Ptr sa, T* p, T* last, UINT idx)
00118 : segmented_array (sa), ptr (p), segment_last (last) {
00119 map_idx = sa->Block_index(idx);
00120 }
00121
00122 SEGMENTED_ARRAY_ITERATOR (ARRAY_Ptr sa, UINT idx)
00123 : segmented_array (sa) {
00124 map_idx = sa->Block_index(idx);
00125 ptr = &(sa->Entry(idx));
00126 segment_last = sa->Block_end(map_idx);
00127 }
00128
00129 SEGMENTED_ARRAY_ITERATOR () {}
00130
00131 REF operator* () const { return *ptr; }
00132 VALUE_Ptr Ptr () const { return ptr; }
00133 VALUE_Ptr operator->() const { return ptr; }
00134 UINT Index () const {
00135 return map_idx * segmented_array->Block_size() +
00136 (ptr - segmented_array->Block_begin(map_idx));
00137 }
00138
00139 self& operator ++ () {
00140 ++ptr;
00141 if (ptr == segment_last) {
00142 UINT map_entries =
00143 (segment_last - segmented_array->Block_begin(map_idx)) /
00144 segmented_array->Block_size ();
00145 if (map_idx + map_entries < segmented_array->Block_index_end()) {
00146 map_idx += map_entries;
00147 ptr = segmented_array->Block_begin(map_idx);
00148 segment_last = segmented_array->Block_end(map_idx);
00149 }
00150 }
00151 return *this;
00152 }
00153
00154 self operator ++ (int) {
00155 self tmp = *this;
00156 ++(*this);
00157 return tmp;
00158 }
00159
00160 BOOL operator == (const self& x) const { return ptr == x.ptr; }
00161 BOOL operator != (const self& x) const { return !(*this == x); }
00162
00163 };
00164
00165
00166 template <class T, UINT block_size = 128>
00167 class SEGMENTED_ARRAY
00168 {
00169 private:
00170 typedef std::pair<T *, BOOL> thingy;
00171 std::vector<thingy, mempool_allocator<thingy> > map;
00172 MEM_POOL *pool;
00173 UINT size_;
00174 UINT max_size_;
00175 INT block_base;
00176
00177
00178 UINT next_block_size;
00179 T *block;
00180
00181 private:
00182 typedef SEGMENTED_ARRAY<T, block_size> self;
00183
00184 public:
00185 typedef T base_type;
00186
00187 typedef T value_type;
00188 typedef value_type* pointer;
00189 typedef const value_type* const_pointer;
00190 typedef value_type& reference;
00191 typedef const value_type& const_reference;
00192 typedef UINT size_type;
00193 typedef INT difference_type;
00194
00195 typedef SEGMENTED_ARRAY_ITERATOR<self*, T, pointer, reference>
00196 iterator;
00197 typedef SEGMENTED_ARRAY_ITERATOR<const self*, T,
00198 const_pointer, const_reference>
00199 const_iterator;
00200
00201 private:
00202
00203
00204
00205 UINT Round_up (UINT s) {
00206 UINT mask = block_size - 1;
00207 return (s + mask) & ~mask;
00208 }
00209
00210 void Update_Map (T *marker, UINT new_size, BOOL own_memory);
00211
00212 void Pop_Map ();
00213
00214
00215 void Allocate ();
00216
00217 T& New_entry () {
00218 if (size_ == max_size_) Allocate ();
00219 return block[size_++ - block_base];
00220 }
00221
00222
00223 void Copy (const T* x, UINT n) {
00224 std::copy(x, x + n, block + (size_ - block_base));
00225 size_ += n;
00226 }
00227
00228
00229
00230 UINT next_block_idx(UINT block_idx) const {
00231 for ( ; block_idx + 1 < map.size() &&
00232 map[block_idx].first + block_size == map[block_idx + 1].first ;
00233 ++block_idx)
00234 {}
00235 return block_idx + 1;
00236 }
00237
00238 public:
00239
00240 SEGMENTED_ARRAY(MEM_POOL *m = Malloc_Mem_Pool) : pool (m), map (m) {
00241 size_ = max_size_ = next_block_size = 0;
00242 block_base = -1;
00243 block = 0;
00244 }
00245
00246 ~SEGMENTED_ARRAY() {
00247
00248
00249 for (typename std::vector<thingy, mempool_allocator<thingy> >::iterator
00250 entry = map.begin();
00251 entry != map.end();
00252 ++entry) {
00253
00254 if (entry->second) {
00255 MEM_POOL_FREE(pool, entry->first);
00256 }
00257 }
00258 }
00259
00260 UINT Block_size () const { return block_size; }
00261
00262 UINT Size () const { return size_; }
00263 UINT size () const { return size_; }
00264
00265 T& Entry (UINT idx) {
00266 Is_True (idx < size_, ("Array subscript out of bound"));
00267 return map[idx / block_size].first[idx % block_size];
00268 }
00269
00270 const T& Entry (UINT idx) const {
00271 Is_True (idx < size_, ("Array subscript out of bound"));
00272 return map[idx / block_size].first[idx % block_size];
00273 }
00274 T& operator[] (UINT idx) { return Entry(idx); }
00275 const T& operator[] (UINT idx) const { return Entry(idx); }
00276
00277 iterator begin () {
00278 return iterator (this, map[0].first, Block_end (0), 0);
00279 }
00280
00281 iterator end () {
00282 return iterator (this, block + (size_ - block_base),
00283 block + (max_size_ - block_base), size_);
00284 }
00285
00286 const_iterator begin () const {
00287 return const_iterator (this, map[0].first, Block_end (0), 0);
00288 }
00289
00290 const_iterator end () const {
00291 return const_iterator (this, block + (size_ - block_base),
00292 block + (max_size_ - block_base), size_);
00293 }
00294
00295
00296 T& New_entry (UINT& idx) { idx = size_; return New_entry (); }
00297
00298 UINT Insert (const T& x);
00299
00300 void Delete_last () {
00301 --size_;
00302 if (size_ == block_base)
00303 Pop_Map ();
00304 }
00305
00306
00307 void Delete_last (UINT n);
00308
00309 void Delete_down_to (UINT idx) {
00310 if (size_ > idx)
00311 Delete_last (size_ - idx);
00312 }
00313
00314
00315 UINT Insert (const T* x, UINT n_elemt);
00316
00317
00318 UINT Transfer (T* x, UINT n_elemt);
00319
00320
00321
00322 void Reserve (UINT n_elemt) {
00323 if (max_size_ - size_ + next_block_size < n_elemt)
00324 next_block_size = n_elemt - (max_size_ - size_);
00325 }
00326
00327
00328 UINT Get_block_size (UINT idx) const {
00329 UINT block_idx = idx / block_size;
00330 return std::min(next_block_idx(block_idx) * block_size, size_) - idx;
00331 }
00332
00333 UINT Block_index (UINT idx) const { return idx / block_size; }
00334
00335
00336 UINT Block_index_end () const { return map.size(); }
00337
00338 T* Block_begin (UINT block_idx) { return map[block_idx].first; }
00339 const T* Block_begin (UINT block_idx) const { return map[block_idx].first; }
00340
00341 T* Block_end(UINT block_idx) {
00342 return Block_begin(block_idx) +
00343 (next_block_idx(block_idx) - block_idx) * block_size;
00344 }
00345
00346 const T* Block_end(UINT block_idx) const {
00347 return Block_begin(block_idx) +
00348 (next_block_idx(block_idx) - block_idx) * block_size;
00349 }
00350
00351 };
00352
00353
00354 template <class T, UINT block_size>
00355 inline void
00356 SEGMENTED_ARRAY<T,block_size>::Update_Map(T *marker,
00357 UINT new_size,
00358 BOOL own_memory)
00359 {
00360 do {
00361 map.push_back(std::pair<T*, BOOL>(marker, own_memory));
00362
00363 new_size -= block_size;
00364 marker += block_size;
00365 } while (new_size);
00366 }
00367
00368
00369
00370 template <class T, UINT block_size>
00371 void
00372 SEGMENTED_ARRAY<T,block_size>::Pop_Map ()
00373 {
00374 next_block_size += max_size_ - block_base;
00375 MEM_POOL_FREE (pool, block);
00376
00377 T *last_map_entry;
00378 do {
00379 last_map_entry = (map.end() - 1)->first;
00380 map.pop_back ();
00381 } while (last_map_entry != block);
00382
00383 max_size_ = size_;
00384 if (size_ > 0) {
00385 Is_True(size_ >= block_size,
00386 ("SEGMENTED_ARRAY: size in limbo"));
00387 block_base = size_ - block_size;
00388 UINT idx = block_base / block_size;
00389 block = map[idx].first;
00390 while (idx > 0 && map[idx - 1].first + block_size == block) {
00391 block = map[--idx].first;
00392 block_base -= block_size;
00393 }
00394 }
00395 else {
00396 Is_True(map.begin() == map.end(),
00397 ("SEGMENTED_ARRAY::Pop_Map: Map should be empty"));
00398 block_base = -1;
00399 block = NULL;
00400 }
00401 }
00402
00403
00404 template <class T, UINT block_size>
00405 void
00406 SEGMENTED_ARRAY<T,block_size>::Allocate ()
00407 {
00408 Is_True (size_ == max_size_, ("Invalid internal state in segmented array"));
00409
00410 UINT new_size;
00411
00412 if (next_block_size == 0)
00413 new_size = block_size;
00414 else {
00415 new_size = Round_up (next_block_size);
00416 next_block_size = 0;
00417 }
00418
00419 block = (T *) MEM_POOL_Alloc (pool, new_size * sizeof(T));
00420 max_size_ += new_size;
00421 block_base = size_;
00422
00423 Update_Map (block, new_size, TRUE);
00424
00425 }
00426
00427
00428 template <class T, UINT block_size>
00429 void
00430 SEGMENTED_ARRAY<T,block_size>::Delete_last (UINT n)
00431 {
00432 while (n >= size_ - block_base) {
00433 n -= size_ - block_base;
00434 size_ = block_base;
00435 Pop_Map ();
00436 }
00437
00438 size_ -= n;
00439 }
00440
00441
00442 template <class T, UINT block_size>
00443 inline UINT
00444 SEGMENTED_ARRAY<T,block_size>::Insert (const T& x)
00445 {
00446 UINT idx = size_;
00447 T &entry = New_entry ();
00448
00449 entry = x;
00450 return idx;
00451 }
00452
00453
00454 template <class T, UINT block_size>
00455 UINT
00456 SEGMENTED_ARRAY<T,block_size>::Insert (const T* x, UINT n_elemt)
00457 {
00458 UINT result = size_;
00459 if (size_ + n_elemt <= max_size_) {
00460 Copy (x, n_elemt);
00461 return result;
00462 }
00463
00464 UINT space_left = max_size_ - size_;
00465 Copy (x, space_left);
00466 n_elemt -= space_left;
00467
00468 Reserve (n_elemt);
00469 Allocate ();
00470 Copy (x + space_left, n_elemt);
00471
00472 return result;
00473 }
00474
00475
00476 template <class T, UINT block_size>
00477 UINT
00478 SEGMENTED_ARRAY<T,block_size>::Transfer (T* x, UINT n_elemt)
00479 {
00480 UINT result = size_;
00481
00482 if (size_ + n_elemt <= max_size_) {
00483 Copy (x, n_elemt);
00484 return result;
00485 }
00486
00487 UINT space_left = max_size_ - size_;
00488 if (space_left > 0) {
00489 Copy (x, space_left);
00490 n_elemt -= space_left;
00491 x += space_left;
00492 }
00493
00494 if (n_elemt >= block_size) {
00495 UINT reused_size = n_elemt & ~(block_size - 1);
00496 block = x;
00497 Update_Map (block, reused_size, FALSE);
00498 block_base = size_;
00499 size_ += reused_size;
00500 max_size_ += reused_size;
00501 n_elemt -= reused_size;
00502 x += reused_size;
00503 if (next_block_size > reused_size)
00504 next_block_size -= reused_size;
00505 else
00506 next_block_size = 0;
00507 }
00508
00509 if (n_elemt > 0) {
00510 Allocate ();
00511 Copy (x, n_elemt);
00512 }
00513
00514 return result;
00515
00516 }
00517
00518
00519 template <class T, UINT block_size, class OP>
00520 inline void
00521 For_all_entries (SEGMENTED_ARRAY<T, block_size>& array, const OP &op,
00522 UINT32 first = 0)
00523 {
00524 UINT last = array.size ();
00525
00526 while (first < last) {
00527 T *block = &array[first];
00528 UINT size = array.Get_block_size (first);
00529 for (UINT j = 0; j < size; ++j, ++block)
00530 op (first + j, block);
00531 first += size;
00532 }
00533 }
00534
00535
00536
00537
00538 #if 0
00539
00540 template <class T, UINT block_size, class OP>
00541 inline void
00542 For_all_entries (const SEGMENTED_ARRAY<T, block_size>& array, const OP &op,
00543 UINT32 first = 0)
00544 {
00545 UINT last = array.size ();
00546
00547 while (first < last) {
00548 const T *block = &array[first];
00549 UINT size = array.Get_block_size (first);
00550 for (UINT j = 0; j < size; ++j, ++block)
00551 op (first + j, block);
00552 first += size;
00553 }
00554 }
00555
00556 #endif
00557
00558 template <class T, UINT block_size, class OP>
00559 inline void
00560 For_all_blocks (SEGMENTED_ARRAY<T, block_size>& array, const OP &op)
00561 {
00562 UINT max_size = array.size ();
00563 UINT i = 0;
00564
00565 while (i < max_size) {
00566 T *block = &array[i];
00567 UINT size = array.Get_block_size (i);
00568 op (i, block, size);
00569 i += size;
00570 }
00571 }
00572
00573
00574 #define NOT_FOUND ((UINT) -1)
00575
00576 template <class T, UINT block_size, class PREDICATE>
00577 inline UINT
00578 Find_entry_if (const SEGMENTED_ARRAY<T, block_size>& array,
00579 const PREDICATE& pred, UINT i = 0)
00580 {
00581 UINT max_size = array.size ();
00582
00583 while (i < max_size) {
00584 const T *block = &array[i];
00585 UINT size = array.Get_block_size (i);
00586 for (UINT j = 0; j < size; ++j, ++block)
00587 if (pred (i+j, block))
00588 return i + j;
00589 i += size;
00590 }
00591
00592 return (UINT) NOT_FOUND;
00593 }
00594
00595
00596
00597
00598
00599 template <class T, UINT block_size>
00600 UINT32
00601 Copy_array_range (const SEGMENTED_ARRAY<T, block_size>& from_array,
00602 SEGMENTED_ARRAY<T, block_size>& to_array,
00603 UINT32 first_idx = 0, UINT32 last_idx = (UINT32) -1)
00604 {
00605 if (last_idx > from_array.size ())
00606 last_idx = from_array.size ();
00607
00608 Is_True (last_idx >= first_idx, ("Invalid copy range"));
00609
00610 UINT32 entries = last_idx - first_idx;
00611
00612 to_array.Reserve (entries);
00613
00614 while (first_idx < last_idx) {
00615 const T* block = &from_array[first_idx];
00616 UINT32 size = from_array.Get_block_size (first_idx);
00617 if (size > last_idx - first_idx)
00618 size = last_idx - first_idx;
00619
00620 to_array.Insert (block, size);
00621 first_idx += size;
00622 }
00623
00624 return entries;
00625 }
00626
00627 #endif