-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathAsyncObjectPool.cs
144 lines (132 loc) · 3.23 KB
/
AsyncObjectPool.cs
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Meadow.UnitTestTemplate
{
/// <summary>
/// Warning: careful usage of this class is required to avoid deadlocks.
/// Concurrent usage of the synchronous and async methods can cause a deadlock.
/// </summary>
public class AsyncObjectPool<TItem> : IDisposable where TItem : class
{
readonly SemaphoreSlim _semaphore;
readonly List<TItem> _items;
readonly Func<Task<TItem>> _createItem;
public AsyncObjectPool(Func<Task<TItem>> createItem)
{
_semaphore = new SemaphoreSlim(1, 1);
_items = new List<TItem>();
_createItem = createItem;
}
public async Task<TItem> Get()
{
await _semaphore.WaitAsync();
try
{
TItem item;
if (_items.Count > 0)
{
item = _items[0];
_items.RemoveAt(0);
}
else
{
item = await _createItem();
}
return item;
}
finally
{
_semaphore.Release();
}
}
public async Task PutAsync(TItem item)
{
await _semaphore.WaitAsync();
try
{
_items.Add(item);
}
finally
{
_semaphore.Release();
}
}
public void Put(TItem item)
{
_semaphore.Wait();
try
{
_items.Add(item);
}
finally
{
_semaphore.Release();
}
}
public async Task<TItem[]> GetItemsAsync()
{
await _semaphore.WaitAsync();
try
{
return _items.ToArray();
}
finally
{
_semaphore.Release();
}
}
public TItem[] GetItems()
{
_semaphore.Wait();
try
{
return _items.ToArray();
}
finally
{
_semaphore.Release();
}
}
public async Task<bool> HasItemsAsync()
{
await _semaphore.WaitAsync();
try
{
return _items.Count > 0;
}
finally
{
_semaphore.Release();
}
}
public bool HasItems()
{
_semaphore.Wait();
try
{
return _items.Count > 0;
}
finally
{
_semaphore.Release();
}
}
public void Dispose()
{
_semaphore.Wait();
_semaphore.Dispose();
foreach (var item in _items)
{
if (item is IDisposable disposableItem)
{
disposableItem.Dispose();
}
}
_items.Clear();
}
}
}