Add 'Weak_ptr' to the public Genode API

So far, the lifetime-management utilities 'Weak_ptr' and 'Locked_ptr'
had been preserved for core-internal use only. However, the utilities
are handy for many use cases outside of core where object lifetimes
must be managed. So we promote them to the public API.
This commit is contained in:
Norman Feske 2014-06-05 15:55:34 +02:00
parent c652655bcb
commit 0be6817226
7 changed files with 50 additions and 51 deletions

View File

@ -14,7 +14,7 @@
*
* The utilities provided herein implement a more elegant pattern called
* "weak pointers" to deal with such situations. An object that might
* disappear at any time is represented by the 'Volatile_object' class
* disappear at any time is represented by the 'Weak_object' class
* template. It keeps track of a list of so-called weak pointers pointing
* to the object. A weak pointer, in turn, holds privately the pointer to the
* object alongside a validity flag. It cannot be used to dereference the
@ -25,14 +25,14 @@
* can (and should) be detected via the 'Locked_ptr::is_valid()' function prior
* dereferencing the pointer.
*
* In the event a volatile object gets destructed, all weak pointers that point
* In the event a weak object gets destructed, all weak pointers that point
* to the object are automatically invalidated. So a subsequent conversion into
* a locked pointer will yield an invalid pointer, which can be detected (in
* contrast to a dangling pointer).
*
* To use this mechanism, the destruction of a volatile object must be
* To use this mechanism, the destruction of a weak object must be
* deferred until no locked pointer points to the object anymore. This is
* done by calling the function 'Volatile_object::lock_for_destruction()'
* done by calling the function 'Weak_object::lock_for_destruction()'
* at the beginning of the destructor of the to-be-destructed object.
* When this function returns, all weak pointers to the object will have been
* invalidated. So it is save to destruct and free the object.
@ -45,17 +45,18 @@
* under the terms of the GNU General Public License version 2.
*/
#ifndef _CORE__INCLUDE__LIFETIME_H_
#define _CORE__INCLUDE__LIFETIME_H_
#ifndef _INCLUDE__BASE__WEAK_PTR_H_
#define _INCLUDE__BASE__WEAK_PTR_H_
#include <base/lock.h>
#include <util/list.h>
namespace Genode {
class Volatile_object_base;
class Weak_object_base;
class Weak_ptr_base;
class Locked_ptr_base;
template <typename T> struct Volatile_object;
template <typename T> struct Weak_object;
template <typename T> struct Weak_ptr;
template <typename T> struct Locked_ptr;
}
@ -65,22 +66,22 @@ class Genode::Weak_ptr_base : public Genode::List<Weak_ptr_base>::Element
{
private:
friend class Volatile_object_base;
friend class Weak_object_base;
friend class Locked_ptr_base;
Lock mutable _lock;
Volatile_object_base *_obj;
bool _valid; /* true if '_obj' points to an
existing object */
Lock mutable _lock;
Weak_object_base *_obj;
bool _valid; /* true if '_obj' points to an
existing object */
inline void _adopt(Volatile_object_base *obj);
inline void _adopt(Weak_object_base *obj);
inline void _disassociate();
protected:
Volatile_object_base *obj() const { return _valid ? _obj: 0; }
Weak_object_base *obj() const { return _valid ? _obj: 0; }
explicit inline Weak_ptr_base(Volatile_object_base *obj);
explicit inline Weak_ptr_base(Weak_object_base *obj);
public:
@ -108,7 +109,7 @@ class Genode::Weak_ptr_base : public Genode::List<Weak_ptr_base>::Element
};
class Genode::Volatile_object_base
class Genode::Weak_object_base
{
private:
@ -123,16 +124,16 @@ class Genode::Volatile_object_base
/**
* Lock used to defer the destruction of an object derived from
* 'Volatile_object_base'
* 'Weak_object_base'
*/
Lock _destruct_lock;
protected:
inline ~Volatile_object_base();
inline ~Weak_object_base();
/**
* To be called from 'Volatile_object<T>' only
* To be called from 'Weak_object<T>' only
*/
template <typename T>
Weak_ptr<T> _weak_ptr();
@ -140,7 +141,7 @@ class Genode::Volatile_object_base
public:
/**
* Function to be called by the destructor of a volatile object to
* Function to 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() { _destruct_lock.lock(); }
@ -156,7 +157,7 @@ class Genode::Locked_ptr_base
{
protected:
Volatile_object_base *curr;
Weak_object_base *curr;
inline Locked_ptr_base(Weak_ptr_base &weak_ptr);
inline ~Locked_ptr_base();
@ -187,7 +188,7 @@ struct Genode::Weak_ptr : Genode::Weak_ptr_base
template <typename T>
struct Genode::Volatile_object : Genode::Volatile_object_base
struct Genode::Weak_object : Genode::Weak_object_base
{
Weak_ptr<T> weak_ptr() { return _weak_ptr<T>(); }
};
@ -200,6 +201,8 @@ struct Genode::Locked_ptr : Genode::Locked_ptr_base
T *operator -> () { return static_cast<T *>(curr); }
T &operator * () { return *static_cast<T *>(curr); }
bool is_valid() const { return curr != 0; }
};
@ -208,7 +211,7 @@ struct Genode::Locked_ptr : Genode::Locked_ptr_base
** Implementation **
********************/
void Genode::Weak_ptr_base::_adopt(Genode::Volatile_object_base *obj)
void Genode::Weak_ptr_base::_adopt(Genode::Weak_object_base *obj)
{
if (!obj)
return;
@ -252,7 +255,7 @@ void Genode::Weak_ptr_base::_disassociate()
}
Genode::Weak_ptr_base::Weak_ptr_base(Genode::Volatile_object_base *obj)
Genode::Weak_ptr_base::Weak_ptr_base(Genode::Weak_object_base *obj)
{
_adopt(obj);
}
@ -267,7 +270,7 @@ void Genode::Weak_ptr_base::operator = (Weak_ptr_base const &other)
if (&other == this)
return;
Volatile_object_base *obj = other.obj();
Weak_object_base *obj = other.obj();
_disassociate();
_adopt(obj);
}
@ -292,14 +295,14 @@ Genode::Weak_ptr_base::~Weak_ptr_base()
template <typename T>
Genode::Weak_ptr<T> Genode::Volatile_object_base::_weak_ptr()
Genode::Weak_ptr<T> Genode::Weak_object_base::_weak_ptr()
{
Weak_ptr_base result(this);
return *static_cast<Weak_ptr<T> *>(&result);
}
Genode::Volatile_object_base::~Volatile_object_base()
Genode::Weak_object_base::~Weak_object_base()
{
{
Lock::Guard guard(_list_lock);
@ -334,4 +337,4 @@ Genode::Locked_ptr_base::~Locked_ptr_base()
curr->_destruct_lock.unlock();
}
#endif /* _CORE__INCLUDE__LIFETIME_H_ */
#endif /* _INCLUDE__BASE__WEAK_PTR_H_ */

View File

@ -15,11 +15,11 @@
#define _CORE__INCLUDE__ADDRESS_SPACE_H_
#include <base/stdint.h>
#include <lifetime.h>
#include <base/weak_ptr.h>
namespace Genode { struct Address_space; }
struct Genode::Address_space : Genode::Volatile_object<Genode::Address_space>
struct Genode::Address_space : Genode::Weak_object<Genode::Address_space>
{
/**
* Flush memory mappings of virtual address range

View File

@ -18,9 +18,7 @@
#include <util/string.h>
#include <base/lock.h>
#include <base/trace/types.h>
/* core includes */
#include <lifetime.h>
#include <base/weak_ptr.h>
/* base-internal include */
#include <trace/control.h>
@ -42,7 +40,7 @@ struct Genode::Trace::Source_owner { };
*/
class Genode::Trace::Source
:
public Genode::Volatile_object<Genode::Trace::Source>,
public Genode::Weak_object<Genode::Trace::Source>,
public Genode::List<Genode::Trace::Source>::Element
{
private:

View File

@ -25,10 +25,10 @@
#include <base/lock.h>
#include <base/trace/types.h>
#include <base/env.h>
#include <base/weak_ptr.h>
#include <dataspace/client.h>
/* core includes */
#include <lifetime.h>
#include <trace/source_registry.h>
/* base-internal include */

View File

@ -1,5 +1,5 @@
/*
* \brief Test for lifetime-management utilities
* \brief Test for weak-pointer utilities
* \author Norman Feske
* \date 2013-03-12
*/
@ -15,11 +15,9 @@
#include <base/printf.h>
#include <base/env.h>
#include <base/thread.h>
#include <base/weak_ptr.h>
#include <timer_session/connection.h>
/* core includes */
#include <lifetime.h>
/********************************************************************
** Hooks for obtaining internal information of the tested classes **
@ -28,7 +26,7 @@
static int weak_ptr_cnt;
void Genode::Volatile_object_base::debug_info() const
void Genode::Weak_object_base::debug_info() const
{
/* count number of weak pointers pointing to the object */
weak_ptr_cnt = 0;
@ -49,7 +47,7 @@ void Genode::Weak_ptr_base::debug_info() const
struct Fatal_error { };
static void assert_weak_ptr_cnt(Genode::Volatile_object_base const *obj,
static void assert_weak_ptr_cnt(Genode::Weak_object_base const *obj,
int expected_cnt)
{
obj->debug_info();
@ -81,13 +79,13 @@ static void assert_weak_ptr_valid(Genode::Weak_ptr_base const &ptr, bool valid)
static bool object_is_constructed;
struct Object : Genode::Volatile_object<Object>
struct Object : Genode::Weak_object<Object>
{
Object() { object_is_constructed = true; }
~Object()
{
Volatile_object<Object>::lock_for_destruction();
Weak_object<Object>::lock_for_destruction();
object_is_constructed = false;
}
};
@ -262,7 +260,7 @@ int main(int argc, char **argv)
{
using namespace Genode;
printf("--- test-lifetime started ---\n");
printf("--- test-weak_ptr started ---\n");
printf("\n-- test tracking of weak pointers --\n");
test_weak_pointer_tracking();
@ -273,6 +271,6 @@ int main(int argc, char **argv)
printf("\n-- test acquisition failure --\n");
test_acquisition_failure();
printf("\n--- finished test-lifetime ---\n");
printf("\n--- finished test-weak_ptr ---\n");
return 0;
}

View File

@ -1,4 +1,4 @@
TARGET = test-lifetime
TARGET = test-weak_ptr
SRC_CC = main.cc
LIBS = base
INC_DIR += $(REP_DIR)/src/core/include

View File

@ -1,4 +1,4 @@
build "core init drivers/timer test/lifetime"
build "core init drivers/timer test/weak_ptr"
create_boot_directory
@ -21,16 +21,16 @@ install_config {
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="test-lifetime">
<start name="test-weak_ptr">
<resource name="RAM" quantum="10M"/>
</start>
</config>
}
build_boot_image "core init timer test-lifetime"
build_boot_image "core init timer test-weak_ptr"
append qemu_args "-nographic -m 64"
run_genode_until "--- finished test-lifetime ---.*\n" 30
run_genode_until "--- finished test-weak_ptr ---.*\n" 30
puts "Test succeeded"