diff options
author | joe <joe@jerkface.net> | 2017-09-15 03:36:00 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2017-09-15 03:36:00 -0400 |
commit | 2d26a10be45a377cd76346336de9667b278a2c28 (patch) | |
tree | 0b9ac9680beef23bfe0aa8830d112642e8cfccef /src | |
parent | 2fb1f3507075c4cce4f33096ce0080bb14fd2704 (diff) |
Moved TriadCommittee to hierarchical location.
Diffstat (limited to 'src')
-rw-r--r-- | src/Control/TriadCommittee.hs | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/Control/TriadCommittee.hs b/src/Control/TriadCommittee.hs new file mode 100644 index 00000000..88e665b6 --- /dev/null +++ b/src/Control/TriadCommittee.hs | |||
@@ -0,0 +1,89 @@ | |||
1 | {-# LANGUAGE TupleSections #-} | ||
2 | module Control.TriadCommittee where | ||
3 | |||
4 | import Control.Concurrent.STM | ||
5 | import Control.Monad | ||
6 | import Data.Maybe | ||
7 | |||
8 | |||
9 | data TriadSlot = SlotA | SlotB | SlotC | ||
10 | deriving (Eq,Ord,Enum,Show,Read) | ||
11 | |||
12 | data TriadCommittee voter a = TriadCommittee | ||
13 | { triadDecider :: TVar TriadSlot | ||
14 | , triadA :: TVar (Maybe (voter,a)) | ||
15 | , triadB :: TVar (Maybe (voter,a)) | ||
16 | , triadC :: TVar (Maybe (voter,a)) | ||
17 | , triadNewDecision :: a -> STM () | ||
18 | } | ||
19 | |||
20 | triadSlot :: TriadSlot -> TriadCommittee voter a -> TVar (Maybe (voter,a)) | ||
21 | triadSlot SlotA = triadA | ||
22 | triadSlot SlotB = triadB | ||
23 | triadSlot SlotC = triadC | ||
24 | |||
25 | triadDecision :: a -> TriadCommittee voter a -> STM a | ||
26 | triadDecision fallback triad = do | ||
27 | slot <- readTVar (triadDecider triad) | ||
28 | maybe fallback snd <$> readTVar (triadSlot slot triad) | ||
29 | |||
30 | |||
31 | newTriadCommittee :: (a -> STM ()) -> STM (TriadCommittee voter a) | ||
32 | newTriadCommittee onChange = | ||
33 | TriadCommittee <$> newTVar SlotA | ||
34 | <*> newTVar Nothing | ||
35 | <*> newTVar Nothing | ||
36 | <*> newTVar Nothing | ||
37 | <*> pure onChange | ||
38 | |||
39 | |||
40 | triadCountVotes :: Eq a => Maybe a -> TriadCommittee voter a -> STM () | ||
41 | triadCountVotes prior triad = do | ||
42 | a <- fmap ((SlotA,) . snd) <$> readTVar (triadA triad) | ||
43 | b <- fmap ((SlotB,) . snd) <$> readTVar (triadB triad) | ||
44 | c <- fmap ((SlotC,) . snd) <$> readTVar (triadC triad) | ||
45 | let (slot,vote) = case catMaybes [a,b,c] of | ||
46 | [ (x,xvote) | ||
47 | , (y,yvote) | ||
48 | , (z,zvote) ] -> if xvote == yvote then (x,Just xvote) | ||
49 | else (z,Just zvote) | ||
50 | [] -> (SlotA,Nothing) | ||
51 | ((slot,vote):_) -> (slot, Just vote) | ||
52 | writeTVar (triadDecider triad) slot | ||
53 | case vote of | ||
54 | Just v | vote /= prior -> triadNewDecision triad v | ||
55 | _ -> return () | ||
56 | |||
57 | |||
58 | addVote :: (Eq voter, Eq a) => TriadCommittee voter a -> voter -> a -> STM () | ||
59 | addVote triad voter vote = do | ||
60 | a <- (SlotA,) . fmap fst <$> readTVar (triadA triad) | ||
61 | b <- (SlotB,) . fmap fst <$> readTVar (triadB triad) | ||
62 | c <- (SlotC,) . fmap fst <$> readTVar (triadC triad) | ||
63 | let avail (_,Nothing) = True | ||
64 | avail (_,Just x ) = (x == voter) | ||
65 | slots = filter avail [a,b,c] | ||
66 | forM_ (take 1 slots) $ \(slot,_) -> do | ||
67 | prior <- do | ||
68 | slotp <- readTVar (triadDecider triad) | ||
69 | fmap snd <$> readTVar (triadSlot slotp triad) | ||
70 | writeTVar (triadSlot slot triad) | ||
71 | (Just (voter,vote)) | ||
72 | triadCountVotes prior triad | ||
73 | |||
74 | |||
75 | delVote :: (Eq voter, Eq a) => TriadCommittee voter a -> voter -> STM () | ||
76 | delVote triad voter = do | ||
77 | a <- (SlotA,) . fmap fst <$> readTVar (triadA triad) | ||
78 | b <- (SlotB,) . fmap fst <$> readTVar (triadB triad) | ||
79 | c <- (SlotC,) . fmap fst <$> readTVar (triadC triad) | ||
80 | let match (_,Just x ) = (x == voter) | ||
81 | match _ = False | ||
82 | slots = filter match [a,b,c] | ||
83 | forM_ (take 1 slots) $ \(slot,_) -> do | ||
84 | prior <- do | ||
85 | slotp <- readTVar (triadDecider triad) | ||
86 | fmap snd <$> readTVar (triadSlot slotp triad) | ||
87 | writeTVar (triadSlot slot triad) Nothing | ||
88 | triadCountVotes prior triad | ||
89 | |||