Terraria v1.4.4.9
Terraria source code documentation
All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Events Macros
AsynchronousChannel.cs
Go to the documentation of this file.
3
5
6internal sealed class AsynchronousChannel<T> : IDisposable
7{
8 private readonly T[][] _buffer;
9
10 private readonly int _index;
11
12 private volatile int _producerBufferIndex;
13
14 private volatile int _consumerBufferIndex;
15
16 private volatile bool _done;
17
18 private T[] _producerChunk;
19
21
22 private T[] _consumerChunk;
23
25
26 private readonly int _chunkSize;
27
29
31
32 private volatile int _producerIsWaiting;
33
34 private volatile int _consumerIsWaiting;
35
37
38 internal bool IsFull
39 {
40 get
41 {
42 int producerBufferIndex = _producerBufferIndex;
43 int consumerBufferIndex = _consumerBufferIndex;
44 if (producerBufferIndex != consumerBufferIndex - 1)
45 {
46 if (consumerBufferIndex == 0)
47 {
48 return producerBufferIndex == _buffer.Length - 1;
49 }
50 return false;
51 }
52 return true;
53 }
54 }
55
57
58 internal bool IsDone => _done;
59
60 internal AsynchronousChannel(int index, int chunkSize, CancellationToken cancellationToken, IntValueEvent consumerEvent)
61 : this(index, 512, chunkSize, cancellationToken, consumerEvent)
62 {
63 }
64
65 internal AsynchronousChannel(int index, int capacity, int chunkSize, CancellationToken cancellationToken, IntValueEvent consumerEvent)
66 {
67 if (chunkSize == 0)
68 {
69 chunkSize = Scheduling.GetDefaultChunkSize<T>();
70 }
71 _index = index;
72 _buffer = new T[capacity + 1][];
76 _consumerEvent = consumerEvent;
77 _chunkSize = chunkSize;
78 _producerChunk = new T[chunkSize];
81 }
82
83 internal void FlushBuffers()
84 {
86 }
87
88 internal void SetDone()
89 {
90 _done = true;
91 lock (this)
92 {
93 if (_consumerEvent != null)
94 {
96 }
97 }
98 }
99
100 internal void Enqueue(T item)
101 {
102 int producerChunkIndex = _producerChunkIndex;
103 _producerChunk[producerChunkIndex] = item;
104 if (producerChunkIndex == _chunkSize - 1)
105 {
107 _producerChunk = new T[_chunkSize];
108 }
109 _producerChunkIndex = (producerChunkIndex + 1) % _chunkSize;
110 }
111
112 private void EnqueueChunk(T[] chunk)
113 {
114 if (IsFull)
115 {
117 }
118 int producerBufferIndex = _producerBufferIndex;
119 _buffer[producerBufferIndex] = chunk;
120 Interlocked.Exchange(ref _producerBufferIndex, (producerBufferIndex + 1) % _buffer.Length);
122 {
125 }
126 }
127
128 private void WaitUntilNonFull()
129 {
130 do
131 {
134 if (IsFull)
135 {
137 }
138 else
139 {
141 }
142 }
143 while (IsFull);
144 }
145
146 private void FlushCachedChunk()
147 {
148 if (_producerChunk != null && _producerChunkIndex != 0)
149 {
150 T[] array = new T[_producerChunkIndex];
153 _producerChunk = null;
154 }
155 }
156
157 internal bool TryDequeue([MaybeNullWhen(false)][AllowNull] ref T item)
158 {
159 if (_consumerChunk == null)
160 {
162 {
163 return false;
164 }
166 }
170 {
171 _consumerChunk = null;
172 }
173 return true;
174 }
175
176 private bool TryDequeueChunk([NotNullWhen(true)] ref T[] chunk)
177 {
179 {
180 return false;
181 }
182 chunk = InternalDequeueChunk();
183 return true;
184 }
185
186 internal bool TryDequeue([MaybeNullWhen(false)][AllowNull] ref T item, ref bool isDone)
187 {
188 isDone = false;
189 if (_consumerChunk == null)
190 {
191 if (!TryDequeueChunk(ref _consumerChunk, ref isDone))
192 {
193 return false;
194 }
196 }
200 {
201 _consumerChunk = null;
202 }
203 return true;
204 }
205
206 private bool TryDequeueChunk([NotNullWhen(true)] ref T[] chunk, ref bool isDone)
207 {
208 isDone = false;
209 while (IsChunkBufferEmpty)
210 {
212 {
213 isDone = true;
214 return false;
215 }
218 {
219 return false;
220 }
222 }
223 chunk = InternalDequeueChunk();
224 return true;
225 }
226
228 {
229 int consumerBufferIndex = _consumerBufferIndex;
230 T[] result = _buffer[consumerBufferIndex];
231 _buffer[consumerBufferIndex] = null;
232 Interlocked.Exchange(ref _consumerBufferIndex, (consumerBufferIndex + 1) % _buffer.Length);
233 if (_producerIsWaiting == 1 && !IsFull)
234 {
237 }
238 return result;
239 }
240
241 internal void DoneWithDequeueWait()
242 {
244 }
245
246 public void Dispose()
247 {
248 lock (this)
249 {
251 _producerEvent = null;
252 _consumerEvent = null;
253 }
254 }
255}
static unsafe void Copy(Array sourceArray, Array destinationArray, int length)
Definition Array.cs:624
bool TryDequeue([MaybeNullWhen(false)][AllowNull] ref T item, ref bool isDone)
AsynchronousChannel(int index, int chunkSize, CancellationToken cancellationToken, IntValueEvent consumerEvent)
bool TryDequeueChunk([NotNullWhen(true)] ref T[] chunk, ref bool isDone)
readonly CancellationToken _cancellationToken
bool TryDequeueChunk([NotNullWhen(true)] ref T[] chunk)
bool TryDequeue([MaybeNullWhen(false)][AllowNull] ref T item)
AsynchronousChannel(int index, int capacity, int chunkSize, CancellationToken cancellationToken, IntValueEvent consumerEvent)
static int Exchange(ref int location1, int value)