From: Remi Gacogne Date: Wed, 16 Jun 2021 15:41:26 +0000 (+0200) Subject: Document how our wrappers around mutexes work X-Git-Tag: dnsdist-1.7.0-alpha1~62^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ffb924354db23fde48fd426e4d7a681c3ae13b14;p=thirdparty%2Fpdns.git Document how our wrappers around mutexes work --- diff --git a/pdns/lock.hh b/pdns/lock.hh index d49bb7a3f7..1b60d46a5e 100644 --- a/pdns/lock.hh +++ b/pdns/lock.hh @@ -23,6 +23,60 @@ #include #include +/* + 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> d_data; + + or with a shared mutex instead: + + SharedLockGuarded> 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: