summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Core/LockingSemaphore.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Core/LockingSemaphore.cs')
-rw-r--r--Xamarin.Forms.Core/LockingSemaphore.cs51
1 files changed, 51 insertions, 0 deletions
diff --git a/Xamarin.Forms.Core/LockingSemaphore.cs b/Xamarin.Forms.Core/LockingSemaphore.cs
new file mode 100644
index 00000000..b9fd20a9
--- /dev/null
+++ b/Xamarin.Forms.Core/LockingSemaphore.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ internal class LockingSemaphore
+ {
+ static readonly Task Completed = Task.FromResult(true);
+ readonly Queue<TaskCompletionSource<bool>> _waiters = new Queue<TaskCompletionSource<bool>>();
+ int _currentCount;
+
+ public LockingSemaphore(int initialCount)
+ {
+ if (initialCount < 0)
+ throw new ArgumentOutOfRangeException("initialCount");
+ _currentCount = initialCount;
+ }
+
+ public void Release()
+ {
+ TaskCompletionSource<bool> toRelease = null;
+ lock(_waiters)
+ {
+ if (_waiters.Count > 0)
+ toRelease = _waiters.Dequeue();
+ else
+ ++_currentCount;
+ }
+ if (toRelease != null)
+ toRelease.TrySetResult(true);
+ }
+
+ public Task WaitAsync(CancellationToken token)
+ {
+ lock(_waiters)
+ {
+ if (_currentCount > 0)
+ {
+ --_currentCount;
+ return Completed;
+ }
+ var waiter = new TaskCompletionSource<bool>();
+ _waiters.Enqueue(waiter);
+ token.Register(() => waiter.TrySetCanceled());
+ return waiter.Task;
+ }
+ }
+ }
+} \ No newline at end of file