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