Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♪ Any singleton will do #20273

Merged
merged 2 commits into from
Feb 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/common/TracepointProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

struct md_config_t;

class TracepointProvider : public md_config_obs_t, boost::noncopyable {
class TracepointProvider : public md_config_obs_t {
public:
struct Traits {
const char *library;
Expand Down Expand Up @@ -49,11 +49,16 @@ class TracepointProvider : public md_config_obs_t, boost::noncopyable {
const char *config_key);
~TracepointProvider() override;

TracepointProvider(const TracepointProvider&) = delete;
TracepointProvider operator =(const TracepointProvider&) = delete;
TracepointProvider(TracepointProvider&&) = delete;
TracepointProvider operator =(TracepointProvider&&) = delete;

template <const Traits &traits>
static void initialize(CephContext *cct) {
#ifdef WITH_LTTNG
TypedSingleton<traits> *singleton;
cct->lookup_or_create_singleton_object(singleton, traits.library);
cct->lookup_or_create_singleton_object<TypedSingleton<traits>>(
traits.library, cct);
#endif
}

Expand Down
8 changes: 2 additions & 6 deletions src/common/ceph_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -639,18 +639,14 @@ CephContext::CephContext(uint32_t module_type_,
_crypto_aes = CryptoHandler::create(CEPH_CRYPTO_AES);
_crypto_random.reset(new CryptoRandom());

MempoolObs *mempool_obs = 0;
lookup_or_create_singleton_object(mempool_obs, "mempool_obs");
lookup_or_create_singleton_object<MempoolObs>("mempool_obs", this);
}

CephContext::~CephContext()
{
associated_objs.clear();
join_service_thread();

for (map<string, SingletonWrapper*>::iterator it = _associated_objs.begin();
it != _associated_objs.end(); ++it)
delete it->second;

if (_cct_perf) {
_perf_counters_collection->remove(_cct_perf);
delete _cct_perf;
Expand Down
81 changes: 48 additions & 33 deletions src/common/ceph_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@
#ifndef CEPH_CEPHCONTEXT_H
#define CEPH_CEPHCONTEXT_H

#include <set>
#include <atomic>
#include <map>
#include <memory>
#include <mutex>
#include <atomic>
#include <set>
#include <string>
#include <string_view>
#include <typeinfo>
#include <typeindex>

#include <boost/noncopyable.hpp>
#include "include/any.h"

#include "common/cmdparse.h"
#include "common/code_environment.h"
Expand Down Expand Up @@ -61,6 +66,11 @@ class CephContext {
enum code_environment_t code_env=CODE_ENVIRONMENT_UTILITY,
int init_flags_ = 0);

CephContext(const CephContext&) = delete;
CephContext& operator =(const CephContext&) = delete;
CephContext(CephContext&&) = delete;
CephContext& operator =(CephContext&&) = delete;

// ref count!
private:
~CephContext();
Expand Down Expand Up @@ -129,20 +139,28 @@ class CephContext {
void do_command(std::string command, cmdmap_t& cmdmap, std::string format,
ceph::bufferlist *out);

template<typename T>
void lookup_or_create_singleton_object(T*& p, const std::string &name) {
std::lock_guard<ceph::spinlock> lg(_associated_objs_lock);

if (!_associated_objs.count(name)) {
p = new T(this);
_associated_objs[name] = new TypedSingletonWrapper<T>(p);
} else {
TypedSingletonWrapper<T> *wrapper =
dynamic_cast<TypedSingletonWrapper<T> *>(_associated_objs[name]);
assert(wrapper != NULL);
p = wrapper->singleton;
static constexpr std::size_t largest_singleton = sizeof(void*) * 72;

template<typename T, typename... Args>
T& lookup_or_create_singleton_object(std::string_view name,
Args&&... args) {
static_assert(sizeof(T) <= largest_singleton,
"Please increase largest singleton.");
std::lock_guard lg(associated_objs_lock);
std::type_index type = typeid(T);

auto i = associated_objs.find(std::make_pair(name, type));
if (i == associated_objs.cend()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, trying to add a duplicate is /not/ a failure.

i = associated_objs.emplace_hint(
i,
std::piecewise_construct,
std::forward_as_tuple(name, type),
std::forward_as_tuple(std::in_place_type<T>,
std::forward<Args>(args)...));
}
return ceph::any_cast<T&>(i->second);
}

/**
* get a crypto handler
*/
Expand Down Expand Up @@ -206,23 +224,7 @@ class CephContext {
}

private:
struct SingletonWrapper : boost::noncopyable {
virtual ~SingletonWrapper() {}
};

template <typename T>
struct TypedSingletonWrapper : public SingletonWrapper {
TypedSingletonWrapper(T *p) : singleton(p) {
}
~TypedSingletonWrapper() override {
delete singleton;
}

T *singleton;
};

CephContext(const CephContext &rhs);
CephContext &operator=(const CephContext &rhs);

/* Stop and join the Ceph Context's service thread */
void join_service_thread();
Expand Down Expand Up @@ -260,8 +262,21 @@ class CephContext {

ceph::HeartbeatMap *_heartbeat_map;

ceph::spinlock _associated_objs_lock;
std::map<std::string, SingletonWrapper*> _associated_objs;
ceph::spinlock associated_objs_lock;

struct associated_objs_cmp {
using is_transparent = std::true_type;
template<typename T, typename U>
bool operator ()(const std::pair<T, std::type_index>& l,
const std::pair<U, std::type_index>& r) const noexcept {
return ((l.first < r.first) ||
(l.first == r.first && l.second < r.second));
}
};

std::map<std::pair<std::string, std::type_index>,
ceph::immobile_any<largest_singleton>,
associated_objs_cmp> associated_objs;

ceph::spinlock _fork_watchers_lock;
std::vector<ForkWatcher*> _fork_watchers;
Expand Down