public ulong Add(ScaleoutMapping mapping)
{
// keep looping in TryAddImpl until it succeeds
ulong newMessageId;
while (!TryAddImpl(mapping, out newMessageId)) ;
// When TryAddImpl succeeds, record the fact that a message was just added to the
// store. We increment the next free id rather than set it explicitly since
// multiple threads might be trying to write simultaneously. There is a nifty
// side effect to this: _nextFreeMessageId will *always* return the total number
// of messages that *all* threads agree have ever been added to the store. (The
// actual number may be higher, but this field will eventually catch up as threads
// flush data.)
Interlocked.Increment(ref _nextFreeMessageId);
return newMessageId;
}