This file is indexed.

/usr/share/doc/libghc-stm-chans-doc/html/src/Control-Concurrent-STM-TBMChan.html is in libghc-stm-chans-doc 3.0.0.4-5build1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
<title>src/Control/Concurrent/STM/TBMChan.hs</title>
<link type='text/css' rel='stylesheet' href='hscolour.css' />
</head>
<body>
<pre><a name="line-1"></a><span class='hs-comment'>{-# OPTIONS_GHC -Wall -fwarn-tabs #-}</span>
<a name="line-2"></a><span class='hs-comment'>{-# LANGUAGE CPP, DeriveDataTypeable #-}</span>
<a name="line-3"></a>
<a name="line-4"></a><span class='hs-comment'>-- HACK: in GHC 7.10, Haddock complains about Control.Monad.STM and</span>
<a name="line-5"></a><span class='hs-comment'>-- System.IO.Unsafe being imported but unused. However, if we use</span>
<a name="line-6"></a><span class='hs-comment'>-- CPP to avoid including them under Haddock, then it will fail to</span>
<a name="line-7"></a><span class='hs-comment'>-- compile!</span>
<a name="line-8"></a><span class='hs-cpp'>#ifdef __HADDOCK__</span>
<a name="line-9"></a><span class='hs-comment'>{-# OPTIONS_GHC -fno-warn-unused-imports #-}</span>
<a name="line-10"></a><span class='hs-cpp'>#endif</span>
<a name="line-11"></a>
<a name="line-12"></a><span class='hs-cpp'>#if __GLASGOW_HASKELL__ &gt;= 701</span>
<a name="line-13"></a><span class='hs-cpp'>#  ifdef __HADDOCK__</span>
<a name="line-14"></a><span class='hs-comment'>{-# LANGUAGE Trustworthy #-}</span>
<a name="line-15"></a><span class='hs-cpp'>#  else</span>
<a name="line-16"></a><span class='hs-comment'>{-# LANGUAGE Safe #-}</span>
<a name="line-17"></a><span class='hs-cpp'>#  endif</span>
<a name="line-18"></a><span class='hs-cpp'>#endif</span>
<a name="line-19"></a><span class='hs-comment'>----------------------------------------------------------------</span>
<a name="line-20"></a><span class='hs-comment'>--                                                    2015.03.29</span>
<a name="line-21"></a><span class='hs-comment'>-- |</span>
<a name="line-22"></a><span class='hs-comment'>-- Module      :  Control.Concurrent.STM.TBMChan</span>
<a name="line-23"></a><span class='hs-comment'>-- Copyright   :  Copyright (c) 2011--2015 wren gayle romano</span>
<a name="line-24"></a><span class='hs-comment'>-- License     :  BSD</span>
<a name="line-25"></a><span class='hs-comment'>-- Maintainer  :  wren@community.haskell.org</span>
<a name="line-26"></a><span class='hs-comment'>-- Stability   :  provisional</span>
<a name="line-27"></a><span class='hs-comment'>-- Portability :  non-portable (GHC STM, DeriveDataTypeable)</span>
<a name="line-28"></a><span class='hs-comment'>--</span>
<a name="line-29"></a><span class='hs-comment'>-- A version of "Control.Concurrent.STM.TChan" where the queue is</span>
<a name="line-30"></a><span class='hs-comment'>-- bounded in length and closeable. This combines the abilities of</span>
<a name="line-31"></a><span class='hs-comment'>-- "Control.Concurrent.STM.TBChan" and "Control.Concurrent.STM.TMChan".</span>
<a name="line-32"></a><span class='hs-comment'>-- This variant incorporates ideas from Thomas M. DuBuisson's</span>
<a name="line-33"></a><span class='hs-comment'>-- @bounded-tchan@ package in order to reduce contention between</span>
<a name="line-34"></a><span class='hs-comment'>-- readers and writers.</span>
<a name="line-35"></a><span class='hs-comment'>----------------------------------------------------------------</span>
<a name="line-36"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Concurrent</span><span class='hs-varop'>.</span><span class='hs-conid'>STM</span><span class='hs-varop'>.</span><span class='hs-conid'>TBMChan</span>
<a name="line-37"></a>    <span class='hs-layout'>(</span>
<a name="line-38"></a>    <span class='hs-comment'>-- * The TBMChan type</span>
<a name="line-39"></a>      <span class='hs-conid'>TBMChan</span><span class='hs-conid'>()</span>
<a name="line-40"></a>    <span class='hs-comment'>-- ** Creating TBMChans</span>
<a name="line-41"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>newTBMChan</span>
<a name="line-42"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>newTBMChanIO</span>
<a name="line-43"></a>    <span class='hs-comment'>-- I don't know how to define dupTBMChan with the correct semantics</span>
<a name="line-44"></a>    <span class='hs-comment'>-- ** Reading from TBMChans</span>
<a name="line-45"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>readTBMChan</span>
<a name="line-46"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>tryReadTBMChan</span>
<a name="line-47"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>peekTBMChan</span>
<a name="line-48"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>tryPeekTBMChan</span>
<a name="line-49"></a>    <span class='hs-comment'>-- ** Writing to TBMChans</span>
<a name="line-50"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>writeTBMChan</span>
<a name="line-51"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>tryWriteTBMChan</span>
<a name="line-52"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>unGetTBMChan</span>
<a name="line-53"></a>    <span class='hs-comment'>-- ** Closing TBMChans</span>
<a name="line-54"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>closeTBMChan</span>
<a name="line-55"></a>    <span class='hs-comment'>-- ** Predicates</span>
<a name="line-56"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>isClosedTBMChan</span>
<a name="line-57"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>isEmptyTBMChan</span>
<a name="line-58"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>isFullTBMChan</span>
<a name="line-59"></a>    <span class='hs-comment'>-- ** Other functionality</span>
<a name="line-60"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>estimateFreeSlotsTBMChan</span>
<a name="line-61"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>freeSlotsTBMChan</span>
<a name="line-62"></a>    <span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-63"></a>
<a name="line-64"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Prelude</span>             <span class='hs-varid'>hiding</span> <span class='hs-layout'>(</span><span class='hs-varid'>reads</span><span class='hs-layout'>)</span>
<a name="line-65"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Typeable</span>       <span class='hs-layout'>(</span><span class='hs-conid'>Typeable</span><span class='hs-layout'>)</span>
<a name="line-66"></a><span class='hs-cpp'>#if __GLASGOW_HASKELL__ &lt; 710</span>
<a name="line-67"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Applicative</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varop'>&lt;$&gt;</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-68"></a><span class='hs-cpp'>#endif</span>
<a name="line-69"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span><span class='hs-varop'>.</span><span class='hs-conid'>STM</span>   <span class='hs-layout'>(</span><span class='hs-conid'>STM</span><span class='hs-layout'>,</span> <span class='hs-varid'>retry</span><span class='hs-layout'>)</span>
<a name="line-70"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Concurrent</span><span class='hs-varop'>.</span><span class='hs-conid'>STM</span><span class='hs-varop'>.</span><span class='hs-conid'>TVar</span>
<a name="line-71"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Concurrent</span><span class='hs-varop'>.</span><span class='hs-conid'>STM</span><span class='hs-varop'>.</span><span class='hs-conid'>TChan</span> <span class='hs-comment'>-- N.B., GHC only</span>
<a name="line-72"></a>
<a name="line-73"></a><span class='hs-comment'>-- N.B., we need a Custom cabal build-type for this to work.</span>
<a name="line-74"></a><span class='hs-cpp'>#ifdef __HADDOCK__</span>
<a name="line-75"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span><span class='hs-varop'>.</span><span class='hs-conid'>STM</span>   <span class='hs-layout'>(</span><span class='hs-varid'>atomically</span><span class='hs-layout'>)</span>
<a name="line-76"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>IO</span><span class='hs-varop'>.</span><span class='hs-conid'>Unsafe</span>    <span class='hs-layout'>(</span><span class='hs-varid'>unsafePerformIO</span><span class='hs-layout'>)</span>
<a name="line-77"></a><span class='hs-cpp'>#endif</span>
<a name="line-78"></a><span class='hs-comment'>----------------------------------------------------------------</span>
<a name="line-79"></a>
<a name="line-80"></a><a name="TBMChan"></a><span class='hs-comment'>-- | @TBMChan@ is an abstract type representing a bounded closeable</span>
<a name="line-81"></a><a name="TBMChan"></a><span class='hs-comment'>-- FIFO channel.</span>
<a name="line-82"></a><a name="TBMChan"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>TBMChan</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>TBMChan</span>
<a name="line-83"></a>    <span class='hs-comment'>{-# UNPACK #-}</span> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>TVar</span> <span class='hs-conid'>Bool</span><span class='hs-layout'>)</span>
<a name="line-84"></a>    <span class='hs-comment'>{-# UNPACK #-}</span> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>TVar</span> <span class='hs-conid'>Int</span><span class='hs-layout'>)</span>
<a name="line-85"></a>    <span class='hs-comment'>{-# UNPACK #-}</span> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>TVar</span> <span class='hs-conid'>Int</span><span class='hs-layout'>)</span>
<a name="line-86"></a>    <span class='hs-comment'>{-# UNPACK #-}</span> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>TChan</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-87"></a>    <span class='hs-keyword'>deriving</span> <span class='hs-layout'>(</span><span class='hs-conid'>Typeable</span><span class='hs-layout'>)</span>
<a name="line-88"></a><span class='hs-comment'>-- The components are:</span>
<a name="line-89"></a><span class='hs-comment'>-- * Whether the channel has been closed.</span>
<a name="line-90"></a><span class='hs-comment'>-- * How many free slots we /know/ we have available.</span>
<a name="line-91"></a><span class='hs-comment'>-- * How many slots have been freed up by successful reads since</span>
<a name="line-92"></a><span class='hs-comment'>--   the last time the slot count was synchronized by 'isFullTBChan'.</span>
<a name="line-93"></a><span class='hs-comment'>-- * The underlying TChan.</span>
<a name="line-94"></a>
<a name="line-95"></a>
<a name="line-96"></a><a name="newTBMChan"></a><span class='hs-comment'>-- | Build and returns a new instance of @TBMChan@ with the given</span>
<a name="line-97"></a><span class='hs-comment'>-- capacity. /N.B./, we do not verify the capacity is positive, but</span>
<a name="line-98"></a><span class='hs-comment'>-- if it is non-positive then 'writeTBMChan' will always retry and</span>
<a name="line-99"></a><span class='hs-comment'>-- 'isFullTBMChan' will always be true.</span>
<a name="line-100"></a><span class='hs-definition'>newTBMChan</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-layout'>(</span><span class='hs-conid'>TBMChan</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-101"></a><span class='hs-definition'>newTBMChan</span> <span class='hs-varid'>n</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-102"></a>    <span class='hs-varid'>closed</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newTVar</span> <span class='hs-conid'>False</span>
<a name="line-103"></a>    <span class='hs-varid'>slots</span>  <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newTVar</span> <span class='hs-varid'>n</span>
<a name="line-104"></a>    <span class='hs-varid'>reads</span>  <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newTVar</span> <span class='hs-num'>0</span>
<a name="line-105"></a>    <span class='hs-varid'>chan</span>   <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newTChan</span>
<a name="line-106"></a>    <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>TBMChan</span> <span class='hs-varid'>closed</span> <span class='hs-varid'>slots</span> <span class='hs-varid'>reads</span> <span class='hs-varid'>chan</span><span class='hs-layout'>)</span>
<a name="line-107"></a>
<a name="line-108"></a>
<a name="line-109"></a><a name="newTBMChanIO"></a><span class='hs-comment'>-- | @IO@ version of 'newTBMChan'. This is useful for creating</span>
<a name="line-110"></a><span class='hs-comment'>-- top-level @TBMChan@s using 'unsafePerformIO', because using</span>
<a name="line-111"></a><span class='hs-comment'>-- 'atomically' inside 'unsafePerformIO' isn't possible.</span>
<a name="line-112"></a><span class='hs-definition'>newTBMChanIO</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>TBMChan</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-113"></a><span class='hs-definition'>newTBMChanIO</span> <span class='hs-varid'>n</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-114"></a>    <span class='hs-varid'>closed</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newTVarIO</span> <span class='hs-conid'>False</span>
<a name="line-115"></a>    <span class='hs-varid'>slots</span>  <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newTVarIO</span> <span class='hs-varid'>n</span>
<a name="line-116"></a>    <span class='hs-varid'>reads</span>  <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newTVarIO</span> <span class='hs-num'>0</span>
<a name="line-117"></a>    <span class='hs-varid'>chan</span>   <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newTChanIO</span>
<a name="line-118"></a>    <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>TBMChan</span> <span class='hs-varid'>closed</span> <span class='hs-varid'>slots</span> <span class='hs-varid'>reads</span> <span class='hs-varid'>chan</span><span class='hs-layout'>)</span>
<a name="line-119"></a>
<a name="line-120"></a>
<a name="line-121"></a><a name="readTBMChan"></a><span class='hs-comment'>-- | Read the next value from the @TBMChan@, retrying if the channel</span>
<a name="line-122"></a><span class='hs-comment'>-- is empty (and not closed). We return @Nothing@ immediately if</span>
<a name="line-123"></a><span class='hs-comment'>-- the channel is closed and empty.</span>
<a name="line-124"></a><span class='hs-definition'>readTBMChan</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TBMChan</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-layout'>(</span><span class='hs-conid'>Maybe</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-125"></a><span class='hs-definition'>readTBMChan</span> <span class='hs-layout'>(</span><span class='hs-conid'>TBMChan</span> <span class='hs-varid'>closed</span> <span class='hs-sel'>_slots</span> <span class='hs-varid'>reads</span> <span class='hs-varid'>chan</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-126"></a>    <span class='hs-varid'>b</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readTVar</span> <span class='hs-varid'>closed</span>
<a name="line-127"></a>    <span class='hs-keyword'>if</span> <span class='hs-varid'>b</span>
<a name="line-128"></a>        <span class='hs-keyword'>then</span> <span class='hs-keyword'>do</span>
<a name="line-129"></a>            <span class='hs-varid'>mx</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>tryReadTChan</span> <span class='hs-varid'>chan</span>
<a name="line-130"></a>            <span class='hs-keyword'>case</span> <span class='hs-varid'>mx</span> <span class='hs-keyword'>of</span>
<a name="line-131"></a>                <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-varid'>mx</span>
<a name="line-132"></a>                <span class='hs-conid'>Just</span> <span class='hs-sel'>_x</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
<a name="line-133"></a>                    <span class='hs-varid'>modifyTVar'</span> <span class='hs-varid'>reads</span> <span class='hs-layout'>(</span><span class='hs-num'>1</span> <span class='hs-varop'>+</span><span class='hs-layout'>)</span>
<a name="line-134"></a>                    <span class='hs-varid'>return</span> <span class='hs-varid'>mx</span>
<a name="line-135"></a>        <span class='hs-keyword'>else</span> <span class='hs-keyword'>do</span>
<a name="line-136"></a>            <span class='hs-varid'>x</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readTChan</span> <span class='hs-varid'>chan</span>
<a name="line-137"></a>            <span class='hs-varid'>modifyTVar'</span> <span class='hs-varid'>reads</span> <span class='hs-layout'>(</span><span class='hs-num'>1</span> <span class='hs-varop'>+</span><span class='hs-layout'>)</span>
<a name="line-138"></a>            <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span>
<a name="line-139"></a><span class='hs-comment'>{- 
<a name="line-140"></a>-- The above is slightly optimized over the clearer:
<a name="line-141"></a>readTBMChan (TBMChan closed _slots reads chan) =
<a name="line-142"></a>    b  &lt;- readTVar closed
<a name="line-143"></a>    b' &lt;- isEmptyTChan chan
<a name="line-144"></a>    if b &amp;&amp; b'
<a name="line-145"></a>        then return Nothing
<a name="line-146"></a>        else do
<a name="line-147"></a>            x &lt;- readTChan chan
<a name="line-148"></a>            modifyTVar' reads (1 +)
<a name="line-149"></a>            return (Just x)
<a name="line-150"></a>-- TODO: compare Core and benchmarks; is the loss of clarity worth it?
<a name="line-151"></a>-}</span>
<a name="line-152"></a>
<a name="line-153"></a>
<a name="line-154"></a><a name="tryReadTBMChan"></a><span class='hs-comment'>-- | A version of 'readTBMChan' which does not retry. Instead it</span>
<a name="line-155"></a><span class='hs-comment'>-- returns @Just Nothing@ if the channel is open but no value is</span>
<a name="line-156"></a><span class='hs-comment'>-- available; it still returns @Nothing@ if the channel is closed</span>
<a name="line-157"></a><span class='hs-comment'>-- and empty.</span>
<a name="line-158"></a><span class='hs-definition'>tryReadTBMChan</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TBMChan</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-layout'>(</span><span class='hs-conid'>Maybe</span> <span class='hs-layout'>(</span><span class='hs-conid'>Maybe</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-159"></a><span class='hs-definition'>tryReadTBMChan</span> <span class='hs-layout'>(</span><span class='hs-conid'>TBMChan</span> <span class='hs-varid'>closed</span> <span class='hs-sel'>_slots</span> <span class='hs-varid'>reads</span> <span class='hs-varid'>chan</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-160"></a>    <span class='hs-varid'>b</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readTVar</span> <span class='hs-varid'>closed</span>
<a name="line-161"></a>    <span class='hs-keyword'>if</span> <span class='hs-varid'>b</span>
<a name="line-162"></a>        <span class='hs-keyword'>then</span> <span class='hs-keyword'>do</span>
<a name="line-163"></a>            <span class='hs-varid'>mx</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>tryReadTChan</span> <span class='hs-varid'>chan</span>
<a name="line-164"></a>            <span class='hs-keyword'>case</span> <span class='hs-varid'>mx</span> <span class='hs-keyword'>of</span>
<a name="line-165"></a>                <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-conid'>Nothing</span>
<a name="line-166"></a>                <span class='hs-conid'>Just</span> <span class='hs-sel'>_x</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
<a name="line-167"></a>                    <span class='hs-varid'>modifyTVar'</span> <span class='hs-varid'>reads</span> <span class='hs-layout'>(</span><span class='hs-num'>1</span> <span class='hs-varop'>+</span><span class='hs-layout'>)</span>
<a name="line-168"></a>                    <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varid'>mx</span><span class='hs-layout'>)</span>
<a name="line-169"></a>        <span class='hs-keyword'>else</span> <span class='hs-keyword'>do</span>
<a name="line-170"></a>            <span class='hs-varid'>mx</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>tryReadTChan</span> <span class='hs-varid'>chan</span>
<a name="line-171"></a>            <span class='hs-keyword'>case</span> <span class='hs-varid'>mx</span> <span class='hs-keyword'>of</span>
<a name="line-172"></a>                <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varid'>mx</span><span class='hs-layout'>)</span>
<a name="line-173"></a>                <span class='hs-conid'>Just</span> <span class='hs-sel'>_x</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
<a name="line-174"></a>                    <span class='hs-varid'>modifyTVar'</span> <span class='hs-varid'>reads</span> <span class='hs-layout'>(</span><span class='hs-num'>1</span> <span class='hs-varop'>+</span><span class='hs-layout'>)</span>
<a name="line-175"></a>                    <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varid'>mx</span><span class='hs-layout'>)</span>
<a name="line-176"></a><span class='hs-comment'>{- 
<a name="line-177"></a>-- The above is slightly optimized over the clearer:
<a name="line-178"></a>tryReadTBMChan (TBMChan closed _slots reads chan) =
<a name="line-179"></a>    b  &lt;- readTVar closed
<a name="line-180"></a>    b' &lt;- isEmptyTChan chan
<a name="line-181"></a>    if b &amp;&amp; b'
<a name="line-182"></a>        then return Nothing
<a name="line-183"></a>        else do
<a name="line-184"></a>            mx &lt;- tryReadTBMChan chan
<a name="line-185"></a>            case mx of
<a name="line-186"></a>                Nothing -&gt; return (Just mx)
<a name="line-187"></a>                Just _x -&gt; do
<a name="line-188"></a>                    modifyTVar' reads (1 +)
<a name="line-189"></a>                    return (Just mx)
<a name="line-190"></a>-- TODO: compare Core and benchmarks; is the loss of clarity worth it?
<a name="line-191"></a>-}</span>
<a name="line-192"></a>
<a name="line-193"></a>
<a name="line-194"></a><a name="peekTBMChan"></a><span class='hs-comment'>-- | Get the next value from the @TBMChan@ without removing it,</span>
<a name="line-195"></a><span class='hs-comment'>-- retrying if the channel is empty.</span>
<a name="line-196"></a><span class='hs-definition'>peekTBMChan</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TBMChan</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-layout'>(</span><span class='hs-conid'>Maybe</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-197"></a><span class='hs-definition'>peekTBMChan</span> <span class='hs-layout'>(</span><span class='hs-conid'>TBMChan</span> <span class='hs-varid'>closed</span> <span class='hs-sel'>_slots</span> <span class='hs-sel'>_reads</span> <span class='hs-varid'>chan</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-198"></a>    <span class='hs-varid'>b</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readTVar</span> <span class='hs-varid'>closed</span>
<a name="line-199"></a>    <span class='hs-keyword'>if</span> <span class='hs-varid'>b</span>
<a name="line-200"></a>        <span class='hs-keyword'>then</span> <span class='hs-keyword'>do</span>
<a name="line-201"></a>            <span class='hs-varid'>b'</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>isEmptyTChan</span> <span class='hs-varid'>chan</span>
<a name="line-202"></a>            <span class='hs-keyword'>if</span> <span class='hs-varid'>b'</span>
<a name="line-203"></a>                <span class='hs-keyword'>then</span> <span class='hs-varid'>return</span> <span class='hs-conid'>Nothing</span>
<a name="line-204"></a>                <span class='hs-keyword'>else</span> <span class='hs-conid'>Just</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>peekTChan</span> <span class='hs-varid'>chan</span>
<a name="line-205"></a>        <span class='hs-keyword'>else</span> <span class='hs-conid'>Just</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>peekTChan</span> <span class='hs-varid'>chan</span>
<a name="line-206"></a><span class='hs-comment'>{-
<a name="line-207"></a>-- The above is lazier reading from @chan@ than the clearer:
<a name="line-208"></a>peekTBMChan (TBMChan closed _slots _reads chan) = do
<a name="line-209"></a>    b  &lt;- isEmptyTChan chan
<a name="line-210"></a>    b' &lt;- readTVar closed
<a name="line-211"></a>    if b &amp;&amp; b' 
<a name="line-212"></a>        then return Nothing
<a name="line-213"></a>        else Just &lt;$&gt; peekTChan chan
<a name="line-214"></a>-- TODO: compare Core and benchmarks; is the loss of clarity worth it?
<a name="line-215"></a>-}</span>
<a name="line-216"></a>
<a name="line-217"></a>
<a name="line-218"></a><a name="tryPeekTBMChan"></a><span class='hs-comment'>-- | A version of 'peekTBMChan' which does not retry. Instead it</span>
<a name="line-219"></a><span class='hs-comment'>-- returns @Just Nothing@ if the channel is open but no value is</span>
<a name="line-220"></a><span class='hs-comment'>-- available; it still returns @Nothing@ if the channel is closed</span>
<a name="line-221"></a><span class='hs-comment'>-- and empty.</span>
<a name="line-222"></a><span class='hs-definition'>tryPeekTBMChan</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TBMChan</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-layout'>(</span><span class='hs-conid'>Maybe</span> <span class='hs-layout'>(</span><span class='hs-conid'>Maybe</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-223"></a><span class='hs-definition'>tryPeekTBMChan</span> <span class='hs-layout'>(</span><span class='hs-conid'>TBMChan</span> <span class='hs-varid'>closed</span> <span class='hs-sel'>_slots</span> <span class='hs-sel'>_reads</span> <span class='hs-varid'>chan</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-224"></a>    <span class='hs-varid'>b</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readTVar</span> <span class='hs-varid'>closed</span>
<a name="line-225"></a>    <span class='hs-keyword'>if</span> <span class='hs-varid'>b</span>
<a name="line-226"></a>        <span class='hs-keyword'>then</span> <span class='hs-varid'>fmap</span> <span class='hs-conid'>Just</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>tryPeekTChan</span> <span class='hs-varid'>chan</span>
<a name="line-227"></a>        <span class='hs-keyword'>else</span> <span class='hs-conid'>Just</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>tryPeekTChan</span> <span class='hs-varid'>chan</span>
<a name="line-228"></a><span class='hs-comment'>{-
<a name="line-229"></a>-- The above is lazier reading from @chan@ (and removes an extraneous isEmptyTChan when using the compatibility layer) than the clearer:
<a name="line-230"></a>tryPeekTBMChan (TBMChan closed _slots _reads chan) = do
<a name="line-231"></a>    b  &lt;- isEmptyTChan chan
<a name="line-232"></a>    b' &lt;- readTVar closed
<a name="line-233"></a>    if b &amp;&amp; b' 
<a name="line-234"></a>        then return Nothing
<a name="line-235"></a>        else Just &lt;$&gt; tryPeekTChan chan
<a name="line-236"></a>-- TODO: compare Core and benchmarks; is the loss of clarity worth it?
<a name="line-237"></a>-}</span>
<a name="line-238"></a>
<a name="line-239"></a>
<a name="line-240"></a><a name="writeTBMChan"></a><span class='hs-comment'>-- | Write a value to a @TBMChan@, retrying if the channel is full.</span>
<a name="line-241"></a><span class='hs-comment'>-- If the channel is closed then the value is silently discarded.</span>
<a name="line-242"></a><span class='hs-comment'>-- Use 'isClosedTBMChan' to determine if the channel is closed</span>
<a name="line-243"></a><span class='hs-comment'>-- before writing, as needed.</span>
<a name="line-244"></a><span class='hs-definition'>writeTBMChan</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TBMChan</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-conid'>()</span>
<a name="line-245"></a><span class='hs-definition'>writeTBMChan</span> <span class='hs-varid'>self</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>TBMChan</span> <span class='hs-varid'>closed</span> <span class='hs-varid'>slots</span> <span class='hs-sel'>_reads</span> <span class='hs-varid'>chan</span><span class='hs-layout'>)</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-246"></a>    <span class='hs-varid'>b</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readTVar</span> <span class='hs-varid'>closed</span>
<a name="line-247"></a>    <span class='hs-keyword'>if</span> <span class='hs-varid'>b</span>
<a name="line-248"></a>        <span class='hs-keyword'>then</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span> <span class='hs-comment'>-- Discard silently</span>
<a name="line-249"></a>        <span class='hs-keyword'>else</span> <span class='hs-keyword'>do</span>
<a name="line-250"></a>            <span class='hs-varid'>n</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>estimateFreeSlotsTBMChan</span> <span class='hs-varid'>self</span>
<a name="line-251"></a>            <span class='hs-keyword'>if</span> <span class='hs-varid'>n</span> <span class='hs-varop'>&lt;=</span> <span class='hs-num'>0</span>
<a name="line-252"></a>                <span class='hs-keyword'>then</span> <span class='hs-varid'>retry</span>
<a name="line-253"></a>                <span class='hs-keyword'>else</span> <span class='hs-keyword'>do</span>
<a name="line-254"></a>                    <span class='hs-varid'>writeTVar</span> <span class='hs-varid'>slots</span> <span class='hs-varop'>$!</span> <span class='hs-varid'>n</span> <span class='hs-comment'>-</span> <span class='hs-num'>1</span>
<a name="line-255"></a>                    <span class='hs-varid'>writeTChan</span> <span class='hs-varid'>chan</span> <span class='hs-varid'>x</span>
<a name="line-256"></a>
<a name="line-257"></a>
<a name="line-258"></a><a name="tryWriteTBMChan"></a><span class='hs-comment'>-- | A version of 'writeTBMChan' which does not retry. Returns @Just</span>
<a name="line-259"></a><span class='hs-comment'>-- True@ if the value was successfully written, @Just False@ if it</span>
<a name="line-260"></a><span class='hs-comment'>-- could not be written (but the channel was open), and @Nothing@</span>
<a name="line-261"></a><span class='hs-comment'>-- if it was discarded (i.e., the channel was closed).</span>
<a name="line-262"></a><span class='hs-definition'>tryWriteTBMChan</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TBMChan</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-layout'>(</span><span class='hs-conid'>Maybe</span> <span class='hs-conid'>Bool</span><span class='hs-layout'>)</span>
<a name="line-263"></a><span class='hs-definition'>tryWriteTBMChan</span> <span class='hs-varid'>self</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>TBMChan</span> <span class='hs-varid'>closed</span> <span class='hs-varid'>slots</span> <span class='hs-sel'>_reads</span> <span class='hs-varid'>chan</span><span class='hs-layout'>)</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-264"></a>    <span class='hs-varid'>b</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readTVar</span> <span class='hs-varid'>closed</span>
<a name="line-265"></a>    <span class='hs-keyword'>if</span> <span class='hs-varid'>b</span>
<a name="line-266"></a>        <span class='hs-keyword'>then</span> <span class='hs-varid'>return</span> <span class='hs-conid'>Nothing</span>
<a name="line-267"></a>        <span class='hs-keyword'>else</span> <span class='hs-keyword'>do</span>
<a name="line-268"></a>            <span class='hs-varid'>n</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>estimateFreeSlotsTBMChan</span> <span class='hs-varid'>self</span>
<a name="line-269"></a>            <span class='hs-keyword'>if</span> <span class='hs-varid'>n</span> <span class='hs-varop'>&lt;=</span> <span class='hs-num'>0</span>
<a name="line-270"></a>                <span class='hs-keyword'>then</span> <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-conid'>False</span><span class='hs-layout'>)</span>
<a name="line-271"></a>                <span class='hs-keyword'>else</span> <span class='hs-keyword'>do</span>
<a name="line-272"></a>                    <span class='hs-varid'>writeTVar</span> <span class='hs-varid'>slots</span> <span class='hs-varop'>$!</span> <span class='hs-varid'>n</span> <span class='hs-comment'>-</span> <span class='hs-num'>1</span>
<a name="line-273"></a>                    <span class='hs-varid'>writeTChan</span> <span class='hs-varid'>chan</span> <span class='hs-varid'>x</span>
<a name="line-274"></a>                    <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-conid'>True</span><span class='hs-layout'>)</span>
<a name="line-275"></a>
<a name="line-276"></a>
<a name="line-277"></a><a name="unGetTBMChan"></a><span class='hs-comment'>-- | Put a data item back onto a channel, where it will be the next</span>
<a name="line-278"></a><span class='hs-comment'>-- item read. If the channel is closed then the value is silently</span>
<a name="line-279"></a><span class='hs-comment'>-- discarded; you can use 'peekTBMChan' to circumvent this in certain</span>
<a name="line-280"></a><span class='hs-comment'>-- circumstances. /N.B./, this could allow the channel to temporarily</span>
<a name="line-281"></a><span class='hs-comment'>-- become longer than the specified limit, which is necessary to</span>
<a name="line-282"></a><span class='hs-comment'>-- ensure that the item is indeed the next one read.</span>
<a name="line-283"></a><span class='hs-definition'>unGetTBMChan</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TBMChan</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-conid'>()</span>
<a name="line-284"></a><span class='hs-definition'>unGetTBMChan</span> <span class='hs-layout'>(</span><span class='hs-conid'>TBMChan</span> <span class='hs-varid'>closed</span> <span class='hs-varid'>slots</span> <span class='hs-sel'>_reads</span> <span class='hs-varid'>chan</span><span class='hs-layout'>)</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-285"></a>    <span class='hs-varid'>b</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readTVar</span> <span class='hs-varid'>closed</span>
<a name="line-286"></a>    <span class='hs-keyword'>if</span> <span class='hs-varid'>b</span>
<a name="line-287"></a>        <span class='hs-keyword'>then</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span> <span class='hs-comment'>-- Discard silently</span>
<a name="line-288"></a>        <span class='hs-keyword'>else</span> <span class='hs-keyword'>do</span>
<a name="line-289"></a>            <span class='hs-varid'>modifyTVar'</span> <span class='hs-varid'>slots</span> <span class='hs-layout'>(</span><span class='hs-varid'>subtract</span> <span class='hs-num'>1</span><span class='hs-layout'>)</span>
<a name="line-290"></a>            <span class='hs-varid'>unGetTChan</span> <span class='hs-varid'>chan</span> <span class='hs-varid'>x</span>
<a name="line-291"></a>
<a name="line-292"></a>
<a name="line-293"></a><a name="closeTBMChan"></a><span class='hs-comment'>-- | Closes the @TBMChan@, preventing any further writes.</span>
<a name="line-294"></a><span class='hs-definition'>closeTBMChan</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TBMChan</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-conid'>()</span>
<a name="line-295"></a><span class='hs-definition'>closeTBMChan</span> <span class='hs-layout'>(</span><span class='hs-conid'>TBMChan</span> <span class='hs-varid'>closed</span> <span class='hs-sel'>_slots</span> <span class='hs-sel'>_reads</span> <span class='hs-sel'>_chan</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
<a name="line-296"></a>    <span class='hs-varid'>writeTVar</span> <span class='hs-varid'>closed</span> <span class='hs-conid'>True</span>
<a name="line-297"></a>
<a name="line-298"></a>
<a name="line-299"></a><a name="isClosedTBMChan"></a><span class='hs-comment'>-- | Returns @True@ if the supplied @TBMChan@ has been closed.</span>
<a name="line-300"></a><span class='hs-definition'>isClosedTBMChan</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TBMChan</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-conid'>Bool</span>
<a name="line-301"></a><span class='hs-definition'>isClosedTBMChan</span> <span class='hs-layout'>(</span><span class='hs-conid'>TBMChan</span> <span class='hs-varid'>closed</span> <span class='hs-sel'>_slots</span> <span class='hs-sel'>_reads</span> <span class='hs-sel'>_chan</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
<a name="line-302"></a>    <span class='hs-varid'>readTVar</span> <span class='hs-varid'>closed</span>
<a name="line-303"></a>
<a name="line-304"></a><span class='hs-comment'>{-
<a name="line-305"></a>-- | Returns @True@ if the supplied @TBMChan@ has been closed.
<a name="line-306"></a>isClosedTBMChanIO :: TBMChan a -&gt; IO Bool
<a name="line-307"></a>isClosedTBMChanIO (TBMChan closed _slots _reads _chan) =
<a name="line-308"></a>    readTVarIO closed
<a name="line-309"></a>-}</span>
<a name="line-310"></a>
<a name="line-311"></a>
<a name="line-312"></a><a name="isEmptyTBMChan"></a><span class='hs-comment'>-- | Returns @True@ if the supplied @TBMChan@ is empty (i.e., has</span>
<a name="line-313"></a><span class='hs-comment'>-- no elements). /N.B./, a @TBMChan@ can be both ``empty'' and</span>
<a name="line-314"></a><span class='hs-comment'>-- ``full'' at the same time, if the initial limit was non-positive.</span>
<a name="line-315"></a><span class='hs-definition'>isEmptyTBMChan</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TBMChan</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-conid'>Bool</span>
<a name="line-316"></a><span class='hs-definition'>isEmptyTBMChan</span> <span class='hs-layout'>(</span><span class='hs-conid'>TBMChan</span> <span class='hs-sel'>_closed</span> <span class='hs-sel'>_slots</span> <span class='hs-sel'>_reads</span> <span class='hs-varid'>chan</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
<a name="line-317"></a>    <span class='hs-varid'>isEmptyTChan</span> <span class='hs-varid'>chan</span>
<a name="line-318"></a>
<a name="line-319"></a>
<a name="line-320"></a><a name="isFullTBMChan"></a><span class='hs-comment'>-- | Returns @True@ if the supplied @TBMChan@ is full (i.e., is</span>
<a name="line-321"></a><span class='hs-comment'>-- over its limit). /N.B./, a @TBMChan@ can be both ``empty'' and</span>
<a name="line-322"></a><span class='hs-comment'>-- ``full'' at the same time, if the initial limit was non-positive.</span>
<a name="line-323"></a><span class='hs-comment'>-- /N.B./, a @TBMChan@ may still be full after reading, if</span>
<a name="line-324"></a><span class='hs-comment'>-- 'unGetTBMChan' was used to go over the initial limit.</span>
<a name="line-325"></a><span class='hs-comment'>--</span>
<a name="line-326"></a><span class='hs-comment'>-- This is equivalent to: @liftM (&lt;= 0) estimateFreeSlotsTBMChan@</span>
<a name="line-327"></a><span class='hs-definition'>isFullTBMChan</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TBMChan</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-conid'>Bool</span>
<a name="line-328"></a><span class='hs-definition'>isFullTBMChan</span> <span class='hs-layout'>(</span><span class='hs-conid'>TBMChan</span> <span class='hs-sel'>_closed</span> <span class='hs-varid'>slots</span> <span class='hs-varid'>reads</span> <span class='hs-sel'>_chan</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-329"></a>    <span class='hs-varid'>n</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readTVar</span> <span class='hs-varid'>slots</span>
<a name="line-330"></a>    <span class='hs-keyword'>if</span> <span class='hs-varid'>n</span> <span class='hs-varop'>&lt;=</span> <span class='hs-num'>0</span>
<a name="line-331"></a>        <span class='hs-keyword'>then</span> <span class='hs-keyword'>do</span>
<a name="line-332"></a>            <span class='hs-varid'>m</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readTVar</span> <span class='hs-varid'>reads</span>
<a name="line-333"></a>            <span class='hs-keyword'>let</span> <span class='hs-varid'>n'</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>n</span> <span class='hs-varop'>+</span> <span class='hs-varid'>m</span>
<a name="line-334"></a>            <span class='hs-varid'>writeTVar</span> <span class='hs-varid'>slots</span> <span class='hs-varop'>$!</span> <span class='hs-varid'>n'</span>
<a name="line-335"></a>            <span class='hs-varid'>writeTVar</span> <span class='hs-varid'>reads</span> <span class='hs-num'>0</span>
<a name="line-336"></a>            <span class='hs-varid'>return</span> <span class='hs-varop'>$!</span> <span class='hs-varid'>n'</span> <span class='hs-varop'>&lt;=</span> <span class='hs-num'>0</span>
<a name="line-337"></a>        <span class='hs-keyword'>else</span> <span class='hs-varid'>return</span> <span class='hs-conid'>False</span>
<a name="line-338"></a>
<a name="line-339"></a>
<a name="line-340"></a><a name="estimateFreeSlotsTBMChan"></a><span class='hs-comment'>-- | Estimate the number of free slots. If the result is positive,</span>
<a name="line-341"></a><span class='hs-comment'>-- then it's a minimum bound; if it's non-positive then it's exact.</span>
<a name="line-342"></a><span class='hs-comment'>-- It will only be negative if the initial limit was negative or</span>
<a name="line-343"></a><span class='hs-comment'>-- if 'unGetTBMChan' was used to go over the initial limit.</span>
<a name="line-344"></a><span class='hs-comment'>--</span>
<a name="line-345"></a><span class='hs-comment'>-- This function always contends with writers, but only contends</span>
<a name="line-346"></a><span class='hs-comment'>-- with readers when it has to; compare against 'freeSlotsTBMChan'.</span>
<a name="line-347"></a><span class='hs-definition'>estimateFreeSlotsTBMChan</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TBMChan</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-conid'>Int</span>
<a name="line-348"></a><span class='hs-definition'>estimateFreeSlotsTBMChan</span> <span class='hs-layout'>(</span><span class='hs-conid'>TBMChan</span> <span class='hs-sel'>_closed</span> <span class='hs-varid'>slots</span> <span class='hs-varid'>reads</span> <span class='hs-sel'>_chan</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-349"></a>    <span class='hs-varid'>n</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readTVar</span> <span class='hs-varid'>slots</span>
<a name="line-350"></a>    <span class='hs-keyword'>if</span> <span class='hs-varid'>n</span> <span class='hs-varop'>&gt;</span> <span class='hs-num'>0</span>
<a name="line-351"></a>        <span class='hs-keyword'>then</span> <span class='hs-varid'>return</span> <span class='hs-varid'>n</span>
<a name="line-352"></a>        <span class='hs-keyword'>else</span> <span class='hs-keyword'>do</span>
<a name="line-353"></a>            <span class='hs-varid'>m</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readTVar</span> <span class='hs-varid'>reads</span>
<a name="line-354"></a>            <span class='hs-keyword'>let</span> <span class='hs-varid'>n'</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>n</span> <span class='hs-varop'>+</span> <span class='hs-varid'>m</span>
<a name="line-355"></a>            <span class='hs-varid'>writeTVar</span> <span class='hs-varid'>slots</span> <span class='hs-varop'>$!</span> <span class='hs-varid'>n'</span>
<a name="line-356"></a>            <span class='hs-varid'>writeTVar</span> <span class='hs-varid'>reads</span> <span class='hs-num'>0</span>
<a name="line-357"></a>            <span class='hs-varid'>return</span> <span class='hs-varid'>n'</span>
<a name="line-358"></a>
<a name="line-359"></a>
<a name="line-360"></a><a name="freeSlotsTBMChan"></a><span class='hs-comment'>-- | Return the exact number of free slots. The result can be</span>
<a name="line-361"></a><span class='hs-comment'>-- negative if the initial limit was negative or if 'unGetTBMChan'</span>
<a name="line-362"></a><span class='hs-comment'>-- was used to go over the initial limit.</span>
<a name="line-363"></a><span class='hs-comment'>--</span>
<a name="line-364"></a><span class='hs-comment'>-- This function always contends with both readers and writers;</span>
<a name="line-365"></a><span class='hs-comment'>-- compare against 'estimateFreeSlotsTBMChan'.</span>
<a name="line-366"></a><span class='hs-definition'>freeSlotsTBMChan</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TBMChan</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-conid'>Int</span>
<a name="line-367"></a><span class='hs-definition'>freeSlotsTBMChan</span> <span class='hs-layout'>(</span><span class='hs-conid'>TBMChan</span> <span class='hs-sel'>_closed</span> <span class='hs-varid'>slots</span> <span class='hs-varid'>reads</span> <span class='hs-sel'>_chan</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-368"></a>    <span class='hs-varid'>n</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readTVar</span> <span class='hs-varid'>slots</span>
<a name="line-369"></a>    <span class='hs-varid'>m</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readTVar</span> <span class='hs-varid'>reads</span>
<a name="line-370"></a>    <span class='hs-keyword'>let</span> <span class='hs-varid'>n'</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>n</span> <span class='hs-varop'>+</span> <span class='hs-varid'>m</span>
<a name="line-371"></a>    <span class='hs-varid'>writeTVar</span> <span class='hs-varid'>slots</span> <span class='hs-varop'>$!</span> <span class='hs-varid'>n'</span>
<a name="line-372"></a>    <span class='hs-varid'>writeTVar</span> <span class='hs-varid'>reads</span> <span class='hs-num'>0</span>
<a name="line-373"></a>    <span class='hs-varid'>return</span> <span class='hs-varid'>n'</span>
<a name="line-374"></a>
<a name="line-375"></a><span class='hs-comment'>----------------------------------------------------------------</span>
<a name="line-376"></a><span class='hs-comment'>----------------------------------------------------------- fin.</span>
</pre></body>
</html>