@@ 0,0 1,373 @@
+hardwood
+========
+
+Erlang style concurrency for CHICKEN Scheme, heavily inspired by
+termite.
+
+This is a fork of hardwood with support for CHICKEN 5, plus additional
+changes for my own use.
+
+> All the Termite API is currently not implemented and probably never
+> will. Also, some incompatibilities are to be expected.
+
+Requirements
+------------
+
+ * [matchable][]
+ * [ksuid][]
+
+[matchable]: https://wiki.call-cc.org/eggref/5/matchable
+[match]: https://wiki.call-cc.org/eggref/5/matchable#interface
+[ksuid]: https://git.sr.ht/~nilium/chicken-ksuid
+[test]: https://wiki.call-cc.org/eggref/5/test
+
+Bugs and Limitations
+--------------------
+
+ * There is currently no support for nodes.
+
+Source code
+-----------
+
+The source code for this fork of hardwood is available in a [git
+repository](https://git.sr.ht/~nilium/hardwood) on Sourcehut.
+
+You can clone it with: `git clone https://git.sr.ht/~nilium/hardwood`
+
+### Original Source
+
+The original hardwood code is available in a [git
+repository](https://www.upyum.com/cgit.cgi/hardwood/).
+
+You can clone it with: `git clone git://upyum.com/hardwood`
+
+Author
+------
+
+Adrien Ramos, heavily inspired by the Termite project of Guillaume
+Germain.
+
+Documentation
+-------------
+
+### Notes
+
+Hardwood processes are implemented as simple srfi-18 threads so they
+behave in the same ways. The name `process` was chosen as per
+Erlang's nomenclature.
+
+As a general rule, mutation should be avoided when using hardwood,
+especially inside messages themselves as there is no copy involved.
+
+`TIMEOUT` in the following definitions can be (as per srfi-18) either
+of the following:
+
+ * an srfi-18 time object, which represents an absolute point in time
+ * a number, which represents a relative time in seconds
+ * #f for no timeout
+
+If `DEFAULT` is specified when `TIMEOUT` is, it is returned in case
+of timeout. Otherwise `timeout-condition` is signaled.
+
+### Constants
+
+#### timeout-condition
+
+Condition object raised when a timeout is reached.
+
+### Predicates
+
+#### monitor-ref?
+
+```
+[procedure] (monitor-ref? OBJ)
+```
+
+Whether `obj` is a monitor reference or not.
+
+#### pid?
+
+```
+[procedure] (pid? OBJ)
+```
+
+Whether `obj` is a `pid` object or not.
+
+#### process-exist?
+
+```
+[procedure] (process-exist? PID)
+```
+
+Whether `pid` is a running process or not.
+
+#### timeout-condition?
+
+```
+[procedure] (timeout-condition? OBJ)
+```
+
+Whether `obj` is `timeout-condition` or not.
+
+### Fundamental Operations
+
+#### spawn
+
+```
+[procedure] (spawn PROC . ARGS)
+```
+
+Create a process running `(proc args ...)` and returns its `pid`.
+
+#### self
+
+```
+[procedure] (self)
+```
+
+Return the current process' `pid`.
+
+#### setup-thread
+
+```
+[procedure] (setup-thread [THREAD])
+```
+
+Make `thread` a hardwood process.
+
+If given, `thread` must be a srfi-18 thread. Otherwise, the current
+thread is used.
+
+#### make-tag
+
+```
+[procedure] (make-tag)
+```
+
+Return a new `tag`.
+
+Tags are guaranteed to be universally unique.
+
+#### monitor
+
+```
+[procedure] (monitor PID)
+```
+
+The calling process starts monitoring the `pid` process.
+
+Return a monitor reference `ref`.
+
+If that process exits, either normally or not, the caller process will
+be informed with a message of the form:
+
+```scheme
+('DOWN ref pid reason)
+```
+
+where `reason` can be one of the following:
+
+; symbol `exited` : the process exited normally
+; symbol `no-process` : the process didn't exist
+; list `('condition c)` : the process exited because of condition `c`
+
+#### demonitor
+
+```
+[procedure] (demonitor ref)
+```
+
+Stop the monitor associated with `ref`.
+
+#### !
+
+```
+[procedure] (! PID MSG)
+```
+
+Send `msg` to process `pid`.
+
+#### !!
+
+```
+[procedure] (!! LIST MSG)
+```
+
+`List` must be a list of pids.
+
+Send `msg` to all pids in `list`
+
+#### ?
+
+```
+[syntax] (? [TIMEOUT [DEFAULT]])
+```
+
+Fetch the first message from the mailbox.
+
+#### ??
+
+```
+[procedure] (?? PRED [TIMEOUT [DEFAULT]])
+```
+
+Fetch the next message that matches `pred`.
+
+#### !?
+
+```
+[procedure] (!? PID MSG [TIMEOUT [DEFAULT]])
+```
+
+Send `msg` to process `pid` and wait for a reply.
+
+The actual message sent to `pid` is (list (self) tag `msg`).
+
+This procedure wait for a reply of the form (list tag `reply`) and
+returns `reply`.
+
+#### recv
+
+```
+[syntax] (recv PAT [...] [(after TIMEOUT TMO-ACTION ...)])
+```
+
+Match incoming messages against `PAT ...`.
+
+Each pattern must be a valid pattern for [`match`][match].
+
+Optionally, do `tmo-action` after `timeout`.
+
+> This version of `recv` is incompatible with the one defined in the
+> Termite paper and implementation as it uses the syntax of the
+> [matchable][] egg.
+
+Examples
+--------
+
+### Making the REPL process a hardwood process
+
+Inside csi:
+```scheme
+(use hardwood srfi-18)
+(setup-thread)
+```
+
+This can be useful to communicate with other processes from the REPL, as
+in the following examples.
+
+### Making a "server" process
+
+```scheme
+(use hardwood srfi-18)
+(setup-thread)
+
+(define pong-server
+ (spawn
+ (lambda ()
+ (let loop ()
+ (recv
+ (((? pid? pid) 'ping) (! pid 'pong)
+ (loop))
+ (else (loop))))
+
+(! pong-server (list (self) 'ping))
+
+(?) --> pong
+```
+
+### Selective message retrieval
+
+```scheme
+(use hardwood srfi-18)
+(setup-thread)
+
+(! (self) 1)
+(! (self) 2)
+(! (self) 3)
+
+(?) --> 1
+(?? odd?) --> 3
+(?) --> 2
+```
+
+### RPC service
+
+```scheme
+(use hardwood srfi-18)
+(setup-thread)
+
+(define rpc-server
+ (spawn
+ (lambda ()
+ (let loop ()
+ (recv
+ ((from tag ('add a b))
+ (! from (list tag (+ a b)))))
+ (loop)))))
+
+(!? rpc-server '(add 21 21)) ---> 42
+```
+
+### Monitoring processes
+
+```scheme
+(use hardwood srfi-18)
+(setup-thread)
+
+(define pid
+ (spawn
+ (lambda ()
+ (recv
+ (x (/ 0)))))))
+
+(define ref (monitor pid))
+
+(! pid 'msg)
+(?) --> ('DOWN ref pid ('condition exn))
+```
+
+Version History
+---------------
+
+ * `0.5`: setup-thread now uses the current-thread by default, macro
+ helper procedures are not exported from the module anymore (thanks
+ Evan for the patches!).
+ * `0.4`: Bug fixes; tests now use the [test][] egg; in-process call
+ history is now more useful.
+ * `0.3`: Bug fix; `!!` function; spawn accepts procedure arguments;
+ monitor references.
+ * `0.2`: Implement process monitoring.
+ * `0.1`: Initial release.
+
+License
+-------
+
+The license text can be found in the accompanying
+[LICENSE.txt](./LICENSE.txt), and is also reproduced below:
+
+> Copyright (c) 2014, Adrien Ramos <kooda@upyum.com>
+> All rights reserved.
+>
+> Redistribution and use in source and binary forms, with or without
+> modification, are permitted provided that the following conditions are
+> met:
+>
+> 1. Redistributions of source code must retain the above copyright
+> notice, this list of conditions and the following disclaimer.
+>
+> 2. Redistributions in binary form must reproduce the above copyright
+> notice, this list of conditions and the following disclaimer in the
+> documentation and/or other materials provided with the distribution.
+>
+> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+> "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+> LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+> A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+> HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+> SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+> LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+> DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+> THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+> (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+> OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.