- Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathDistributed.hs
More file actions
Latest commit
103 lines (84 loc) · 3.59 KB
/
Copy pathDistributed.hs
File metadata and controls
103 lines (84 loc) · 3.59 KB
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
{-# LANGUAGE GeneralizedNewtypeDeriving #-} -- Allows automatic derivation of e.g. Monad
{-# LANGUAGE DeriveGeneric #-} -- Allows Generic, for auto-generation of serialization code
{-# LANGUAGE TemplateHaskell #-} -- Allows automatic creation of Lenses for ServerState
importControl.Distributed.Process.Node (initRemoteTable, runProcess, newLocalNode)
importControl.Distributed.Process (Process, ProcessId,
send, say, expect, getSelfPid, spawnLocal, match, receiveWait)
importNetwork.Transport.TCP (createTransport, defaultTCPParameters)
importData.Binary (Binary) -- Objects have to be binary to send over the network
importGHC.Generics (Generic) -- For auto-derivation of serialization
importData.Typeable (Typeable) -- For safe serialization
importControl.Monad.RWS.Strict (
RWS, MonadReader, MonadWriter, MonadState,
ask, tell, get, execRWS, liftIO)
importControl.Monad (replicateM, forever)
importControl.Concurrent (threadDelay)
importControl.Lens (makeLenses, (+=), (%%=))
importSystem.Random (StdGen, Random, randomR, newStdGen)
dataBingBong=Bing | Bong
deriving (Show, Generic, Typeable)
dataMessage=Message{senderOf::ProcessId, recipientOf::ProcessId, msg::BingBong}
deriving (Show, Generic, Typeable)
dataTick=Tickderiving (Show, Generic, Typeable)
instanceBinaryBingBong
instanceBinaryMessage
instanceBinaryTick
dataServerState=ServerState{
_bingCount::Int,
_bongCount::Int,
_randomGen::StdGen
}deriving (Show)
makeLenses ''ServerState
dataServerConfig=ServerConfig{
myId::ProcessId,
peers:: [ProcessId]
}deriving (Show)
newtypeServerActiona=ServerAction{runAction::RWSServerConfig [Message] ServerStatea}
deriving (Functor, Applicative, Monad, MonadStateServerState,
MonadWriter [Message], MonadReaderServerConfig)
tickHandler::Tick->ServerAction()
tickHandler Tick=do
ServerConfig myPid peers <- ask
random <- randomWithin (0, length peers -1)
let peer = peers !! random
sendBingBongTo peer Bing
msgHandler::Message->ServerAction()
msgHandler (Message sender recipient Bing) =do
bingCount +=1
sendBingBongTo sender Bong
msgHandler (Message sender recipient Bong) =do
bongCount +=1
sendBingBongTo::ProcessId->BingBong->ServerAction()
sendBingBongTo recipient bingbong =do
ServerConfig myId _ <- ask
tell [Message myId recipient bingbong]
randomWithin::Randomr=> (r,r) ->ServerActionr
randomWithin bounds = randomGen %%= randomR bounds
runServer::ServerConfig->ServerState->Process()
runServer config state =do
let run handler msg =return$ execRWS (runAction $ handler msg) config state
(state', outputMessages) <- receiveWait [
match $ run msgHandler,
match $ run tickHandler]
say $"Current state: "++show state'
mapM (\msg -> send (recipientOf msg) msg) outputMessages
runServer config state'
spawnServer::ProcessProcessId
spawnServer = spawnLocal $do
myPid <- getSelfPid
otherPids <- expect
spawnLocal $ forever $do
liftIO $ threadDelay (10^6)
send myPid Tick
randomGen <- liftIO newStdGen
runServer (ServerConfig myPid otherPids) (ServerState00 randomGen)
spawnServers::Int->Process()
spawnServers count =do
pids <- replicateM count spawnServer
mapM_ (`send` pids) pids
main =do
Right transport <- createTransport "localhost""0" defaultTCPParameters
backendNode <- newLocalNode transport initRemoteTable
runProcess backendNode (spawnServers 10)
putStrLn"Push enter to exit"
getLine