pike.git / lib / modules / Concurrent.pmod

version» Context lines:

pike.git/lib/modules/Concurrent.pmod:433:    protected string _sprintf(int t)    {    return t=='O' && sprintf("%O(%s,%O)", this_program,    ([ STATE_PENDING : "pending",    STATE_REJECTED : "rejected",    STATE_FULFILLED : "fulfilled" ])[state],    result);    }   }    - class aggregate_state { + class AggregateState + {    private Promise promise;    private int(0..) promises;    private int(0..) succeeded, failed;    final array(mixed) results;    final int(0..) min_failures;    final int(-1..) max_failures;    final mixed accumulator;    final function(mixed, mixed, mixed ... : mixed) fold_fun;    final array(mixed) extra;    -  private void create(Promise p) { +  private void create(Promise p) +  {    if (p->_materialised || p->_materialised++)    error("Cannot materialise a Promise more than once.\n");    promise = p;    }    -  final void materialise() { +  final void materialise() +  {    Thread.MutexKey key = mux->lock(); -  if (promise->_astate) { +  if (promise->_astate) +  {    promise->_astate = 0;    key = 0; -  if (results) { +  if (results) +  {    promises = sizeof(results);    array(Future) futures = results;    if (fold_fun)    results = 0; -  foreach(futures; int idx; Future f) { +  foreach(futures; int idx; Future f) +  {    f->on_failure(cb_failure, idx);    f->on_success(cb_success, idx);    }    }    }    key = 0;    }    -  private void fold_one(mixed val) { +  private void fold_one(mixed val) +  {    mixed err = catch (accumulator = fold_fun(val, accumulator, @extra));    if (err && promise)    promise->failure(err);    }    -  private void fold(function(mixed:void) failsucc) { +  private void fold(function(mixed:void) failsucc) +  {    failsucc(fold_fun ? accumulator : results);    results = 0; // Free memory    }    -  private void cb_failure(mixed value, int idx) { +  private void cb_failure(mixed value, int idx) +  {    Promise p; // Cache it, to cover a failure race -  if (p = promise) { +  if (p = promise) +  {    Thread.MutexKey key = mux->lock(); -  do { -  if (!p->state) { +  do +  { +  if (!p->state) +  {    ++failed; -  if (max_failures < failed && max_failures >= 0) { +  if (max_failures < failed && max_failures >= 0) +  {    key = 0;    p->try_failure(value);    break;    }    int success = succeeded + failed == promises;    key = 0;    if (results)    results[idx] = value;    else    fold_one(value); -  if (success) { +  if (success) +  {    fold(failed >= min_failures ? p->success : p->failure);    break;    } -  } else +  } +  else    key = 0;    return;    } while (0);    promise = 0; // Free backreference    }    }    -  private void cb_success(mixed value, int idx) { +  private void cb_success(mixed value, int idx) +  {    Promise p; // Cache it, to cover a failure race -  if (p = promise) { +  if (p = promise) +  {    Thread.MutexKey key = mux->lock(); -  do { -  if (!p->state) { +  do +  { +  if (!p->state) +  {    ++succeeded; -  if (promises - min_failures < succeeded) { +  if (promises - min_failures < succeeded) +  {    key = 0;    p->try_failure(value);    break;    }    int success = succeeded + failed == promises;    key = 0;    if (results)    results[idx] = value;    else    fold_one(value); -  if (success) { +  if (success) +  {    fold(p->success);    break;    } -  } else +  } +  else    key = 0;    return;    } while (0);    promise = 0; // Free backreference    }    }   }      //! Promise to provide a @[Future] value.   //!
pike.git/lib/modules/Concurrent.pmod:555:   //! that is directly returned to the user is the return   //! value from @[future()].   //!   //! @seealso   //! @[Future], @[future()]   class Promise   {    inherit Future;       final int _materialised; -  final aggregate_state _astate; +  final AggregateState _astate;       //! Creates a new promise, optionally initialised from a traditional callback    //! driven method via @expr{executor(resolve, reject, extra ... )@}.    //!    //! @seealso    //! @url{https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise@}    protected void create(void|    function(function(mixed:void), -  function(mixed:void), mixed ...:void) executor, mixed ... extra) { +  function(mixed:void), mixed ...:void) executor, mixed ... extra) +  {    if (executor)    executor(success, failure, @extra);    }    -  Future on_success(function(mixed, mixed ... : void) cb, mixed ... extra) { -  if (_astate) catch(_astate->materialise()); // catches race for _astate == 0 +  Future on_success(function(mixed, mixed ... : void) cb, mixed ... extra) +  { +  if (_astate) +  catch(_astate->materialise()); // catches race for _astate == 0    return ::on_success(cb, @extra);    }    -  Future on_failure(function(mixed, mixed ... : void) cb, mixed ... extra) { -  if (_astate) catch(_astate->materialise()); // catches race for _astate == 0 +  Future on_failure(function(mixed, mixed ... : void) cb, mixed ... extra) +  { +  if (_astate) +  catch(_astate->materialise()); // catches race for _astate == 0    return ::on_failure(cb, @extra);    }    -  mixed get() { -  if (_astate) catch(_astate->materialise()); // catches race for _astate == 0 +  mixed get() +  { +  if (_astate) +  catch(_astate->materialise()); // catches race for _astate == 0    return ::get();    }       //! The future value that we promise.    Future future()    {    return Future::this;    }       protected this_program finalise(State newstate, mixed value, int try,    array(array(function(mixed, mixed ...: void)|array(mixed))) cbs, -  void|function(mixed : void) globalfailure) { +  void|function(mixed : void) globalfailure) +  {    Thread.MutexKey key = mux->lock(); -  if (!state) { +  if (!state) +  {    state = newstate;    result = value;    key = 0;    cond->broadcast(); -  if (sizeof(cbs)) { +  if (sizeof(cbs)) +  {    foreach(cbs; ; array cb)    if (cb)    call_out(cb[0], 0, value, @cb[1..]); -  } else if (globalfailure) +  } +  else if (globalfailure)    call_out(globalfailure, 0, value); -  } else { +  } +  else +  {    key = 0;    if (!try)    error("Promise has already been finalised.\n");    }    return this_program::this;    }       //! @decl this_program success(mixed value)    //!    //! Fulfill the @[Future].
pike.git/lib/modules/Concurrent.pmod:688:    //! and in that case schedule the @[on_failure()] callbacks to be    //! called as soon as possible.    //!    //! @seealso    //! @[failure()], @[success()], @[on_failure()]    inline this_program try_failure(mixed value)    {    return state ? this_program::this : failure(value, 1);    }    -  inline private void fill_astate() { +  inline private void fill_astate() +  {    if (!_astate) -  _astate = aggregate_state(this); +  _astate = AggregateState(this);    }       //! Add futures to the list of futures which the current object depends upon.    //!    //! If called without arguments it will produce a new @[Future]    //! from a new @[Promise] which is implictly added to the dependency list.    //!    //! @param futures    //! The list of @expr{futures@} we want to add to the list we depend upon.    //!