Thread overview
[D-runtime] Adding atomic ops to Druntime
Dec 07, 2009
Sean Kelly
Dec 07, 2009
Brad Roberts
Dec 07, 2009
Sean Kelly
December 06, 2009
The further we get with adding concurrency features to D the more I find myself wishing there were a module for doing atomic ops in Druntime.  I have one sitting around that I'd love to roll in if it passes muster.  It's based on Alexander Terekhov's atomic<> class proposed in comp.programming.threads ages ago, and is very similar to a subset of what the C++ 0x committee settled on--the relevant portion of the C++ 0x proposal is here:

http://www.open-std.org/JTC1/sc22/wg21/docs/papers/2007/n2427.html#ImplFunctions

Here's an outline of the API:

T atomicLoad(msync ms = msync.seq, T)( ref T val );
void atomicStore(msync ms = msync.seq, T)( inout T val, T newval );
bool atomicStoreIf(msync ms = msync.seq, T)( inout T val, T newval, T equalTo );
T atomicIncrement(msync ms = msync.seq, T)( inout T val );
T atomicDecrement(msync ms = msync.seq, T)( inout T val );

struct Atomic(T)
{
    T load(msync ms = msync.seq)();
    void store(msync ms = msync.seq)( T val );
    bool storeIf(msync ms = msync.seq)( T newval, T equalTo );
  static if( isNumericType!T )
  {
    T increment(msync ms = msync.seq)();
    T decrement(msync ms = msync.seq)();
  }
}

enum msync
{
    raw,    /// not sequenced
    hlb,    /// hoist-load barrier
    hsb,    /// hoist-store barrier
    slb,    /// sink-load barrier
    ssb,    /// sink-store barrier
    acq,    /// hoist-load + hoist-store barrier
    rel,    /// sink-load + sink-store barrier
    seq,    /// fully sequenced (acq + rel)
}

(atomicStoreIf is equivalent to atomic_compare_swap in C++)

The Atomic struct could probably be done away with, given the existence of shared in D2, and all but acq, rel, seq, and raw could be eliminated from msync as well.  From a functionality standpoint, I think it's fairly minimal for an atomics package, but I'd rather add than cut stuff later.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/d-runtime/attachments/20091206/a4c3fc96/attachment.htm>
December 06, 2009
My biggest problem with this design is that it encourages people to try to optimize their atomic ops.  The vast majority of people will get it wrong.  If it was me, I'd only have fully sequenced operations.  If you really need anything else, there's always inline asm.

Sean Kelly wrote:
> The further we get with adding concurrency features to D the more I find myself wishing there were a module for doing atomic ops in Druntime.  I have one sitting around that I'd love to roll in if it passes muster.  It's based on Alexander Terekhov's atomic<> class proposed in comp.programming.threads ages ago, and is very similar to a subset of what the C++ 0x committee settled on--the relevant portion of the C++ 0x proposal is here:
> 
> http://www.open-std.org/JTC1/sc22/wg21/docs/papers/2007/n2427.html#ImplFunctions
> 
> Here's an outline of the API:
> 
> T atomicLoad(msync ms = msync.seq, T)( ref T val );
> void atomicStore(msync ms = msync.seq, T)( inout T val, T newval );
> bool atomicStoreIf(msync ms = msync.seq, T)( inout T val, T newval, T equalTo );
> T atomicIncrement(msync ms = msync.seq, T)( inout T val );
> T atomicDecrement(msync ms = msync.seq, T)( inout T val );
> 
> struct Atomic(T)
> {
>     T load(msync ms = msync.seq)();
>     void store(msync ms = msync.seq)( T val );
>     bool storeIf(msync ms = msync.seq)( T newval, T equalTo );
>   static if( isNumericType!T )
>   {
>     T increment(msync ms = msync.seq)();
>     T decrement(msync ms = msync.seq)();
>   }
> }
> 
> enum msync
> {
>     raw,    /// not sequenced
>     hlb,    /// hoist-load barrier
>     hsb,    /// hoist-store barrier
>     slb,    /// sink-load barrier
>     ssb,    /// sink-store barrier
>     acq,    /// hoist-load + hoist-store barrier
>     rel,    /// sink-load + sink-store barrier
>     seq,    /// fully sequenced (acq + rel)
> }
> 
> (atomicStoreIf is equivalent to atomic_compare_swap in C++)
> 
> The Atomic struct could probably be done away with, given the existence of shared in D2, and all but acq, rel, seq, and raw could be eliminated from msync as well.  From a functionality standpoint, I think it's fairly minimal for an atomics package, but I'd rather add than cut stuff later.
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> D-runtime mailing list
> D-runtime at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/d-runtime

December 06, 2009
Yeah, I don't expect the finer-grained barriers to see much use, but I'm hesitant to eliminate the option to have them altogether.  I was hoping it would be enough to have fully synchronized be the default, and just hang a big "Here be Dragons" above the msync enum.

On Dec 6, 2009, at 9:57 PM, Brad Roberts wrote:

> My biggest problem with this design is that it encourages people to try to optimize their atomic ops.  The vast majority of people will get it wrong.  If it was me, I'd only have fully sequenced operations.  If you really need anything else, there's always inline asm.