#include <lib/sconfig.h>
#include <lib/threads/atomic.h>
Include dependency graph for refnode.h:
This graph shows which files directly or indirectly include this file:
Go to the source code of this file.
Classes | |
struct | _RefNode_VoidNSPC |
Internally used by RefNode template:. More... | |
class | InternalRefNodeBase |
FIXME This is the base class for the internally used (unique resource) class. This version is not thread-safe at all. More... | |
class | InternalRefNodeBase_ThreadSave |
This is the base class for the internally used (unique resource) class. This version is thread-safe. More... | |
class | RefNode |
This is the reference counting C++-safe type for the user. More... | |
Defines | |
#define | _TemplateLibrary_RefNode_H_ 1 |
HOW IT IS MEANT TO WORK
You have some resource which needs to be shared using reference counting. Then, put this into the "internal class" which you derive from InternalRefNodeBase (which will add an integer for reference counting as the only overhead). Let's say the shared resource is
class _IBuffer : InternalRefNodeBase { char *allocated; size_t size; public: int BoFoo(char *x,int y); int pubval; ... };
Now, we need to create such an object once and want to have it shared:
_IBuffer *internal_b=new _IBuffer(...); RefNode<_IBuffer> b(internal_b);
Now, we can savely go on using the RefNode<_IBuffer>:
RefNode<_IBuffer> c=b;
In order to avoid all that template typing, I recommend to use a typedef:
typedef RefNode<_IBuffer> Buffer;
Access to all elements in the internal ref node can easily be obtained through the overloaded operator->():
c->BoFoo("hello",5);
c->pubval=123;
(*c).foo();
Of course, you should never delete the internal class directly. It will delete itself automatically once all references to it are deleted, i.e. the reference counter gets zero.
There is a second parameter type in the RefNode template: NSPC. This can be used to include a namespace class. For example one might have the following class:
class _IBuffer : InternalRefNodeBase { public: enum Flags { UseMMap, UseMalloc }; private: char *allocated; // etc... (see above) };
In this case, one would of course like to be able to write
Buffer::Flags f=Buffer::UseMMap;
_IBuffer::Flags f=_IBuffer::UseMMap;
To easily solve this problem, put the enum into a "namespace class" and use it as second argument to the RefNode template:
class _IBufferNamespace { public: enum Flags { UseMMap, UseMalloc }; }; class _IBuffer : InternalRefNodeBase, public _IBufferNamespace { char *allocated; // etc... (see above) }; typedef RefNode<_IBuffer,_IBufferNamespace> Buffer; // And now we can use: Buffer::Flags = Buffer::UseMMap;
class _IBuffer : InternalRefNodeBase { private: size_t len; public: ssize_t length() { return(this ? len : -1); } };
THREADS:
RefNode<_IBuffer> b, c; ... mutex_for_b.lock(); // aquire lock b=c; if(!b) do_something(); // operate on b mutex_for_b.unlock(); // release lock
Definition in file refnode.h.
|
|