remove restrictions on order of initial_reserve_id() calls
This commit is contained in:
parent
ca02924197
commit
90af2a0339
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue