Initial work
This commit is contained in:
commit
3222551702
374 changed files with 40290 additions and 0 deletions
236
external/android-emugl/shared/emugl/common/id_to_object_map.cpp
vendored
Normal file
236
external/android-emugl/shared/emugl/common/id_to_object_map.cpp
vendored
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
// Copyright (C) 2014 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "emugl/common/id_to_object_map.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace emugl {
|
||||
|
||||
namespace {
|
||||
|
||||
typedef IdToObjectMapBase::KeyType KeyType;
|
||||
|
||||
enum {
|
||||
kMinShift = 3,
|
||||
kMaxShift = 31,
|
||||
kMinCapacity = (1 << kMinShift),
|
||||
kLoadScale = 1024,
|
||||
kMinLoad = kLoadScale/4, // 25% minimum load.
|
||||
kMaxLoad = kLoadScale*3/4, // 75% maximum load.
|
||||
|
||||
kInvalidKey = IdToObjectMapBase::kMaxId + 1U,
|
||||
kTombstone = IdToObjectMapBase::kMaxId + 2U,
|
||||
};
|
||||
|
||||
// Return a number that indicates if the current |capacity| is appropriate
|
||||
// to hold |size| items in our map.
|
||||
// -1 -> the capacity is too small and needs to be increased.
|
||||
// 0 -> the capacity is ok.
|
||||
// +1 -> the capacity is too large and needs to be decreased.
|
||||
int capacityCompare(size_t shift, size_t size) {
|
||||
size_t capacity = 1U << shift;
|
||||
// Essentially, one can rewrite:
|
||||
// load < minLoad
|
||||
// as:
|
||||
// size / capacity < minLoad
|
||||
// capacity * minLoad > size
|
||||
if (capacity * kMinLoad > size * kLoadScale)
|
||||
return +1;
|
||||
|
||||
// Similarly, one can rewrite:
|
||||
// load > maxLoad
|
||||
// as:
|
||||
// size / capacity > maxLoad
|
||||
// capacity * maxLoad < size
|
||||
if (capacity * kMaxLoad < size * kLoadScale)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t probeKeys(const KeyType* keys, size_t shift, KeyType key) {
|
||||
static const int kPrimes[] = {
|
||||
1, /* For 1 << 0 */
|
||||
2,
|
||||
3,
|
||||
7,
|
||||
13,
|
||||
31,
|
||||
61,
|
||||
127,
|
||||
251,
|
||||
509,
|
||||
1021,
|
||||
2039,
|
||||
4093,
|
||||
8191,
|
||||
16381,
|
||||
32749,
|
||||
65521, /* For 1 << 16 */
|
||||
131071,
|
||||
262139,
|
||||
524287,
|
||||
1048573,
|
||||
2097143,
|
||||
4194301,
|
||||
8388593,
|
||||
16777213,
|
||||
33554393,
|
||||
67108859,
|
||||
134217689,
|
||||
268435399,
|
||||
536870909,
|
||||
1073741789,
|
||||
2147483647 /* For 1 << 31 */
|
||||
};
|
||||
|
||||
size_t slot = key % kPrimes[shift];
|
||||
size_t step = 0;
|
||||
for (;;) {
|
||||
KeyType k = keys[slot];
|
||||
if (k == kInvalidKey || k == kTombstone || k == key)
|
||||
return slot;
|
||||
|
||||
step += 1;
|
||||
slot = (slot + step) & (1U << shift);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
IdToObjectMapBase::IdToObjectMapBase() :
|
||||
mCount(0), mShift(kMinShift) {
|
||||
size_t capacity = 1U << mShift;
|
||||
mKeys = static_cast<KeyType*>(::calloc(sizeof(mKeys[0]), capacity));
|
||||
mValues = static_cast<void**>(::calloc(sizeof(mValues[0]), capacity));
|
||||
for (size_t n = 0; n < capacity; ++n) {
|
||||
mKeys[n] = kInvalidKey;
|
||||
}
|
||||
}
|
||||
|
||||
IdToObjectMapBase::~IdToObjectMapBase() {
|
||||
mShift = 0;
|
||||
mCount = 0;
|
||||
::free(mKeys);
|
||||
::free(mValues);
|
||||
}
|
||||
|
||||
bool IdToObjectMapBase::contains(KeyType key) const {
|
||||
size_t slot = probeKeys(mKeys, mShift, key);
|
||||
switch (mKeys[slot]) {
|
||||
case kInvalidKey:
|
||||
case kTombstone:
|
||||
return false;
|
||||
default:
|
||||
;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IdToObjectMapBase::find(KeyType key, void** value) const {
|
||||
size_t slot = probeKeys(mKeys, mShift, key);
|
||||
if (!isValidKey(mKeys[slot])) {
|
||||
*value = NULL;
|
||||
return false;
|
||||
}
|
||||
*value = mValues[slot];
|
||||
return true;
|
||||
}
|
||||
|
||||
void* IdToObjectMapBase::set(KeyType key, void* value) {
|
||||
if (!value)
|
||||
return remove(key);
|
||||
|
||||
size_t slot = probeKeys(mKeys, mShift, key);
|
||||
void* result;
|
||||
if (isValidKey(mKeys[slot])) {
|
||||
result = mValues[slot];
|
||||
mValues[slot] = value;
|
||||
} else {
|
||||
mKeys[slot] = key;
|
||||
mValues[slot] = value;
|
||||
result = NULL;
|
||||
mCount++;
|
||||
resize(mCount);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void* IdToObjectMapBase::remove(KeyType key) {
|
||||
size_t slot = probeKeys(mKeys, mShift, key);
|
||||
if (!isValidKey(mKeys[slot]))
|
||||
return NULL;
|
||||
|
||||
void* result = mValues[slot];
|
||||
mValues[slot] = NULL;
|
||||
mKeys[slot] = kTombstone;
|
||||
mCount--;
|
||||
return result;
|
||||
}
|
||||
|
||||
void IdToObjectMapBase::resize(size_t newSize) {
|
||||
int ret = capacityCompare(mShift, newSize);
|
||||
if (!ret)
|
||||
return;
|
||||
|
||||
size_t oldCapacity = 1U << mShift;
|
||||
size_t newShift = mShift;
|
||||
|
||||
if (ret < 0) {
|
||||
// Capacity is too small and must be increased.
|
||||
do {
|
||||
if (newShift == kMaxShift)
|
||||
break;
|
||||
++newShift;
|
||||
} while (capacityCompare(newShift, newSize) < 0);
|
||||
} else {
|
||||
// Capacity is too large and must be decreased.
|
||||
do {
|
||||
if (newShift == kMinShift)
|
||||
break;
|
||||
newShift--;
|
||||
} while (capacityCompare(newShift, newSize) > 0);
|
||||
}
|
||||
if (newShift == mShift)
|
||||
return;
|
||||
|
||||
// Allocate new arrays.
|
||||
size_t newCapacity = 1U << newShift;
|
||||
KeyType* newKeys = static_cast<KeyType*>(
|
||||
::calloc(sizeof(newKeys[0]), newCapacity));
|
||||
void** newValues = static_cast<void**>(
|
||||
::calloc(sizeof(newValues[0]), newCapacity));
|
||||
for (size_t n = 0; n < newCapacity; ++n)
|
||||
newKeys[n] = kInvalidKey;
|
||||
|
||||
// Copy old entries into new arrays.
|
||||
for (size_t n = 0; n < oldCapacity; ++n) {
|
||||
KeyType key = mKeys[n];
|
||||
if (isValidKey(key)) {
|
||||
size_t newSlot = probeKeys(newKeys, newShift, key);
|
||||
newKeys[newSlot] = key;
|
||||
newValues[newSlot] = mValues[n];
|
||||
}
|
||||
}
|
||||
|
||||
// Swap arrays, and get rid of old ones.
|
||||
::free(mKeys);
|
||||
::free(mValues);
|
||||
mKeys = newKeys;
|
||||
mValues = newValues;
|
||||
mShift = newShift;
|
||||
}
|
||||
|
||||
} // namespace emugl
|
||||
Loading…
Add table
Add a link
Reference in a new issue