Commit 5f8e2b66 authored by Andrey Kamakin's avatar Andrey Kamakin

Added iterator single threaded test and removed Utils.h.

Ref T8874
parent 446be901
......@@ -21,7 +21,7 @@ public:
typedef V Value;
typedef KT KeyTraits;
typedef VT ValueTraits;
typedef typename BestFit<Key>::Unsigned Hash;
typedef quint32 Hash;
typedef Leapfrog<ConcurrentMap_Leapfrog> Details;
private:
......@@ -337,13 +337,6 @@ public:
return m_value != Value(ValueTraits::NullValue);
}
Key getKey() const
{
Q_ASSERT(isValid());
// Since we've forbidden concurrent inserts (for now), nonatomic would suffice here, but let's plan ahead:
return KeyTraits::dehash(m_hash);
}
Value getValue() const
{
Q_ASSERT(isValid());
......
......@@ -11,7 +11,6 @@
#ifndef LEAPFROG_H
#define LEAPFROG_H
#include "Util.h"
#include "MapTraits.h"
#include "SimpleJobCoordinator.h"
#include "QSBR.h"
......@@ -62,7 +61,7 @@ struct Leapfrog {
Q_ASSERT(tableSize >= 4);
quint64 numGroups = tableSize >> 2;
Table* table = (Table*) std::malloc(sizeof(Table) + sizeof(CellGroup) * numGroups);
new(table) Table(tableSize - 1);
new (table) Table(tableSize - 1);
for (quint64 i = 0; i < numGroups; i++) {
CellGroup* group = table->getCellGroups() + i;
......@@ -117,7 +116,7 @@ struct Leapfrog {
{
TableMigration* migration =
(TableMigration*) std::malloc(sizeof(TableMigration) + sizeof(TableMigration::Source) * numSources);
new(migration) TableMigration(map);
new (migration) TableMigration(map);
migration->m_workerStatus.storeNonatomic(0);
migration->m_overflowed.storeNonatomic(false);
......
......@@ -11,30 +11,44 @@
#ifndef MAPTRAITS_H
#define MAPTRAITS_H
#include "Util.h"
#include <QtCore>
#include <QDebug>
inline quint64 roundUpPowerOf2(quint64 v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v |= v >> 32;
v++;
return v;
}
inline bool isPowerOf2(quint64 v)
{
return (v & (v - 1)) == 0;
}
template <class T>
struct DefaultKeyTraits {
typedef T Key;
typedef typename BestFit<T>::Unsigned Hash;
typedef quint32 Hash;
static const Key NullKey = Key(0);
static const Hash NullHash = Hash(0);
static Hash hash(T key)
{
return avalanche(Hash(key));
}
static Key dehash(Hash hash)
{
return (T) deavalanche(hash);
return std::hash<qint32>()(Hash(key)) & std::hash<qint32>()(Hash(key));
}
};
template <class T>
struct DefaultValueTraits {
typedef T Value;
typedef typename BestFit<T>::Unsigned IntType;
typedef quint32 IntType;
static const IntType NullValue = 0;
static const IntType Redirect = 1;
};
......
......@@ -63,7 +63,7 @@ private:
m_pendingActions.swap(m_deferredActions);
m_remaining = m_numContexts;
for (quint64 i = 0; i < m_status.size(); i++) {
for (qint32 i = 0; i < m_status.size(); i++) {
m_status[i].wasIdle = 0;
}
}
......@@ -123,7 +123,7 @@ public:
}
}
for (quint64 i = 0; i < actions.size(); i++) {
for (qint32 i = 0; i < actions.size(); i++) {
actions[i]();
}
}
......@@ -170,7 +170,7 @@ public:
onAllQuiescentStatesPassed(actions);
}
for (quint64 i = 0; i < actions.size(); i++) {
for (qint32 i = 0; i < actions.size(); i++) {
actions[i]();
}
}
......@@ -180,13 +180,13 @@ public:
// This is like saying that all contexts are quiescent,
// so we can issue all actions at once.
// No lock is taken.
for (quint64 i = 0; i < m_pendingActions.size(); i++) {
for (qint32 i = 0; i < m_pendingActions.size(); i++) {
m_pendingActions[i]();
}
m_pendingActions.clear();
for (quint64 i = 0; i < m_deferredActions.size(); i++) {
for (qint32 i = 0; i < m_deferredActions.size(); i++) {
m_deferredActions[i]();
}
......
/*------------------------------------------------------------------------
Junction: Concurrent data structures in C++
Copyright (c) 2016 Jeff Preshing
Distributed under the Simplified BSD License.
Original location: https://github.com/preshing/junction
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the LICENSE file for more information.
------------------------------------------------------------------------*/
#ifndef UTIL_H
#define UTIL_H
#include <QtCore>
template <typename T>
struct BestFit;
template <>
struct BestFit<qint32> {
typedef quint32 Unsigned;
typedef qint32 Signed;
};
template <>
struct BestFit<quint32> {
typedef quint32 Unsigned;
typedef qint32 Signed;
};
template <>
struct BestFit<qint64> {
typedef quint64 Unsigned;
typedef qint64 Signed;
};
template <>
struct BestFit<quint64> {
typedef quint64 Unsigned;
typedef qint64 Signed;
};
template <class T>
struct BestFit<T*> {
typedef quint64 Unsigned;
typedef qint64 Signed;
};
inline quint32 roundUpPowerOf2(quint32 v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
inline qint32 roundUpPowerOf2(qint32 v)
{
return (qint32) roundUpPowerOf2((quint32) v);
}
inline quint64 roundUpPowerOf2(quint64 v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v |= v >> 32;
v++;
return v;
}
inline qint64 roundUpPowerOf2(qint64 v)
{
return (qint64) roundUpPowerOf2((quint64) v);
}
inline bool isPowerOf2(quint64 v)
{
return (v & (v - 1)) == 0;
}
// from code.google.com/p/smhasher/wiki/MurmurHash3
inline quint32 avalanche(quint32 h)
{
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
inline quint32 deavalanche(quint32 h)
{
h ^= h >> 16;
h *= 0x7ed1b41d;
h ^= (h ^ (h >> 13)) >> 13;
h *= 0xa5cb9243;
h ^= h >> 16;
return h;
}
// from code.google.com/p/smhasher/wiki/MurmurHash3
inline quint64 avalanche(quint64 h)
{
h ^= h >> 33;
h *= 0xff51afd7ed558ccd;
h ^= h >> 33;
h *= 0xc4ceb9fe1a85ec53;
h ^= h >> 33;
return h;
}
inline quint64 deavalanche(quint64 h)
{
h ^= h >> 33;
h *= 0x9cb4b2f8129337db;
h ^= h >> 33;
h *= 0x4f74430c22a54005;
h ^= h >> 33;
return h;
}
#endif // UTIL_H
......@@ -11,7 +11,7 @@
#define NUM_CYCLES 50000
#define NUM_THREADS 10
typedef ConcurrentMap_Leapfrog<int, int> ConcurrentMap;
typedef ConcurrentMap_Leapfrog<qint32, qint32> ConcurrentMap;
class StressJobLockless : public QRunnable
{
......@@ -120,4 +120,23 @@ void LockfreeMapTest::stressTestLockless()
QVERIFY(totalSum == 0);
}
void LockfreeMapTest::iteratorTest()
{
ConcurrentMap map;
qint32 sum = 0;
for (qint32 i = 2; i < 100; ++i) {
map.assign(i, i);
sum += i;
}
ConcurrentMap::Iterator iter(map);
qint32 testSum = 0;
while (iter.isValid()) {
testSum += iter.getValue();
iter.next();
}
QVERIFY(sum == testSum);
}
QTEST_GUILESS_MAIN(LockfreeMapTest)
......@@ -10,6 +10,7 @@ class LockfreeMapTest : public QObject
private Q_SLOTS:
void testOperations();
void stressTestLockless();
void iteratorTest();
};
#endif // KIS_LOCK_FREE_MAP_TEST_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment