summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2013-06-18 20:15:43 -0400
committerjoe <joe@jerkface.net>2013-06-18 20:15:43 -0400
commitd48d40840f96eba78e3de5e59a0ffb14cca76714 (patch)
tree1cc943b79d8c8523d6145e170c83f9f333e7bf95
parent65dbc306a66e28b2bc16ff63912ea5f762cdea37 (diff)
Switched from MVar to STM monad.
-rw-r--r--Presence/main.hs58
1 files changed, 37 insertions, 21 deletions
diff --git a/Presence/main.hs b/Presence/main.hs
index e5d3046c..f77e582b 100644
--- a/Presence/main.hs
+++ b/Presence/main.hs
@@ -34,14 +34,12 @@ import qualified Data.Set as Set
34import Data.Set as Set (Set,(\\)) 34import Data.Set as Set (Set,(\\))
35import qualified Data.Map as Map 35import qualified Data.Map as Map
36import Data.Map as Map (Map) 36import Data.Map as Map (Map)
37import Control.Concurrent.MVar -- .Strict 37
38import Control.Concurrent.STM
38import Control.Concurrent (threadDelay) 39import Control.Concurrent (threadDelay)
39import Control.Concurrent.Chan
40import Control.DeepSeq 40import Control.DeepSeq
41import Control.Monad.Trans.Maybe 41import Control.Monad.Trans.Maybe
42-- import Control.Monad.Trans.Class
43import Control.Monad.IO.Class 42import Control.Monad.IO.Class
44-- import Debug.Trace
45 43
46import ByteStringOperators 44import ByteStringOperators
47import qualified Data.ByteString.Lazy.Char8 as L 45import qualified Data.ByteString.Lazy.Char8 as L
@@ -117,7 +115,7 @@ matchResource tty jid = maybe Away (avail . (==tty)) $ resource jid
117 avail False = Away 115 avail False = Away
118 116
119sendPresence chan jid status = 117sendPresence chan jid status =
120 (liftIO . writeChan chan . Just . Presence jid $ status) :: MaybeT IO () 118 (liftIO . atomically . writeTChan chan . Presence jid $ status) :: MaybeT IO ()
121 119
122lookupT jid subscribers = MaybeT . return $ Map.lookup jid subscribers 120lookupT jid subscribers = MaybeT . return $ Map.lookup jid subscribers
123 121
@@ -129,8 +127,21 @@ update_presence subscribers state getStatus =
129 sendPresence chan jid status 127 sendPresence chan jid status
130 putStrLn $ bshow jid <++> " " <++> bshow status 128 putStrLn $ bshow jid <++> " " <++> bshow status
131 129
132track_login :: MVar (ByteString,Set JID,Map JID (Chan MaybePresence)) -> t -> IO () 130type RefCount = Int
133track_login mvar e = do 131
132data PresenceState = PresenceState {
133 currentTTY :: TVar ByteString,
134 activeUsers :: TVar (Set JID),
135 subscriberMap :: TVar (Map JID (RefCount,TChan Presence))
136 }
137
138newPresenceState = atomically $ do
139 tty <- newTVar ""
140 us <- newTVar (Set.empty)
141 subs <- newTVar (Map.empty)
142 return $ PresenceState tty us subs
143
144track_login state e = do
134#ifndef NOUTMP 145#ifndef NOUTMP
135 us <- UTmp.users 146 us <- UTmp.users
136#else 147#else
@@ -140,26 +151,31 @@ track_login mvar e = do
140 if L.take 3 tty == "tty" 151 if L.take 3 tty == "tty"
141 then Just (jid user host tty) 152 then Just (jid user host tty)
142 else Nothing 153 else Nothing
143 jids = Set.fromList $ mapMaybe (toJabberId "localhost") us 154 new_users = Set.fromList $ mapMaybe (toJabberId "localhost") us
144 (tty,users,subscribers) 155 (tty,known_users,subs) <- atomically $ do
145 <- modifyMVar mvar $ \(tty,st,xs) -> 156 tty <- readTVar $ currentTTY state
146 return ((tty,jids,xs),(tty,st,xs)) 157 st <- flip swapTVar new_users $ activeUsers state
147 let arrivals = jids \\ users 158 xs <- readTVar $ subscriberMap state
148 departures = users \\ jids 159 return (tty,st,fmap snd xs)
149 update_presence subscribers departures $ const Offline 160 let arrivals = new_users \\ known_users
150 update_presence subscribers arrivals $ matchResource tty 161 departures = known_users \\ new_users
151 162 update_presence subs departures $ const Offline
152on_chvt mvar vtnum = do 163 update_presence subs arrivals $ matchResource tty
164
165on_chvt state vtnum = do
153 let tty = L.snoc "tty" $ intToDigit (fromIntegral vtnum) 166 let tty = L.snoc "tty" $ intToDigit (fromIntegral vtnum)
154 L.putStrLn $ "VT switch: " <++> tty 167 L.putStrLn $ "VT switch: " <++> tty
155 (users,subscribers) <- modifyMVar mvar $ \(_,us,xs) -> do 168 (users,subs) <- atomically $ do
156 return ((tty,us,xs),(us,xs)) 169 us <- readTVar $ activeUsers state
157 update_presence subscribers users $ matchResource tty 170 subs <- readTVar $ subscriberMap state
171 writeTVar (currentTTY state) tty
172 return (us,fmap snd subs)
173 update_presence subs users $ matchResource tty
158 174
159 175
160start :: IO () 176start :: IO ()
161start = do 177start = do
162 tracked <- newMVar ("",Set.empty,Map.empty) 178 tracked <- newPresenceState
163 let dologin e = track_login tracked e 179 let dologin e = track_login tracked e
164 dologin :: t -> IO () 180 dologin :: t -> IO ()
165 installHandler sigUSR1 (Catch (dologin (userError "signaled"))) Nothing 181 installHandler sigUSR1 (Catch (dologin (userError "signaled"))) Nothing