caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Jerome Vouillon <vouillon@pps.jussieu.fr>
To: Chris Hecker <checker@d6.com>
Cc: caml-list@inria.fr
Subject: [Caml-list] Coroutines
Date: Sun, 6 Oct 2002 20:13:45 +0200	[thread overview]
Message-ID: <20021006181345.GA23808@strontium.pps.jussieu.fr> (raw)
In-Reply-To: <4.3.2.7.2.20021004000748.030bd2c0@mail.d6.com>

On Fri, Oct 04, 2002 at 03:25:44AM -0700, Chris Hecker wrote:
> I'm looking at implementing fibers/coroutines/cooperative-threads 
> (described below for reference) in ocaml, and I've run into a small issue, 
> a question, and a couple confusions.

I just spent a few hours implementing a small coroutine library.  It
is fully written in Ocaml.  Below is a quick description.  Would it
satisfy your needs ? I can send you a copy, or make it available on the
Web if you like.

-- Jérôme

A coroutine returning values of type 'a has type 'a output.

    type 'a output

You can spawn it.  You then get an handle of type 'a input

    type 'a input
    val spawn : 'a output -> 'a input

The caller can get a value from the coroutine.

    val receive : 'a input -> 'a

A coroutine can return a value of type 'a.

    val send : 'a -> 'a output

It can also exit.  If a caller try to get more values from the
coroutine afterwards, an exception Exited will be raised.

    exception Exited
    val exit : 'a output

Coroutines can be combined sequentially: "e >> fun  () -> e'" is a
routine that behaves first as "e", then as "e'".

    val (>>) : 'a output -> (unit -> 'a output) -> 'a output

It is sometimes useful to have a coroutine "nop" that does nothing.
Note that the expression "nop >> fun () -> e" behaves as "e", while
the expression "exit >> (fun ()-> e)" behaves as "exit".

    val nop : 'a output

So for instance, the coroutine f below returns the integers 1, 2 and
3, then exits.

    # let f =
        spawn
          (send 1 >> fun () ->
           send 2 >> fun () ->
           send 3);;
    val f : int Coroutines.input = <abstr>
    # receive f;;
    - : int = 1
    # receive f;;
    - : int = 2
    # receive f;;
    - : int = 3
    # receive f;;
    Exception: Coroutines.Exited.

You can define a coroutine "indexed ~len:n f" which returns
successively "f 0", "f 1", ... "f (n - 1)".

    let rec indexed_rec f n l =
      if n = l then exit else
      send (f n) >> fun () ->
      indexed_rec f (n + 1) l

    let indexed ?(len = -1) f = spawn (indexed_rec f 0 len)

You can use it to define an array iterator.

    let array_iterator a = indexed ~len:(Array.length a) (fun i -> a.(i))

So, "array_iterator [|1;2;3|]" will behave just the same as "f" above.

The coroutine below returns all integers starting from "first".

    let integers first = indexed (fun i -> i + first)

As a more complex example, here is the Erathostenes sieve implemented
using coroutines.

    let rec filter_rec p st =
      let v = receive st in
      (if p v then send v else nop) >> fun () ->
      filter_rec p st

    let filter p st = spawn (filter_rec p st)

    let filter_multiples n st = filter (fun m -> not (m mod n = 0)) st

    let rec primes_rec st =
      let n = receive st in
      send n >> fun () ->
      primes_rec (filter_multiples n st)

    let primes = spawn (primes_rec (integers 2))
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


  reply	other threads:[~2002-10-06 18:13 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-10-04 10:25 [Caml-list] gc question: thread stacks, fibers, etc Chris Hecker
2002-10-06 18:13 ` Jerome Vouillon [this message]
2002-10-06 19:46   ` [Caml-list] Coroutines Chris Hecker
2002-10-12 15:58   ` John Max Skaller
2002-10-12 16:33 ` [Caml-list] gc question: thread stacks, fibers, etc John Max Skaller
2002-10-12 18:54   ` Chris Hecker
2002-10-13  8:32 ` Xavier Leroy
2002-10-14  7:18   ` Chris Hecker

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20021006181345.GA23808@strontium.pps.jussieu.fr \
    --to=vouillon@pps.jussieu.fr \
    --cc=caml-list@inria.fr \
    --cc=checker@d6.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).