Click here to Skip to main content
Click here to Skip to main content

Implement Thread Safe One-shot Bool Flag with Interlocked.Exchange()

, 4 Dec 2013
Rate this:
Please Sign up or sign in to vote.
Wrapping Interlocked.Exchange to mimic a thread safe one-shot bool flag

Introduction

While studying several articles on the C# IDisposable pattern (e.g. Implementing IDisposable and the Dispose Pattern Properly[^]), I was contemplating on the thread safe access of the Dispose() method.

If I have the need to program code that runs exactly once in a multi-threaded environment, there are several approaches. Let's look into some alternatives:

Ignorant Approach

The ignorant approach simply does not care about multi-threading - no good.

Ignorant
bool _called = false;
//...
void Ignorant()
{
    if (!_called)
    {
        _called = true;
        // ...do once... -- maybe not! --
    }
}

Locked Access

These approaches take care of multi-threading issues. But they are both a bit verbose, and one has to not forget setting the lock properly (not to talk forgetting to reset the state so that it cannot be called anymore). This is probably the most common way to do it, which does not mean that it is the best way, though... Wink | ;)

Excessive (lock for the whole computation) Smarter (only lock while check-and-set the called state)
bool _called = false;
//...
void ExcessiveLocking()
{
    lock (this)
    {
        if (!_called)
        {
            _called = true;
            // ...do once...
        }
    }
}


bool _called = false;
//...
void SmarterLocking()
{
    bool called = _called;
    lock(this)
    {
        called = _called;
        _called = true;
    }
    if (!called)
    {
        // ...do once...
    }
}

Interlocked.Exchange

This is the less known approach. The uneasy thing is, that there is no Interlocked functions for bool. Not so nice to introduce states for something that is naturally handled by boolean value.

Interlocked with int state
const int NOTCALLED = 0;
const int CALLED = 1;
int _state = NOTCALLED;
//...
void InterlockedCheck()
{
    if (Interlocked.Exchange(ref _state, CALLED) == NOTCALLED)
    {
        // ...do once...
    }
}

ThreadSafeOneShotFlag

First the intended usage:

Explicit call Mimic bool
ThreadSafeSingleShotFlag _calledOnce = false;
//...
void SingleShotExplicit()
{
    if (_calledOnce.CheckAndSetFirstCall)
    {
        // ...do once...
    }
}
ThreadSafeSingleShotFlag _calledOnce = false;
//...
void SingleShotMimicBool()
{
    if (!_calledOnce)
    {
        // ...do once...
    }
}

The above code mimics the bool behavior: init by false (= not called yet). And allowing to check and set the called flag. What may be disturbing is the fact that the ! operator not only returns the value, but also sets it. No need to set the value to true within the block. Therefore I provide the explicit access too.

Here goes the code:

/// <summary>Flag-like class that returns at most once the value true.</summary>
/// <example>
/// <code>
/// ThreadSafeSingleShot calledOnce = false;
/// ...
/// if (!calledOnce) // returns with the first call the initial value 
/// and then returns always false
/// {
///    ...
/// }
/// </code>
/// </example>
public class ThreadSafeSingleShotFlag
{
    private static int INIT = 0;
    private static int CALLED = 1;
    private int _state = INIT;
    /// <summary>Explicit call to check and set if this is the first call</summary>
    public bool CheckAndSetFirstCall
    { get { return Interlocked.Exchange(ref _state, CALLED) == INIT;  } }
    
    /// <summary>usually init by false</summary>
    public static implicit operator ThreadSafeSingleShotFlag (bool called)
    {
        return new ThreadSafeSingleShotFlag() { _state = called ? CALLED : INIT };
    }
    /// <summary>if init to false, returns true with the first call, then always false - 
    /// if init to true, always returns false.</summary>
    public static bool operator !(ThreadSafeSingleShotFlag obj)
    {
        return obj.CheckAndSetFirstCall;
    }
}

ThreadSafeSingleShotGuard

Instead of trying to mimic a boolean type (and therefore confusing developers), it might be advised to implement a pure wrapper for the Interlocked.Exchange for a bool. This makes it less vulnerable to unintended use.

First again the intended use:

Mimic Interlocked for bool
ThreadSafeOneShotGuard _guard = ThreadSafeOneShotGuard();
//...
void GuardCheck()
{
    if (_guard.CheckAndSetFirstCall)
    {
        // ...do once...
    }
}

And the respective implementation of the guard class:

/// <summary>
/// Thread safe enter once into a code block:
/// the first call to CheckAndSetFirstCall returns always true,
/// all subsequent call return false.
/// </summary>
public class ThreadSafeSingleShotGuard
{
    private static int NOTCALLED = 0;
    private static int CALLED = 1;
    private int _state = NOTCALLED;
    /// <summary>Explicit call to check and set if this is the first call</summary>
    public bool CheckAndSetFirstCall
    { get { return Interlocked.Exchange(ref _state, CALLED) == NOTCALLED; } }
}

Important Note

The ThreadSafeSingleShotGuard could be used in Dispose pattern, where as the ThreadSafeSingleShotFlag is a bit dangerous: A Dispose() method should never allocate memory. With the ThreadSafeSingleShotFlag, one could use _calledOnce = true;, which would allocate a new object... which is bad. So, don't use the ThreadSafeSingleShotFlag - use ThreadSafeSingleShotGuard instead.

Summary

If Interlocked.Exchange would provide bool support, the whole tip would stop at the respective section above.

This single shot Guard is an attempt to mimic a thread safe one shot flag of the non thread safe form: if (!flag) { flag = true; ... }. It mimics Interlocked.Exchange for bool to ensure that a block is called only once in a multi-threaded environment. If properly used, it could make code more robust. E.g. it could be used in the Dispose pattern to make it thread safe.

ThreadSafeSingleShotGuard _disposeGuard = new ThreadSafeSingleShotGuard();
...
protected virtual void Dispose(bool disposing)
{
   if (_disposeGuard.CheckAndSetFirstCall)
   {
       if (disposing)
       ...
   }
}

I prefer the ThreadSafeSingleShotGuard over the ThreadSafeSingleShotFlag since the guard has less bells and whistles that can cause problems (e.g. no implicit conversion, no surprise in the not-operator (is not a pure function[^] in the given solution of the Flag class), etc.).

Comments are very welcome, especially, how others deal with the issue of not having bool support in the Interlocked class. Which of the above alternatives (or any further) are in real life use?

History

  • V1.0 2012-04-30 Initial version
  • V1.1 2012-04-30 Enhanced summary
  • V1.2 2012-04-30 Add Guard class to replace Flag class to make the solution more robust
  • V1.3 2013-12-04 Fix "Smarter" lock code (thanks to tommy008)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Andreas Gieriet
Founder eXternSoft GmbH
Switzerland Switzerland
I feel comfortable on a variety of systems (UNIX, Windows, cross-compiled embedded systems, etc.) in a variety of languages, environments, and tools.
I have a particular affinity to computer language analysis, testing, as well as quality management.
 
More information about what I do for a living can be found at my LinkedIn Profile and on my company's web page (German only).
Follow on   LinkedIn

Comments and Discussions

 
QuestionNice one, a 5 PinmemberHaBiX4-Dec-13 8:35 
AnswerRe: Nice one, a 5 [modified] PinprofessionalAndreas Gieriet4-Dec-13 11:53 
GeneralThoughts PinprofessionalPIEBALDconsult4-Dec-13 8:05 
GeneralRe: Thoughts PinprofessionalAndreas Gieriet4-Dec-13 11:50 
QuestionDispose should NOT be thread-safe PinmemberWilliam E. Kempf4-Dec-13 6:29 
AnswerRe: Dispose should NOT be thread-safe PinprofessionalAndreas Gieriet4-Dec-13 11:48 
BugLocked Access Smater will never do once Pinmembertonny0084-Dec-13 2:32 
GeneralRe: Locked Access Smater will never do once [modified] PinprofessionalAndreas Gieriet4-Dec-13 4:36 
QuestionWhy not just use C# volatile bool for the flag? [modified] PinmemberIvan Pechorin24-Nov-13 11:32 
AnswerRe: Why not just use C# volatile bool for the flag? PinprofessionalAndreas Gieriet24-Nov-13 22:04 
GeneralMy vote of 3 Pinmemberjfriedman30-Apr-12 13:27 
GeneralRe: My vote of 3 PinprofessionalAndreas Gieriet24-Nov-13 22:06 
GeneralRe: My vote of 3 PinmemberHaBiX4-Dec-13 8:39 
GeneralRe: My vote of 3 Pinprofessionaljfriedman4-Dec-13 9:36 
QuestionClever but potentially misleading PinadminChris Maunder30-Apr-12 1:55 
AnswerRe: Clever but potentially misleading [modified] PinmemberAndreas Gieriet30-Apr-12 4:08 
GeneralRe: Clever but potentially misleading PinadminChris Maunder30-Apr-12 6:31 
GeneralRe: Clever but potentially misleading (Not bad but why not using Monitor?) PinmemberMember 342354613-Dec-12 17:43 
GeneralRe: Clever but potentially misleading (Not bad but why not using Monitor?) PinmemberMember 342354613-Dec-12 17:58 
GeneralRe: Clever but potentially misleading (Not bad but why not using Monitor?) PinmemberAndreas Gieriet16-Dec-12 12:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140902.1 | Last Updated 4 Dec 2013
Article Copyright 2012 by Andreas Gieriet
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid