Merge pull request #9394 from Icinga/bugfix/atomic-members-2.12

Synchronize all access to auto-generated class members (from .ti files)
This commit is contained in:
Alexander Aleksandrovič Klimov 2022-06-23 11:32:33 +02:00 committed by GitHub
commit 0b66a3578d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 76 additions and 19 deletions

View File

@ -4,6 +4,9 @@
#define ATOMIC_H
#include <atomic>
#include <mutex>
#include <type_traits>
#include <utility>
namespace icinga
{
@ -38,6 +41,51 @@ public:
}
};
/**
* Wraps any T into a std::atomic<T>-like interface that locks using a mutex.
*
* In contrast to std::atomic<T>, Locked<T> is also valid for types that are not trivially copyable.
* In case T is trivially copyable, std::atomic<T> is almost certainly the better choice.
*
* @ingroup base
*/
template<typename T>
class Locked
{
public:
inline T load() const
{
std::unique_lock<std::mutex> lock(m_Mutex);
return m_Value;
}
inline void store(T desired)
{
std::unique_lock<std::mutex> lock(m_Mutex);
m_Value = std::move(desired);
}
private:
mutable std::mutex m_Mutex;
T m_Value;
};
/**
* Type alias for std::atomic<T> if possible, otherwise Locked<T> is used as a fallback.
*
* @ingroup base
*/
template <typename T>
using AtomicOrLocked =
#if defined(__GNUC__) && __GNUC__ < 5
// GCC does not implement std::is_trivially_copyable until version 5.
typename std::conditional<std::is_fundamental<T>::value || std::is_pointer<T>::value, std::atomic<T>, Locked<T>>::type;
#else /* defined(__GNUC__) && __GNUC__ < 5 */
typename std::conditional<std::is_trivially_copyable<T>::value, std::atomic<T>, Locked<T>>::type;
#endif /* defined(__GNUC__) && __GNUC__ < 5 */
}
#endif /* ATOMIC_H */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 << "\tAtomicOrLocked<" << field.Type.GetRealType() << "> 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 <boost/signals2.hpp>" << std::endl << std::endl;