In my previous post, I mentioned that I had actually 4 implementations proposal and I commented two of them, which were within the drafted requirements but had an issue with fairness: in both cases, one could bypass the thread pool queue altogether.
Let’s turn our attention to the other two, which are interesting because they share a common issue while having radically different approach.
C#, very short one
using System; | |
using System.Threading.Tasks; | |
namespace Seq | |
{ | |
public class Sequencer | |
{ | |
private readonly object _lock = new object(); | |
private Task _task = Task.FromResult(0); | |
public void Dispatch(Action action) | |
{ | |
lock (_lock) | |
{ | |
_task = _task.ContinueWith(_ => action()); | |
} | |
} | |
} | |
} |
Clearly, the .Net version benefits from the TPL features. That being said, they are actually very close as they share the same algorithm: ordering is secured by creating a private queue, and non concurrency is ensured by making sure at most one task is enqueued or executing in the .net threadpool.
Contract is fulfilled, albeit with a steep price in terms of performance, or more precisely latency. As a task is actually dispatched only after the previous one have been executed, there is a minimum delay between two tasks. So, once again there is a fairness issue. It is obvious that non sequenced tasks would be executed faster than sequenced ones.