Skip to content

Commit 50d2e0c

Browse files
committed
Updated README
1 parent 0927bd3 commit 50d2e0c

File tree

3 files changed

+128
-4
lines changed

3 files changed

+128
-4
lines changed

README.md

Lines changed: 126 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,128 @@
1-
Experiment to reproduce erlang style processes in browser.
1+
Experiment to reproduce erlang style processes in browser. The api follows the one from Erlang. All are found on the `Scheduler` class
2+
3+
4+
### Running Examples
25

36
* `jspm install`
4-
* `python -m SimpleHTTPServer 8000`
7+
* `python -m SimpleHTTPServer 8000`
8+
9+
Going to `localhost:8000` will show links to examples.
10+
11+
One example is an implementation of a GenServer. The other example is 2 processes talking
12+
to each other.
13+
14+
#### Usage
15+
16+
* First, import the Scheduler create a new instance of one.
17+
```javascript
18+
import { Scheduler } from "processes";
19+
let scheduler = self.scheduler || new Scheduler();
20+
```
21+
22+
* Now you can spawn processes using the scheduler.
23+
24+
A process will switch to other processes when yield is used and will run until it completes.
25+
26+
```javascript
27+
var pid1 = scheduler.spawn(function*(){
28+
while(true){
29+
30+
yield scheduler.receive(function(value){
31+
return console.log(value);
32+
});
33+
34+
scheduler.send(pid2, "message from 1");
35+
}
36+
});
37+
38+
scheduler.register("Sally", pid1);
39+
40+
var pid2 = scheduler.spawn(function*(){
41+
while(true){
42+
scheduler.send("Sally", "message from 2");
43+
44+
yield scheduler.receive(function(value){
45+
return console.log(value);
46+
});
47+
}
48+
});
49+
50+
```
51+
52+
### API
53+
54+
* Scheduler
55+
* `spawn(fun*) : pid` - Starts a process represented by the given generator function
56+
* `spawn(module, fun, args) : pid` - Starts a process using the generator function from the specified module
57+
* `link(pid) : void` - links the current process with the process from the given pid
58+
* `unlink(pid) : void` - unlinks the current process from the process from the given pid
59+
* `register(name, pid) : void` - registers the given name to the pid
60+
* `registered(name) : pid` - returns the pid registered by the given name or null if not registered
61+
* `unregister(pid) : void` - unregisters the names associated with the pid
62+
* `pid()` : pid` - returns the current process's pid
63+
* `pidof(obj) : pid` - takes the input and tries to find the pid. Input can be a `pid`, `Process`, or name the pid is associated with
64+
* `send(pid, msg) : msg` - sends a message the the process represented by the pid
65+
* `receive(fun, timeout = 0, timeoutFn = () => true)` - Tells the current process to receive a message that the function can handle. If no match then the process is put in the suspended state until a message arrives or the timeout is reached. If the timeout is reached and no msg matches, then the timeoutFn is called
66+
* `sleep(duration)` - puts the current process to sleep
67+
* `exit(reason)` - terminates the current process with the given reason.
68+
* `exit(pid, reason)` - tells the process with the pid to exit with the given reason
69+
* `error(reason)` - terminates the current process with an error
70+
* `process_flag(flag, value)` - Sets flags on the current process.
71+
* Note: the only flag respected is the `Symbol.for("trap_exit")` flag. If value is `true`, then exit signals from linked processes are turned into messages and sent to the current processes mailbox. If value is `false`, the exit is treated as normal and terminates the process. Setting it to `true` is useful for supervising processes.
72+
* `put(key, value)` - Adds a value to the current process's dictionary
73+
* `get(key)` - Gets a value from the current process's dictionary
74+
* `get()` - Gets the current process's dictionary
75+
* `get_keys()` - Gets all the keys from the current process's dictionary
76+
* `erase(key)` - Removes the key and the associated value from the current process`s dictionary
77+
* `erase()` - Removes all entries from the current process's dictionary
78+
79+
* `Scheduler.run(fun, args, context = null)` - A static generator function used to wrap a normal function or generator. If fun is a function, it returns the value, if it's a generator, then it delegates yielding to the generator.
80+
81+
* GenServer
82+
* **Note**: Genserver expects a module the has the following functions:
83+
* `init(args)` - Must return an array containing a symbol and the initial state
84+
* `handle_call(action, from, state)` - Called when `GenServer.call` is called. This function is given the action, the pid of the calling process, and the current state. Must return `[reply, return_value, new_state]` where reply is a symbol ,usually `Symbol.for("reply"), the value to return to the process, and lastly, the new state of the GenServer.
85+
* handle_cast(action, state) - Called when `GenServer.cast` is called. his function is given the action, and the current state. Must return `[reply, return_value, new_state]` where reply is a symbol ,usually `Symbol.for("noreply"), and lastly, the new state of the GenServer.
86+
87+
* `start(module, args)` - Starts a GenServer with the given module and args
88+
* `start_link(module, args)` - Starts a GenServer with the given module and args
89+
* `call* (server, action) - Sends the GenServer a action and waits for it to respond with a value.
90+
* `cast* (server, action) - Sends the GenServer a action to update a value.
91+
* `stop (server) - Stops the GenServer.
92+
93+
#### GenServer Example
94+
95+
An example of a Stack using a GenServer
96+
97+
```javascript
98+
import { Scheduler, GenServer } from "processes";
99+
self.scheduler = self.scheduler || new Scheduler();
100+
101+
const Stack = {
102+
init: function(args){
103+
return [Symbol.for("ok"), args];
104+
},
105+
106+
handle_call: function(action, pid, state){
107+
return [Symbol.for("reply"), state[0], state.slice(1)];
108+
},
109+
110+
111+
handle_cast: function(action, state){
112+
return [Symbol.for("noreply"), [action[1]].concat(state)];
113+
}
114+
}
115+
116+
self.scheduler.spawn(function*(){
117+
const [ok, pid] = yield* Scheduler.run(GenServer.start, [Stack, ["hello"]]);
118+
119+
let a = yield* Scheduler.run(GenServer.call, [pid, "pop"]);
120+
console.log(a); // "hello"
121+
122+
let b = yield* Scheduler.run(GenServer.cast, [pid, ["push", "world"]]);
123+
console.log(b); // Symbol.for("ok")
124+
125+
let c = yield* Scheduler.run(GenServer.call, [pid, "pop"]);
126+
console.log(c); // "world"
127+
});
128+
```

examples/gen_server.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use strict";
22

3-
import { Scheduler, GenServer } from "../src/processes.js";
3+
import { Scheduler, GenServer } from "../src/processes";
44
self.scheduler = self.scheduler || new Scheduler();
55

66
const Stack = {

examples/send_receive.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use strict";
22

3-
import { Scheduler, GenServer } from "../src/processes.js";
3+
import { Scheduler, GenServer } from "../src/processes";
44
self.scheduler = self.scheduler || new Scheduler();
55

66

0 commit comments

Comments
 (0)