Full memory barrier and ExclusiveReceiverGroup

197 views Asked by At

With the following code:

var dispatcherQueue = new DispatcherQueue();

long totalSum = 0;

Arbiter.Activate(
    dispatcherQueue,
    Arbiter.Interleave(
        new TeardownReceiverGroup(),
        new ExclusiveReceiverGroup(
            Arbiter.Receive<ComputationCompleteResult>(
                true,
                portSet,
                computationResult => totalSum += computationResult.Result
            ),
        new ConcurrentReceiverGroup(
            // Imagine that there is a persistent Receiver registered here
        )
    )
);

Do I need to generate a full memory barrier around totalSum += computationResult.Result? The handler in the Receiver registration of the ExclusiveReceiverGroup will be invoked by the thread pool because dispatcherQueue doesn't use a Dispatcher. I've read that the thread pool generates a memory barrier for callbacks it invokes, but does that just guarantee freshness for the callback reference itself?

ExclusiveReceiverGroup doesn't run concurrently with any other code, so incrementing totalSum by computationResult.Result doesn't have to be atomic. I know that Interlocked.Add generates a full fence implicitly, but I just want to see if I can get away without using that even.

This is a theoretical problem. I don't actually have any code like the example code above, and I don't have any use-cases for such code. So, I want to avoid "use Interlocked.Add just in case" answers. This is more a "let's learn something new" question.

1

There are 1 answers

1
spender On

My understanding is that because the ExclusiveReceiverGroup effectively only ever executes a single thread-instance of its delegate at any one time, no (further) memory barrier is required. The whole point of the ExclusiveReceiverGroup is to tackle the pernicious problem of shared state, and as such it's specifically designed so one can avoid locking. This would be regardless of the pool/dispatcher you are using.