add support for absl::Mutex

This commit is contained in:
greg
2019-04-13 20:22:13 -04:00
parent 9f5a7a37f0
commit bbc746d34a
3 changed files with 164 additions and 64 deletions
+1 -6
View File
@@ -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
View File
@@ -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());
+158 -57
View File
@@ -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