concurrency_util: Mutex wrapper

This commit is contained in:
Michael Carlberg 2016-12-26 10:33:23 +01:00
parent f80d8ebf5b
commit 334c454eec
2 changed files with 61 additions and 52 deletions

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <atomic> #include <atomic>
#include <chrono>
#include <map> #include <map>
#include <mutex> #include <mutex>
#include <thread> #include <thread>
@ -10,6 +11,8 @@
POLYBAR_NS POLYBAR_NS
namespace chrono =std::chrono;
using namespace std::chrono_literals;
namespace this_thread = std::this_thread; namespace this_thread = std::this_thread;
using std::atomic; using std::atomic;
@ -17,32 +20,18 @@ using std::map;
using std::mutex; using std::mutex;
using std::thread; using std::thread;
namespace concurrency_util {
namespace locking_strategy {
struct no_backoff {
bool operator()() {
return true;
}
};
struct yield_backoff {
bool operator()() {
this_thread::yield();
return false;
}
};
}
class spin_lock : public non_copyable_mixin<spin_lock> { class spin_lock : public non_copyable_mixin<spin_lock> {
public: public:
/** struct no_backoff_strategy {
* Construct spin_lock bool operator()();
*/ };
spin_lock() = default; struct yield_backoff_strategy {
bool operator()();
};
public:
explicit spin_lock() = default;
/**
* Lock using custom strategy
*/
template <typename Backoff> template <typename Backoff>
void lock(Backoff backoff) noexcept { void lock(Backoff backoff) noexcept {
while (m_locked.test_and_set(std::memory_order_acquire)) { while (m_locked.test_and_set(std::memory_order_acquire)) {
@ -50,24 +39,31 @@ namespace concurrency_util {
} }
} }
/** void lock() noexcept;
* Lock using default strategy void unlock() noexcept;
*/
void lock() noexcept {
lock(locking_strategy::no_backoff{});
}
/**
* Unlock
*/
void unlock() noexcept {
m_locked.clear(std::memory_order_release);
}
protected: protected:
std::atomic_flag m_locked{false}; std::atomic_flag m_locked{false};
}; };
template <typename T>
class mutex_wrapper : public T {
public:
template <typename... Args>
explicit mutex_wrapper(Args&&... args) : T(forward<Args>(args)...) {}
void lock() const noexcept {
m_mtx.lock();
}
void unlock() const noexcept {
m_mtx.unlock();
};
private:
mutable mutex m_mtx;
};
namespace concurrency_util {
size_t thread_id(const thread::id id); size_t thread_id(const thread::id id);
} }

View File

@ -2,12 +2,25 @@
POLYBAR_NS POLYBAR_NS
bool spin_lock::no_backoff_strategy::operator()() {
return true;
}
bool spin_lock::yield_backoff_strategy::operator()() {
this_thread::yield();
return false;
}
void spin_lock::lock() noexcept {
lock(no_backoff_strategy{});
}
void spin_lock::unlock() noexcept {
m_locked.clear(std::memory_order_release);
}
namespace concurrency_util { namespace concurrency_util {
size_t thread_id(const thread::id id) { size_t thread_id(const thread::id id) {
static size_t idx{1_z}; static size_t idx{1_z};
static mutex mtx; static mutex_wrapper<map<thread::id, size_t>> ids;
static map<thread::id, size_t> ids; std::lock_guard<decltype(ids)> lock(ids);
std::lock_guard<mutex> lock(mtx);
if (ids.find(id) == ids.end()) { if (ids.find(id) == ids.end()) {
ids[id] = idx++; ids[id] = idx++;
} }