blob: 4f5eeee57206660bc6375023fe381efb788ef7df (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
#if NO_SEMAPHORE && SILVERLIGHT
using System;
using System.Threading;
namespace System.Reactive.Threading
{
//Monitor based implementation of Semaphore
//that mimicks the .NET Semaphore class (System.Threading.Semaphore)
internal sealed class Semaphore : IDisposable
{
private int m_currentCount;
private readonly int m_maximumCount;
private readonly object m_lockObject;
private bool m_disposed;
public Semaphore(int initialCount, int maximumCount)
{
if (initialCount < 0)
{
throw new ArgumentOutOfRangeException("initialCount", "Non-negative number required.");
}
if (maximumCount < 1)
{
throw new ArgumentOutOfRangeException("maximumCount", "Positive number required.");
}
if (initialCount > maximumCount)
{
throw new ArgumentException("Initial count must be smaller than maximum");
}
m_currentCount = initialCount;
m_maximumCount = maximumCount;
m_lockObject = new object();
}
public int Release()
{
return this.Release(1);
}
public int Release(int releaseCount)
{
if (releaseCount < 1)
{
throw new ArgumentOutOfRangeException("releaseCount", "Positive number required.");
}
if (m_disposed)
{
throw new ObjectDisposedException("Semaphore");
}
var oldCount = default(int);
lock (m_lockObject)
{
oldCount = m_currentCount;
if (releaseCount + m_currentCount > m_maximumCount)
{
throw new ArgumentOutOfRangeException("releaseCount", "Amount of releases would overflow maximum");
}
m_currentCount += releaseCount;
//PulseAll makes sure all waiting threads get queued for acquiring the lock
//Pulse would only queue one thread.
Monitor.PulseAll(m_lockObject);
}
return oldCount;
}
public bool WaitOne()
{
return WaitOne(Timeout.Infinite);
}
public bool WaitOne(int millisecondsTimeout)
{
if (m_disposed)
{
throw new ObjectDisposedException("Semaphore");
}
lock (m_lockObject)
{
while (m_currentCount == 0)
{
if (!Monitor.Wait(m_lockObject, millisecondsTimeout))
{
return false;
}
}
m_currentCount--;
return true;
}
}
public bool WaitOne(TimeSpan timeout)
{
return WaitOne((int)timeout.TotalMilliseconds);
}
public void Close()
{
Dispose();
}
public void Dispose()
{
//the .NET CLR semaphore does not release waits upon dispose
//so we don't do that either.
m_disposed = true;
}
}
}
#endif
|