File: SampleVar.lhs

package info (click to toggle)
hugs 1.4.199801-1
  • links: PTS
  • area: non-free
  • in suites: slink
  • size: 7,220 kB
  • ctags: 5,609
  • sloc: ansic: 32,083; haskell: 12,143; yacc: 949; perl: 823; sh: 602; makefile: 236
file content (85 lines) | stat: -rw-r--r-- 2,149 bytes parent folder | download | duplicates (3)
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
%
% (c) The GRASP/AQUA Project, Glasgow University, 1995
%
\section[SampleVar]{Sample variables}

Sample variables are slightly different from a normal @MVar@:

\begin{itemize}
\item Reading an empty @SampleVar@ causes the reader to block.
    (same as @takeMVar@ on empty @MVar@)
\item Reading a filled @SampleVar@ empties it and returns value.
    (same as @takeMVar@)
\item Writing to an empty @SampleVar@ fills it with a value, and
potentially, wakes up a blocked reader  (same as for @putMVar@ on empty @MVar@).
\item Writing to a filled @SampleVar@ overwrites the current value.
 (different from @putMVar@ on full @MVar@.)
\end{itemize}

\begin{code}
module SampleVar
       (
         SampleVar,        --:: type _ =
 
         newSampleVar,     --:: IO (SampleVar a)
	 emptySampleVar,   --:: SampleVar a -> IO ()
	 readSampleVar,	   --:: SampleVar a -> IO a
	 writeSampleVar	   --:: SampleVar a -> a -> IO ()

       ) where

import ConcBase


type SampleVar a
 = MVar (Int,		-- 1  == full
			-- 0  == empty
			-- <0 no of readers blocked
          MVar a)

-- Initally, a @SampleVar@ is empty/unfilled.

newEmptySampleVar :: IO (SampleVar a)
newEmptySampleVar
 = newEmptyMVar          >>= \ val ->
   newMVar (0,val)

newSampleVar :: a -> IO (SampleVar a)
newSampleVar a = do
   v <- newEmptySampleVar
   writeSampleVar v a
   return v

emptySampleVar :: SampleVar a -> IO ()
emptySampleVar v
 = takeMVar v         >>= \ (readers,var) ->
   if readers >= 0 then
     putMVar v (0,var)
   else
     putMVar v (readers,var)

--
-- filled => make empty and grab sample
-- not filled => try to grab value, empty when read val.
--
readSampleVar :: SampleVar a -> IO a
readSampleVar svar
 = takeMVar svar                >>= \ (readers,val) ->
   putMVar svar (readers-1,val) >>
   takeMVar val

--
-- filled => overwrite
-- not filled => fill, write val
--
writeSampleVar :: SampleVar a -> a -> IO ()
writeSampleVar svar v
 = takeMVar svar  >>= \ (readers, val) ->
   case readers of
     1 -> 
       swapMVar val v 	    >> 
       putMVar svar (1,val)
     _ -> 
       putMVar val v >> 
       putMVar svar (min 1 (readers+1), val)
\end{code}