Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 41 additions & 25 deletions lib/base/registry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
#define REGISTRY_H

#include "base/i2-base.hpp"
#include "base/atomic.hpp"
#include "base/exception.hpp"
#include "base/string.hpp"
#include <boost/signals2.hpp>
#include <map>
#include "base/singleton.hpp"
#include <shared_mutex>
#include <stdexcept>
#include <unordered_map>
#include <mutex>

namespace icinga
Expand All @@ -17,22 +21,31 @@ namespace icinga
*
* @ingroup base
*/
template<typename U, typename T>
template<typename T>
class Registry
{
public:
typedef std::map<String, T> ItemMap;
typedef std::unordered_map<String, T> ItemMap;

static Registry* GetInstance()
{
return Singleton<Registry>::GetInstance();
}

void Register(const String& name, const T& item)
{
std::unique_lock<std::mutex> lock(m_Mutex);
std::unique_lock lock (m_Mutex);

if (m_Frozen) {
BOOST_THROW_EXCEPTION(std::logic_error("Registry is read-only and must not be modified."));
}

RegisterInternal(name, item, lock);
m_Items[name] = item;
}

T GetItem(const String& name) const
{
std::unique_lock<std::mutex> lock(m_Mutex);
auto lock (ReadLockUnlessFrozen());

auto it = m_Items.find(name);

Expand All @@ -44,33 +57,36 @@ class Registry

ItemMap GetItems() const
{
std::unique_lock<std::mutex> lock(m_Mutex);
auto lock (ReadLockUnlessFrozen());

return m_Items; /* Makes a copy of the map. */
}

boost::signals2::signal<void (const String&, const T&)> OnRegistered;
boost::signals2::signal<void (const String&)> OnUnregistered;

private:
mutable std::mutex m_Mutex;
typename Registry<U, T>::ItemMap m_Items;

void RegisterInternal(const String& name, const T& item, std::unique_lock<std::mutex>& lock)
/**
* Freeze the registry, preventing further updates.
*
* This only prevents inserting, replacing or deleting values from the registry.
* This operation has no effect on objects referenced by the values, these remain mutable if they were before.
*/
void Freeze()
{
bool old_item = false;

if (m_Items.erase(name) > 0)
old_item = true;
std::unique_lock lock (m_Mutex);

m_Items[name] = item;
m_Frozen.store(true);
}

lock.unlock();
private:
mutable std::shared_mutex m_Mutex;
Atomic<bool> m_Frozen {false};
ItemMap m_Items;

if (old_item)
OnUnregistered(name);
std::shared_lock<std::shared_mutex> ReadLockUnlessFrozen() const
{
if (m_Frozen.load(std::memory_order_relaxed)) {
return {};
}

OnRegistered(name, item);
return std::shared_lock(m_Mutex);
}
};

Expand Down
5 changes: 0 additions & 5 deletions lib/db_ido/dbtype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,3 @@ std::set<DbType::Ptr> DbType::GetAllTypes()

return result;
}

DbTypeRegistry *DbTypeRegistry::GetInstance()
{
return Singleton<DbTypeRegistry>::GetInstance();
}
12 changes: 0 additions & 12 deletions lib/db_ido/dbtype.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include "db_ido/i2-db_ido.hpp"
#include "base/object.hpp"
#include "base/registry.hpp"
#include "base/singleton.hpp"
#include <set>

namespace icinga
Expand Down Expand Up @@ -57,17 +56,6 @@ class DbType final : public Object
ObjectMap m_Objects;
};

/**
* A registry for DbType objects.
*
* @ingroup ido
*/
class DbTypeRegistry : public Registry<DbTypeRegistry, DbType::Ptr>
{
public:
static DbTypeRegistry *GetInstance();
};

/**
* Factory function for DbObject-based classes.
*
Expand Down
10 changes: 4 additions & 6 deletions lib/remote/apiaction.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */

#include "remote/apiaction.hpp"
#include "base/singleton.hpp"

using namespace icinga;

INITIALIZE_ONCE_WITH_PRIORITY([]{
ApiActionRegistry::GetInstance()->Freeze();
}, InitializePriority::FreezeNamespaces);

ApiAction::ApiAction(std::vector<String> types, Callback action)
: m_Types(std::move(types)), m_Callback(std::move(action))
{ }
Expand All @@ -28,8 +31,3 @@ void ApiAction::Register(const String& name, const ApiAction::Ptr& action)
{
ApiActionRegistry::GetInstance()->Register(name, action);
}

ApiActionRegistry *ApiActionRegistry::GetInstance()
{
return Singleton<ApiActionRegistry>::GetInstance();
}
6 changes: 1 addition & 5 deletions lib/remote/apiaction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,7 @@ class ApiAction final : public Object
*
* @ingroup remote
*/
class ApiActionRegistry : public Registry<ApiActionRegistry, ApiAction::Ptr>
{
public:
static ApiActionRegistry *GetInstance();
};
using ApiActionRegistry = Registry<ApiAction::Ptr>;

#define REGISTER_APIACTION(name, types, callback) \
INITIALIZE_ONCE([]() { \
Expand Down
10 changes: 4 additions & 6 deletions lib/remote/apifunction.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */

#include "remote/apifunction.hpp"
#include "base/singleton.hpp"

using namespace icinga;

INITIALIZE_ONCE_WITH_PRIORITY([]{
ApiFunctionRegistry::GetInstance()->Freeze();
}, InitializePriority::FreezeNamespaces);

ApiFunction::ApiFunction(const char* name, Callback function)
: m_Name(name), m_Callback(std::move(function))
{ }
Expand All @@ -23,8 +26,3 @@ void ApiFunction::Register(const String& name, const ApiFunction::Ptr& function)
{
ApiFunctionRegistry::GetInstance()->Register(name, function);
}

ApiFunctionRegistry *ApiFunctionRegistry::GetInstance()
{
return Singleton<ApiFunctionRegistry>::GetInstance();
}
6 changes: 1 addition & 5 deletions lib/remote/apifunction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,7 @@ class ApiFunction final : public Object
*
* @ingroup base
*/
class ApiFunctionRegistry : public Registry<ApiFunctionRegistry, ApiFunction::Ptr>
{
public:
static ApiFunctionRegistry *GetInstance();
};
using ApiFunctionRegistry = Registry<ApiFunction::Ptr>;

#define REGISTER_APIFUNCTION(name, ns, callback) \
INITIALIZE_ONCE([]() { \
Expand Down
6 changes: 0 additions & 6 deletions lib/remote/eventqueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include "remote/eventqueue.hpp"
#include "remote/filterutility.hpp"
#include "base/io-engine.hpp"
#include "base/singleton.hpp"
#include "base/logger.hpp"
#include "base/utility.hpp"
#include <boost/asio/spawn.hpp>
Expand Down Expand Up @@ -125,11 +124,6 @@ void EventQueue::Register(const String& name, const EventQueue::Ptr& function)
EventQueueRegistry::GetInstance()->Register(name, function);
}

EventQueueRegistry *EventQueueRegistry::GetInstance()
{
return Singleton<EventQueueRegistry>::GetInstance();
}

std::mutex EventsInbox::m_FiltersMutex;
std::map<String, EventsInbox::Filter> EventsInbox::m_Filters ({{"", EventsInbox::Filter{1, Expression::Ptr()}}});

Expand Down
6 changes: 1 addition & 5 deletions lib/remote/eventqueue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,7 @@ class EventQueue final : public Object
*
* @ingroup base
*/
class EventQueueRegistry : public Registry<EventQueueRegistry, EventQueue::Ptr>
{
public:
static EventQueueRegistry *GetInstance();
};
using EventQueueRegistry = Registry<EventQueue::Ptr>;

enum class EventType : uint_fast8_t
{
Expand Down
Loading