diff options
author | Sam T <pxqr.sta@gmail.com> | 2013-06-13 07:20:42 +0400 |
---|---|---|
committer | Sam T <pxqr.sta@gmail.com> | 2013-06-13 07:20:42 +0400 |
commit | 9557004a2c916d475038f99cf26e5c36bbbae0a4 (patch) | |
tree | d6436c30aaaf9ab6332dcb57d78d1f0a8a3298b6 | |
parent | 758286a8fce87597d86965239934b824f9e0511b (diff) |
~ Use safe semaphores.
-rw-r--r-- | bittorrent.cabal | 18 | ||||
-rw-r--r-- | src/Network/BitTorrent/Internal.hs | 29 |
2 files changed, 28 insertions, 19 deletions
diff --git a/bittorrent.cabal b/bittorrent.cabal index 28188ce3..73e8bef2 100644 --- a/bittorrent.cabal +++ b/bittorrent.cabal | |||
@@ -54,10 +54,15 @@ library | |||
54 | 54 | ||
55 | 55 | ||
56 | build-depends: | 56 | build-depends: |
57 | -- Basic packages | ||
58 | base == 4.* | 57 | base == 4.* |
59 | , stm >= 2.4 | 58 | |
59 | -- Control packages | ||
60 | , mtl | 60 | , mtl |
61 | , lens | ||
62 | |||
63 | -- Concurrency packages | ||
64 | , SafeSemaphore | ||
65 | , stm >= 2.4 | ||
61 | 66 | ||
62 | -- Data packages | 67 | -- Data packages |
63 | , array >= 0.4 | 68 | , array >= 0.4 |
@@ -68,28 +73,27 @@ library | |||
68 | , text >= 0.11.0 | 73 | , text >= 0.11.0 |
69 | , vector | 74 | , vector |
70 | 75 | ||
71 | -- encoding/serialization packages | 76 | -- Encoding/Serialization packages |
72 | , bencoding >= 0.1 | 77 | , bencoding >= 0.1 |
73 | , cereal >= 0.3 | 78 | , cereal >= 0.3 |
74 | , urlencoded >= 0.4 | 79 | , urlencoded >= 0.4 |
75 | 80 | ||
76 | -- time packages | 81 | -- Time packages |
77 | , time >= 0.1 | 82 | , time >= 0.1 |
78 | , old-locale >= 1.0 | 83 | , old-locale >= 1.0 |
79 | 84 | ||
80 | -- network related packages | 85 | -- Network packages |
81 | , network >= 2.4 | 86 | , network >= 2.4 |
82 | , HTTP >= 4000.2 | 87 | , HTTP >= 4000.2 |
83 | , krpc | 88 | , krpc |
84 | 89 | ||
85 | -- conduits | 90 | -- Conduits |
86 | , conduit == 1.* | 91 | , conduit == 1.* |
87 | , network-conduit == 1.* | 92 | , network-conduit == 1.* |
88 | , cereal-conduit >= 0.5 | 93 | , cereal-conduit >= 0.5 |
89 | , resourcet | 94 | , resourcet |
90 | 95 | ||
91 | -- Misc | 96 | -- Misc |
92 | , lens | ||
93 | , data-default | 97 | , data-default |
94 | , cryptohash | 98 | , cryptohash |
95 | , filepath >= 1 | 99 | , filepath >= 1 |
diff --git a/src/Network/BitTorrent/Internal.hs b/src/Network/BitTorrent/Internal.hs index f762bf34..2fadd9ce 100644 --- a/src/Network/BitTorrent/Internal.hs +++ b/src/Network/BitTorrent/Internal.hs | |||
@@ -58,6 +58,7 @@ module Network.BitTorrent.Internal | |||
58 | import Control.Applicative | 58 | import Control.Applicative |
59 | import Control.Concurrent | 59 | import Control.Concurrent |
60 | import Control.Concurrent.STM | 60 | import Control.Concurrent.STM |
61 | import Control.Concurrent.MSem as MSem | ||
61 | import Control.Lens | 62 | import Control.Lens |
62 | import Control.Monad.State | 63 | import Control.Monad.State |
63 | import Control.Monad.Reader | 64 | import Control.Monad.Reader |
@@ -106,6 +107,8 @@ startProgress = Progress 0 0 | |||
106 | Client session | 107 | Client session |
107 | -----------------------------------------------------------------------} | 108 | -----------------------------------------------------------------------} |
108 | 109 | ||
110 | type ThreadCount = Int | ||
111 | |||
109 | -- | In one application we could have many clients with difference | 112 | -- | In one application we could have many clients with difference |
110 | -- ID's and different enabled extensions. | 113 | -- ID's and different enabled extensions. |
111 | data ClientSession = ClientSession { | 114 | data ClientSession = ClientSession { |
@@ -119,10 +122,10 @@ data ClientSession = ClientSession { | |||
119 | , allowedExtensions :: [Extension] | 122 | , allowedExtensions :: [Extension] |
120 | 123 | ||
121 | -- | Semaphor used to bound number of active P2P sessions. | 124 | -- | Semaphor used to bound number of active P2P sessions. |
122 | , activeThreads :: QSem | 125 | , activeThreads :: MSem ThreadCount |
123 | 126 | ||
124 | -- | Max number of active connections. | 127 | -- | Max number of active connections. |
125 | , maxActive :: Int | 128 | , maxActive :: ThreadCount |
126 | 129 | ||
127 | , swarmSessions :: TVar (Set SwarmSession) | 130 | , swarmSessions :: TVar (Set SwarmSession) |
128 | 131 | ||
@@ -139,7 +142,7 @@ instance Ord ClientSession where | |||
139 | getCurrentProgress :: MonadIO m => ClientSession -> m Progress | 142 | getCurrentProgress :: MonadIO m => ClientSession -> m Progress |
140 | getCurrentProgress = liftIO . readTVarIO . currentProgress | 143 | getCurrentProgress = liftIO . readTVarIO . currentProgress |
141 | 144 | ||
142 | newClient :: Int -- ^ Maximum count of active P2P Sessions. | 145 | newClient :: ThreadCount -- ^ Maximum count of active P2P Sessions. |
143 | -> [Extension] -- ^ Extensions allowed to use. | 146 | -> [Extension] -- ^ Extensions allowed to use. |
144 | -> IO ClientSession | 147 | -> IO ClientSession |
145 | 148 | ||
@@ -151,7 +154,7 @@ newClient n exts = do | |||
151 | ClientSession | 154 | ClientSession |
152 | <$> newPeerID | 155 | <$> newPeerID |
153 | <*> pure exts | 156 | <*> pure exts |
154 | <*> newQSem n | 157 | <*> MSem.new n |
155 | <*> pure n | 158 | <*> pure n |
156 | <*> newTVarIO S.empty | 159 | <*> newTVarIO S.empty |
157 | <*> pure mgr | 160 | <*> pure mgr |
@@ -161,6 +164,8 @@ newClient n exts = do | |||
161 | Swarm session | 164 | Swarm session |
162 | -----------------------------------------------------------------------} | 165 | -----------------------------------------------------------------------} |
163 | 166 | ||
167 | type SessionCount = Int | ||
168 | |||
164 | -- | Extensions are set globally by | 169 | -- | Extensions are set globally by |
165 | -- Swarm session are un | 170 | -- Swarm session are un |
166 | data SwarmSession = SwarmSession { | 171 | data SwarmSession = SwarmSession { |
@@ -169,7 +174,7 @@ data SwarmSession = SwarmSession { | |||
169 | 174 | ||
170 | -- | Represent count of peers we _currently_ can connect to in the | 175 | -- | Represent count of peers we _currently_ can connect to in the |
171 | -- swarm. Used to bound number of concurrent threads. | 176 | -- swarm. Used to bound number of concurrent threads. |
172 | , vacantPeers :: QSem | 177 | , vacantPeers :: MSem SessionCount |
173 | 178 | ||
174 | -- | Modify this carefully updating global progress. | 179 | -- | Modify this carefully updating global progress. |
175 | , clientBitfield :: TVar Bitfield | 180 | , clientBitfield :: TVar Bitfield |
@@ -187,7 +192,7 @@ newSwarmSession :: Int -> Bitfield -> ClientSession -> Torrent | |||
187 | newSwarmSession n bf cs @ ClientSession {..} t @ Torrent {..} | 192 | newSwarmSession n bf cs @ ClientSession {..} t @ Torrent {..} |
188 | = SwarmSession <$> pure t | 193 | = SwarmSession <$> pure t |
189 | <*> pure cs | 194 | <*> pure cs |
190 | <*> newQSem n | 195 | <*> MSem.new n |
191 | <*> newTVarIO bf | 196 | <*> newTVarIO bf |
192 | <*> newTVarIO S.empty | 197 | <*> newTVarIO S.empty |
193 | 198 | ||
@@ -199,10 +204,10 @@ newLeacher :: ClientSession -> Torrent -> IO SwarmSession | |||
199 | newLeacher cs t @ Torrent {..} | 204 | newLeacher cs t @ Torrent {..} |
200 | = newSwarmSession defLeacherConns (haveNone (pieceCount tInfo)) cs t | 205 | = newSwarmSession defLeacherConns (haveNone (pieceCount tInfo)) cs t |
201 | 206 | ||
202 | defSeederConns :: Int | 207 | defSeederConns :: SessionCount |
203 | defSeederConns = defaultUnchokeSlots | 208 | defSeederConns = defaultUnchokeSlots |
204 | 209 | ||
205 | defLeacherConns :: Int | 210 | defLeacherConns :: SessionCount |
206 | defLeacherConns = defaultNumWant | 211 | defLeacherConns = defaultNumWant |
207 | 212 | ||
208 | --isLeacher :: SwarmSession -> IO Bool | 213 | --isLeacher :: SwarmSession -> IO Bool |
@@ -219,13 +224,13 @@ haveDone ix = | |||
219 | 224 | ||
220 | enterSwarm :: SwarmSession -> IO () | 225 | enterSwarm :: SwarmSession -> IO () |
221 | enterSwarm SwarmSession {..} = do | 226 | enterSwarm SwarmSession {..} = do |
222 | waitQSem (activeThreads clientSession) | 227 | MSem.wait (activeThreads clientSession) |
223 | waitQSem vacantPeers | 228 | MSem.wait vacantPeers |
224 | 229 | ||
225 | leaveSwarm :: SwarmSession -> IO () | 230 | leaveSwarm :: SwarmSession -> IO () |
226 | leaveSwarm SwarmSession {..} = do | 231 | leaveSwarm SwarmSession {..} = do |
227 | signalQSem vacantPeers | 232 | MSem.signal vacantPeers |
228 | signalQSem (activeThreads clientSession) | 233 | MSem.signal (activeThreads clientSession) |
229 | 234 | ||
230 | waitVacancy :: SwarmSession -> IO () -> IO () | 235 | waitVacancy :: SwarmSession -> IO () -> IO () |
231 | waitVacancy se = | 236 | waitVacancy se = |