struct agent_event *agent_event;
struct ltt_ust_event fake_event;
- memset(&fake_event, 0, sizeof(fake_event));
agent_event = lttng::utils::container_of(node, &agent_event::node);
/*
{
int ret = 0, i;
- memset(output, 0, sizeof(struct snapshot_output));
-
/*
* max_size of -1ULL means unset. Set to default (unlimited).
*/
struct snapshot_output *snapshot_output_alloc()
{
- return zmalloc<snapshot_output>();
+ return new snapshot_output;
}
/*
consumer_output_send_destroy_relayd(obj->consumer);
consumer_output_put(obj->consumer);
}
- free(obj);
+
+ delete obj;
}
/*
struct consumer_output;
struct snapshot_output {
- uint32_t id;
- uint64_t max_size;
+ uint32_t id = 0;
+ uint64_t max_size = 0;
/* Number of snapshot taken with that output. */
- uint64_t nb_snapshot;
- char name[NAME_MAX];
- struct consumer_output *consumer;
- int kernel_sockets_copied;
- int ust_sockets_copied;
+ uint64_t nb_snapshot = 0;
+ char name[NAME_MAX] = {};
+ struct consumer_output *consumer = nullptr;
+ bool kernel_sockets_copied = false;
+ bool ust_sockets_copied = false;
/*
* Contains the string with "<date>-<time>" for when the snapshot command
* is triggered. This is to make sure every streams will use the same time
* for the directory output.
*/
- char datetime[16];
+ char datetime[16] = {};
/* Indexed by ID. */
- struct lttng_ht_node_ulong node;
+ struct lttng_ht_node_ulong node = {};
};
struct snapshot {
*/
static int match_str(struct cds_lfht_node *node, const void *key)
{
- struct lttng_ht_node_str *match_node =
- lttng::utils::container_of(node, <tng_ht_node_str::node);
+ auto *match_node = reinterpret_cast<lttng_ht_node_str *>(
+ lttng::utils::container_of(node, <tng_ht_node_str::node));
return hash_match_key_str(match_node->key, (void *) key);
}
*/
static int match_ulong(struct cds_lfht_node *node, const void *key)
{
- struct lttng_ht_node_ulong *match_node =
- lttng::utils::container_of(node, <tng_ht_node_ulong::node);
+ auto *match_node = reinterpret_cast<lttng_ht_node_ulong *>(
+ lttng::utils::container_of(node, <tng_ht_node_ulong::node));
return hash_match_key_ulong((void *) match_node->key, (void *) key);
}
*/
static int match_u64(struct cds_lfht_node *node, const void *key)
{
- struct lttng_ht_node_u64 *match_node =
- lttng::utils::container_of(node, <tng_ht_node_u64::node);
+ auto *match_node = reinterpret_cast<lttng_ht_node_u64 *>(
+ lttng::utils::container_of(node, <tng_ht_node_u64::node));
return hash_match_key_u64(&match_node->key, (void *) key);
}
*/
static int match_two_u64(struct cds_lfht_node *node, const void *key)
{
- struct lttng_ht_node_two_u64 *match_node =
- lttng::utils::container_of(node, <tng_ht_node_two_u64::node);
+ auto *match_node = reinterpret_cast<lttng_ht_node_two_u64 *>(
+ lttng::utils::container_of(node, <tng_ht_node_two_u64::node));
return hash_match_key_two_u64((void *) &match_node->key, (void *) key);
}
if (!node_ptr) {
return nullptr;
} else {
- return lttng::utils::container_of(node_ptr, <tng_ht_node_ulong::node);
+ return reinterpret_cast<lttng_ht_node_ulong *>(
+ lttng::utils::container_of(node_ptr, <tng_ht_node_ulong::node));
}
}
return nullptr;
} else {
LTTNG_ASSERT(node_ptr == &node->node);
- return lttng::utils::container_of(node_ptr, <tng_ht_node_u64::node);
+ return reinterpret_cast<lttng_ht_node_u64 *>(
+ lttng::utils::container_of(node_ptr, <tng_ht_node_u64::node));
}
}
struct cds_lfht_iter iter;
};
-struct lttng_ht_node_str {
- char *key;
+struct lttng_ht_node {
struct cds_lfht_node node;
+};
+
+struct lttng_ht_node_str : public lttng_ht_node {
+ char *key;
struct rcu_head head;
};
-struct lttng_ht_node_ulong {
+struct lttng_ht_node_ulong : public lttng_ht_node {
unsigned long key;
- struct cds_lfht_node node;
struct rcu_head head;
};
-struct lttng_ht_node_u64 {
+struct lttng_ht_node_u64 : public lttng_ht_node {
uint64_t key;
- struct cds_lfht_node node;
struct rcu_head head;
};
uint64_t key2;
};
-struct lttng_ht_node_two_u64 {
+struct lttng_ht_node_two_u64 : public lttng_ht_node {
struct lttng_ht_two_u64 key;
- struct cds_lfht_node node;
struct rcu_head head;
};
return nullptr;
}
- return lttng::utils::container_of(node, &NodeType::node);
+ return reinterpret_cast<NodeType *>(lttng::utils::container_of(node, &NodeType::node));
+}
+
+template <class ParentType, class NodeType>
+ParentType *lttng_ht_node_container_of(cds_lfht_node *node, const NodeType ParentType::*Member)
+{
+ /*
+ * The node member is within lttng_ht_node, the parent class of all ht wrapper nodes. We
+ * compute the address of the ht wrapper node from the native lfht node.
+ */
+ auto *wrapper_node = lttng::utils::container_of(node, &NodeType::node);
+
+ /* Knowing the address of the wrapper node, we can get that of the contained type. */
+ return lttng::utils::container_of(static_cast<NodeType *>(wrapper_node), Member);
}
#endif /* _LTT_HT_H */
#define LTTNG_URCU_H
#define _LGPL_SOURCE
+#include <common/exception.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/macros.hpp>
+
+#include <iterator>
#include <mutex>
#include <urcu.h>
+#include <urcu/rculfhash.h>
namespace lttng {
namespace urcu {
using unique_read_lock = std::unique_lock<details::read_lock>;
+namespace details {
+
+/* Implementation for types that contain a straight cds_lfht_node. */
+template <typename ContainedType, typename NodeType, NodeType ContainedType::*Member>
+static typename std::enable_if<std::is_same<cds_lfht_node, NodeType>::value, ContainedType *>::type
+get_element_from_node(cds_lfht_node& node)
+{
+ return lttng::utils::container_of(&node, Member);
+}
+
+/* Specialization for NodeType deriving from lttng_ht_node. */
+template <typename ContainedType, typename NodeType, NodeType ContainedType::*Member>
+static typename std::enable_if<std::is_base_of<lttng_ht_node, NodeType>::value, ContainedType *>::type
+get_element_from_node(cds_lfht_node& node)
+{
+ return lttng_ht_node_container_of(&node, Member);
+}
+} /* namespace details */
+
+/*
+ * The lfht_iteration_adapter class template wraps the liburcu lfht API to provide iteration
+ * capabilities. It allows users to iterate over a lock-free hash table 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 <typename ContainedType, typename NodeType, NodeType ContainedType::*Member>
+class lfht_iteration_adapter {
+public:
+ /* Nested iterator class defines the iterator for lfht_iteration_adapter. */
+ class iterator : public std::iterator<std::input_iterator_tag, std::uint64_t> {
+ /* Allow lfht_iteration_adapter to access private members of iterator_base. */
+ friend lfht_iteration_adapter;
+
+ public:
+ iterator(const iterator& other) = default;
+ iterator(iterator&& other) noexcept = default;
+ ~iterator() = default;
+
+ /* Move to the next element in the hash table. */
+ iterator& operator++()
+ {
+ cds_lfht_next(&_ht, &_it);
+ return *this;
+ }
+
+ bool operator==(const iterator& other) const noexcept
+ {
+ /* Compare pointed nodes by address. */
+ return other._it.node == _it.node;
+ }
+
+ bool operator!=(const iterator& other) const noexcept
+ {
+ return !(*this == other);
+ }
+
+ /* Dereference the iterator to access the contained element. */
+ ContainedType *operator*() const
+ {
+ auto *node = _it.node;
+
+ /* Throw an exception if dereferencing an end iterator. */
+ if (!node) {
+ LTTNG_THROW_OUT_OF_RANGE(
+ "Dereferenced an iterator at the end of a liburcu hashtable");
+ }
+
+ /* Retrieve the element from the node. */
+ return details::get_element_from_node<ContainedType, NodeType, Member>(
+ *node);
+ }
+
+ private:
+ iterator(cds_lfht& ht, const cds_lfht_iter& it) : _ht(ht), _it(it)
+ {
+ }
+
+ /* Reference to the hash table being iterated over. */
+ cds_lfht& _ht;
+ /* Native lfht iterator pointing to the current position. */
+ cds_lfht_iter _it;
+ };
+
+ explicit lfht_iteration_adapter(cds_lfht& ht) : _ht(ht)
+ {
+ }
+
+ /* Return an iterator to the beginning of the hash table. */
+ iterator begin() const noexcept
+ {
+ cds_lfht_iter it;
+
+ cds_lfht_first(&_ht, &it);
+ return iterator(_ht, it);
+ }
+
+ /* Return an iterator to the end of the hash table. */
+ iterator end() const noexcept
+ {
+ const cds_lfht_iter it = {};
+
+ return iterator(_ht, it);
+ }
+
+private:
+ /* 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;
+};
+
} /* namespace urcu */
} /* namespace lttng */