Print this page
enable v8plus_call to be used in any thread


 542 various practitioners around the world.  In this model, your method or
 543 function takes a callback argument and returns immediately after enqueuing a
 544 task to run on one of the threads in the Node.js worker thread pool.  That
 545 task consists of a C function to be run on the worker thread, which may not
 546 use any V8 (or v8+) state, and a function to be run in the main event loop
 547 thread when that task has completed.  The latter function is normally
 548 expected to invoke the caller's original callback.  In v8+, this takes the
 549 following form:
 550 
 551         void *
 552         async_worker(void *cop, void *ctxp)
 553         {
 554                 my_object_t *op = cop;
 555                 my_context_t *cp = ctxp;
 556                 my_result_t *rp = ...;
 557 
 558                 /*
 559                  * In thread pool context -- do not call any of the
 560                  * following functions:
 561                  * v8plus_obj_hold()
 562                  * v8plus_obj_rele()
 563                  * v8plus_jsfunc_hold()
 564                  * v8plus_jsfunc_rele()
 565                  * v8plus_call()
 566                  * v8plus_method_call_direct()
 567                  * v8plus_defer()
 568                  *
 569                  * If you touch anything inside op, you may need locking to
 570                  * protect against functions called in the main thread.
 571                  */
 572                 ...
 573 
 574                 return (rp);
 575         }
 576 
 577         void
 578         async_completion(void *cop, void *ctxp, void *resp)
 579         {
 580                 my_object_t *op = cop;
 581                 my_context_t *cp = ctxp;
 582                 my_result_t *rp = resp;
 583                 nvlist_t *cbap;
 584                 nvlist_t *cbrp;
 585 


 671                 nvlist_free(eap);
 672                 nvlist_free(erp);
 673         }
 674 
 675 This example will generate an event named "my_event" and propagate it to
 676 listeners registered with the `MyObjectWrapper` instance.  If additional
 677 arguments are associated with the event, they may be added to `eap` and will
 678 also be passed along to listeners as arguments to their callbacks.
 679 
 680 ### void v8plus_obj_hold(const void *op)
 681 
 682 Places a hold on the V8 representation of the specified C object.  This is
 683 rarely necessary; `v8plus_defer()` performs this action for you, but other
 684 asynchronous mechanisms may require it.  If you are returning from a method
 685 call but have stashed a reference to the object somewhere and are not
 686 calling `v8plus_defer()`, you must call this first.  Holds and releases must
 687 be balanced.  Use of the object within a thread after releasing is a bug.
 688 
 689 ### void v8plus_obj_rele(const void *op)
 690 
 691 Releases a hold placed by `v8plus_obj_hold()`.


 692 
 693 ### void v8plus_jsfunc_hold(v8plus_jsfunc_t f)
 694 
 695 Places a hold on the V8 representation of the specified JavaScript function.
 696 This is required when returning from a C function that has stashed a
 697 reference to the function, typically to use it asynchronously as a callback.
 698 All holds must be balanced with a release.  Because a single hold is placed
 699 on such objects when passed to you in an argument list (and released for you
 700 when you return), it is legal to reference and even to invoke such a
 701 function without first placing an additional hold on it.
 702 
 703 ### void v8plus_jsfunc_rele(v8plus_jsfunc_t f)
 704 
 705 Releases a hold placed by `v8plus_jsfunc_hold()`.


 706 
 707 ### void v8plus_defer(void *op, void *ctx, worker, completion)
 708 
 709 Enqueues work to be performed in the Node.js shared thread pool.  The object
 710 `op` and context `ctx` are passed as arguments to `worker` executing in a
 711 thread from that pool.  The same two arguments, along with the worker's
 712 return value, are passed to `completion` executing in the main event loop
 713 thread.  See example above.
 714 
 715 ### nvlist_t *v8plus_call(v8plus_jsfunc_t f, const nvlist_t *ap)
 716 
 717 Calls the JavaScript function referred to by `f` with encoded arguments
 718 `ap`.  The return value is the encoded return value of the function.  The
 719 argument and return value encoding match the encodings that are used by C
 720 functions that provide methods.
 721 












 722 ### nvlist_t *v8plus_method_call(void *op, const char *name, const nvlist_t *ap)
 723 
 724 Calls the method named by `name` in the native object `op` with encoded
 725 argument list `ap`.  The method must exist and must be a JavaScript
 726 function.  Such functions may be attached by JavaScript code as in the event
 727 emitter example above.  The effects of using this function to call a native
 728 method are undefined.
 729 
 730 As JavaScript functions must be called from the event loop thread,
 731 `v8plus_method_call()` contains logic to determine whether we are in the
 732 correct context or not.  If we are running on some other thread we will
 733 queue the request and sleep, waiting for the event loop thread to make the
 734 call.  In the simple case, where we are already in the correct thread, we
 735 make the call directly.
 736 
 737 ## FAQ
 738 
 739 - Why?
 740 
 741 Because C++ is garbage.  Writing good software is challenging enough without
 742 trying to understand a bunch of implicit side effects or typing templated
 743 identifiers that can't fit in 80 columns without falling afoul of the
 744 language's ambiguous grammar.  Don't get me started.
 745 
 746 - Why not use [FFI](https://github.com/rbranson/node-ffi)?
 747 
 748 FFI is really cool; it offers us the ability to use C libraries without
 749 writing bindings at all.  However, it also exposes a lot of C nastiness to
 750 JavaScript code, essentially placing the interface boundary in consuming
 751 code itself.  This pretty much breaks the JavaScript interface model --
 752 for example, you can't really have a function that inspects the types of its
 753 arguments -- and requires you to write an additional C library anyway if you
 754 want or need to do something natively that's not quite what the C library
 755 already does.  Of course, one could use it to write "bindings" in JavaScript




 542 various practitioners around the world.  In this model, your method or
 543 function takes a callback argument and returns immediately after enqueuing a
 544 task to run on one of the threads in the Node.js worker thread pool.  That
 545 task consists of a C function to be run on the worker thread, which may not
 546 use any V8 (or v8+) state, and a function to be run in the main event loop
 547 thread when that task has completed.  The latter function is normally
 548 expected to invoke the caller's original callback.  In v8+, this takes the
 549 following form:
 550 
 551         void *
 552         async_worker(void *cop, void *ctxp)
 553         {
 554                 my_object_t *op = cop;
 555                 my_context_t *cp = ctxp;
 556                 my_result_t *rp = ...;
 557 
 558                 /*
 559                  * In thread pool context -- do not call any of the
 560                  * following functions:
 561                  * v8plus_obj_hold()
 562                  * v8plus_obj_rele_direct()
 563                  * v8plus_jsfunc_hold()
 564                  * v8plus_jsfunc_rele_direct()
 565                  * v8plus_call_direct()
 566                  * v8plus_method_call_direct()
 567                  * v8plus_defer()
 568                  *
 569                  * If you touch anything inside op, you may need locking to
 570                  * protect against functions called in the main thread.
 571                  */
 572                 ...
 573 
 574                 return (rp);
 575         }
 576 
 577         void
 578         async_completion(void *cop, void *ctxp, void *resp)
 579         {
 580                 my_object_t *op = cop;
 581                 my_context_t *cp = ctxp;
 582                 my_result_t *rp = resp;
 583                 nvlist_t *cbap;
 584                 nvlist_t *cbrp;
 585 


 671                 nvlist_free(eap);
 672                 nvlist_free(erp);
 673         }
 674 
 675 This example will generate an event named "my_event" and propagate it to
 676 listeners registered with the `MyObjectWrapper` instance.  If additional
 677 arguments are associated with the event, they may be added to `eap` and will
 678 also be passed along to listeners as arguments to their callbacks.
 679 
 680 ### void v8plus_obj_hold(const void *op)
 681 
 682 Places a hold on the V8 representation of the specified C object.  This is
 683 rarely necessary; `v8plus_defer()` performs this action for you, but other
 684 asynchronous mechanisms may require it.  If you are returning from a method
 685 call but have stashed a reference to the object somewhere and are not
 686 calling `v8plus_defer()`, you must call this first.  Holds and releases must
 687 be balanced.  Use of the object within a thread after releasing is a bug.
 688 
 689 ### void v8plus_obj_rele(const void *op)
 690 
 691 Releases a hold placed by `v8plus_obj_hold()`.  This function may be called
 692 safely from any thread; releases from threads other than the main event loop
 693 are non-blocking and will occur some time in the future.
 694 
 695 ### void v8plus_jsfunc_hold(v8plus_jsfunc_t f)
 696 
 697 Places a hold on the V8 representation of the specified JavaScript function.
 698 This is required when returning from a C function that has stashed a
 699 reference to the function, typically to use it asynchronously as a callback.
 700 All holds must be balanced with a release.  Because a single hold is placed
 701 on such objects when passed to you in an argument list (and released for you
 702 when you return), it is legal to reference and even to invoke such a
 703 function without first placing an additional hold on it.
 704 
 705 ### void v8plus_jsfunc_rele(v8plus_jsfunc_t f)
 706 
 707 Releases a hold placed by `v8plus_jsfunc_hold()`.  This function may be called
 708 safely from any thread; releases from threads other than the main event loop
 709 thread are non-blocking and will occur some time in the future.
 710 
 711 ### void v8plus_defer(void *op, void *ctx, worker, completion)
 712 
 713 Enqueues work to be performed in the Node.js shared thread pool.  The object
 714 `op` and context `ctx` are passed as arguments to `worker` executing in a
 715 thread from that pool.  The same two arguments, along with the worker's
 716 return value, are passed to `completion` executing in the main event loop
 717 thread.  See example above.
 718 
 719 ### nvlist_t *v8plus_call(v8plus_jsfunc_t f, const nvlist_t *ap)
 720 
 721 Calls the JavaScript function referred to by `f` with encoded arguments
 722 `ap`.  The return value is the encoded return value of the function.  The
 723 argument and return value encoding match the encodings that are used by C
 724 functions that provide methods.
 725 
 726 As JavaScript functions must be called from the event loop thread,
 727 `v8plus_call()` contains logic to determine whether we are in the
 728 correct context or not.  If we are running on some other thread we will
 729 queue the request and sleep, waiting for the event loop thread to make the
 730 call.  In the simple case, where we are already in the correct thread, we
 731 make the call directly.
 732 
 733 Note that when passing JavaScript functions around as callbacks, you must use
 734 first use `v8plus_jsfunc_hold()` from within the main event loop thread.  Once
 735 finished with the function, you may pass it to `v8plus_jsfunc_rele()` from any
 736 thread to clean up.
 737 
 738 ### nvlist_t *v8plus_method_call(void *op, const char *name, const nvlist_t *ap)
 739 
 740 Calls the method named by `name` in the native object `op` with encoded
 741 argument list `ap`.  The method must exist and must be a JavaScript
 742 function.  Such functions may be attached by JavaScript code as in the event
 743 emitter example above.  The effects of using this function to call a native
 744 method are undefined.
 745 
 746 When called from threads other than the main event loop thread,
 747 `v8plus_method_call()` uses the same queue-and-block logic as described above
 748 in `v8plus_call()`.



 749 
 750 ## FAQ
 751 
 752 - Why?
 753 
 754 Because C++ is garbage.  Writing good software is challenging enough without
 755 trying to understand a bunch of implicit side effects or typing templated
 756 identifiers that can't fit in 80 columns without falling afoul of the
 757 language's ambiguous grammar.  Don't get me started.
 758 
 759 - Why not use [FFI](https://github.com/rbranson/node-ffi)?
 760 
 761 FFI is really cool; it offers us the ability to use C libraries without
 762 writing bindings at all.  However, it also exposes a lot of C nastiness to
 763 JavaScript code, essentially placing the interface boundary in consuming
 764 code itself.  This pretty much breaks the JavaScript interface model --
 765 for example, you can't really have a function that inspects the types of its
 766 arguments -- and requires you to write an additional C library anyway if you
 767 want or need to do something natively that's not quite what the C library
 768 already does.  Of course, one could use it to write "bindings" in JavaScript