From: Jérémie Galarneau Date: Mon, 29 Jul 2024 20:23:47 +0000 (+0000) Subject: urcu: add lfht_filtered_iteration_adapter helper X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=8d1de59a75d02123cfd69e3e18dd841c688881fe;p=lttng-tools.git urcu: add lfht_filtered_iteration_adapter helper The urcu lfht macros often make use of caa_container_of (and other equivalent variations) which use offsetof. Unfortunately, offsetof is conditionally supported by compilers for non-POD types. The tree already has lttng::utils::container_of to work around this problem. This new utils makes it possible to iterate on the elements of an lfht that match a given key without using those macros. Those iterations are the main reason such warnings are emitted. The interface of lfht_filtered_iteration_adapter also allows the use of ranged-for loops. Change-Id: I9acd3fa9f6523de8006bc9107bcca6b6b654d6fa Signed-off-by: Jérémie Galarneau --- diff --git a/src/common/urcu.hpp b/src/common/urcu.hpp index efd2dc759..659e3c3d0 100644 --- a/src/common/urcu.hpp +++ b/src/common/urcu.hpp @@ -111,7 +111,7 @@ class lfht_iteration_adapter { public: /* Nested iterator class defines the iterator for lfht_iteration_adapter. */ class iterator : public std::iterator { - /* Allow lfht_iteration_adapter to access private members of iterator_base. */ + /* Allow lfht_iteration_adapter to access private members of iterator. */ friend lfht_iteration_adapter; public: @@ -155,7 +155,7 @@ public: *node); } - private: + protected: iterator(cds_lfht& ht, const cds_lfht_iter& it) : _ht(ht), _it(it) { } @@ -187,13 +187,112 @@ public: return iterator(_ht, it); } -private: +protected: /* Reference to the hash table being iterated over. */ cds_lfht& _ht; /* RCU read lock held during the iteration. */ const lttng::urcu::read_lock_guard read_lock; }; +/* + * The lfht_filtered_iteration_adapter class template wraps the liburcu lfht API to provide + * iteration capabilities over a result set. It allows users to iterate over a lock-free hash + * table's elements matching a given key with ranged-for semantics while holding the RCU read lock. + * The reader lock is held for the lifetime of the iteration adapter (i.e. not the lifetime of the + * iterators it provides). + */ +template +class lfht_filtered_iteration_adapter + : public lfht_iteration_adapter { +public: + /* Nested iterator class defines the iterator for lfht_filtered_iteration_adapter. */ + class iterator : public lfht_iteration_adapter::iterator { + /* Allow lfht_filtered_iteration_adapter to access private members of iterator. */ + friend lfht_filtered_iteration_adapter; + + public: + iterator(const iterator& other) = default; + iterator(iterator&& other) noexcept = default; + ~iterator() = default; + iterator& operator=(const iterator&) = delete; + iterator& operator=(iterator&&) noexcept = delete; + + /* Move to the next element in the result set. */ + iterator& operator++() + { + LTTNG_ASSERT(this->_it.node); + /* NOLINTBEGIN(cppcoreguidelines-pro-type-const-cast) */ + cds_lfht_next_duplicate( + &this->_ht, + _match_function, + reinterpret_cast(const_cast(_key)), + &this->_it); + /* NOLINTEND(cppcoreguidelines-pro-type-const-cast) */ + return *this; + } + + private: + iterator(cds_lfht& ht, + const cds_lfht_iter& it, + const KeyType *key, + cds_lfht_match_fct match_function) : + lfht_iteration_adapter::iterator(ht, it), + _key(key), + _match_function(match_function) + { + } + + /* Only used to create an end iterator. */ + iterator(cds_lfht& ht, const cds_lfht_iter& it) : + lfht_iteration_adapter::iterator(ht, it), + _key(nullptr), + _match_function(nullptr) + { + } + + const KeyType *_key; + const cds_lfht_match_fct _match_function; + }; + + explicit lfht_filtered_iteration_adapter(cds_lfht& ht, + const KeyType *key, + unsigned long key_hash, + cds_lfht_match_fct match_function) : + lfht_iteration_adapter(ht), + _key(key), + _key_hash(key_hash), + _match_function(match_function) + { + } + + /* Return an iterator to the first result. */ + iterator begin() const noexcept + { + cds_lfht_iter it; + + /* NOLINTBEGIN(cppcoreguidelines-pro-type-const-cast) */ + cds_lfht_lookup(&this->_ht, + _key_hash, + _match_function, + reinterpret_cast(const_cast(_key)), + &it); + /* NOLINTEND(cppcoreguidelines-pro-type-const-cast) */ + return iterator(this->_ht, it, _key, _match_function); + } + + iterator end() const noexcept + { + const cds_lfht_iter it = {}; + + return iterator(this->_ht, it); + } + +private: + const KeyType *_key; + const unsigned long _key_hash; + const cds_lfht_match_fct _match_function; +}; + } /* namespace urcu */ } /* namespace lttng */