Skip to content
This repository was archived by the owner on Apr 23, 2023. It is now read-only.

Commit 0a02169

Browse files
author
Jack Tang
committed
update readme
1 parent 3be6025 commit 0a02169

File tree

2 files changed

+53
-28
lines changed

2 files changed

+53
-28
lines changed

README.md

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,39 @@ Simplify Nim Inter-Thread Communication
44

55
## Overview
66

7-
- Each thread has a fixed unique `name`.
8-
- Each thread is associated with one [`Channel`](https://nim-lang.org/docs/channels.html#Channel).
9-
- Each thread processes its channel with `threadproxy.poll`.
10-
- JSON is the data exchange format.
7+
ThreadProxy help you manage threads and channels. You don't have to declare them explicitly.
8+
ThreadProxy also provide a little thread-name-system and do name resolution for you.
9+
10+
Some key-points:
11+
12+
- Each thread has a unique `name` assigned at creation.
13+
- Each thread start processesing its messages with `poll()`.
14+
- JSON is the *ONLY* data exchange format.
1115
- Threads can talk with each other with `name` reference.
12-
- Threads can talk with each other in one-way with `send()`.
13-
- Threads can talk with each other in two-way with `ask()`.
16+
- Threads can talk with each other in one-way with `send(...): Future[void]`.
17+
- Threads can talk with each other in two-way with `ask(...): Future[JsonNode]`.
1418
- The order of creation of threads does not matter as long as the target thread is running at the time of calling `send` or `ask`.
1519

1620
## Usage
1721

1822
The typical pattern should look like the following.
1923

2024
```nim
21-
import threadproxy
25+
import threadproxy # ---- 1
2226
23-
proc fooMain(proxy: ThreadProxy) {.thread.} =
27+
proc fooMain(proxy: ThreadProxy) {.thread.} = # ---- 2
2428
# setup and then poll threadProxy
25-
proxy.onData "action1": result = action1(data)
26-
proxy.onData "action2": result = action2(data)
29+
proxy.on "action1", proc(data: JsonNode): Future[JsonNode] {.gcsafe.} = # ---- 3
30+
result = action1(data)
31+
32+
proxy.onData "action2": # ---- 4
33+
result = action2(data)
34+
35+
proxy.onDefault proc(action: string, data: JsonNode): Future[JsonNode] {.gcsafe.} = # ---- 5
36+
reuslt = ...
37+
2738
# ...
28-
asyncCheck proxy.poll()
39+
asyncCheck proxy.poll() # ---- 6
2940
3041
# ...
3142
# do something here
@@ -35,14 +46,13 @@ proc fooMain(proxy: ThreadProxy) {.thread.} =
3546
3647
proc main() =
3748
# create, setup and then poll mainThreadProxy
38-
let proxy = newMainThreadProxy("main")
39-
proxy.onData "action1": result = action1(data)
40-
proxy.onData "action2": result = action2(data)
49+
let proxy = newMainThreadProxy("main") # ---- 7
50+
proxy.onData "action1": result = action1(data) # ---- 8
4151
# ...
42-
asyncCheck proxy.poll()
52+
asyncCheck proxy.poll() # ---- 9
4353
4454
# create threads
45-
proxy.createThread("foo1", fooMain)
55+
proxy.createThread("foo1", fooMain) # ---- 10
4656
proxy.createThread("foo2", fooMain)
4757
#...
4858
@@ -56,18 +66,31 @@ when isMainModeul:
5666
main()
5767
```
5868

69+
1. `import threadproxy` will also `import json, asyncdispatch`. They are almost always used together.
70+
2. Define an entry function for threads. If you don't want to declare thread on your own, the argument must be a `ThreadProxy`. Also note that the `{.thread.}` pragma must be present.
71+
3. Define a handler for `action`. The handler function is responsible for both `send` and `ask` handling. A `nil` return value will be converted to `JNull`
72+
4. Similar to `on`, but a template version that save you from typing `proc...` everytime. The argument `data` is injected and so the name `onData`
73+
5. Default handler for all unregistered actions. There is also a templated version `onDefaultData` that work similarly.
74+
6. Start processing messages on channels asychronously . This must be called exactly once, otherwise nothing will happen.
75+
7. Create a `MainThreadProxy` with a name. `MainThreadProxy` is also a `ThreadProxy` with responsibilities to handle threads and channels.
76+
8. Define handlers for MainThreadProxy similar to that in fooMain.
77+
9. Start processing messages similar to that in fooMain.
78+
10. Create thread with a name and entry function.
79+
5980
## Examples
6081

6182
Example 1: simple ask
6283

6384
```nim
64-
import threadproxy, asyncdispatch
85+
import threadproxy
6586
6687
proc workerMain(proxy: ThreadProxy) {.thread.} =
6788
# register action handler
68-
proxy.onData "double":
69-
let x = data.getInt()
70-
return %(2*x)
89+
proxy.onData "sum":
90+
var x = 0
91+
for n in data:
92+
x += n.getInt()
93+
return %x
7194
7295
# start processing channel
7396
waitFor proxy.poll()
@@ -80,8 +103,8 @@ proc main() =
80103
proxy.createThread("worker_0", workerMain)
81104
82105
# ask worker_0 to double 10
83-
let answer = waitFor proxy.ask("worker_0", "double", %10)
84-
assert answer == %20
106+
let answer = waitFor proxy.ask("worker_0", "sum", %[2,3,5,7])
107+
assert answer == %17
85108
86109
when isMainModule:
87110
main()

examples/simple_ask.nim

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
import threadproxy, asyncdispatch
1+
import threadproxy
22

33
proc workerMain(proxy: ThreadProxy) {.thread.} =
44
# register action handler
5-
proxy.onData "double":
6-
let x = data.getInt()
7-
return %(2*x)
5+
proxy.onData "sum":
6+
var x = 0
7+
for n in data:
8+
x += n.getInt()
9+
return %x
810

911
# start processing channel
1012
waitFor proxy.poll()
@@ -17,8 +19,8 @@ proc main() =
1719
proxy.createThread("worker_0", workerMain)
1820

1921
# ask worker_0 to double 10
20-
let answer = waitFor proxy.ask("worker_0", "double", %10)
21-
assert answer == %20
22+
let answer = waitFor proxy.ask("worker_0", "sum", %[2,3,5,7])
23+
assert answer == %17
2224

2325
when isMainModule:
2426
main()

0 commit comments

Comments
 (0)