genode/repos/base/include/base/weak_ptr.h

453 lines
9.4 KiB
C
Raw Normal View History

/*
* \brief Utilities for object life-time management
* \author Norman Feske
* \date 2013-03-09
*/
/*
* Copyright (C) 2013-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _INCLUDE__BASE__WEAK_PTR_H_
#define _INCLUDE__BASE__WEAK_PTR_H_
2020-02-19 16:26:40 +01:00
#include <base/blockade.h>
#include <base/mutex.h>
#include <base/log.h>
#include <util/list.h>
namespace Genode {
class Weak_object_base;
class Weak_ptr_base;
class Locked_ptr_base;
template <typename T> struct Weak_object;
template <typename T> struct Weak_ptr;
template <typename T> struct Locked_ptr;
}
/**
* Type-agnostic base class of a weak pointer
*
* This class implements the mechanics of the the 'Weak_ptr' class template.
* It is not used directly.
*/
class Genode::Weak_ptr_base : public Genode::List<Weak_ptr_base>::Element
{
private:
friend class Weak_object_base;
friend class Locked_ptr_base;
2020-02-19 16:26:40 +01:00
Mutex mutable _mutex { };
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Weak_object_base *_obj { nullptr };
/*
2020-02-19 16:26:40 +01:00
* This blocakde is used to synchronize destruction of a weak pointer
* and its corresponding weak object that happen simultaneously
*/
2020-02-19 16:26:40 +01:00
Blockade mutable _destruct { };
inline void _adopt(Weak_object_base *obj);
inline void _disassociate();
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Weak_ptr_base(Weak_ptr_base const &);
protected:
explicit inline Weak_ptr_base(Weak_object_base *obj);
public:
/**
* Default constructor, produces invalid pointer
*/
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Weak_ptr_base() { }
inline ~Weak_ptr_base();
/**
* Assignment operator
*/
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
inline Weak_ptr_base &operator = (Weak_ptr_base const &other);
/**
* Test for equality
*/
inline bool operator == (Weak_ptr_base const &other) const;
/**
* Return pointer to object if it exists, or 0 if object vanished
*
* \noapi
*/
Weak_object_base *obj() const { return _obj; }
/**
* Inspection hook for unit test
*
* \noapi
*/
void debug_info() const;
};
/**
* Type-agnostic base class of a weak object
*/
class Genode::Weak_object_base
{
private:
friend class Weak_ptr_base;
friend class Locked_ptr_base;
/**
* List of weak pointers currently pointing to the object
*/
2020-02-19 16:26:40 +01:00
Mutex _list_mutex { };
List<Weak_ptr_base> _list { };
/**
* Buffers dequeued weak pointer that get invalidated currently
*/
Weak_ptr_base *_ptr_in_destruction = nullptr;
/**
2020-02-19 16:26:40 +01:00
* Mutex to synchronize access to object
*/
2020-02-19 16:26:40 +01:00
Mutex _mutex { };
protected:
/**
* To be called from 'Weak_object<T>' only
*
* \noapi
*/
template <typename T>
Weak_ptr<T> _weak_ptr();
public:
/**
* This exception signals a weak pointer that the object
* is in destruction progress
*/
class In_destruction : Exception {};
~Weak_object_base()
{
if (_list.first())
error("Weak object ", this, " not destructed properly "
"there are still dangling pointers to it");
}
void disassociate(Weak_ptr_base *ptr)
{
if (!ptr) return;
{
2020-02-19 16:26:40 +01:00
Mutex::Guard guard(_list_mutex);
/*
* If the weak pointer that tries to disassociate is currently
* removed to invalidate it by the weak object's destructor,
2020-02-19 16:26:40 +01:00
* signal that fact to the pointer, so it can free it's mutex,
* and block until invalidation is finished.
*/
if (_ptr_in_destruction == ptr)
throw In_destruction();
_list.remove(ptr);
}
}
/**
* Mark object as safe to be destructed
*
* This method must be called by the destructor of a weak object to
* defer the destruction until no 'Locked_ptr' is held to the object.
*/
void lock_for_destruction()
{
/*
* Loop through the list of weak pointers and invalidate them
*/
while (true) {
/*
* To prevent dead-locks we always have to hold
2020-02-19 16:26:40 +01:00
* the order of mutex access, therefore we first
* dequeue one weak pointer and free the list mutex again
*/
{
2020-02-19 16:26:40 +01:00
Mutex::Guard guard(_list_mutex);
_ptr_in_destruction = _list.first();
/* if the list is empty we're done */
if (!_ptr_in_destruction) break;
_list.remove(_ptr_in_destruction);
}
{
2020-02-19 16:26:40 +01:00
Mutex::Guard guard(_ptr_in_destruction->_mutex);
_ptr_in_destruction->_obj = nullptr;
/*
* unblock a weak pointer that tried to disassociate
* in the meantime
*/
2020-02-19 16:26:40 +01:00
_ptr_in_destruction->_destruct.wakeup();
}
}
/*
2020-02-19 16:26:40 +01:00
* synchronize with locked pointers that already acquired
* the mutex before the corresponding weak pointer got invalidated
*/
2020-02-19 16:26:40 +01:00
_mutex.acquire();
}
/**
* Inspection hook for unit test
*
* \noapi
*/
void debug_info() const;
};
class Genode::Locked_ptr_base
{
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
private:
/*
* Noncopyable
*/
Locked_ptr_base(Locked_ptr_base const &);
Locked_ptr_base &operator = (Locked_ptr_base const &);
protected:
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Weak_object_base *curr = nullptr;
/**
* Constructor
*
* \noapi
*/
inline Locked_ptr_base(Weak_ptr_base &weak_ptr);
/**
* Destructor
*
* \noapi
*/
inline ~Locked_ptr_base();
};
/**
* Weak pointer to a given type
*
* A weak pointer can be obtained from a weak object (an object that inherits
* the 'Weak_object' class template) and safely survives the lifetime of the
* associated weak object. If the weak object disappears, all
* weak pointers referring to the object are automatically invalidated.
* To avoid race conditions between the destruction and use of a weak object,
* a weak pointer cannot be de-reference directly. To access the object, a
* weak pointer must be turned into a locked pointer ('Locked_ptr').
*/
template <typename T>
struct Genode::Weak_ptr : Genode::Weak_ptr_base
{
/**
* Default constructor creates invalid pointer
*/
Weak_ptr() { }
/**
* Copy constructor
*/
Weak_ptr(Weak_ptr<T> const &other) : Weak_ptr_base(other.obj()) { }
/**
* Assignment operator
*/
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
inline Weak_ptr &operator = (Weak_ptr<T> const &other)
{
*static_cast<Weak_ptr_base *>(this) = other;
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
return *this;
}
};
/**
* Weak object
*
* This class template must be inherited in order to equip an object with
* the weak-pointer mechanism.
*
* \param T type of the derived class
*/
template <typename T>
struct Genode::Weak_object : Genode::Weak_object_base
{
/**
* Obtain a weak pointer referring to the weak object
*/
Weak_ptr<T> weak_ptr() { return _weak_ptr<T>(); }
/**
* Const version of 'weak_ptr'
*
* This function is useful in cases where the returned weak pointer is
* merely used for comparison operations.
*/
Weak_ptr<T const> const weak_ptr_const() const
{
/*
* We strip off the constness of 'this' to reuse the internal non-const
* code of the weak object. The executed operations are known to not
* alter the state of the weak object.
*/
return const_cast<Weak_object *>(this)->_weak_ptr<T const>();
}
};
/**
* Locked pointer
*
* A locked pointer is constructed from a weak pointer. After construction,
* its validity can (and should) be checked by calling the 'valid'
* method. If the locked pointer is valid, the pointed-to object is known to
* be locked until the locked pointer is destroyed. During this time, the
* locked pointer can safely be de-referenced.
*
* The typical pattern of using a locked pointer is to declare it as a
* local variable. Once the execution leaves the scope of the variable, the
* locked pointer is destructed, which unlocks the pointed-to weak object.
* It effectively serves as a lock guard.
*/
template <typename T>
struct Genode::Locked_ptr : Genode::Locked_ptr_base
{
Locked_ptr(Weak_ptr<T> &weak_ptr) : Locked_ptr_base(weak_ptr) { }
T *operator -> () { return static_cast<T *>(curr); }
T &operator * () { return *static_cast<T *>(curr); }
/**
* Returns true if the locked pointer is valid
*
* Only if valid, the locked pointer can be de-referenced. Otherwise,
* the attempt will result in a null-pointer access.
*/
bool valid() const { return curr != nullptr; }
};
/********************
** Implementation **
********************/
void Genode::Weak_ptr_base::_adopt(Genode::Weak_object_base *obj)
{
_obj = obj;
if (_obj)
{
2020-02-19 16:26:40 +01:00
Mutex::Guard guard(_obj->_list_mutex);
_obj->_list.insert(this);
}
}
void Genode::Weak_ptr_base::_disassociate()
{
/* defer destruction of object */
try {
2020-02-19 16:26:40 +01:00
Mutex::Guard guard(_mutex);
if (_obj) _obj->disassociate(this);
} catch(Weak_object_base::In_destruction&) {
2020-02-19 16:26:40 +01:00
_destruct.block();
}
}
Genode::Weak_ptr_base::Weak_ptr_base(Genode::Weak_object_base *obj)
{
_adopt(obj);
}
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Genode::Weak_ptr_base &
Genode::Weak_ptr_base::operator = (Weak_ptr_base const &other)
{
/* self assignment */
if (&other == this)
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
return *this;
_disassociate();
{
2020-02-19 16:26:40 +01:00
Mutex::Guard guard(other._mutex);
_adopt(other._obj);
}
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
return *this;
}
bool Genode::Weak_ptr_base::operator == (Weak_ptr_base const &other) const
{
if (&other == this)
return true;
2020-02-19 16:26:40 +01:00
Mutex::Guard guard_this(_mutex), guard_other(other._mutex);
return (_obj == other._obj);
}
Genode::Weak_ptr_base::~Weak_ptr_base()
{
_disassociate();
}
template <typename T>
Genode::Weak_ptr<T> Genode::Weak_object_base::_weak_ptr()
{
Weak_ptr_base result(this);
return *static_cast<Weak_ptr<T> *>(&result);
}
Genode::Locked_ptr_base::Locked_ptr_base(Weak_ptr_base &weak_ptr)
: curr(nullptr)
{
2020-02-19 16:26:40 +01:00
Mutex::Guard guard(weak_ptr._mutex);
if (!weak_ptr.obj()) return;
curr = weak_ptr.obj();
2020-02-19 16:26:40 +01:00
curr->_mutex.acquire();
}
Genode::Locked_ptr_base::~Locked_ptr_base()
{
if (curr)
2020-02-19 16:26:40 +01:00
curr->_mutex.release();
}
#endif /* _INCLUDE__BASE__WEAK_PTR_H_ */