1
-
2
1
// <Snippet1>
3
2
// This example shows a ReaderWriterLock protecting a shared
4
3
// resource that is read concurrently and written exclusively
@@ -23,7 +22,6 @@ public ref class Test
23
22
// </Snippet2>
24
23
literal int numThreads = 26 ;
25
24
static bool running = true ;
26
- static Random^ rnd = gcnew Random;
27
25
28
26
// Statistics.
29
27
static int readerTimeouts = 0 ;
@@ -32,10 +30,11 @@ public ref class Test
32
30
static int writes = 0 ;
33
31
static void ThreadProc ()
34
32
{
35
-
33
+ Random^ rnd = gcnew Random;
34
+
36
35
// As long as a thread runs, it randomly selects
37
- // various ways to read and write from the shared
38
- // resource. Each of the methods demonstrates one
36
+ // various ways to read and write from the shared
37
+ // resource. Each of the methods demonstrates one
39
38
// or more features of ReaderWriterLock.
40
39
while ( running )
41
40
{
@@ -44,12 +43,12 @@ public ref class Test
44
43
ReadFromResource ( 10 );
45
44
else
46
45
if ( action < .81 )
47
- ReleaseRestore ( 50 );
46
+ ReleaseRestore ( rnd, 50 );
48
47
else
49
48
if ( action < .90 )
50
- UpgradeDowngrade ( 100 );
49
+ UpgradeDowngrade ( rnd, 100 );
51
50
else
52
- WriteToResource ( 100 );
51
+ WriteToResource ( rnd, 100 );
53
52
}
54
53
}
55
54
@@ -64,23 +63,23 @@ public ref class Test
64
63
rwl->AcquireReaderLock ( timeOut );
65
64
try
66
65
{
67
-
66
+
68
67
// It is safe for this thread to read from
69
68
// the shared resource.
70
69
Display ( String::Format ( " reads resource value {0}" , resource ) );
71
70
Interlocked::Increment ( reads );
72
71
}
73
72
finally
74
73
{
75
-
74
+
76
75
// Ensure that the lock is released.
77
76
rwl->ReleaseReaderLock ();
78
77
}
79
78
80
79
}
81
- catch ( ApplicationException^ )
80
+ catch ( ApplicationException^ )
82
81
{
83
-
82
+
84
83
// The reader lock request timed out.
85
84
Interlocked::Increment ( readerTimeouts );
86
85
}
@@ -92,14 +91,14 @@ public ref class Test
92
91
// <Snippet4>
93
92
// Shows how to request and release the writer lock, and
94
93
// how to handle time-outs.
95
- static void WriteToResource ( int timeOut )
94
+ static void WriteToResource ( Random^ rnd, int timeOut )
96
95
{
97
96
try
98
97
{
99
98
rwl->AcquireWriterLock ( timeOut );
100
99
try
101
100
{
102
-
101
+
103
102
// It is safe for this thread to read or write
104
103
// from the shared resource.
105
104
resource = rnd->Next ( 500 );
@@ -108,15 +107,15 @@ public ref class Test
108
107
}
109
108
finally
110
109
{
111
-
110
+
112
111
// Ensure that the lock is released.
113
112
rwl->ReleaseWriterLock ();
114
113
}
115
114
116
115
}
117
- catch ( ApplicationException^ )
116
+ catch ( ApplicationException^ )
118
117
{
119
-
118
+
120
119
// The writer lock request timed out.
121
120
Interlocked::Increment ( writerTimeouts );
122
121
}
@@ -129,32 +128,32 @@ public ref class Test
129
128
// Shows how to request a reader lock, upgrade the
130
129
// reader lock to the writer lock, and downgrade to a
131
130
// reader lock again.
132
- static void UpgradeDowngrade ( int timeOut )
131
+ static void UpgradeDowngrade ( Random^ rnd, int timeOut )
133
132
{
134
133
try
135
134
{
136
135
rwl->AcquireReaderLock ( timeOut );
137
136
try
138
137
{
139
-
138
+
140
139
// It is safe for this thread to read from
141
140
// the shared resource.
142
141
Display ( String::Format ( " reads resource value {0}" , resource ) );
143
142
Interlocked::Increment ( reads );
144
-
143
+
145
144
// If it is necessary to write to the resource,
146
- // you must either release the reader lock and
145
+ // you must either release the reader lock and
147
146
// then request the writer lock, or upgrade the
148
147
// reader lock. Note that upgrading the reader lock
149
148
// puts the thread in the write queue, behind any
150
- // other threads that might be waiting for the
149
+ // other threads that might be waiting for the
151
150
// writer lock.
152
151
try
153
152
{
154
153
LockCookie lc = rwl->UpgradeToWriterLock ( timeOut );
155
154
try
156
155
{
157
-
156
+
158
157
// It is safe for this thread to read or write
159
158
// from the shared resource.
160
159
resource = rnd->Next ( 500 );
@@ -163,36 +162,36 @@ public ref class Test
163
162
}
164
163
finally
165
164
{
166
-
165
+
167
166
// Ensure that the lock is released.
168
167
rwl->DowngradeFromWriterLock ( lc );
169
168
}
170
169
171
170
}
172
- catch ( ApplicationException^ )
171
+ catch ( ApplicationException^ )
173
172
{
174
-
173
+
175
174
// The upgrade request timed out.
176
175
Interlocked::Increment ( writerTimeouts );
177
176
}
178
177
179
-
180
- // When the lock has been downgraded, it is
178
+
179
+ // When the lock has been downgraded, it is
181
180
// still safe to read from the resource.
182
181
Display ( String::Format ( " reads resource value {0}" , resource ) );
183
182
Interlocked::Increment ( reads );
184
183
}
185
184
finally
186
185
{
187
-
186
+
188
187
// Ensure that the lock is released.
189
188
rwl->ReleaseReaderLock ();
190
189
}
191
190
192
191
}
193
- catch ( ApplicationException^ )
192
+ catch ( ApplicationException^ )
194
193
{
195
-
194
+
196
195
// The reader lock request timed out.
197
196
Interlocked::Increment ( readerTimeouts );
198
197
}
@@ -207,37 +206,37 @@ public ref class Test
207
206
// to determine whether another thread has obtained
208
207
// a writer lock since this thread last accessed the
209
208
// resource.
210
- static void ReleaseRestore ( int timeOut )
209
+ static void ReleaseRestore ( Random^ rnd, int timeOut )
211
210
{
212
211
int lastWriter;
213
212
try
214
213
{
215
214
rwl->AcquireReaderLock ( timeOut );
216
215
try
217
216
{
218
-
217
+
219
218
// It is safe for this thread to read from
220
219
// the shared resource. Cache the value. (You
221
220
// might do this if reading the resource is
222
221
// an expensive operation.)
223
222
int resourceValue = resource;
224
223
Display ( String::Format ( " reads resource value {0}" , resourceValue ) );
225
224
Interlocked::Increment ( reads );
226
-
225
+
227
226
// Save the current writer sequence number.
228
227
lastWriter = rwl->WriterSeqNum ;
229
-
228
+
230
229
// Release the lock, and save a cookie so the
231
230
// lock can be restored later.
232
231
LockCookie lc = rwl->ReleaseLock ();
233
-
234
- // Wait for a random interval (up to a
232
+
233
+ // Wait for a random interval (up to a
235
234
// quarter of a second), and then restore
236
235
// the previous state of the lock. Note that
237
236
// there is no timeout on the Restore method.
238
237
Thread::Sleep ( rnd->Next ( 250 ) );
239
238
rwl->RestoreLock ( lc );
240
-
239
+
241
240
// Check whether other threads obtained the
242
241
// writer lock in the interval. If not, then
243
242
// the cached value of the resource is still
@@ -255,15 +254,15 @@ public ref class Test
255
254
}
256
255
finally
257
256
{
258
-
257
+
259
258
// Ensure that the lock is released.
260
259
rwl->ReleaseReaderLock ();
261
260
}
262
261
263
262
}
264
- catch ( ApplicationException^ )
263
+ catch ( ApplicationException^ )
265
264
{
266
-
265
+
267
266
// The reader lock request timed out.
268
267
Interlocked::Increment ( readerTimeouts );
269
268
}
@@ -273,7 +272,7 @@ public ref class Test
273
272
274
273
// </Snippet6>
275
274
// Helper method briefly displays the most recent
276
- // thread action. Comment out calls to Display to
275
+ // thread action. Comment out calls to Display to
277
276
// get a better idea of throughput.
278
277
static void Display ( String^ msg )
279
278
{
@@ -288,7 +287,7 @@ public ref class Test
288
287
int main ()
289
288
{
290
289
array<String^>^args = Environment::GetCommandLineArgs ();
291
-
290
+
292
291
// Start a series of threads. Each thread randomly
293
292
// performs reads and writes on the shared resource.
294
293
array<Thread^>^t = gcnew array<Thread^>(Test::numThreads);
@@ -301,7 +300,7 @@ int main()
301
300
Thread::Sleep ( 300 );
302
301
303
302
}
304
-
303
+
305
304
// Tell the threads to shut down, then wait until they all
306
305
// finish.
307
306
Test::running = false ;
@@ -310,7 +309,7 @@ int main()
310
309
t[ i ]->Join ();
311
310
312
311
}
313
-
312
+
314
313
// Display statistics.
315
314
Console::WriteLine ( " \r\n {0} reads, {1} writes, {2} reader time-outs, {3} writer time-outs." , Test::reads, Test::writes, Test::readerTimeouts, Test::writerTimeouts );
316
315
Console::WriteLine ( " Press ENTER to exit." );
0 commit comments