Print this page
XXX error handling cleanup
XXX rework to avoid changing api
XXX well, it works now...
XXX first cut of crosscall

Split Close
Expand all
Collapse all
          --- old/./v8plus_subr.cc
          +++ new/./v8plus_subr.cc
↓ open down ↓ 21 lines elided ↑ open up ↑
  22   22  typedef struct cb_hdl {
  23   23          v8::Handle<v8::Function> ch_hdl;
  24   24          uint_t ch_refs;
  25   25          boolean_t ch_persist;
  26   26  } cb_hdl_t;
  27   27  
  28   28  static std::unordered_map<uint64_t, cb_hdl_t> cbhash;
  29   29  static uint64_t cbnext;
  30   30  static void (*__real_nvlist_free)(nvlist_t *);
  31   31  
       32 +
  32   33  static const char *
  33   34  cstr(const v8::String::Utf8Value &v)
  34   35  {
  35   36          return (*v);
  36   37  }
  37   38  
  38   39  /*
  39   40   * Convenience macros for adding stuff to an nvlist and returning on failure.
  40   41   */
  41   42  #define LA_U(_l, _n, _e) \
↓ open down ↓ 404 lines elided ↑ open up ↑
 446  447                  }
 447  448          } else if ((err = nvlist_add_v8_Value(rp, "res", res)) != 0) {
 448  449                  nvlist_free(rp);
 449  450                  return (v8plus_nverr(err, "res"));
 450  451          }
 451  452  
 452  453          return (rp);
 453  454  }
 454  455  
 455  456  extern "C" nvlist_t *
 456      -v8plus_method_call(void *cop, const char *name, const nvlist_t *lp)
      457 +v8plus_method_call_direct(void *cop, const char *name, const nvlist_t *lp)
 457  458  {
 458  459          v8plus::ObjectWrap *op = v8plus::ObjectWrap::objlookup(cop);
 459  460          const int max_argc = nvlist_length(lp);
 460  461          int argc, err;
 461  462          v8::Handle<v8::Value> argv[max_argc];
 462  463          v8::Handle<v8::Value> res;
 463  464          nvlist_t *rp;
 464  465  
      466 +        if (v8plus::ObjectWrap::in_event_thread() != _B_TRUE)
      467 +                v8plus_panic("direct method call outside of event loop");
      468 +
 465  469          argc = max_argc;
 466  470          nvlist_to_v8_argv(lp, &argc, argv);
 467  471  
 468  472          if ((err = nvlist_alloc(&rp, NV_UNIQUE_NAME, 0)) != 0)
 469  473                  return (v8plus_nverr(err, NULL));
 470  474  
 471  475          v8::TryCatch tc;
 472  476          res = op->call(name, argc, argv);
 473  477          if (tc.HasCaught()) {
 474  478                  err = nvlist_add_v8_Value(rp, "err", tc.Exception());
↓ open down ↓ 3 lines elided ↑ open up ↑
 478  482                          return (v8plus_nverr(err, "err"));
 479  483                  }
 480  484          } else if ((err = nvlist_add_v8_Value(rp, "res", res)) != 0) {
 481  485                  nvlist_free(rp);
 482  486                  return (v8plus_nverr(err, "res"));
 483  487          }
 484  488  
 485  489          return (rp);
 486  490  }
 487  491  
      492 +extern "C" void
      493 +v8plus_async_callback(uv_async_t *async, __attribute__((unused)) int status)
      494 +{
      495 +        if (v8plus::ObjectWrap::in_event_thread() != _B_TRUE)
      496 +                v8plus_panic("async callback called outside of event loop");
      497 +
      498 +        for (;;) {
      499 +                v8plus_async_call_t *ac;
      500 +
      501 +                if ((ac = v8plus::ObjectWrap::next_async_call()) == NULL)
      502 +                        break;
      503 +
      504 +                if (pthread_mutex_lock(&ac->ac_mtx) != 0)
      505 +                        v8plus_panic("could not lock async call mutex");
      506 +
      507 +                if (ac->ac_run == _B_TRUE)
      508 +                        v8plus_panic("async call already run");
      509 +
      510 +                ac->ac_return = v8plus_method_call_direct(ac->ac_cop,
      511 +                    ac->ac_name, ac->ac_lp);
      512 +                ac->ac_run = _B_TRUE;
      513 +
      514 +                if (pthread_cond_broadcast(&ac->ac_cv) != 0)
      515 +                        v8plus_panic("could not signal async call condvar");
      516 +                if (pthread_mutex_unlock(&ac->ac_mtx) != 0)
      517 +                        v8plus_panic("could not unlock async call mutex");
      518 +        }
      519 +}
      520 +
      521 +extern "C" nvlist_t *
      522 +v8plus_method_call(void *cop, const char *name, const nvlist_t *lp)
      523 +{
      524 +        v8plus_async_call_t ac;
      525 +
      526 +        if (v8plus::ObjectWrap::in_event_thread() == _B_TRUE) {
      527 +                /*
      528 +                 * We're running in the event loop thread, so we can make the
      529 +                 * call directly.
      530 +                 */
      531 +                return (v8plus_method_call_direct(cop, name, lp));
      532 +        }
      533 +
      534 +        /*
      535 +         * As we cannot manipulate v8plus/V8/Node structures directly from
      536 +         * outside the event loop thread, we push the call arguments onto a
      537 +         * queue and post to the event loop thread.  We then sleep on our
      538 +         * condition variable until the event loop thread makes the call
      539 +         * for us and wakes us up.
      540 +         */
      541 +        ac.ac_cop = cop;
      542 +        ac.ac_name = name;
      543 +        ac.ac_lp = lp;
      544 +        if (pthread_mutex_init(&ac.ac_mtx, NULL) != 0)
      545 +                v8plus_panic("could not init async call mutex");
      546 +        if (pthread_cond_init(&ac.ac_cv, NULL) != 0)
      547 +                v8plus_panic("could not init async call condvar");
      548 +        ac.ac_run = _B_FALSE;
      549 +        ac.ac_return = NULL;
      550 +
      551 +        v8plus::ObjectWrap::post_async_call(&ac);
      552 +
      553 +        if (pthread_mutex_lock(&ac.ac_mtx) != 0)
      554 +                v8plus_panic("could not lock async call mutex");
      555 +        while (ac.ac_run == _B_FALSE) {
      556 +                if (pthread_cond_wait(&ac.ac_cv, &ac.ac_mtx) != 0)
      557 +                        v8plus_panic("could not wait on async call condvar");
      558 +        }
      559 +
      560 +        return (ac.ac_return);
      561 +}
      562 +
 488  563  extern "C" int
 489  564  nvlist_lookup_v8plus_jsfunc(const nvlist_t *lp, const char *name,
 490  565      v8plus_jsfunc_t *vp)
 491  566  {
 492  567          uint64_t *lvp;
 493  568          uint_t nv;
 494  569          int err;
 495  570  
 496  571          err = nvlist_lookup_uint64_array(const_cast<nvlist_t *>(lp),
 497  572              name, &lvp, &nv);
↓ open down ↓ 147 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX