mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-23 13:45:04 +02:00
Merge pull request #9606 from Icinga/initialize-once
INITIALIZE_ONCE_WITH_PRIORITY: use enum for priority values and use std::function
This commit is contained in:
commit
a0286e9c64
@ -61,28 +61,28 @@ private:
|
|||||||
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), false); \
|
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), false); \
|
||||||
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
|
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
|
||||||
nsp->SetAttribute(#name, new ConstEmbeddedNamespaceValue(sf)); \
|
nsp->SetAttribute(#name, new ConstEmbeddedNamespaceValue(sf)); \
|
||||||
}, 10)
|
}, InitializePriority::RegisterFunctions)
|
||||||
|
|
||||||
#define REGISTER_SAFE_FUNCTION(ns, name, callback, args) \
|
#define REGISTER_SAFE_FUNCTION(ns, name, callback, args) \
|
||||||
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
|
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
|
||||||
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), true); \
|
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), true); \
|
||||||
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
|
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
|
||||||
nsp->SetAttribute(#name, new ConstEmbeddedNamespaceValue(sf)); \
|
nsp->SetAttribute(#name, new ConstEmbeddedNamespaceValue(sf)); \
|
||||||
}, 10)
|
}, InitializePriority::RegisterFunctions)
|
||||||
|
|
||||||
#define REGISTER_FUNCTION_NONCONST(ns, name, callback, args) \
|
#define REGISTER_FUNCTION_NONCONST(ns, name, callback, args) \
|
||||||
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
|
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
|
||||||
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), false); \
|
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), false); \
|
||||||
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
|
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
|
||||||
nsp->SetAttribute(#name, new EmbeddedNamespaceValue(sf)); \
|
nsp->SetAttribute(#name, new EmbeddedNamespaceValue(sf)); \
|
||||||
}, 10)
|
}, InitializePriority::RegisterFunctions)
|
||||||
|
|
||||||
#define REGISTER_SAFE_FUNCTION_NONCONST(ns, name, callback, args) \
|
#define REGISTER_SAFE_FUNCTION_NONCONST(ns, name, callback, args) \
|
||||||
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
|
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
|
||||||
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), true); \
|
Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), true); \
|
||||||
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
|
Namespace::Ptr nsp = ScriptGlobal::Get(#ns); \
|
||||||
nsp->SetAttribute(#name, new EmbeddedNamespaceValue(sf)); \
|
nsp->SetAttribute(#name, new EmbeddedNamespaceValue(sf)); \
|
||||||
}, 10)
|
}, InitializePriority::RegisterFunctions)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
bool icinga::InitializeOnceHelper(void (*func)(), int priority)
|
bool icinga::InitializeOnceHelper(const std::function<void()>& func, InitializePriority priority)
|
||||||
{
|
{
|
||||||
Loader::AddDeferredInitializer(func, priority);
|
Loader::AddDeferredInitializer(func, priority);
|
||||||
return true;
|
return true;
|
||||||
|
@ -4,16 +4,35 @@
|
|||||||
#define INITIALIZE_H
|
#define INITIALIZE_H
|
||||||
|
|
||||||
#include "base/i2-base.hpp"
|
#include "base/i2-base.hpp"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace icinga
|
namespace icinga
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Priority values for use with the INITIALIZE_ONCE_WITH_PRIORITY macro.
|
||||||
|
*
|
||||||
|
* The values are given in the order of initialization.
|
||||||
|
*/
|
||||||
|
enum class InitializePriority {
|
||||||
|
CreateNamespaces,
|
||||||
|
InitIcingaApplication,
|
||||||
|
RegisterTypeType,
|
||||||
|
RegisterObjectType,
|
||||||
|
RegisterPrimitiveTypes,
|
||||||
|
RegisterBuiltinTypes,
|
||||||
|
RegisterFunctions,
|
||||||
|
RegisterTypes,
|
||||||
|
EvaluateConfigFragments,
|
||||||
|
Default,
|
||||||
|
};
|
||||||
|
|
||||||
#define I2_TOKENPASTE(x, y) x ## y
|
#define I2_TOKENPASTE(x, y) x ## y
|
||||||
#define I2_TOKENPASTE2(x, y) I2_TOKENPASTE(x, y)
|
#define I2_TOKENPASTE2(x, y) I2_TOKENPASTE(x, y)
|
||||||
|
|
||||||
#define I2_UNIQUE_NAME(prefix) I2_TOKENPASTE2(prefix, __COUNTER__)
|
#define I2_UNIQUE_NAME(prefix) I2_TOKENPASTE2(prefix, __COUNTER__)
|
||||||
|
|
||||||
bool InitializeOnceHelper(void (*func)(), int priority = 0);
|
bool InitializeOnceHelper(const std::function<void()>& func, InitializePriority priority = InitializePriority::Default);
|
||||||
|
|
||||||
#define INITIALIZE_ONCE(func) \
|
#define INITIALIZE_ONCE(func) \
|
||||||
namespace { namespace I2_UNIQUE_NAME(io) { \
|
namespace { namespace I2_UNIQUE_NAME(io) { \
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
boost::thread_specific_ptr<std::priority_queue<DeferredInitializer> >& Loader::GetDeferredInitializers()
|
boost::thread_specific_ptr<Loader::DeferredInitializerPriorityQueue>& Loader::GetDeferredInitializers()
|
||||||
{
|
{
|
||||||
static boost::thread_specific_ptr<std::priority_queue<DeferredInitializer> > initializers;
|
static boost::thread_specific_ptr<DeferredInitializerPriorityQueue> initializers;
|
||||||
return initializers;
|
return initializers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,10 +25,10 @@ void Loader::ExecuteDeferredInitializers()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Loader::AddDeferredInitializer(const std::function<void()>& callback, int priority)
|
void Loader::AddDeferredInitializer(const std::function<void()>& callback, InitializePriority priority)
|
||||||
{
|
{
|
||||||
if (!GetDeferredInitializers().get())
|
if (!GetDeferredInitializers().get())
|
||||||
GetDeferredInitializers().reset(new std::priority_queue<DeferredInitializer>());
|
GetDeferredInitializers().reset(new Loader::DeferredInitializerPriorityQueue());
|
||||||
|
|
||||||
GetDeferredInitializers().get()->push(DeferredInitializer(callback, priority));
|
GetDeferredInitializers().get()->push(DeferredInitializer(callback, priority));
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#define LOADER_H
|
#define LOADER_H
|
||||||
|
|
||||||
#include "base/i2-base.hpp"
|
#include "base/i2-base.hpp"
|
||||||
|
#include "base/initialize.hpp"
|
||||||
#include "base/string.hpp"
|
#include "base/string.hpp"
|
||||||
#include <boost/thread/tss.hpp>
|
#include <boost/thread/tss.hpp>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
@ -14,13 +15,13 @@ namespace icinga
|
|||||||
struct DeferredInitializer
|
struct DeferredInitializer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DeferredInitializer(std::function<void ()> callback, int priority)
|
DeferredInitializer(std::function<void ()> callback, InitializePriority priority)
|
||||||
: m_Callback(std::move(callback)), m_Priority(priority)
|
: m_Callback(std::move(callback)), m_Priority(priority)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
bool operator<(const DeferredInitializer& other) const
|
bool operator>(const DeferredInitializer& other) const
|
||||||
{
|
{
|
||||||
return m_Priority < other.m_Priority;
|
return m_Priority > other.m_Priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()()
|
void operator()()
|
||||||
@ -30,7 +31,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::function<void ()> m_Callback;
|
std::function<void ()> m_Callback;
|
||||||
int m_Priority;
|
InitializePriority m_Priority;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,13 +42,18 @@ private:
|
|||||||
class Loader
|
class Loader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void AddDeferredInitializer(const std::function<void ()>& callback, int priority = 0);
|
static void AddDeferredInitializer(const std::function<void ()>& callback, InitializePriority priority = InitializePriority::Default);
|
||||||
static void ExecuteDeferredInitializers();
|
static void ExecuteDeferredInitializers();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Loader();
|
Loader();
|
||||||
|
|
||||||
static boost::thread_specific_ptr<std::priority_queue<DeferredInitializer> >& GetDeferredInitializers();
|
// Deferred initializers are run in the order of the definition of their enum values.
|
||||||
|
// Therefore, initializers that should be run first have lower enum values and
|
||||||
|
// the order of the std::priority_queue has to be reversed using std::greater.
|
||||||
|
using DeferredInitializerPriorityQueue = std::priority_queue<DeferredInitializer, std::vector<DeferredInitializer>, std::greater<>>;
|
||||||
|
|
||||||
|
static boost::thread_specific_ptr<DeferredInitializerPriorityQueue>& GetDeferredInitializers();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ INITIALIZE_ONCE_WITH_PRIORITY([]() {
|
|||||||
type->SetPrototype(Object::GetPrototype());
|
type->SetPrototype(Object::GetPrototype());
|
||||||
Type::Register(type);
|
Type::Register(type);
|
||||||
Object::TypeInstance = type;
|
Object::TypeInstance = type;
|
||||||
}, 20);
|
}, InitializePriority::RegisterObjectType);
|
||||||
|
|
||||||
String ObjectType::GetName() const
|
String ObjectType::GetName() const
|
||||||
{
|
{
|
||||||
|
@ -37,7 +37,7 @@ private:
|
|||||||
icinga::Type::Ptr t = new PrimitiveType(#type, "None"); \
|
icinga::Type::Ptr t = new PrimitiveType(#type, "None"); \
|
||||||
t->SetPrototype(prototype); \
|
t->SetPrototype(prototype); \
|
||||||
icinga::Type::Register(t); \
|
icinga::Type::Register(t); \
|
||||||
}, 15)
|
}, InitializePriority::RegisterBuiltinTypes)
|
||||||
|
|
||||||
#define REGISTER_PRIMITIVE_TYPE_FACTORY(type, base, prototype, factory) \
|
#define REGISTER_PRIMITIVE_TYPE_FACTORY(type, base, prototype, factory) \
|
||||||
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
|
INITIALIZE_ONCE_WITH_PRIORITY([]() { \
|
||||||
@ -45,7 +45,7 @@ private:
|
|||||||
t->SetPrototype(prototype); \
|
t->SetPrototype(prototype); \
|
||||||
icinga::Type::Register(t); \
|
icinga::Type::Register(t); \
|
||||||
type::TypeInstance = t; \
|
type::TypeInstance = t; \
|
||||||
}, 15); \
|
}, InitializePriority::RegisterPrimitiveTypes); \
|
||||||
DEFINE_TYPE_INSTANCE(type)
|
DEFINE_TYPE_INSTANCE(type)
|
||||||
|
|
||||||
#define REGISTER_PRIMITIVE_TYPE(type, base, prototype) \
|
#define REGISTER_PRIMITIVE_TYPE(type, base, prototype) \
|
||||||
|
@ -35,11 +35,11 @@ INITIALIZE_ONCE_WITH_PRIORITY([]() {
|
|||||||
|
|
||||||
l_InternalNS = new Namespace(true);
|
l_InternalNS = new Namespace(true);
|
||||||
globalNS->SetAttribute("Internal", new ConstEmbeddedNamespaceValue(l_InternalNS));
|
globalNS->SetAttribute("Internal", new ConstEmbeddedNamespaceValue(l_InternalNS));
|
||||||
}, 1000);
|
}, InitializePriority::CreateNamespaces);
|
||||||
|
|
||||||
INITIALIZE_ONCE_WITH_PRIORITY([]() {
|
INITIALIZE_ONCE([]() {
|
||||||
l_InternalNS->Freeze();
|
l_InternalNS->Freeze();
|
||||||
}, 0);
|
});
|
||||||
|
|
||||||
ScriptFrame::ScriptFrame(bool allocLocals)
|
ScriptFrame::ScriptFrame(bool allocLocals)
|
||||||
: Locals(allocLocals ? new Dictionary() : nullptr), Self(ScriptGlobal::GetGlobals()), Sandboxed(false), Depth(0)
|
: Locals(allocLocals ? new Dictionary() : nullptr), Self(ScriptGlobal::GetGlobals()), Sandboxed(false), Depth(0)
|
||||||
|
@ -15,7 +15,7 @@ INITIALIZE_ONCE_WITH_PRIORITY([]() {
|
|||||||
type->SetPrototype(TypeType::GetPrototype());
|
type->SetPrototype(TypeType::GetPrototype());
|
||||||
Type::TypeInstance = type;
|
Type::TypeInstance = type;
|
||||||
Type::Register(type);
|
Type::Register(type);
|
||||||
}, 20);
|
}, InitializePriority::RegisterTypeType);
|
||||||
|
|
||||||
String Type::ToString() const
|
String Type::ToString() const
|
||||||
{
|
{
|
||||||
|
@ -128,7 +128,7 @@ class TypeImpl
|
|||||||
icinga::Type::Ptr t = new TypeImpl<type>(); \
|
icinga::Type::Ptr t = new TypeImpl<type>(); \
|
||||||
type::TypeInstance = t; \
|
type::TypeInstance = t; \
|
||||||
icinga::Type::Register(t); \
|
icinga::Type::Register(t); \
|
||||||
}, 10); \
|
}, InitializePriority::RegisterTypes); \
|
||||||
DEFINE_TYPE_INSTANCE(type)
|
DEFINE_TYPE_INSTANCE(type)
|
||||||
|
|
||||||
#define REGISTER_TYPE_WITH_PROTOTYPE(type, prototype) \
|
#define REGISTER_TYPE_WITH_PROTOTYPE(type, prototype) \
|
||||||
@ -137,7 +137,7 @@ class TypeImpl
|
|||||||
t->SetPrototype(prototype); \
|
t->SetPrototype(prototype); \
|
||||||
type::TypeInstance = t; \
|
type::TypeInstance = t; \
|
||||||
icinga::Type::Register(t); \
|
icinga::Type::Register(t); \
|
||||||
}, 10); \
|
}, InitializePriority::RegisterTypes); \
|
||||||
DEFINE_TYPE_INSTANCE(type)
|
DEFINE_TYPE_INSTANCE(type)
|
||||||
|
|
||||||
#define DEFINE_TYPE_INSTANCE(type) \
|
#define DEFINE_TYPE_INSTANCE(type) \
|
||||||
|
@ -21,6 +21,6 @@
|
|||||||
std::cerr << icinga::DiagnosticInformation(ex) << std::endl; \
|
std::cerr << icinga::DiagnosticInformation(ex) << std::endl; \
|
||||||
icinga::Application::Exit(1); \
|
icinga::Application::Exit(1); \
|
||||||
} \
|
} \
|
||||||
}, 5)
|
}, icinga::InitializePriority::EvaluateConfigFragments)
|
||||||
|
|
||||||
#endif /* CONFIGFRAGMENT_H */
|
#endif /* CONFIGFRAGMENT_H */
|
||||||
|
@ -26,7 +26,7 @@ static Timer::Ptr l_RetentionTimer;
|
|||||||
|
|
||||||
REGISTER_TYPE(IcingaApplication);
|
REGISTER_TYPE(IcingaApplication);
|
||||||
/* Ensure that the priority is lower than the basic System namespace initialization in scriptframe.cpp. */
|
/* Ensure that the priority is lower than the basic System namespace initialization in scriptframe.cpp. */
|
||||||
INITIALIZE_ONCE_WITH_PRIORITY(&IcingaApplication::StaticInitialize, 50);
|
INITIALIZE_ONCE_WITH_PRIORITY(&IcingaApplication::StaticInitialize, InitializePriority::InitIcingaApplication);
|
||||||
|
|
||||||
void IcingaApplication::StaticInitialize()
|
void IcingaApplication::StaticInitialize()
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user