draft proposal for ref counting in D

Michel Fortin michel.fortin at michelf.ca
Mon Oct 14 12:42:28 PDT 2013


On 2013-10-14 17:57:18 +0000, Rainer Schuetze <r.sagitario at gmx.de> said:

> On 13.10.2013 13:48, Michel Fortin wrote:
>> 
>> For one of my projects I implemented a shared pointer like this. It uses
>> the pointer value itself as a spin lock with the assumption that -1 is
>> an invalid pointer value:
>> 
>> 1. read pointer value
>> 2. if read value is -1 go to line 1 (spin)
>> 3. compare and swap (previously read value <-> -1)
>> 4. if failure go to line 1 (spin)
>> // now pointer is "locked", its value is -1 but we have a copy of the
>> original
>> 5. copy pointer locally or assign to it (and update counter)
>> 6. write back pointer value atomically to replace the -1
>> 
>> No mutex, but there's a spin lock so it's not good if there's contention.
>> 
>> That said, I find it extremely rare to want a shared pointer that isn't
>> already protected by a mutex alongside other variables, or that isn't
>> propagated using some form of message passing.
> 
> Locking is very bad if you have threads at different priorities as it 
> might introduce priority inversion. Spinning is probably even worse in 
> that scenario.

Spinning is good only when you very rarely expect contention, which is 
the case for me. The above code is used once per object the first time 
someone requests a weak pointer for it. Having contention for that just 
doesn't make sense in most usage patterns. But still, being curious I 
added a log message anytime it does actually has to spin, and I have 
yet to see that message once in my logs (which probably means 
aggressive enough unit tests are missing).

If you have a lot of read accesses and rarely write to the pointer you 
could instead try a read-write mutex with concurrent read access. In 
any case, there's no solution that will be ideal in all cases. 
Different situations asks for different trade-offs.

> At work, I use shared pointers all the time to pass information to a 
> real time audio thread. The scheme uses triple-buffering of pointers 
> for a lock free safe transport from/to the real time thread.
> 
> Not having to worry about these low-level locking stuff is one of the 
> good aspects about garbage collecting.

Indeed. The current garbage collector makes it easy to have shared 
pointers to shared objects. But the GC can also interrupt real-time 
threads for an unpredictable duration, how do you cope with that in a 
real-time thread?

I know ARC isn't the ideal solution for all use cases. But neither is 
the GC, especially for real-time applications. So, which one would you 
recommend for a project having a real-time audio thread?

-- 
Michel Fortin
michel.fortin at michelf.ca
http://michelf.ca



More information about the Digitalmars-d mailing list