File: GraphicsEvents.hs

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 (65 lines) | stat: -rw-r--r-- 1,575 bytes parent folder | download
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
module GraphicsEvents(
	Events, newEvents, getEvent, sendEvent, getTick, sendTick,
	Event
	) where

import GraphicsEvent( Event )

import Concurrent
	( MVar, newEmptyMVar, newMVar, takeMVar, putMVar
	, Chan, newChan, readChan, writeChan 
	)

data Events = Events { events :: Chan Event
                     , tick   :: Flag ()
		     }

newEvents :: IO Events
newEvents = do
  events <- newChan 
  tick   <- newFlag
  return (Events { events, tick })

getEvent :: Events -> IO Event
getEvent evs = readChan (events evs)

sendEvent :: Events -> Event -> IO ()
sendEvent evs = writeChan (events evs)

sendTick :: Events -> IO ()
sendTick evs = setFlag (tick evs) ()

getTick :: Events -> IO ()
getTick evs = resetFlag (tick evs)

----------------------------------------------------------------
-- Flags (should be a separate module)
--
--   set   : sets the flag, never blocks, never fails
--   reset : block until the flag is set (and reset it)
--
----------------------------------------------------------------

-- We maintain a list of blocked processes.
-- Blocked processes are "stored" in MVars; the outer MVar
-- is used to implement a critical section.

newtype Flag a = Flag (MVar [MVar a])

newFlag :: IO (Flag a)
newFlag = do
  queue <- newMVar []
  return (Flag queue)

setFlag :: Flag a -> a -> IO ()
setFlag (Flag queue) a = do
  ps <- takeMVar queue
  mapM_ (\ p -> putMVar p a) ps
  putMVar queue []

resetFlag :: Flag a -> IO a
resetFlag (Flag queue) = do
  ps <- takeMVar queue
  p  <- newEmptyMVar 
  putMVar queue (p:ps)
  takeMVar p             -- block