Reference counting for resource management
Denis Koroskin
2korden at gmail.com
Sun Nov 29 16:36:46 PST 2009
On Mon, 30 Nov 2009 03:19:33 +0300, Bartosz Milewski
<bartosz-nospam at relisoft.com> wrote:
> I don't think you need opAssign. The compiler will automatically use
> bitblit and postblit.
>
> Here's my implementation of a reference counted thread id structure for
> comparison:
>
> struct Tid
> {
> this(HANDLE h)
> {
> _h = h;
> Counter * cnt = cast(Counter *)
> core.stdc.stdlib.malloc(Counter.sizeof);
> cnt._n = 1;
> _cnt = cast(shared Counter *) cnt;
> }
> ~this()
> {
> release();
> }
> this(this)
> {
> _cnt.inc;
> }
> // invalidates current Tid object
> Tid transfer()
> {
> Tid tid = { _h, _cnt };
> _cnt = null;
> return tid;
> }
> void release()
> {
> if (_cnt !is null)
> {
> uint newCount = _cnt.dec;
> if (newCount == 0)
> {
> CloseHandle(_h);
> core.stdc.stdlib.free(cast(Counter *)_cnt);
> _cnt = null;
> }
> }
> }
> void start()
> {
> assert(_h != INVALID_HANDLE_VALUE);
> if (ResumeThread(_h) == -1)
> throw new ThreadException("Error resuming thread");
> }
> void join(bool rethrow = true)
> {
> if (_h != INVALID_HANDLE_VALUE)
> if (WaitForSingleObject(_h, INFINITE) != WAIT_OBJECT_0)
> throw new ThreadException("Join failed");
> }
> void setPriority() // dummy for now
> {
> }
> private:
> // Revisit: implement using atomic add
> struct Counter
> {
> uint inc() shared { return ++_n; }
> uint dec() shared { return --_n; }
>
> uint _n = 1;
> }
> private:
> HANDLE _h = INVALID_HANDLE_VALUE;
> shared Counter * _cnt;
> }
>
> LMB Wrote:
>
>> Hello,
>>
>> I've been reading the forums for some time, but this is my first post
>> here :-)
>>
>> I am trying to create yet another D2 wrapper for SQLite. As usual with
>> many C libraries, SQLite provides us some "objects" and functions to
>> create and destroy them. So, I decided to encapsulate these SQLite
>> objects in a struct, and use reference counting to destroys the objects
>> as soon as I can safely do so.
>>
>> The problem is that I can't make it work correctly in all situations.
>> It guess that I am not increasing the reference count on every
>> situation in which my object is copied, because I got "negative"
>> reference counts in some tests. But this is just a guess, I am not sure
>> at all.
>>
>> So, is there any complete example on how to implement reference
>> counting in D2?
>>
>> I found some discussions about ref counting in D, like Bartoz's nice
>> post
>> (http://bartoszmilewski.wordpress.com/2009/08/19/the-anatomy-of-reference-counting/),
>> but not a complete working example.
>>
>> If there is no example around, I'd be pleased if someone could give me
>> any advice. This is what one of my wrappers roughly looks like (for
>> brevity, I removed all code not related to reference counting):
>>
>> struct Database
>> {
>> public this(in string fileName)
>> {
>> sqlite3_open(toStringz(fileName), &db_);
>>
>> refCount_ = cast(uint*)(malloc(uint.sizeof));
>> *refCount_ = 1;
>> }
>>
>> this(this)
>> body
>> {
>> ++(*refCount_);
>> }
>>
>> Database opAssign(Database other)
>> {
>> db_ = other.db_;
>> refCount_ = other.refCount_;
>> ++(*refCount_);
>> return this;
>> }
>>
>> public ~this()
>> {
>> if (refCount_ !is null)
>> {
>> --(*refCount_);
>>
>> if (*refCount_ == 0)
>> {
>> free(refCount_);
>> refCount_ = null;
>> immutable status = sqlite3_close(db_);
>> }
>> }
>> }
>>
>> private sqlite3* db_;
>> private uint* refCount_;
>> }
>>
>>
>> Thanks!
>>
>> LMB
>>
>
I think RefCounted should be flexible enough to re-usable for other data
structures, too (e.g. so that it could be part of Phobos).
By the way, your code has a bug:
Tid tid; // or release() and exisiting Tid
Tid tid2 = tid; // segfault since you don't check if _cnt is null in
postblit
More information about the Digitalmars-d
mailing list