~nilium/hardwood

d2b9e9db8bc1702676bf45e6f333f1501ee938d6 — Noel Cower 3 years ago fd82aa0
Add README.md

Add a README that clarifies that this is a fork of hardwood. This still
retains the link to the original source, since folks might want that,
especially if hardwood is ever updated.
1 files changed, 373 insertions(+), 0 deletions(-)

A README.md
A README.md => README.md +373 -0
@@ 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.