Allow intrusive_ptr<const T> for objects

This allows using ref-counted pointers to const objects. Adds a second typedef
so that T::ConstPtr can be used similar to how T::Ptr currently is.
This commit is contained in:
Julian Brost 2025-07-23 13:06:55 +02:00
parent 0a08fcc0e1
commit a49ec1015d
4 changed files with 26 additions and 24 deletions

View File

@ -201,14 +201,14 @@ Value icinga::GetPrototypeField(const Value& context, const String& field, bool
}
#ifdef I2_LEAK_DEBUG
void icinga::TypeAddObject(Object *object)
void icinga::TypeAddObject(const Object *object)
{
std::unique_lock<std::mutex> lock(l_ObjectCountLock);
String typeName = Utility::GetTypeName(typeid(*object));
l_ObjectCounts[typeName]++;
}
void icinga::TypeRemoveObject(Object *object)
void icinga::TypeRemoveObject(const Object *object)
{
std::unique_lock<std::mutex> lock(l_ObjectCountLock);
String typeName = Utility::GetTypeName(typeid(*object));
@ -239,7 +239,7 @@ INITIALIZE_ONCE([]() {
});
#endif /* I2_LEAK_DEBUG */
void icinga::intrusive_ptr_add_ref(Object *object)
void icinga::intrusive_ptr_add_ref(const Object *object)
{
#ifdef I2_LEAK_DEBUG
if (object->m_References.fetch_add(1) == 0u)
@ -249,7 +249,7 @@ void icinga::intrusive_ptr_add_ref(Object *object)
#endif /* I2_LEAK_DEBUG */
}
void icinga::intrusive_ptr_release(Object *object)
void icinga::intrusive_ptr_release(const Object *object)
{
auto previous (object->m_References.fetch_sub(1));

View File

@ -31,7 +31,8 @@ class ValidationUtils;
extern const Value Empty;
#define DECLARE_PTR_TYPEDEFS(klass) \
typedef intrusive_ptr<klass> Ptr
typedef intrusive_ptr<klass> Ptr; \
typedef intrusive_ptr<const klass> ConstPtr
#define IMPL_TYPE_LOOKUP_SUPER() \
@ -192,7 +193,7 @@ private:
Object(const Object& other) = delete;
Object& operator=(const Object& rhs) = delete;
std::atomic<uint_fast64_t> m_References;
mutable std::atomic<uint_fast64_t> m_References;
mutable std::recursive_mutex m_Mutex;
#ifdef I2_DEBUG
@ -202,17 +203,17 @@ private:
friend struct ObjectLock;
friend void intrusive_ptr_add_ref(Object *object);
friend void intrusive_ptr_release(Object *object);
friend void intrusive_ptr_add_ref(const Object *object);
friend void intrusive_ptr_release(const Object *object);
};
Value GetPrototypeField(const Value& context, const String& field, bool not_found_error, const DebugInfo& debugInfo);
void TypeAddObject(Object *object);
void TypeRemoveObject(Object *object);
void TypeAddObject(const Object *object);
void TypeRemoveObject(const Object *object);
void intrusive_ptr_add_ref(Object *object);
void intrusive_ptr_release(Object *object);
void intrusive_ptr_add_ref(const Object *object);
void intrusive_ptr_release(const Object *object);
template<typename T>
class ObjectImpl

View File

@ -12,8 +12,8 @@ namespace icinga
class SharedObject;
inline void intrusive_ptr_add_ref(SharedObject *object);
inline void intrusive_ptr_release(SharedObject *object);
inline void intrusive_ptr_add_ref(const SharedObject *object);
inline void intrusive_ptr_release(const SharedObject *object);
/**
* Seamless and polymorphistic base for any class to create shared pointers of.
@ -23,8 +23,8 @@ inline void intrusive_ptr_release(SharedObject *object);
*/
class SharedObject
{
friend void intrusive_ptr_add_ref(SharedObject *object);
friend void intrusive_ptr_release(SharedObject *object);
friend void intrusive_ptr_add_ref(const SharedObject *object);
friend void intrusive_ptr_release(const SharedObject *object);
protected:
inline SharedObject() : m_References(0)
@ -38,15 +38,15 @@ protected:
~SharedObject() = default;
private:
Atomic<uint_fast64_t> m_References;
mutable Atomic<uint_fast64_t> m_References;
};
inline void intrusive_ptr_add_ref(SharedObject *object)
inline void intrusive_ptr_add_ref(const SharedObject *object)
{
object->m_References.fetch_add(1);
}
inline void intrusive_ptr_release(SharedObject *object)
inline void intrusive_ptr_release(const SharedObject *object)
{
if (object->m_References.fetch_sub(1) == 1u) {
delete object;

View File

@ -16,13 +16,13 @@ template<class T>
class Shared;
template<class T>
inline void intrusive_ptr_add_ref(Shared<T> *object)
inline void intrusive_ptr_add_ref(const Shared<T> *object)
{
object->m_References.fetch_add(1);
}
template<class T>
inline void intrusive_ptr_release(Shared<T> *object)
inline void intrusive_ptr_release(const Shared<T> *object)
{
if (object->m_References.fetch_sub(1) == 1u) {
delete object;
@ -38,11 +38,12 @@ inline void intrusive_ptr_release(Shared<T> *object)
template<class T>
class Shared : public T
{
friend void intrusive_ptr_add_ref<>(Shared<T> *object);
friend void intrusive_ptr_release<>(Shared<T> *object);
friend void intrusive_ptr_add_ref<>(const Shared<T> *object);
friend void intrusive_ptr_release<>(const Shared<T> *object);
public:
typedef boost::intrusive_ptr<Shared> Ptr;
typedef boost::intrusive_ptr<const Shared> ConstPtr;
/**
* Like std::make_shared, but for this class.
@ -94,7 +95,7 @@ public:
}
private:
Atomic<uint_fast64_t> m_References;
mutable Atomic<uint_fast64_t> m_References;
};
}