diff --git a/lib/base/atomic.hpp b/lib/base/atomic.hpp index 0ebcddefb..62fa37638 100644 --- a/lib/base/atomic.hpp +++ b/lib/base/atomic.hpp @@ -4,6 +4,8 @@ #define ATOMIC_H #include +#include +#include namespace icinga { @@ -38,6 +40,80 @@ public: } }; +/** + * Wraps T into a std::atomic-like interface. + * + * @ingroup base + */ +template +class NotAtomic +{ +public: + inline T load() const + { + return m_Value; + } + + inline void store(T desired) + { + m_Value = std::move(desired); + } + + T m_Value; +}; + +/** + * Tells whether to use std::atomic or NotAtomic. + * + * @ingroup base + */ +template +struct Atomicable +{ + // Doesn't work with too old compilers. + //static constexpr bool value = std::is_trivially_copyable::value && sizeof(T) <= sizeof(void*); + static constexpr bool value = (std::is_fundamental::value || std::is_pointer::value) && sizeof(T) <= sizeof(void*); +}; + +/** + * Uses either std::atomic or NotAtomic depending on atomicable. + * + * @ingroup base + */ +template +struct AtomicTemplate; + +template<> +struct AtomicTemplate +{ + template + struct tmplt + { + typedef NotAtomic type; + }; +}; + +template<> +struct AtomicTemplate +{ + template + struct tmplt + { + typedef std::atomic type; + }; +}; + +/** + * Uses either std::atomic or NotAtomic depending on T. + * + * @ingroup base + */ +template +struct EventuallyAtomic +{ + typedef typename AtomicTemplate::value>::template tmplt::type type; +}; + } #endif /* ATOMIC_H */ diff --git a/lib/base/configobject.ti b/lib/base/configobject.ti index fcfcb0223..3e5859c81 100644 --- a/lib/base/configobject.ti +++ b/lib/base/configobject.ti @@ -59,10 +59,10 @@ abstract class ConfigObject : ConfigObjectBase < ConfigType [config, no_user_modify] String __name (Name); [config, no_user_modify] String "name" (ShortName) { get {{{ - if (m_ShortName.IsEmpty()) + if (m_ShortName.m_Value.IsEmpty()) return GetName(); else - return m_ShortName; + return m_ShortName.m_Value; }}} }; [config, no_user_modify] name(Zone) zone (ZoneName); diff --git a/lib/icinga/host.ti b/lib/icinga/host.ti index 03c606228..1c8a6c9fe 100644 --- a/lib/icinga/host.ti +++ b/lib/icinga/host.ti @@ -21,10 +21,10 @@ class Host : Checkable [config] String display_name { get {{{ - if (m_DisplayName.IsEmpty()) + if (m_DisplayName.m_Value.IsEmpty()) return GetName(); else - return m_DisplayName; + return m_DisplayName.m_Value; }}} }; diff --git a/lib/icinga/hostgroup.ti b/lib/icinga/hostgroup.ti index a4404eafe..efcb45e54 100644 --- a/lib/icinga/hostgroup.ti +++ b/lib/icinga/hostgroup.ti @@ -11,10 +11,10 @@ class HostGroup : CustomVarObject { [config] String display_name { get {{{ - if (m_DisplayName.IsEmpty()) + if (m_DisplayName.m_Value.IsEmpty()) return GetName(); else - return m_DisplayName; + return m_DisplayName.m_Value; }}} }; diff --git a/lib/icinga/service.ti b/lib/icinga/service.ti index bab1ebc8f..f76750ef4 100644 --- a/lib/icinga/service.ti +++ b/lib/icinga/service.ti @@ -33,10 +33,10 @@ class Service : Checkable < ServiceNameComposer [config] String display_name { get {{{ - if (m_DisplayName.IsEmpty()) + if (m_DisplayName.m_Value.IsEmpty()) return GetShortName(); else - return m_DisplayName; + return m_DisplayName.m_Value; }}} }; [config, required] name(Host) host_name; diff --git a/lib/icinga/servicegroup.ti b/lib/icinga/servicegroup.ti index 69f300508..69a0887b9 100644 --- a/lib/icinga/servicegroup.ti +++ b/lib/icinga/servicegroup.ti @@ -11,10 +11,10 @@ class ServiceGroup : CustomVarObject { [config] String display_name { get {{{ - if (m_DisplayName.IsEmpty()) + if (m_DisplayName.m_Value.IsEmpty()) return GetName(); else - return m_DisplayName; + return m_DisplayName.m_Value; }}} }; diff --git a/lib/icinga/timeperiod.ti b/lib/icinga/timeperiod.ti index 27365988e..ccfbcc3d4 100644 --- a/lib/icinga/timeperiod.ti +++ b/lib/icinga/timeperiod.ti @@ -12,10 +12,10 @@ class TimePeriod : CustomVarObject { [config] String display_name { get {{{ - if (m_DisplayName.IsEmpty()) + if (m_DisplayName.m_Value.IsEmpty()) return GetName(); else - return m_DisplayName; + return m_DisplayName.m_Value; }}} }; [config] Dictionary::Ptr ranges; diff --git a/lib/icinga/user.ti b/lib/icinga/user.ti index 450d95358..5de35b523 100644 --- a/lib/icinga/user.ti +++ b/lib/icinga/user.ti @@ -13,10 +13,10 @@ class User : CustomVarObject { [config] String display_name { get {{{ - if (m_DisplayName.IsEmpty()) + if (m_DisplayName.m_Value.IsEmpty()) return GetName(); else - return m_DisplayName; + return m_DisplayName.m_Value; }}} }; [config, no_user_modify, required] array(name(UserGroup)) groups { diff --git a/lib/icinga/usergroup.ti b/lib/icinga/usergroup.ti index 311932171..35c7ccff4 100644 --- a/lib/icinga/usergroup.ti +++ b/lib/icinga/usergroup.ti @@ -11,10 +11,10 @@ class UserGroup : CustomVarObject { [config] String display_name { get {{{ - if (m_DisplayName.IsEmpty()) + if (m_DisplayName.m_Value.IsEmpty()) return GetName(); else - return m_DisplayName; + return m_DisplayName.m_Value; }}} }; diff --git a/tools/mkclass/classcompiler.cpp b/tools/mkclass/classcompiler.cpp index fd30df8e1..f6793da50 100644 --- a/tools/mkclass/classcompiler.cpp +++ b/tools/mkclass/classcompiler.cpp @@ -797,7 +797,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&) << "{" << std::endl; if (field.GetAccessor.empty() && !(field.Attributes & FANoStorage)) - m_Impl << "\t" << "return m_" << field.GetFriendlyName() << ";" << std::endl; + m_Impl << "\t" << "return m_" << field.GetFriendlyName() << ".load();" << std::endl; else m_Impl << field.GetAccessor << std::endl; @@ -835,7 +835,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&) if (field.SetAccessor.empty() && !(field.Attributes & FANoStorage)) - m_Impl << "\t" << "m_" << field.GetFriendlyName() << " = value;" << std::endl; + m_Impl << "\t" << "m_" << field.GetFriendlyName() << ".store(value);" << std::endl; else m_Impl << field.SetAccessor << std::endl << std::endl; @@ -1044,7 +1044,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&) if (field.Attributes & FANoStorage) continue; - m_Header << "\t" << field.Type.GetRealType() << " m_" << field.GetFriendlyName() << ";" << std::endl; + m_Header << "\tEventuallyAtomic<" << field.Type.GetRealType() << ">::type m_" << field.GetFriendlyName() << ";" << std::endl; } /* signal */ @@ -1431,6 +1431,7 @@ void ClassCompiler::CompileStream(const std::string& path, std::istream& input, << "#include \"base/type.hpp\"" << std::endl << "#include \"base/value.hpp\"" << std::endl << "#include \"base/array.hpp\"" << std::endl + << "#include \"base/atomic.hpp\"" << std::endl << "#include \"base/dictionary.hpp\"" << std::endl << "#include " << std::endl << std::endl;