Atomic wait-then-take operation on number - c#

I have the following class:
public class AtomicLong
{
private long initial;
private long value;
public AtomicLong(long value = 0)
{
this.initial = value;
this.value = value;
}
public class Handle : IDisposable
{
private AtomicLong source;
private long amount;
public Handle(AtomicLong source, long amount)
{
this.source = source;
this.amount = amount;
}
public void Dispose()
{
if (source == null)
return;
Interlocked.Add(ref source.value, amount);
source = null;
}
}
public Handle Claim(long amount)
{
if (amount > initial)
throw new ArgumentOutOfRangeException("amount", amount, "Must be no more than the initial amount.");
if (amount < 0)
throw new ArgumentOutOfRangeException("amount", amount, "Must be nonnegative.");
while (true)
{
var oldValue = Interlocked.Read(ref value);
var newValue = oldValue - amount;
if (newValue >= 0 &&
oldValue == Interlocked.CompareExchange(ref value, newValue, oldValue))
{
return new Handle(this, amount);
}
}
}
}
An example usage of this is that I can have a single AtomicLong unusedMemory which represents the current number of bytes of memory available to a set of workers. (It's not meant to be anywhere near exact - it's just a rough measure.) I then do this on a bunch of different worker threads:
while (true)
{
var unitOfWork = WaitForUnitOfWork();
long requiredMemory = unitOfWork.RequiredMemory;
using (var handle = unusedMemory.Claim(requiredMemory))
{
//wait until requireMemory can be claimed from unusedMemory
//do work with reserved memory, represented by handle
//when handle disposes, memory is released back to the unusedMemory
}
}
The problem with my AtomicLong class is that calls to Claim will busy-wait until they return. I'd like to fix this by using some kind of OS-level wait handle abstraction.
Can you suggest how I could go about doing that?
Motivation
Consider the following scenario:
unusedMemory starts with an initial value of 10GB (10 << 30)
100 worker threads
10 units of work, each taking 10GB and 1 minute to perform
first worker calls Claim(10 << 30) and it nearly-immediately returns
it begins doing work that will finish after 1 minute
some 9 other workers make an identical call to Claim(10 << 30) and do a "bad" busy wait for 1 minute
9 threads doing something like a while(true){/*do nothing*/} loop in the Claim method!
lots of needless CPU usage
the rest of the workers (90) do a "good" OS-level wait in the WaitForUnitOfWork() method
The important point: Claim is only "cheap" if the requested amount of memory is actually available to be claimed. If it isn't, busy-waiting happens until it is available.
Just to be entirely clear, in the Claim method, I'm pointing out the exact expression which makes all the difference (newValue >= 0):
while (true)
{
var oldValue = Interlocked.Read(ref value);
var newValue = oldValue - amount;
if (newValue >= 0 && // <--------------------------- THIS IS THE PROBLEM
oldValue == Interlocked.CompareExchange(ref value, newValue, oldValue))
{
return new Handle(this, amount);
}
}
The question is not about whether Interlocked.CompareExchange is going to be expensive - I'm aware it's cheap. The question is about how to deal with the busy-waiting that occurs in the case when the amount a caller wants to Claim is currently greater than the amount in the AtomicLong.
If you have a completely different approach to solving this kind of problem, or see some flaw in what I already have, I'd like to hear about that too!

You have several options.
For instance, you can create a smarter busy-wait, by putting the active thread to sleep for a given time interval, so it doesn't always check your condition, but it does it periodically.
Another solution is to create a custom event and wait for that event in your active thread, and you can define a custom event which will fulfill your task I believe.
You can read more about events here. You can read about custom event creation here.

Here's the solution I came up with:
Parameters
obj: the synchronization object used by Monitor
pollIterval: the rate at which calls will poll until a successful transaction attempt
value: the value being modified by the transaction
precondition: an optional condition that must be true at the start of the transaction
transform: the operation that changes the value
postcondition: an optional condition that must be true at the end of the transaction
Code
public static class AtomicHelper
{
public static void LongTransaction(
object obj,
TimeSpan pollInterval,
ref long value,
Func<long, bool> precondition,
Func<long, long> transform,
Func<long, bool> postcondition)
{
while (true)
{
var oldValue = Interlocked.Read(ref value);
if (precondition != null && !precondition(oldValue))
{
Monitor.Wait(obj, pollInterval);
continue;
}
var newValue = transform(oldValue);
if (postcondition != null && !postcondition(newValue))
{
Monitor.Wait(obj, pollInterval);
continue;
}
if (Interlocked.CompareExchange(ref value, newValue, oldValue) == oldValue)
{
Monitor.PulseAll(obj);
return;
}
}
}
}
Example Usage
long n = 10;
object obj = new object();
//On many different threads, run this concurrently:
AtomicHelper.LongTransaction(
obj,
TimeSpan.FromSeconds(1),
ref n,
null,
x => x - 1,
x => x >= 0);
Thread.Sleep(TimeSpan.FromSeconds(3));
AtomicHelper.LongTransaction(
obj,
TimeSpan.Zero,
ref n,
null,
x => x + 1,
null);

Related

Best solution for stopping a piece of code to be called multiple times?

I have a method which is been called every 1 hour. But sometimes the method operations are not been completed fully within one hour and the method is again been called which causes confusion. So I have to find out if the previous method is been completed. Which is the best solution for this problem?
// will be called for every one hour where the value will be repeated
// At sometimes it is possible for the same value to be called continually
for the next hour and at that time problem occurs
Void Method(int value)
{
If(value =0)
// Do some operations which may exceed one hour
Else If(value =1)
// Do some operation’s which may exceed one hour
.
.
.
}
Thanks,
One question would be what do you want to happen if the method is called while it is still running?
This code will just drop the 2nd call
private bool _running = false;
private readonly object _lock = new object();
void Method(int value)
{
lock (_lock)
{
if (_running)
{
return;
}
else
{
_running = true;
}
}
if (value == 0)
{
// Do some operations which may exceed one hour
}
else if (value == 1)
{
// Do some operation’s which may exceed one hour
}
_running = false;
}
A simple idea is to save the state in a class field, so that the method checks to see if it's free to do some work or not. This will mean that if you call the method and it's busy, the work won't happen for your call:
private static bool methodIsBusy = false;
private static void WaitAndWriteMessage(TimeSpan waitTime, string message)
{
// If we're busy, return right away
if (methodIsBusy) return;
// Let future calls know we're busy
methodIsBusy = true;
Thread.Sleep(waitTime);
Console.Write($"Method ran at: {DateTime.Now.ToString("hh:mm:ss")}. ");
Console.WriteLine(message);
// Allow future calls to run now
methodIsBusy = false;
}
Our test method:
private static void Main()
{
for(int i = 0; i < 3; i++)
{
Task.Run(() => WaitAndWriteMessage(TimeSpan.FromSeconds(5),
$"Method called at {DateTime.Now.ToString("hh:mm:ss")}."));
Thread.Sleep(1000);
}
Console.ReadKey();
GetKeyFromUser("\nDone!\nPress any key to exit...");
}
Output
(Only the first of the three messages was printed)
Another idea is to use a lock, which means that calls to the method will pile up if the method is busy. All calls will eventually get completed, but if every call is longer than the iteration time in which the method is called, it will get further and further behind:
private static object methodLocker = new object();
private static void WaitAndWriteMessage(TimeSpan waitTime, string message)
{
// Lock on a common object, so this call will wait
// until there are no locks before it can continue
lock (methodLocker)
{
Thread.Sleep(waitTime);
Console.Write($"Method ran at: {DateTime.Now.ToString("hh:mm:ss")}. ");
Console.WriteLine(message);
}
}
Our test method again:
private static void Main()
{
for(int i = 0; i < 3; i++)
{
Task.Run(() => WaitAndWriteMessage(TimeSpan.FromSeconds(5),
$"Method called at {DateTime.Now.ToString("hh:mm:ss")}."));
Thread.Sleep(1000);
}
Console.ReadKey();
}
Output
(Notice the difference between when the message was called and when it executed gets longer each time)

Locking and ref values from external function

I'm trying to track down a bug that I think might be related to the applications multithreading. I've simplified the code below:
class Outer {
private static int count;
//this function is called from multiple threads in quick succession
public void DoFoo() {
Inner.Increment(ref count);
}
}
class Inner {
private readonly static object mLock = new object();
public static string Increment(ref count) {
lock (mLock) (
if (count > 1000)
count = 0;
count++;
}
return count.ToString();
}
}
Can the locking guarantee the safety of a variable passed in that way? Is there any copying of count going on that seems non-obvious and may break the memory safety? I was thinking it might return a new int and do the assignment at the end of the method or something. Apart from that it's my understanding that the lock section would handle any caching issues.
The error which bought the issue to our attention was seemingly one of the threads having a stale version of count.
The problem here is that some other thread could read directly Outer.count when it is == 0, because you can access Outer.count without first having obtained a lock (normally as written in your code, count can be 0 only before the first call to Inner.Increment, from then on it can only have a value between 1 and 1001)
Lockless can be done in this way:
class Inner
{
public static string Increment(ref int count)
{
while (true)
{
int original = count;
int next = original;
if (next > 1000)
{
next = 0;
}
next++;
if (Interlocked.CompareExchange(ref count, next, original) == original)
{
return next.ToString();
}
}
}
}
I'm calculating a next value and using it (through Interlocked.CompareExchange) only if count hasn't changed in the meantime.

Howto avoid concurrently calling a method without blocking?

I want to run a cleanup task that might run for several seconds. Multiple threads could call this task but I want to run this task only once. All other invokations should just skip.
The following is my current implementation but I cannot imagine there is not a better solution in the .net framework resulting in less lines of code.
object taskLock;
bool isRunning;
void Task()
{
if (isRunning) return;
try
{
lock (taskLock)
{
if (isRunning) return;
isRunning = true;
}
// Perform the magic
}
finally
{
isRunning = false;
}
}
Yes, there is a better solution. You can use Interlocked.CompareExchange, the code becomes simpler and lock-free:
class Worker
{
private volatile int isRunning = 0;
public void DoWork()
{
if (isRunning == 0 && Interlocked.CompareExchange(ref isRunning, 1, 0) == 0)
{
try
{
DoTheMagic();
}
finally
{
isRunning = 0;
}
}
}
private void DoTheMagic()
{
// do something interesting
}
}
In this case Interlocked.CompareExchange does the following as an atomic operation (pseudo-code):
wasRunning = isRunning;
if isRunning = 0 then
isRunning = 1
end if
return wasRunning
From the MSDN documentation:
public static int CompareExchange(
ref int location1,
int value,
int comparand
)
If comparand and the value in location1 are equal, then value is
stored in location1. Otherwise, no operation is performed. The compare
and exchange operations are performed as an atomic operation. The
return value of CompareExchange is the original value in location1,
whether or not the exchange takes place

Correct way to implement a resource pool

I'm trying to implement something that manages a pool of resources such that the calling code can request an object and will be given one from the pool if it's available, or else it will be made to wait. I'm having trouble getting the synchronization to work correctly however. What I have in my pool class is something like this (where autoEvent is an AutoResetEvent initially set as signaled:
public Foo GetFooFromPool()
{
autoEvent.WaitOne();
var foo = Pool.FirstOrDefault(p => !p.InUse);
if (foo != null)
{
foo.InUse = true;
autoEvent.Set();
return foo;
}
else if (Pool.Count < Capacity)
{
System.Diagnostics.Debug.WriteLine("count {0}\t capacity {1}", Pool.Count, Capacity);
foo = new Foo() { InUse = true };
Pool.Add(foo);
autoEvent.Set();
return foo;
}
else
{
return GetFooFromPool();
}
}
public void ReleaseFoo(Foo p)
{
p.InUse = false;
autoEvent.Set();
}
The idea is when you call GetFooFromPool, you wait until signaled, then you try and find an existing Foo that is not in use. If you find one, we set it to InUse and then fire a signal so other threads can proceed. If we don't find one, we check to see if the the pool is full. If not, we create a new Foo, add it to the pool and signal again. If neither of those conditions are satisfied, we are made to wait again by calling GetFooFromPool again.
Now in ReleaseFoo we just set InUse back to false, and signal the next thread waiting in GetFooFromPool (if any) to try and get a Foo.
The problem seems to be in my managing the size of the pool. With a capacity of 5, I'm ending up with 6 Foos. I can see in my debug line count 0 appear a couple of times and count 1 might appear a couple of times also. So clearly I have multiple threads getting into the block when, as far as I can see, they shouldn't be able to.
What am I doing wrong here?
Edit: A double check lock like this:
else if (Pool.Count < Capacity)
{
lock(locker)
{
if (Pool.Count < Capacity)
{
System.Diagnostics.Debug.WriteLine("count {0}\t capacity {1}", Pool.Count, Capacity);
foo = new Foo() { InUse = true };
Pool.Add(foo);
autoEvent.Set();
return foo;
}
}
}
Does seem to fix the problem, but I'm not sure it's the most elegant way to do it.
As was already mentioned in the comments, a counting semaphore is your friend.
Combine this with a concurrent stack and you have got a nice simple, thread safe implementation, where you can still lazily allocate your pool items.
The bare-bones implementation below provides an example of this approach. Note that another advantage here is that you do not need to "contaminate" your pool items with an InUse member as a flag to track stuff.
Note that as a micro-optimization, a stack is preferred over a queue in this case, because it will provide the most recently returned instance from the pool, that may still be in e.g. L1 cache.
public class GenericConcurrentPool<T> : IDisposable where T : class
{
private readonly SemaphoreSlim _sem;
private readonly ConcurrentStack<T> _itemsStack;
private readonly Action<T> _onDisposeItem;
private readonly Func<T> _factory;
public GenericConcurrentPool(int capacity, Func<T> factory, Action<T> onDisposeItem = null)
{
_itemsStack = new ConcurrentStack<T>(new T[capacity]);
_factory = factory;
_onDisposeItem = onDisposeItem;
_sem = new SemaphoreSlim(capacity);
}
public async Task<T> CheckOutAsync()
{
await _sem.WaitAsync();
return Pop();
}
public T CheckOut()
{
_sem.Wait();
return Pop();
}
public void CheckIn(T item)
{
Push(item);
_sem.Release();
}
public void Dispose()
{
_sem.Dispose();
if (_onDisposeItem != null)
{
T item;
while (_itemsStack.TryPop(out item))
{
if (item != null)
_onDisposeItem(item);
}
}
}
private T Pop()
{
T item;
var result = _itemsStack.TryPop(out item);
Debug.Assert(result);
return item ?? _factory();
}
private void Push(T item)
{
Debug.Assert(item != null);
_itemsStack.Push(item);
}
}
There are a few problems with what you're doing, but your specific race condition is likely caused by a situation like the following. Imagine you have a capacity of one.
1) There is one unused item in the pool.
2) Thread #1 grabs it and signals the event.
3) Thread #2 finds no available event and gets inside the capacity block. It does not add the item yet.
4) Thread #1 returns the item to the pool and signals the event.
5) Repeat steps 1, 2, and 3 using two other threads (e.g. #3, #4).
6) Thread #2 adds an item to the pool.
7) Thread #4 adds an item to the pool.
There are now two items in a pool with a capacity of one.
Your implementation has other potential issues, however.
Depending on how your Pool.Count and Add() are synchronized, you might not see an up-to-date value.
You could potentially have multiple threads grab the same unused item.
Controlling access with an AutoResetEvent opens yourself up to difficult to find issues (like this one) because you are trying to use a lockless solution instead of just taking a lock and using Monitor.Wait() and Monitor.Pulse() for this purpose.

lock-free calc: how to sum N double numbers that are changing by other threads?

upd: Let me rephrase my question shortly.
There are N double numbers. There are N dedicated threads each of them update own double number (_cachedProduct in the example below).
Somehow I need to have sum of these numbers and I need IndexUpdated event to be raised ASAP after any double number is changed (it would be nice if such event can be raised in 10 µs or less).
Below is how I tried to implement this task
===============================================
To calculate stock exchange index I create private double[] _cachedProduct; field. These field is written
by many threads
// called from another threads
public override void InstrumentUpdated(Instrument instrument)
{
if (!_initialized)
{
if (!Initialize())
{
return;
}
}
int instrumentId = instrument.Id;
OrderBook ob = Program.market.OrderBook(instrument);
if (ob.MedianOrAskOrBid == null)
{
_cachedProduct[instrumentId] = 0;
}
else
{
_cachedProduct[instrumentId] = ((double) ob.MedianOrAskOrBid)*_ammounts[instrumentId];
}
}
_ammounts is pre-initialized array and please ignore Initialize method and variable - they just works.
In loop I just sum all _cachedProduct and when values changes I notify others.
Task.Factory.StartNew(() =>
{
while(true)
{
if (_initialized)
{
break;
}
}
while (true)
{
CalculateAndNotify();
//Thread.Sleep(5);
}
}
, TaskCreationOptions.LongRunning);
protected void CalculateAndNotify()
{
var oldValue = Value;
Calculate();
if (oldValue != Value)
{
NotifyIndexChanged();
}
}
protected override void Calculate()
{
double result = 0;
for (int i = 0; i < _instrumentIds.Count(); i++)
{
int instrumentId = _instrumentIds[i];
if (_cachedProduct[instrumentId] == 0)
{
Value = null;
return;
}
result += _cachedProduct[instrumentId];;
}
Value = result;
}
I must use Interlocked to update my double _cachedProduct values but please ignore that fact now, what other problems with this code do you see?
Should I call Calculate method inside while(true) so I always use one core without delays. My machine has 24 cores so I was thinking this is ok.
However without Thread.Sleep(5) (commented) I do see significant slow-down in the program overall and I do not understand why. Program executes several dozens times slower in many places.
The question is if my idea of using while(true) without any locking at all is OK. Or should I introduce some locking method so I would only Calculate index when one of of _cachedProduct is updated?
I think you might get better performance and clearer code if you do not use an extra thread and loop for your sum. On every change to an instrument you calculate the difference and immediately update the index and perform the notify
So if a thread calls InstrumentUpdated for a single instrument;
change = newvalue - currentvalue;
// used interlocked here to change the index threadsafe
StockExchangeSum = Interlocked.Add(ref StockExchangeSum,change);
NotifyIndexChanged();
Can double[] be a more complex type?
How does WaitHandle.WaitAny compare performance wise?
Something like as follows.
private Index[] indicies;
public class Index
{
public WaitHandle Updated =
new EventWaitHandle(false, EventResetMode.AutoReset);
public double _value;
public double Value
{
get {return _value;}
set
{
if(_value != value)
{
_value = value;
Updated.Set();
}
}
}
}
TaskFactory.StartNew(() =>
{
while(true)
{
WaitHandle.Any(indicies.Select(i => i.Updated));
CalculateAndNotify();
}
});
Some points for you to think about
Have you tried profiling your calculation block in isolation to the rest of the code? I noticed this in your Calculate function:
for (int i = 0; i < _instrumentIds.Count(); i++)
_instrumentIds.Count() invokes an iteration over the entire collection and it is possible this is invoked for each trip around the loop. i.e. you are doing N^2/2 iterations of _instrumentIds
Is the _instrumentIdsIEnumerable being modified during this calculation operation? If so you could get all sorts of race conditions leading to incorrect answers.
Is the Task containing CalculateAndNotify called once or is it called many times (nested)? E.g. is there some operation inside CalculateAndNotify that could cause it to be triggered recursively?
If so, you might find you have several calculations performing simultaneously (using more than one thread until the pool is starved). Can you include some logging on start/end of operation and perhaps count the number of simultaneous calculations to check this?
If this is an issue you could include some logic whereby the CalculateAndNotify operation is queued up and new calculate operations cannot be executed until the previous has completed.

Categories