#if OPENSSL_VERSION_NUMBER < 0x10100000L
static std::atomic_uint32_t crypto_refs;
-static std::vector<ceph::shared_mutex> ssl_mutexes {
- static_cast<size_t>(std::max(CRYPTO_num_locks(), 0))
-};
+
+static auto ssl_mutexes = ceph::make_lock_container<ceph::shared_mutex>(
+ static_cast<size_t>(std::max(CRYPTO_num_locks(), 0)),
+ [](const size_t i) {
+ return ceph::make_shared_mutex(
+ std::string("ssl-mutex-") + std::to_string(i));
+ });
static struct {
// we could use e.g. unordered_set instead at the price of providing
#pragma once
+#include <utility>
+#include "common/containers.h"
+
// What and why
// ============
//
return {};
}
+ template <typename ...Args>
+ shared_mutex make_shared_mutex(Args&& ...args) {
+ return {};
+ }
+
#define ceph_mutex_is_locked(m) true
#define ceph_mutex_is_locked_by_me(m) true
}
#endif // CEPH_DEBUG_MUTEX
#endif // WITH_SEASTAR
+
+namespace ceph {
+
+template <class LockT,
+ class LockFactoryT>
+ceph::containers::tiny_vector<LockT> make_lock_container(
+ const std::size_t num_instances,
+ LockFactoryT&& lock_factory)
+{
+ return {
+ num_instances, [&](const std::size_t i, auto emplacer) {
+ // this will be called `num_instances` times
+ new (emplacer.data()) LockT {lock_factory(i)};
+ }
+ };
+}
+} // namespace ceph
+
// 4. std::unique_ptr<ValueT>: extra indirection together with memory
// fragmentation.
-template<typename Value, std::size_t InternalCapacity>
+template<typename Value, std::size_t InternalCapacity = 0>
class tiny_vector {
// NOTE: to avoid false sharing consider aligning to cache line
using storage_unit_t = \
// }
// }
// ```
+ //
+ // For the sake of supporting the ceph::make_mutex() family of
+ // factories, which relies on C++17's guaranteed copy elision,
+ // the emplacer provides `data()` to retrieve the location for
+ // constructing the instance with placement-new. This is handy
+ // as the `emplace()` depends on perfect forwarding, and thus
+ // interfere with the elision for cases like:
+ // ```
+ // emplacer.emplace(ceph::make_mutex("mtx-name"));
+ // ```
+ // See: https://stackoverflow.com/a/52498826
class emplacer {
friend class tiny_vector;
}
public:
+ void* data() {
+ void* const ret = &parent->data[parent->_size++];
+ parent = nullptr;
+ return ret;
+ }
+
template<class... Args>
void emplace(Args&&... args) {
- if (!parent) {
- return;
+ if (parent) {
+ new (data()) Value(std::forward<Args>(args)...);
}
- new (&parent->data[parent->_size++]) Value(std::forward<Args>(args)...);
- parent = nullptr;
}
};