Print this page
XXX keith II


 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()
 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 
 586                 ...


 634         var util = require('util');
 635         var binding = require('./native_binding');
 636         var events = require('events');
 637 
 638         function
 639         MyObjectWrapper()
 640         {
 641                 var self = this;
 642 
 643                 events.EventEmitter.call(this);
 644                 this._native = binding._create.apply(this,
 645                     Array.prototype.slice.call(arguments));
 646                 this._native._emit = function () {
 647                         var args = Array.prototype.slice.call(arguments);
 648                         self.emit.apply(self, args);
 649                 };
 650         }
 651         util.inherits(MyObjectWrapper, events.EventEmitter);
 652 
 653 Then, in C code, you must arrange for libuv to call a C function in the
 654 context of the main event loop.  How to do this depends on what type of
 655 asynchronous event you are waiting for; for example, the `uv_poll` mechanism
 656 will call you back in the appropriate context when a file descriptor becomes
 657 readable or writable.  Because libuv is a C library, you can easily use
 658 these interfaces directly in your v8+ addon.  Your libuv callback might then
 659 contain code looking something like this:
 660 
 661         nvlist_t *eap;
 662         nvlist_t *erp;
 663         my_object_t *op = ...;
 664         ...
 665         eap = v8plus_obj(
 666             V8PLUS_TYPE_STRING, "0", "my_event",
 667             ...,
 668             V8PLUS_TYPE_NONE);
 669 
 670         if (eap != NULL) {
 671                 erp = v8plus_method_call(op, "_emit", eap);
 672                 nvlist_free(eap);
 673                 nvlist_free(erp);
 674         }
 675 
 676 This example will generate an event named "my_event" and propagate it to
 677 listeners registered with the `MyObjectWrapper` instance.  If additional
 678 arguments are associated with the event, they may be added to `eap` and will
 679 also be passed along to listeners as arguments to their callbacks.


 711 `op` and context `ctx` are passed as arguments to `worker` executing in a
 712 thread from that pool.  The same two arguments, along with the worker's
 713 return value, are passed to `completion` executing in the main event loop
 714 thread.  See example above.
 715 
 716 ### nvlist_t *v8plus_call(v8plus_jsfunc_t f, const nvlist_t *ap)
 717 
 718 Calls the JavaScript function referred to by `f` with encoded arguments
 719 `ap`.  The return value is the encoded return value of the function.  The
 720 argument and return value encoding match the encodings that are used by C
 721 functions that provide methods.
 722 
 723 ### nvlist_t *v8plus_method_call(void *op, const char *name, const nvlist_t *ap)
 724 
 725 Calls the method named by `name` in the native object `op` with encoded
 726 argument list `ap`.  The method must exist and must be a JavaScript
 727 function.  Such functions may be attached by JavaScript code as in the event
 728 emitter example above.  The effects of using this function to call a native
 729 method are undefined.
 730 







 731 ## FAQ
 732 
 733 - Why?
 734 
 735 Because C++ is garbage.  Writing good software is challenging enough without
 736 trying to understand a bunch of implicit side effects or typing templated
 737 identifiers that can't fit in 80 columns without falling afoul of the
 738 language's ambiguous grammar.  Don't get me started.
 739 
 740 - Why not use [FFI](https://github.com/rbranson/node-ffi)?
 741 
 742 FFI is really cool; it offers us the ability to use C libraries without
 743 writing bindings at all.  However, it also exposes a lot of C nastiness to
 744 JavaScript code, essentially placing the interface boundary in consuming
 745 code itself.  This pretty much breaks the JavaScript interface model --
 746 for example, you can't really have a function that inspects the types of its
 747 arguments -- and requires you to write an additional C library anyway if you
 748 want or need to do something natively that's not quite what the C library
 749 already does.  Of course, one could use it to write "bindings" in JavaScript
 750 that actually look like a JavaScript interface, which may end up being the




 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 
 586                 ...


 634         var util = require('util');
 635         var binding = require('./native_binding');
 636         var events = require('events');
 637 
 638         function
 639         MyObjectWrapper()
 640         {
 641                 var self = this;
 642 
 643                 events.EventEmitter.call(this);
 644                 this._native = binding._create.apply(this,
 645                     Array.prototype.slice.call(arguments));
 646                 this._native._emit = function () {
 647                         var args = Array.prototype.slice.call(arguments);
 648                         self.emit.apply(self, args);
 649                 };
 650         }
 651         util.inherits(MyObjectWrapper, events.EventEmitter);
 652 
 653 Then, in C code, you must arrange for libuv to call a C function in the
 654 context of the main event loop.  The function `v8plus_method_call()` is safe
 655 to call from any thread: depending on the context in which it is invoked, it
 656 will either make the call directly or queue the call in the main event loop
 657 and block on a reply.  Simply arrange to call back into your JavaScript
 658 object when you wish to post an event:

 659 
 660         nvlist_t *eap;
 661         nvlist_t *erp;
 662         my_object_t *op = ...;
 663         ...
 664         eap = v8plus_obj(
 665             V8PLUS_TYPE_STRING, "0", "my_event",
 666             ...,
 667             V8PLUS_TYPE_NONE);
 668 
 669         if (eap != NULL) {
 670                 erp = v8plus_method_call(op, "_emit", eap);
 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.


 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
 756 that actually look like a JavaScript interface, which may end up being the