Version française
Home     About     Download     Resources     Contact us    

This site is updated infrequently. For up-to-date information, please visit the new OCaml website at

Browse thread
Using camljava library in a multithreaded context
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: 2005-03-07 (16:22)
From: Markus Mottl <markus.mottl@g...>
Subject: Re: [Caml-list] Re: C-threads & callbacks vs camljava in a multithrea ded context

sorry for the delay, but I was extremely busy answering a huge backlog
of mails recently.

On Wed, 23 Feb 2005, EL CHAAR RABIH wrote:
> I sent today a mail concenrning external threads (java threads) and caml.
> When looking inside the caml-list, i came up upon your mail, which attracted
> my attention.
> My goal is to try and switch the jvm thread into a caml thread.
> Is it possible to have your opinion upon my post "Using camljava library in
> a multithreaded context"?
> Is it also possible to have a small example (C and ocaml) realising this
> coordination issue ?

Unfortunately, I have no experience with Java so I cannot tell you
whether there is a way to let Java-threads migrate to OCaml.

My C-solution, which seems to work very well in practice, looks roughly
as follows:

  pthread_mutex_t cb_act_mtx;
  pthread_cond_t cb_act_cnd;
  value *cb_act;

  pthread_mutex_t cb_res_mtx;
  pthread_cond_t cb_res_cnd;

The first mutex and condition variable protect "cb_act", the callback
action to be performed.

If there is a C-thread that wants to call OCaml, it calls the following
function/method (it's actually C++):

  void do_cb(value *action)
      cb_act = action;

      while (not cb_res_avail) pthread_cond_wait(&cb_res_cnd, &cb_res_mtx);

    cb_res_avail = false;

Depending on the kind of action that should be performed, an OCaml-thread
that has previously gone into C-land will eventually convert C-data to
OCaml-values before performing the callback.  After returning it will
signal the C-thread that a result is available (or simply that it has
completed the job).  The OCaml-thread has to perform all the conversions,
because the C-thread must not call the GC.  Our C-function, in which
the OCaml-thread waits for callbacks + associated data looks as follows:

  virtual value handle_cbs()
    while (true) {
          while (cb_act == NULL)
            pthread_cond_wait(&cb_act_cnd, &cb_act_mtx);

      if (cb_act == &v_OnRecordUpdateCallback)
                      vrc_make(rup, free_record_update, lev1_GC_setting));
      else if (cb_act == &v_Terminate) {}
      else cb_sc = caml_callback(*cb_act, Val_int(cb_sc));

        cb_act = NULL;
        cb_res_avail = true;

      if (cb_act == &v_Terminate) return Val_unit;

    return Val_unit;  // we should never get here

In OCaml you just need to specify the external function that the
OCaml-thread should call:

  external handle_cbs : t -> unit = "activ_handle_cbs_stub"

Then do something like the following at startup:

  let wrap_handle_cbs () =
    try handle_cbs cgc
    with exc ->
      (match exc with
      | Status sc ->
          eprintf "Activ-exception: Status %s\n" (Status_code.to_string sc)
      | FieldStatus fs ->
            "Activ-exception: FieldStatus %s\n" (Field_status.to_string fs)
      | _ ->
          eprintf "Exception escaping callback: %s\n" (Printexc.to_string exc)
      exit 2 in
  ignore (Thread.create wrap_handle_cbs ());

I hope that this info is enough so that you can make OCaml- and C-threads
interact smoothly.


Markus Mottl