patterncsharpMinor
A thread-safe initialization guard
Viewed 0 times
initializationthreadguardsafe
Problem
I have written a type with the following public API:
The intention is to use it in services that require initialization, possibly asynchronous with multiple threads attempting to initialize them at once. Something like this:
The idea is to save having to write this kind of guard logic in every service.
My questions are:
Here is the full code (apart from
InitializationGuard
```
using System.Diagnostics;
using System.Threading;
[DebuggerDisplay("Initialized: {IsInitialized}")]
public sealed class InitializationGuard
{
private const int Uninitialized = 0;
private const int Initializing = 1;
private const int Initialized = 2;
private int initializationState;
public sealed class InitializationGuard
{
public bool IsUninitialized
{
get;
}
public bool IsInitializing
{
get;
}
public bool IsInitialized
{
get;
}
public InitializationTransaction BeginInitialization();
public bool TryBeginInitialization(out InitializationTransaction initializationTransaction);
public void EnsureInitialized();
}The intention is to use it in services that require initialization, possibly asynchronous with multiple threads attempting to initialize them at once. Something like this:
public sealed class SomeService : ISomeService
{
private readonly InitializationGuard initializationGuard = new InitializationGuard();
public async Task Initialize()
{
using (var transaction = this.initializationGuard.BeginInitialization())
{
await SomeInitLogic();
transaction.Commit();
}
}
public async Task DoSomethingThatRequiresInitialization()
{
this.initializationGuard.EnsureInitialized();
await SomeOtherLogic();
}
}The idea is to save having to write this kind of guard logic in every service.
My questions are:
- is this a valid approach?
- am I kidding myself that this is truly thread-safe?
- is there perhaps a better approach to the implementation? I'm not particularly happy with the pattern that emerges when using
TryBeginInitialization(), but am not really sure of any viable alternative
Here is the full code (apart from
DisposableBase, which just provides thread-safety when disposing):InitializationGuard
```
using System.Diagnostics;
using System.Threading;
[DebuggerDisplay("Initialized: {IsInitialized}")]
public sealed class InitializationGuard
{
private const int Uninitialized = 0;
private const int Initializing = 1;
private const int Initialized = 2;
private int initializationState;
Solution
private const int Uninitialized = 0;
private const int Initializing = 1;
private const int Initialized = 2;These constants really smell like they want to be an
enum.public bool IsUninitialized
{
get { return this.IsInInitializationState(Uninitialized); }
}
public bool IsInitializing
{
get { return this.IsInInitializationState(Initializing); }
}
public bool IsInitialized
{
get { return this.IsInInitializationState(Initialized); }
}With an
enum InitializationState you wouldn't need these three getters, and could simply make IsInInitializationState public, taking an InitializationState parameter instead of an int, and this.initializationState would be an InitializationState instead of an int, too. The naming already seems to be asking for that.Code Snippets
private const int Uninitialized = 0;
private const int Initializing = 1;
private const int Initialized = 2;public bool IsUninitialized
{
get { return this.IsInInitializationState(Uninitialized); }
}
public bool IsInitializing
{
get { return this.IsInInitializationState(Initializing); }
}
public bool IsInitialized
{
get { return this.IsInInitializationState(Initialized); }
}Context
StackExchange Code Review Q#77942, answer score: 2
Revisions (0)
No revisions yet.