C++ bindings for libpmemobj (part 7) - synchronization primitives

Posted May 31, 2016         « Previous post     Next post »

To finish off the C++ bindings to libpmemobj blog marathon, I will introduce to you the synchronization mechanisms we implemented. They are mostly C++11-like implementations of different kinds of mutexes and the condition variable. They satisfy their respective concepts (Mutex, SharedMutex and so on), the difference is that they are based on the persistent memory resident synchronization primitives provided by libpmemobj.

Mutex

The nvml::obj::mutex class satisfies the requirements of the Mutex and StandardLayoutType concepts. The usage of this class should be really straightforward for anyone who has ever used the std::mutex. The only difference is that the nvml::obj::mutex has to be placed in persistent memory, within a libpmemobj pool. This is because the implementation needs to be able to reset the mutex the next time the pool is opened after a power failure/crash. In persistent memory, the mutex would not be reinitialized automatically in such case.

You can use the nvml::obj::mutex with standard wrapper classes like:

1
2
3
4
5
nvml::obj::mutex pmutex;
{
  std::lock_guard<nvml::obj::mutex> lock(pmutex);
}
std::unique_lock<nvml::obj::mutex> lock(pmutex);

Shared Mutex and Timed Mutex

The nvml::obj::shared_mutex and nvml::obj::timed_mutex are also very similar to their std counterparts. They also satisfy their respective SharedMutex and TimedMutex as well as the StandardLayoutType concepts. Their usage is also very straightforward:

1
2
3
4
5
6
7
8
9
nvml::obj::shared_mutex smutex;
nvml::obj::timed_mutex tmutex;
{
  std::shared_lock<nvml::obj::shared_mutex> lock(smutex);
}
std::unique_lock<nvml::obj::shared_mutex> lock(smutex);

tmutex.try_lock_for(std::chrono::milliseconds(100));
std::unique_lock<nvml::obj::timed_mutex> lock(tmutex);

The nvml::obj::shared_mutex and nvml::obj::timed_mutex are persistent memory resident synchronization mechanisms.

Condition Variable

The nvml::obj::condition_variable, as you probably by now noticed, is pretty much the standard std::condition_variable, with the exception of it being persistent memory resident. The usage is also very similar:

1
2
3
4
5
6
nvml::obj::mutex pmutex;
nvml::obj::condition_variable cond;
pmutex.lock();
cond.wait(proot->pmutex, [&]() { /* check condition here */ });
// do some meaningful work here
pmutex.unlock();

With this we have ended the introduction to the core classes and functions of the C++ bindings to libpmemobj. If you ever find yourself in doubt about the usage of the C++ bindings or NVML in general, don’t hesitate to send us a message on our Google Group.



Posted by @tomaszkapela         « Previous post     Next post »