I needed something similar – I had a method that should only be called once (initialize) and I wanted to implement something similar to the call_once I’ve been using for my C++ development.
- Exactly one execution of exactly one of the functions (passed as
f
to the invocations in the group) is performed. It is undefined which function will be selected for execution. The selected function runs in the same thread as
thecall_once
invocation it was passed to.
- No invocation in the group returns before the abovementioned execution of the selected function is completed successfully, that is, doesn't exit via an exception.
- If the selected function exits via exception, it is propagated to the caller. Another function is then selected and executed.
public static class Call { public static void Once(OnceFlag flag, Action action) { if (flag.CheckIfNotCalledAndSet) { action.Invoke(); } } }
public class OnceFlag { private const int NotCalled = 0; private const int Called = 1; private int _state = NotCalled; internal bool CheckIfCalledAndSet { get { var prev = Interlocked.Exchange(ref _state, Called); return prev == NotCalled; } } internal void Reset() { Interlocked.Exchange(ref _state, NotCalled); } }
class Program { static OnceFlag _flag = new OnceFlag(); static void Main(string[] args) { var t1 = new Thread(() => DoOnce(1)); var t2 = new Thread(() => DoOnce(2)); var t3 = new Thread(() => DoOnce(3)); var t4 = new Thread(() => DoOnce(4)); t1.Start(); t2.Start(); t3.Start(); t4.Start(); t1.Join(); t2.Join(); t3.Join(); t4.Join(); } private static void DoOnce(int index) { Call.Once(_flag, () => Console.WriteLine("Callled (" + index + ")")); } }
public static void Once(OnceFlagSimple flag, Action action) { lock (flag) { if (flag.CheckIfNotCalled) { action.Invoke(); flag.Set(); } } }
Labels: .NET, async, C#, Multi-threading