remove restrictions on order of initial_reserve_id() calls

This commit is contained in:
David Rose 2007-03-16 21:35:26 +00:00
parent ca02924197
commit 90af2a0339
2 changed files with 49 additions and 24 deletions

View File

@ -66,7 +66,7 @@ UniqueIdAllocator(PN_uint32 min, PN_uint32 max)
_size = _max-_min+1; // +1 because min and max are inclusive.
nassertv(_size != 0); // size must be > 0.
_table=new PN_uint32[_size];
_table = new PN_uint32[_size];
nassertv(_table); // This should be redundant if new throws an exception.
for (PN_uint32 i = 0; i < _size; ++i) {
@ -75,7 +75,7 @@ UniqueIdAllocator(PN_uint32 min, PN_uint32 max)
_table[_size - 1] = IndexEnd;
_next_free = 0;
_last_free = _size - 1;
_free=_size;
_free = _size;
}
////////////////////////////////////////////////////////////////////
@ -105,12 +105,10 @@ allocate() {
return IndexEnd;
}
PN_uint32 index = _next_free;
_next_free = _table[_next_free];
#ifndef NDEBUG //[
nassertr(_table[index] != IndexAllocated, IndexEnd);
_next_free = _table[_next_free];
_table[index] = IndexAllocated;
#endif //]
--_free;
@ -127,41 +125,68 @@ allocate() {
// pass). The specified id is removed from the
// available pool.
//
// Because of the limitations of this algorithm, this
// may only be called before the first call to
// allocate(); and all the calls to initial_reserve_id()
// must be made in descending order by id.
// Because of the limitations of this algorithm, this is
// most efficient when it is called before the first
// call to allocate(), and when all the calls to
// initial_reserve_id() are made in descending order by
// id. However, this is a performance warning only; if
// performance is not an issue, any id may be reserved
// at any time.
////////////////////////////////////////////////////////////////////
void UniqueIdAllocator::
initial_reserve_id(PN_uint32 id) {
nassertv(_next_free == 0); // Must call before any call to allocate().
nassertv(id >= _min && id <= _max); // Attempt to reserve out-of-range id.
PN_uint32 index = id - _min; // Convert to _table index.
nassertv(_table[index] != IndexAllocated);
// Because we insist that this call be made before any calls to
// allocate(), and in descending order, it follows that the _table
// is still set up such that _table[i] = i+1, at least for all slots
// <= index. Thus, the free link to slot [index] is guaranteed to
// be the slot right before it.
if (_free == 1) {
// We just reserved the last element in the free chain.
_next_free = IndexEnd;
if (index == 0) {
} else if (_next_free == index) {
// We're reserving the head of the free chain.
_next_free = _table[index];
} else {
nassertv(_table[index - 1] == index);
_table[index - 1] = _table[index];
// Since we don't store back pointers in the free chain, we have
// to search for the element in the free chain that points to this
// index.
// However, there is an easy optimal case: because we expect that
// this call will be made before any calls to allocate(),
// hopefully is it still true that the _table is still set up such
// that _table[i] = i+1 (and if the numbers are reserved in
// descending order, this will be true at least for all i <=
// index). Thus, the free link to slot [index] is expected to be
// the slot right before it, or if not, it usually won't be far
// before it.
PN_uint32 prev_index = index;
while (prev_index > 0 && _table[prev_index - 1] != index) {
--prev_index;
}
if (prev_index > 0 && _table[prev_index - 1] == index) {
// We've found it.
--prev_index;
} else {
// OK, it wasn't found below; we have to search above.
prev_index = index + 1;
while (prev_index < _size && _table[prev_index] != index) {
++prev_index;
}
}
nassertv(_table[prev_index] == index);
_table[prev_index] = _table[index];
if (index == _last_free) {
_last_free = index - 1;
_last_free = prev_index;
}
}
#ifndef NDEBUG //[
_table[index] = IndexAllocated;
#endif //]
--_free;
}

View File

@ -73,7 +73,7 @@ protected:
// IndexEnd.
// For an allocated id, the table entry at the corresponding index
// is undefined (but in debug mode, it contains IndexAllocated).
// contains IndexAllocated.
PN_uint32 *_table;
// The minimum and maximum as passed to the constructor.