pike.git / lib / modules / Concurrent.pmod

version» Context lines:

pike.git/lib/modules/Concurrent.pmod:1:   //! Module for handling multiple concurrent events.    + /* +  * Inspired by https://github.com/couchdeveloper/FutureLib +  */ +    protected enum State {    STATE_PENDING = 0,    STATE_FULFILLED,    STATE_REJECTED,   };      protected Thread.Mutex mux = Thread.Mutex();   protected Thread.Condition cond = Thread.Condition();      //! Value that will be provided asynchronously
pike.git/lib/modules/Concurrent.pmod:69:    object key = mux->lock();    failure_cb = cb;    failure_ctx = extra;    State s = state;    mixed res = result;    key = 0;    if (s == STATE_REJECTED) {    call_out(cb, 0, res, @extra);    }    } +  +  //! Apply @[fun] with @[val] followed by the contents of @[ctx], +  //! and update @[p] with the result. +  protected void apply(mixed val, Promise p, +  function(mixed, mixed ... : mixed) fun, +  array(mixed) ctx) +  { +  mixed err = catch { +  p->success(fun(val, @ctx)); +  return; +  }; +  p->failure(err);    }    -  +  //! Apply @[fun] with @[val] followed by the contents of @[ctx], +  //! and update @[p] with the eventual result. +  protected void apply_flat(mixed val, Promise p, +  function(mixed, mixed ... : Future) fun, +  array(mixed) ctx) +  { +  mixed err = catch { +  Future f = fun(val, @ctx); +  if (!objectp(f) || !f->on_failure || !f->on_success) { +  error("Expected %O to return a Future. Got: %O.\n", +  fun, f); +  } +  f->on_failure(p->failure); +  f->on_success(p->success); +  return; +  }; +  p->failure(err); +  } +  +  //! Apply @[fun] with @[val] followed by the contents of @[ctx], +  //! and update @[p] with @[val] if @[fun] didn't return false. +  //! If @[fun] returned false fail @[p] with @[UNDEFINED]. +  protected void apply_filter(mixed val, Promise p, +  function(mixed, mixed ... : int(0..1)) fun, +  array(mixed) ctx) +  { +  mixed err = catch { +  if (fun(val, @ctx)) { +  p->success(val); +  } else { +  p->failure(UNDEFINED); +  } +  return; +  }; +  p->failure(err); +  } +  +  //! Return a @[Future] that will be fulfilled with the result +  //! of applying @[fun] with the fulfilled result of this @[Future] +  //! followed by @[extra]. +  this_program map(function(mixed, mixed ... : mixed) fun, mixed ... extra) +  { +  Promise p = Promise(); +  on_failure(p->failure); +  on_success(apply, p, fun, extra); +  return p->future(); +  } +  +  //! Return a @[Future] that will be fulfilled with the fulfilled result +  //! of applying @[fun] with the fulfilled result of this @[Future] +  //! followed by @[extra]. +  this_program flat_map(function(mixed, mixed ... : this_program) fun, +  mixed ... extra) +  { +  Promise p = Promise(); +  on_failure(p->failure); +  on_success(apply_flat, p, fun, extra); +  return p->future(); +  } +  +  //! Return a @[Future] that will be fulfilled with either +  //! the fulfiled result of this @[Future], or the result +  //! of applying @[fun] with the failed result followed +  //! by @[extra]. +  this_program recover(function(mixed, mixed ... : mixed) fun, +  mixed ... extra) +  { +  Promise p = Promise(); +  on_success(p->success); +  on_failure(apply, p, fun, extra); +  return p->future(); +  } +  +  //! Return a @[Future] that will be fulfilled with either +  //! the fulfiled result of this @[Future], or the fulfilled result +  //! of applying @[fun] with the failed result followed +  //! by @[extra]. +  this_program recover_with(function(mixed, mixed ... : this_program) fun, +  mixed ... extra) +  { +  Promise p = Promise(); +  on_success(p->success); +  on_failure(apply_flat, p, fun, extra); +  return p->future(); +  } +  +  //! Return a @[Future] that either will by fulfilled by the +  //! fulfilled result of this @[Future] if applying @[fun] +  //! with the result followed by @[extra] returns true, +  //! or will fail with @[UNDEFINED] if it returns false. +  this_program filter(function(mixed, mixed ... : int(0..1)) fun, +  mixed ... extra) +  { +  Promise p = Promise(); +  on_failure(p->failure); +  on_success(apply_filter, p, fun, extra); +  return p->future(); +  } +  +  //! Return a @[Future] that will be fulfilled with either +  //! the result of applying @[success] with the fulfilled result +  //! followed by @[extra], or the result of applying @[failure] +  //! with the failed result followed by @[extra]. +  //! +  //! @[failure] defaults to @[success]. +  //! +  //! @seealso +  //! @[map] +  this_program transform(function(mixed, mixed ... : mixed) success, +  function(mixed, mixed ... : mixed)|void failure, +  mixed ... extra) +  { +  Promise p = Promise(); +  on_success(apply, p, success, extra); +  on_failure(apply, p, failure || success, extra); +  return p->future(); +  } +  +  //! Return a @[Future] that will be fulfilled with either +  //! the fulfilled result of applying @[success] with the fulfilled result +  //! followed by @[extra], or the fulfilled result of applying @[failure] +  //! with the failed result followed by @[extra]. +  //! +  //! @[failure] defaults to @[success]. +  //! +  //! @seealso +  //! @[flat_map] +  this_program transform_with(function(mixed, mixed ... : Future) success, +  function(mixed, mixed ... : Future)|void failure, +  mixed ... extra) +  { +  Promise p = Promise(); +  on_success(apply_flat, p, success, extra); +  on_failure(apply_flat, p, failure || success, extra); +  return p->future(); +  } + } +    //! Promise to provide a @[Future] value.   //! -  + //! Objects of this class are typically kept internal to the + //! code that provides the @[Future] value. The only thing + //! that is directly returned to the user is the return + //! value from @[future()]. + //!   //! @seealso - //! @[Future] + //! @[Future], @[future()]   class Promise   {    inherit Future;       //! The future value that we promise.    Future future()    {    return Future::this;    }