mirror of
https://github.com/greg7mdp/parallel-hashmap.git
synced 2026-08-29 08:34:39 +08:00
add support for absl::Mutex
This commit is contained in:
+1
-6
@@ -28,12 +28,7 @@
|
|||||||
#if 1
|
#if 1
|
||||||
// use Abseil's mutex... faster
|
// use Abseil's mutex... faster
|
||||||
#include "absl/synchronization/mutex.h"
|
#include "absl/synchronization/mutex.h"
|
||||||
struct AbslMutex : protected absl::Mutex
|
#define MTX absl::Mutex
|
||||||
{
|
|
||||||
void lock() { this->Lock(); }
|
|
||||||
void unlock() { this->Unlock(); }
|
|
||||||
};
|
|
||||||
#define MTX AbslMutex //std::mutex
|
|
||||||
#else
|
#else
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#define MTX std::mutex
|
#define MTX std::mutex
|
||||||
|
|||||||
+5
-1
@@ -13,6 +13,10 @@
|
|||||||
#if 1
|
#if 1
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#define MTX std::mutex
|
#define MTX std::mutex
|
||||||
|
#elif 0
|
||||||
|
// Abseil's mutexes are very efficient (at least on windows)
|
||||||
|
#include "absl/synchronization/mutex.h"
|
||||||
|
#define MTX absl::Mutex
|
||||||
#elif 0
|
#elif 0
|
||||||
#include <boost/thread/locks.hpp>
|
#include <boost/thread/locks.hpp>
|
||||||
#include <boost/thread/shared_mutex.hpp>
|
#include <boost/thread/shared_mutex.hpp>
|
||||||
@@ -415,7 +419,7 @@ int main(int argc, char ** argv)
|
|||||||
#endif
|
#endif
|
||||||
else if(!strcmp(argv[2], "random"))
|
else if(!strcmp(argv[2], "random"))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "size = %llu\n", sizeof(hash));
|
fprintf(stderr, "size = %zu\n", sizeof(hash));
|
||||||
timer = _fill_random2(num_keys, hash);
|
timer = _fill_random2(num_keys, hash);
|
||||||
//out("random", num_keys, timer);
|
//out("random", num_keys, timer);
|
||||||
//fprintf(stderr, "inserted %llu\n", hash.size());
|
//fprintf(stderr, "inserted %llu\n", hash.size());
|
||||||
|
|||||||
Vendored
+158
-57
@@ -4587,74 +4587,63 @@ public:
|
|||||||
bool owns_lock() const noexcept { return true; }
|
bool owns_lock() const noexcept { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScopedLock
|
class WriteLock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Mutex mutex_type;
|
typedef Mutex mutex_type;
|
||||||
|
|
||||||
ScopedLock() :
|
WriteLock() : m_(nullptr), locked_(false) {}
|
||||||
m_(nullptr), locked_(false)
|
|
||||||
{}
|
|
||||||
|
|
||||||
explicit ScopedLock(Mutex &m) :
|
explicit WriteLock(Mutex &m) : m_(&m) {
|
||||||
m_(&m)
|
|
||||||
{
|
|
||||||
m_->lock();
|
m_->lock();
|
||||||
locked_ = true;
|
locked_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopedLock(Mutex& m, adopt_lock_t) noexcept :
|
WriteLock(Mutex& m, adopt_lock_t) noexcept :
|
||||||
m_(&m), locked_(true)
|
m_(&m), locked_(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
ScopedLock(Mutex& m, defer_lock_t) noexcept :
|
WriteLock(Mutex& m, defer_lock_t) noexcept :
|
||||||
m_(&m), locked_(false)
|
m_(&m), locked_(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
ScopedLock(Mutex& m, try_to_lock_t) :
|
WriteLock(Mutex& m, try_to_lock_t) :
|
||||||
m_(&m), locked_(false)
|
m_(&m), locked_(false) {
|
||||||
{
|
|
||||||
try_lock();
|
try_lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopedLock(ScopedLock &&o) :
|
WriteLock(WriteLock &&o) :
|
||||||
m_(std::move(o.m_)), locked_(std::move(o.locked_))
|
m_(std::move(o.m_)), locked_(std::move(o.locked_)) {
|
||||||
{
|
|
||||||
o.locked_ = false;
|
o.locked_ = false;
|
||||||
o.m_ = nullptr;
|
o.m_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopedLock& operator=(ScopedLock&& other)
|
WriteLock& operator=(WriteLock&& other) {
|
||||||
{
|
WriteLock temp(std::move(other));
|
||||||
ScopedLock temp(std::move(other));
|
|
||||||
swap(temp);
|
swap(temp);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
~ScopedLock()
|
~WriteLock() {
|
||||||
{
|
|
||||||
if (locked_)
|
if (locked_)
|
||||||
m_->unlock();
|
m_->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void lock()
|
void lock() {
|
||||||
{
|
|
||||||
if (!locked_) {
|
if (!locked_) {
|
||||||
m_->lock();
|
m_->lock();
|
||||||
locked_ = true;
|
locked_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlock()
|
void unlock() {
|
||||||
{
|
|
||||||
if (locked_) {
|
if (locked_) {
|
||||||
m_->unlock();
|
m_->unlock();
|
||||||
locked_ = false;
|
locked_ = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool try_lock()
|
bool try_lock() {
|
||||||
{
|
|
||||||
if (locked_)
|
if (locked_)
|
||||||
return true;
|
return true;
|
||||||
locked_ = m_->try_lock();
|
locked_ = m_->try_lock();
|
||||||
@@ -4663,8 +4652,84 @@ public:
|
|||||||
|
|
||||||
bool owns_lock() const noexcept { return locked_; }
|
bool owns_lock() const noexcept { return locked_; }
|
||||||
|
|
||||||
void swap(ScopedLock &o) noexcept
|
void swap(WriteLock &o) noexcept {
|
||||||
{
|
std::swap(m_, o.m_);
|
||||||
|
std::swap(locked_, o.locked_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mutex *mutex() const noexcept { return m_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Mutex *m_;
|
||||||
|
bool locked_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ReadLock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Mutex mutex_type;
|
||||||
|
|
||||||
|
ReadLock() : m_(nullptr), locked_(false) {}
|
||||||
|
|
||||||
|
explicit ReadLock(Mutex &m) : m_(&m) {
|
||||||
|
m_->lock_shared();
|
||||||
|
locked_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadLock(Mutex& m, adopt_lock_t) noexcept :
|
||||||
|
m_(&m), locked_(true)
|
||||||
|
{}
|
||||||
|
|
||||||
|
ReadLock(Mutex& m, defer_lock_t) noexcept :
|
||||||
|
m_(&m), locked_(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
ReadLock(Mutex& m, try_to_lock_t) :
|
||||||
|
m_(&m), locked_(false) {
|
||||||
|
try_lock_shared();
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadLock(ReadLock &&o) :
|
||||||
|
m_(std::move(o.m_)), locked_(std::move(o.locked_)) {
|
||||||
|
o.locked_ = false;
|
||||||
|
o.m_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadLock& operator=(ReadLock&& other) {
|
||||||
|
ReadLock temp(std::move(other));
|
||||||
|
swap(temp);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ReadLock() {
|
||||||
|
if (locked_)
|
||||||
|
m_->unlock_shared();
|
||||||
|
}
|
||||||
|
|
||||||
|
void lock() {
|
||||||
|
if (!locked_) {
|
||||||
|
m_->lock_shared();
|
||||||
|
locked_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock() {
|
||||||
|
if (locked_) {
|
||||||
|
m_->unlock_shared();
|
||||||
|
locked_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool try_lock() {
|
||||||
|
if (locked_)
|
||||||
|
return true;
|
||||||
|
locked_ = m_->try_lock_shared();
|
||||||
|
return locked_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool owns_lock() const noexcept { return locked_; }
|
||||||
|
|
||||||
|
void swap(ReadLock &o) noexcept {
|
||||||
std::swap(m_, o.m_);
|
std::swap(m_, o.m_);
|
||||||
std::swap(locked_, o.locked_);
|
std::swap(locked_, o.locked_);
|
||||||
}
|
}
|
||||||
@@ -4692,21 +4757,25 @@ public:
|
|||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
// Generic mutex support (always write locks)
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
template <class Mtx_>
|
template <class Mtx_>
|
||||||
class LockableImpl : public Mtx_, public LockableBaseImpl<Mtx_>
|
class LockableImpl : public Mtx_
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using mutex_type = Mtx_;
|
using mutex_type = Mtx_;
|
||||||
using Base = LockableBaseImpl<Mtx_>;
|
using Base = LockableBaseImpl<Mtx_>;
|
||||||
using SharedLock = typename Base::ScopedLock;
|
using SharedLock = typename Base::WriteLock;
|
||||||
using UpgradeLock = typename Base::ScopedLock;
|
using UpgradeLock = typename Base::WriteLock;
|
||||||
using UniqueLock = typename Base::ScopedLock;
|
using UniqueLock = typename Base::WriteLock;
|
||||||
using UpgradeToUnique = typename Base::DoNothing; // we already have unique ownership
|
using UpgradeToUnique = typename Base::DoNothing; // we already have unique ownership
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Null mutex (no-op) - when we don't want internal synchronization
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
template <>
|
template <>
|
||||||
class LockableImpl<phmap::NullMutex>: public phmap::NullMutex, public LockableBaseImpl<phmap::NullMutex>
|
class LockableImpl<phmap::NullMutex>: public phmap::NullMutex
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using mutex_type = phmap::NullMutex;
|
using mutex_type = phmap::NullMutex;
|
||||||
@@ -4717,36 +4786,68 @@ public:
|
|||||||
using UpgradeToUnique = typename Base::DoNothing;
|
using UpgradeToUnique = typename Base::DoNothing;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// Abseil Mutex support (read and write lock support)
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
#ifdef ABSL_SYNCHRONIZATION_MUTEX_H_
|
||||||
|
|
||||||
|
struct AbslMutex : protected absl::Mutex
|
||||||
|
{
|
||||||
|
void lock() { this->Lock(); }
|
||||||
|
void unlock() { this->Unlock(); }
|
||||||
|
void try_lock() { this->TryLock(); }
|
||||||
|
void lock_shared() { this->ReaderLock(); }
|
||||||
|
void unlock_shared() { this->ReaderUnlock(); }
|
||||||
|
void try_lock_shared() { this->ReaderTryLock(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class LockableImpl<absl::Mutex> : public AbslMutex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using mutex_type = phmap::AbslMutex;
|
||||||
|
using Base = LockableBaseImpl<phmap::AbslMutex>;
|
||||||
|
using SharedLock = typename Base::ReadLock;
|
||||||
|
using UpgradeLock = typename Base::WriteLock;
|
||||||
|
using UniqueLock = typename Base::WriteLock;
|
||||||
|
using UpgradeToUnique = typename Base::DoNothing; // we already have unique ownership
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// Boost shared_mutex support (read and write lock support)
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
#ifdef PHMAP_HAS_BOOST_THREAD_MUTEXES
|
#ifdef PHMAP_HAS_BOOST_THREAD_MUTEXES
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
template <>
|
template <>
|
||||||
class LockableImpl<boost::shared_mutex> : public boost::shared_mutex
|
class LockableImpl<boost::shared_mutex> : public boost::shared_mutex
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using mutex_type = boost::shared_mutex;
|
using mutex_type = boost::shared_mutex;
|
||||||
using Base = LockableBaseImpl<boost::shared_mutex>;
|
using Base = LockableBaseImpl<boost::shared_mutex>;
|
||||||
using SharedLock = boost::shared_lock<mutex_type>;
|
using SharedLock = boost::shared_lock<mutex_type>;
|
||||||
using UpgradeLock = boost::unique_lock<mutex_type>; // we assume that boost::shared_mutex can't upgrade
|
using UpgradeLock = boost::unique_lock<mutex_type>; // assume can't upgrade
|
||||||
using UniqueLock = boost::unique_lock<mutex_type>;
|
using UniqueLock = boost::unique_lock<mutex_type>;
|
||||||
using UpgradeToUnique = typename Base::DoNothing; // we already have unique ownership
|
using UpgradeToUnique = typename Base::DoNothing; // we already have unique ownership
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
template <>
|
template <>
|
||||||
class LockableImpl<boost::upgrade_mutex> : public boost::upgrade_mutex
|
class LockableImpl<boost::upgrade_mutex> : public boost::upgrade_mutex
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using mutex_type = boost::upgrade_mutex;
|
using mutex_type = boost::upgrade_mutex;
|
||||||
using SharedLock = boost::shared_lock<mutex_type>;
|
using SharedLock = boost::shared_lock<mutex_type>;
|
||||||
using UpgradeLock = boost::upgrade_lock<mutex_type>;
|
using UpgradeLock = boost::upgrade_lock<mutex_type>;
|
||||||
using UniqueLock = boost::unique_lock<mutex_type>;
|
using UniqueLock = boost::unique_lock<mutex_type>;
|
||||||
using UpgradeToUnique = boost::upgrade_to_unique_lock<mutex_type>;
|
using UpgradeToUnique = boost::upgrade_to_unique_lock<mutex_type>;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif // PHMAP_HAS_BOOST_THREAD_MUTEXES
|
||||||
|
|
||||||
|
|
||||||
} // phmap
|
} // phmap
|
||||||
|
|||||||
Reference in New Issue
Block a user