Skip to content

Instantly share code, notes, and snippets.

@tmattio
Created September 21, 2016 15:10
Show Gist options
  • Save tmattio/1072f07b4e1e2cdfffd14ce7d133e97d to your computer and use it in GitHub Desktop.
Save tmattio/1072f07b4e1e2cdfffd14ce7d133e97d to your computer and use it in GitHub Desktop.
#pragma once
#include <atomic>
#include <condition_variable>
/// A mutex guaranted noexcept that can be used in destructors.
/// See:
/// http://stackoverflow.com/questions/16568990/locking-a-mutex-in-a-destructor-in-c11
template <class Tp_ = std::mutex>
class nothrow_mutex {
public:
nothrow_mutex() noexcept : mutex_(), flag_(), both_(false) {
flag_.clear(std::memory_order_release);
}
~nothrow_mutex() = default;
nothrow_mutex(const nothrow_mutex&) = delete;
nothrow_mutex& operator=(const nothrow_mutex&) = delete;
auto lock() noexcept {
try {
mutex_.lock();
while (flag_.test_and_set(std::memory_order_acquire)) both_ = true;
} catch (...) {
while (flag_.test_and_set(std::memory_order_acquire)) both_ = false;
}
}
auto unlock() noexcept {
if (both_) {
mutex_.unlock();
}
flag_.clear(std::memory_order_release);
}
private:
Tp_ mutex_;
std::atomic_flag flag_;
bool both_;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment