mkclass: make .ti class members atomic if possible

... not to have to lock the objects while setting attributes.
This commit is contained in:
Alexander A. Klimov 2020-03-10 13:19:56 +01:00
parent d5d89b7f39
commit bbe0f2d8c4
10 changed files with 96 additions and 19 deletions

View File

@ -4,6 +4,8 @@
#define ATOMIC_H #define ATOMIC_H
#include <atomic> #include <atomic>
#include <type_traits>
#include <utility>
namespace icinga namespace icinga
{ {
@ -38,6 +40,80 @@ public:
} }
}; };
/**
* Wraps T into a std::atomic<T>-like interface.
*
* @ingroup base
*/
template<class T>
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<T> or NotAtomic<T>.
*
* @ingroup base
*/
template<class T>
struct Atomicable
{
// Doesn't work with too old compilers.
//static constexpr bool value = std::is_trivially_copyable<T>::value && sizeof(T) <= sizeof(void*);
static constexpr bool value = (std::is_fundamental<T>::value || std::is_pointer<T>::value) && sizeof(T) <= sizeof(void*);
};
/**
* Uses either std::atomic<T> or NotAtomic<T> depending on atomicable.
*
* @ingroup base
*/
template<bool atomicable>
struct AtomicTemplate;
template<>
struct AtomicTemplate<false>
{
template<class T>
struct tmplt
{
typedef NotAtomic<T> type;
};
};
template<>
struct AtomicTemplate<true>
{
template<class T>
struct tmplt
{
typedef std::atomic<T> type;
};
};
/**
* Uses either std::atomic<T> or NotAtomic<T> depending on T.
*
* @ingroup base
*/
template<class T>
struct EventuallyAtomic
{
typedef typename AtomicTemplate<Atomicable<T>::value>::template tmplt<T>::type type;
};
} }
#endif /* ATOMIC_H */ #endif /* ATOMIC_H */

View File

@ -59,10 +59,10 @@ abstract class ConfigObject : ConfigObjectBase < ConfigType
[config, no_user_modify] String __name (Name); [config, no_user_modify] String __name (Name);
[config, no_user_modify] String "name" (ShortName) { [config, no_user_modify] String "name" (ShortName) {
get {{{ get {{{
if (m_ShortName.IsEmpty()) if (m_ShortName.m_Value.IsEmpty())
return GetName(); return GetName();
else else
return m_ShortName; return m_ShortName.m_Value;
}}} }}}
}; };
[config, no_user_modify] name(Zone) zone (ZoneName); [config, no_user_modify] name(Zone) zone (ZoneName);

View File

@ -21,10 +21,10 @@ class Host : Checkable
[config] String display_name { [config] String display_name {
get {{{ get {{{
if (m_DisplayName.IsEmpty()) if (m_DisplayName.m_Value.IsEmpty())
return GetName(); return GetName();
else else
return m_DisplayName; return m_DisplayName.m_Value;
}}} }}}
}; };

View File

@ -11,10 +11,10 @@ class HostGroup : CustomVarObject
{ {
[config] String display_name { [config] String display_name {
get {{{ get {{{
if (m_DisplayName.IsEmpty()) if (m_DisplayName.m_Value.IsEmpty())
return GetName(); return GetName();
else else
return m_DisplayName; return m_DisplayName.m_Value;
}}} }}}
}; };

View File

@ -33,10 +33,10 @@ class Service : Checkable < ServiceNameComposer
[config] String display_name { [config] String display_name {
get {{{ get {{{
if (m_DisplayName.IsEmpty()) if (m_DisplayName.m_Value.IsEmpty())
return GetShortName(); return GetShortName();
else else
return m_DisplayName; return m_DisplayName.m_Value;
}}} }}}
}; };
[config, required] name(Host) host_name; [config, required] name(Host) host_name;

View File

@ -11,10 +11,10 @@ class ServiceGroup : CustomVarObject
{ {
[config] String display_name { [config] String display_name {
get {{{ get {{{
if (m_DisplayName.IsEmpty()) if (m_DisplayName.m_Value.IsEmpty())
return GetName(); return GetName();
else else
return m_DisplayName; return m_DisplayName.m_Value;
}}} }}}
}; };

View File

@ -12,10 +12,10 @@ class TimePeriod : CustomVarObject
{ {
[config] String display_name { [config] String display_name {
get {{{ get {{{
if (m_DisplayName.IsEmpty()) if (m_DisplayName.m_Value.IsEmpty())
return GetName(); return GetName();
else else
return m_DisplayName; return m_DisplayName.m_Value;
}}} }}}
}; };
[config] Dictionary::Ptr ranges; [config] Dictionary::Ptr ranges;

View File

@ -13,10 +13,10 @@ class User : CustomVarObject
{ {
[config] String display_name { [config] String display_name {
get {{{ get {{{
if (m_DisplayName.IsEmpty()) if (m_DisplayName.m_Value.IsEmpty())
return GetName(); return GetName();
else else
return m_DisplayName; return m_DisplayName.m_Value;
}}} }}}
}; };
[config, no_user_modify, required] array(name(UserGroup)) groups { [config, no_user_modify, required] array(name(UserGroup)) groups {

View File

@ -11,10 +11,10 @@ class UserGroup : CustomVarObject
{ {
[config] String display_name { [config] String display_name {
get {{{ get {{{
if (m_DisplayName.IsEmpty()) if (m_DisplayName.m_Value.IsEmpty())
return GetName(); return GetName();
else else
return m_DisplayName; return m_DisplayName.m_Value;
}}} }}}
}; };

View File

@ -797,7 +797,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
<< "{" << std::endl; << "{" << std::endl;
if (field.GetAccessor.empty() && !(field.Attributes & FANoStorage)) 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 else
m_Impl << field.GetAccessor << std::endl; 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)) 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 else
m_Impl << field.SetAccessor << std::endl << std::endl; m_Impl << field.SetAccessor << std::endl << std::endl;
@ -1044,7 +1044,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
if (field.Attributes & FANoStorage) if (field.Attributes & FANoStorage)
continue; 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 */ /* signal */
@ -1431,6 +1431,7 @@ void ClassCompiler::CompileStream(const std::string& path, std::istream& input,
<< "#include \"base/type.hpp\"" << std::endl << "#include \"base/type.hpp\"" << std::endl
<< "#include \"base/value.hpp\"" << std::endl << "#include \"base/value.hpp\"" << std::endl
<< "#include \"base/array.hpp\"" << std::endl << "#include \"base/array.hpp\"" << std::endl
<< "#include \"base/atomic.hpp\"" << std::endl
<< "#include \"base/dictionary.hpp\"" << std::endl << "#include \"base/dictionary.hpp\"" << std::endl
<< "#include <boost/signals2.hpp>" << std::endl << std::endl; << "#include <boost/signals2.hpp>" << std::endl << std::endl;