Skip to content

Commit aeb440a

Browse files
committed
Removed numbers from naming scheme and finished MVar tutorial.
1 parent fc45d22 commit aeb440a

8 files changed

+61
-50
lines changed

src/Ex3Channels.hs renamed to src/Channels.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module Ex3Channels where
1+
module Channels where
22

33
import Control.Concurrent.Chan (newChan, writeChan, readChan)
44

src/Ex4DuplicatingChannels.hs renamed to src/DuplicatingChannels.hs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
module Ex4DuplicatingChannels where
1+
module DuplicatingChannels where
22

3-
import Ex1Threads (sleepMs)
3+
import Threads (sleepMs)
44

55
import Control.Concurrent (forkIO)
66
import Control.Concurrent.Chan (newChan, writeChan, readChan, dupChan)

src/Ex3SharedState.hs

-21
This file was deleted.

src/MVarSharedState.hs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module MVarSharedState where
2+
3+
import Threads (sleepMs)
4+
5+
import Control.Concurrent (forkIO)
6+
import Control.Concurrent.MVar (newMVar, takeMVar, putMVar)
7+
import Control.Monad (replicateM)
8+
9+
main = do
10+
counter <- newMVar 0
11+
12+
let increment = do
13+
count <- takeMVar counter
14+
putMVar counter $! count + 1
15+
incrementer = do
16+
replicateM 1000 increment
17+
return ()
18+
19+
threads <- replicateM 5 (forkIO incrementer)
20+
21+
sleepMs 100
22+
count <- takeMVar counter
23+
print count

src/Ex2MVars.hs renamed to src/MVars.hs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
module Ex2MVars where
1+
module MVars where
22

3-
import Ex1Threads (sleepMs)
3+
import Threads (sleepMs)
44

55
import Control.Concurrent (forkIO)
66
import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)

src/Main.hs

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
-- Main entry point to the application.
22
module Main where
33

4-
import qualified Ex1Threads (main)
5-
import qualified Ex2MVars (main)
6-
import qualified Ex3SharedState (main)
7-
import qualified Ex3Channels (main)
8-
import qualified Ex4DuplicatingChannels (main)
4+
import qualified Threads (main)
5+
import qualified MVars (main)
6+
import qualified MVarSharedState (main)
7+
import qualified Channels (main)
8+
import qualified DuplicatingChannels (main)
99

1010
-- The main entry point.
1111
main :: IO ()
1212
main = do
13-
example "Threads" Ex1Threads.main
14-
example "MVar" Ex2MVars.main
15-
example "Shared state" Ex3SharedState.main
16-
example "Channels" Ex3Channels.main
17-
example "Duplicating channels" Ex4DuplicatingChannels.main
13+
example "Threads" Threads.main
14+
example "MVar" MVars.main
15+
example "Shared state" MVarSharedState.main
16+
example "Channels" Channels.main
17+
example "Duplicating channels" DuplicatingChannels.main
1818

1919
example title code = do
2020
putStrLn ("~~~ Running " ++ title ++ " example! ~~~")

src/Ex1Threads.hs renamed to src/Threads.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module Ex1Threads where
1+
module Threads where
22

33
import Control.Concurrent (forkIO, threadDelay)
44
import Data.Foldable (for_)

src/tutorial.md

+22-13
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Since this is the first tutorial, I'm going to explain a couple of things that I
3333
Each of the files in [this directory](.) is a module, and starts with a module definition:
3434

3535
``` haskell
36-
module Ex1Threads where
36+
module Threads where
3737
```
3838

3939
Now we import all the libraries we're going to make use of.
@@ -94,7 +94,7 @@ sleepMs n = threadDelay (n * 1000)
9494

9595
And now we can run our program!
9696

97-
$ runhaskell Ex1Threads.hs
97+
$ runhaskell Threads.hs
9898
main number 1
9999
main number 2
100100
main number 3
@@ -104,7 +104,7 @@ And now we can run our program!
104104
ending!
105105
fork number 3
106106

107-
[See the whole program.](./Ex1Threads.hs)
107+
[See the whole program.](./Threads.hs)
108108

109109
## Thread synchronisation with MVars
110110

@@ -133,12 +133,12 @@ main = do
133133

134134
Running this, you should see the following output:
135135

136-
$ runhaskell Ex2MVars.hs
136+
$ runhaskell MVars.hs
137137
Waiting...
138138
Calculated result!
139139
The answer is: 42
140140

141-
[See the whole program.](./Ex2MVars.hs)
141+
[See the whole program.](./MVars.hs)
142142

143143
## Sharing state with MVars
144144

@@ -153,14 +153,16 @@ In the presence of race conditions, errors will mean often the final result isn'
153153
main = do
154154
counter <- newMVar 0
155155

156-
let increment = modifyMVar_ counter (\c -> return $! c + 1)
157-
let incrementer = do
158-
replicateM 1000 increment
159-
return ()
156+
let increment = do
157+
count <- takeMVar counter
158+
putMVar counter $! count + 1
159+
incrementer = do
160+
replicateM 1000 increment
161+
return ()
160162

161163
threads <- replicateM 5 (forkIO incrementer)
162164

163-
sleepMs 10
165+
sleepMs 100
164166
count <- takeMVar counter
165167
print count
166168
```
@@ -175,6 +177,13 @@ Note that in this case, our application is essentially single-threaded, because
175177
So we gain no _time_ efficiency from using strict application (`$!`) - we could just as easily build up a huge thunk, then have the main thread evaluate it when we `print count`.
176178
However, this costs memory, so evaluating the counter strictly at every step makes the program more _space_ efficient.
177179

180+
Let's give this example a go:
181+
182+
$ runhaskell MVarSharedState.hs
183+
5000
184+
185+
[See the whole program.](./MVarSharedState.hs)
186+
178187
## Channels
179188

180189
Now that we've talked about `MVar`s, let's get up to speed with channels in Haskell.
@@ -225,7 +234,7 @@ Or, more concisely:
225234
> I won't go into too much depth here.
226235
> If you need a gentler and more in-depth introduction to `IO` actions, have a read of [this excellent article](http://blog.jle.im/entry/first-class-statements).
227236
228-
[See the whole program.](./Ex3Channels.hs)
237+
[See the whole program.](./Channels.hs)
229238

230239
## Duplicating channels
231240

@@ -275,7 +284,7 @@ main = do
275284
sleepMs 5
276285
```
277286

278-
$ runhaskell Ex4DuplicatingChannels.hs
287+
$ runhaskell DuplicatingChannels.hs
279288
First read: Hi!
280289
Third read: Bye!
281290
Fourth read: Bye!
@@ -284,7 +293,7 @@ Note that sometimes you may see `Second` getting `Hi!`, or you may see `Hi!` bei
284293
This is due to the vagaries of thread execution, since we didn't do any synchronisation in these examples.
285294
(It's also why I added a `sleepMs` in there - just to make sure the main thread waits for all the messages to filter through.)
286295

287-
[See the whole program.](./Ex4DuplicatingChannels.hs)
296+
[See the whole program.](./DuplicatingChannels.hs)
288297

289298
# 2. Haskell Platform only
290299

0 commit comments

Comments
 (0)