Skip to content

Instantly share code, notes, and snippets.

@lafar6502
Last active January 26, 2021 06:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save lafar6502/8105682 to your computer and use it in GitHub Desktop.
Save lafar6502/8105682 to your computer and use it in GitHub Desktop.
some messy code of a synchronization gateway that allows only a single thread of execution for all passed callbacks. It allows new callbacks to be enqueued while they are being executed by another thread. This implementation is almost certainly broken because I didn't care if it compiles at all and if all closure stuff is done correctly, but hop…
public class ConcurrentGateway
{
private ConcurrentQueue<Action> _workQueue = new ConcurrentQueue<Action>();
private int _writeLock = 0;
[ThreadStatic]
private static AutoResetEvent _waitEvent = new AutoResetEvent(false);
protected static AutoResetEvent GetThreadWaitEvent()
{
var ev = _waitEvent;
if (ev == null)
{
ev = new AutoResetEvent(false);
_waitEvent = ev;
}
return ev;
}
public void DoSynchronized(Action act)
{
bool done = false;
var ev = GetThreadWaitEvent();
_workQueue.Enqueue(delegate() //enqueue the work TBD
{
act();
done = true;
ev.Set();
});
int lk = Interlocked.CompareExchange(ref _writeLock, 1, 0);
if (lk == 0)
{ //I'm a writer thread, do all the work now
Action a2;
while(_workQueue.TryDequeue(out a2)) {
a2();
}
var ov = Interlocked.Exchange(ref _writeLock, 0);
System.Diagnostics.Debug.Assert(ov == 1); //release
}
else
{ //i'm not a writer so I have to wait
if (lk != 1) throw new Exception("LK: " +lk);
while (!done)
{
ev.WaitOne();
}
}
}
}
//with a dedicated handler thread
public class ThreadedConcurrentGateway
{
private ConcurrentQueue<Action> _workQueue = new ConcurrentQueue<Action>();
private Thread _worker;
public ThreadedConcurrentGateway()
{
_worker = new Thread(new ThreadStart(() => {
Action act;
Console.WriteLine("GW thread started");
while (true)
{
if (_workQueue.TryDequeue(out act))
{
act();
}
else
{
_wakeUp.WaitOne();
}
}
}));
_worker.Start();
}
private AutoResetEvent _wakeUp = new AutoResetEvent(false);
[ThreadStatic]
private static AutoResetEvent _waitEvent = new AutoResetEvent(false);
protected static AutoResetEvent GetThreadWaitEvent()
{
var ev = _waitEvent;
if (ev == null)
{
ev = new AutoResetEvent(false);
_waitEvent = ev;
}
return ev;
}
public void DoSynchronized(Action act)
{
bool done = false;
var ev = GetThreadWaitEvent();
_workQueue.Enqueue(delegate() //enqueue the work TBD
{
act();
done = true;
ev.Set();
});
_wakeUp.Set();
while (!done)
{
ev.WaitOne();
}
}
}
@lafar6502
Copy link
Author

This code compiles and runs, but alomst certainly is not correct - there are race conditions just waiting to happen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment