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