]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Document how our wrappers around mutexes work
authorRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 16 Jun 2021 15:41:26 +0000 (17:41 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 17 Aug 2021 12:10:34 +0000 (14:10 +0200)
pdns/lock.hh

index d49bb7a3f73da3f400d05d395ee133f4cc529e92..1b60d46a5e315bbba8b7a6498407a3983b88dd57 100644 (file)
 #include <mutex>
 #include <shared_mutex>
 
+/*
+  This file provides several features around locks:
+
+  - LockGuarded and SharedLockGuarded provide a way to wrap any data structure as
+  protected by a lock (mutex or shared mutex), while making it immediately clear
+  which data is protected by that lock, and preventing any access to the data without
+  holding the lock.
+
+  For example, to protect a set of integers with a simple mutex:
+
+  LockGuarded<std::set<int>> d_data;
+
+  or with a shared mutex instead:
+
+  SharedLockGuarded<std::set<int>> d_data;
+
+  Then the only ways to access the data is to call the lock(), read_only_lock() or try_lock() methods
+  for the simple case, or the read_lock(), write_lock(), try_read_lock() or try_write_lock() for the
+  shared one.
+  Doing so will return a "holder" object, which provides access to the protected data, checking that
+  the lock has really been acquired if needed (try_ cases). The data might be read-only if read_lock(),
+  try_read_lock() or read_only_lock() was called. Access is provided by dereferencing the holder object
+  via '*' or '->', allowing a quick-access syntax:
+
+  return d_data.lock()->size();
+
+  Or when the lock needs to be kept for a bit longer:
+
+  {
+    auto data = d_data.lock();
+    data->clear();
+    data->insert(42);
+  }
+
+  - ReadWriteLock is a very light wrapper around a std::shared_mutex.
+  It used to be useful as a RAII wrapper around pthread_rwlock, but since
+  C++17 we don't actually that, so it's mostly there for historical
+  reasons.
+
+  - ReadLock, WriteLock, TryReadLock and TryWriteLock are there as RAII
+  objects allowing to take a lock and be sure that it will always be unlocked
+  when we exit the block, even with a unforeseen exception.
+  They are light wrappers around std::unique_lock and std::shared_lock
+  since C++17.
+
+  Note that while the use of a shared mutex might be very efficient when the data
+  is predominantly concurrently accessed for reading by multiple threads and not
+  often written to (although if it is almost never updated our StateHolder in
+  sholder.hh might be a better fit), it is significantly more expensive than
+  a regular mutex, so that one might be a better choice if the contention is
+  low. It is wise to start with a regular mutex and actually measure the contention
+  under load before switching to a shared mutex.
+ */
+
 class ReadWriteLock
 {
 public: