22 typedef typename Map::Hash
Hash;
23 typedef typename Map::Value
Value;
66 quint64 numGroups = tableSize >> 2;
68 new (table)
Table(tableSize - 1);
70 for (quint64 i = 0; i < numGroups; i++) {
73 for (quint64 j = 0; j < 4; j++) {
85 this->Table::~Table();
150 return (
Source*)(
this + 1);
154 virtual void run()
override;
165 quint64 idx = hash & sizeMask;
170 if (probeHash == hash) {
172 }
else if (probeHash == KeyTraits::NullHash) {
178 idx = (idx + delta) & sizeMask;
180 cell = group->
cells + (idx & 3);
184 if (probeHash == hash) {
202 quint64 idx = quint64(hash);
206 cell = group->
cells + (idx & 3);
209 if (probeHash == KeyTraits::NullHash) {
218 if (probeHash == hash) {
223 quint64 maxIdx = idx + sizeMask;
224 quint64 linkLevel = 0;
228 prevLink = group->
deltas + ((idx & 3) + linkLevel);
236 cell = group->
cells + (idx & 3);
239 if (probeHash == KeyTraits::NullHash) {
245 }
while (probeHash == KeyTraits::NullHash);
251 if (probeHash == hash) {
257 quint64 prevLinkIdx = idx;
263 while (linearProbesRemaining-- > 0) {
266 cell = group->
cells + (idx & 3);
269 if (probeHash == KeyTraits::NullHash) {
276 quint8 desiredDelta = idx - prevLinkIdx;
283 Hash x = (probeHash ^ hash);
289 if ((x & sizeMask) == 0) {
294 quint8 desiredDelta = idx - prevLinkIdx;
301 overflowIdx = idx + 1;
314 QMutexLocker guard(&table->
mutex);
337 quint64 inUseCells = 0;
338 for (quint64 linearProbesRemaining =
CellsInUseSample; linearProbesRemaining > 0; linearProbesRemaining--) {
351 float estimatedInUse = (sizeMask + 1) * inUseRatio;
360 quint64 srcSizeMask = srcTable->
sizeMask;
363 for (quint64 srcIdx = startIdx; srcIdx < endIdx; srcIdx++) {
365 Cell* srcCell = srcGroup->
cells + (srcIdx & 3);
371 if (srcHash == KeyTraits::NullHash) {
375 if (srcValue ==
Value(ValueTraits::Redirect)) {
379 if (srcValue ==
Value(ValueTraits::NullValue)) {
386 if (srcValue ==
Value(ValueTraits::NullValue)) {
392 if (srcValue ==
Value(ValueTraits::Redirect)) {
396 }
else if (srcValue ==
Value(ValueTraits::Redirect)) {
435 if (doubleCheckedSrcValue == srcValue) {
439 if (srcValue ==
Value(ValueTraits::NullValue)) {
446 srcValue = doubleCheckedSrcValue;
466 quint64 probeStatus = m_workerStatus.load(
Relaxed);
468 if (probeStatus & 1) {
472 }
while (!m_workerStatus.compareExchangeWeak(probeStatus, probeStatus + 2,
Relaxed,
Relaxed));
479 for (quint64 s = 0; s < m_numSources; s++) {
483 if (m_workerStatus.load(
Relaxed) & 1) {
487 if (startIdx >=
source.table->sizeMask + 1)
489 bool overflowed = !migrateRange(
source.table, startIdx);
500 bool oldOverflowed = m_overflowed.exchange(overflowed,
Relaxed);
505 m_workerStatus.fetchOr(1,
Relaxed);
509 qint64 prevRemaining = m_unitsRemaining.fetchSub(1,
Relaxed);
513 if (prevRemaining == 1) {
516 m_workerStatus.fetchOr(1,
Relaxed);
525 if (probeStatus >= 4) {
535 bool overflowed = m_overflowed.loadNonatomic();
538 m_map.publishTableMigration(
this);
540 getSources()[0].table->jobCoordinator.end();
543 Table* origTable = getSources()[0].table;
544 QMutexLocker guard(&origTable->
mutex);
547 if (checkedJob !=
this) {
554 for (quint64 i = 0; i < m_numSources; i++) {
556 getSources()[i].table = NULL;
563 quint64 unitsRemaining = 0;
float value(const T *src, size_t ch)
KisMagneticGraph::vertex_descriptor source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
bool compareExchangeStrong(T &expected, T desired, MemoryOrder memoryOrder)
void storeNonatomic(T value)
T compareExchange(T expected, T desired, MemoryOrder memoryOrder)
T load(MemoryOrder memoryOrder) const
void store(T value, MemoryOrder memoryOrder)
Atomic< qint64 > m_unitsRemaining
bool migrateRange(Table *srcTable, quint64 startIdx)
Source * getSources() const
static TableMigration * create(Map &map, quint64 numSources)
virtual ~TableMigration() override
virtual void run() override
Atomic< bool > m_overflowed
Atomic< quint64 > m_workerStatus
Job * loadConsume() const
void storeRelease(Job *job)
#define KIS_ASSERT_RECOVER_NOOP(cond)
bool isPowerOf2(quint64 v)
quint64 roundUpPowerOf2(quint64 v)
Atomic< quint8 > deltas[8]
Atomic< quint64 > sourceIndex
quint64 getNumMigrationUnits() const
static Table * create(quint64 tableSize)
CellGroup * getCellGroups() const
SimpleJobCoordinator jobCoordinator
static const quint64 CellsInUseSample
static Cell * find(Hash hash, Table *table)
@ InsertResult_InsertedNew
@ InsertResult_AlreadyFound
static const quint64 InitialSize
Map::ValueTraits ValueTraits
static void beginTableMigration(Map &map, Table *table, quint64 overflowIdx)
Q_STATIC_ASSERT(LinearSearchLimit > 0 &&LinearSearchLimit< 256)
static const quint64 LinearSearchLimit
static InsertResult insertOrFind(Hash hash, Table *table, Cell *&cell, quint64 &overflowIdx)
static const quint64 TableMigrationUnitSize
Q_STATIC_ASSERT(CellsInUseSample > 0 &&CellsInUseSample<=LinearSearchLimit)
static void beginTableMigrationToSize(Map &map, Table *table, quint64 nextTableSize)