<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE message PUBLIC
  "-//MLarc//DTD MLarc output files//EN"
  "../../mlarc.dtd"[
  <!ATTLIST message
    listname CDATA #REQUIRED
    title CDATA #REQUIRED
  >
]>

  <?xml-stylesheet href="../../mlarc.xsl" type="text/xsl"?>


<message 
  url="2002/12/c6cf5d6a698ddeb08791e29a39e73382"
  from="Christophe Raffalli &lt;Christophe.Raffalli@u...&gt;"
  author="Christophe Raffalli"
  date="2002-12-15T21:44:14"
  subject="[Caml-list] Continuations: an implementation"
  prev="2002/12/c1c05f314ad9a12a76fe27ff77f36cd8"
  next="2002/12/69ebad4a16ce944d2f01e9878f67739b"
  prev-in-thread="2002/12/cb2c8e18ae2a70b24a14ec6dfa63f9b0"
  prev-thread="2002/12/6e4f1518eb7ad7eee939898ec70eabc8"
  next-thread="2002/12/919e5b9de09938198c2fd0856d238c55"
  root="../../"
  period="month"
  listname="caml-list"
  title="Archives of the Caml mailing list">

<thread subject="[Caml-list] Continuations">
<msg 
  url="2002/12/a7df150482511ac2dc29aad949c1630c"
  from="Ceri Storey &lt;cez@m...&gt;"
  author="Ceri Storey"
  date="2002-12-10T20:28:06"
  subject="[Caml-list] Continuations">
<msg 
  url="2002/12/a76364f857529a996d6c73a20fc6f785"
  from="Eric Merritt &lt;cyberlync@y...&gt;"
  author="Eric Merritt"
  date="2002-12-11T01:43:05"
  subject="[Caml-list] Site down">
</msg>
<msg 
  url="2002/12/17d951b73af6adf7fd25af77db4583f0"
  from="Christophe Raffalli &lt;Christophe.Raffalli@u...&gt;"
  author="Christophe Raffalli"
  date="2002-12-11T09:22:43"
  subject="Re: [Caml-list] Continuations">
</msg>
<msg 
  url="2002/12/cb2c8e18ae2a70b24a14ec6dfa63f9b0"
  from="Michaël_Grünewald &lt;michael-grunewald@w...&gt;"
  author="Michaël_Grünewald"
  date="2002-12-12T18:15:45"
  subject="[Caml-list] Re: Continuations">
<msg 
  url="2002/12/c6cf5d6a698ddeb08791e29a39e73382"
  from="Christophe Raffalli &lt;Christophe.Raffalli@u...&gt;"
  author="Christophe Raffalli"
  date="2002-12-15T21:44:14"
  subject="[Caml-list] Continuations: an implementation">
</msg>
</msg>
</msg>
</thread>

<contents>
Here is an implementation of callcc for OCaml using fork.

The only problems are:
- I did not test it (but it should work)
- The limited number of fork calls

Note: the implementation of fork on Linux, makes a minimum of page copying, so
it should be reasonably fast

-- callcc.mli --
(* callcc fn: standard callcc, uses exit code 3 for internal use. *)

val callcc : (('a -&gt; 'b) -&gt; 'a) -&gt; 'a
----------------

-- callcc.ml ---
open Unix
open Sys

let all_signals = [
   sigabrt;   (* Abnormal termination *)
   sigalrm;   (* Timeout *)
   sigfpe;    (* Arithmetic exception *)
   sighup;    (* Hangup on controlling terminal *)
   sigill;    (* In id hardware instruction *)
   sigint;    (* Interactive interrupt (ctrl-C) *)
   sigkill;   (* Termination (cannot be ignored) *)
   sigpipe;   (* Broken pipe *)
   sigquit;   (* Interactive termination *)
   sigsegv;   (* In id memory reference *)
   sigterm;   (* Termination *)
   sigusr1;   (* Application-defined signal 1 *)
   sigusr2;   (* Application-defined signal 2 *)
(*  sigchld;       Child process terminated, do not ignore that one !*)
   sigcont;   (* Continue *)
   sigstop;   (* Stop *)
   sigtstp;   (* Interactive stop *)
   sigttin;   (* Terminal read from background process *)
   sigttou;   (* Terminal write from background process *)
   sigvtalrm; (* Timeout in virtual time *)
   sigprof   (* Profiling interrupt *)
]

let ignore_all_signals () =
   let previous = List.map (fun s -&gt; try signal s Signal_ignore with Sys_error 
_ -&gt; Signal_ignore) all_signals in
   fun () -&gt;
     List.iter2 (fun s b -&gt; try set_signal s b with Sys_error _ -&gt; ()) 
all_signals previous


let callcc (fn : ('a -&gt; 'b) -&gt; 'a) =
   let filename = Filename.temp_file "callcc" "val" in
   let gn (x : 'a) =
     let ch = open_out filename in
     Marshal.to_channel ch x [Marshal.Closures];
     close_out ch;
     exit 3
   in
   let restore_signals = ignore_all_signals () in
   let pid = fork () in
   if pid = 0 then begin
     restore_signals ();
     fn gn
   end else
     let rec kn pid =
       match waitpid [] pid with
	_, WEXITED 3 -&gt;
	  let ch = open_in filename in
	  let r = Marshal.from_channel ch in
	  close_in ch;
	  remove filename;
	  let pid = fork () in
	  if pid = 0 then (restore_signals (); r) else kn pid
       | _, WEXITED n -&gt; exit n
       | _, _ -&gt; exit 1
     in kn pid
----------------




-- 
Christophe Raffalli
Université de Savoie
Batiment Le Chablais, bureau 21
73376 Le Bourget-du-Lac Cedex

tél: (33) 4 79 75 81 03
fax: (33) 4 79 75 87 42
mail: Christophe.Raffalli@univ-savoie.fr
www: http://www.lama.univ-savoie.fr/~RAFFALLI
---------------------------------------------
IMPORTANT: this mail is signed using PGP/MIME
At least Enigmail/Mozilla, mutt or evolution
can check this signature
---------------------------------------------

</contents>

</message>

