node-haystack Episode 3: Callback model in C++
2016-09-09 17:27
253 查看
Prerequisite
This article assumes readers have the following knowledge:C++14
Multi-Thread
Boost
JavaScript
node.js and add-on
Linux
Callback Mechanism
We have two kinds of callback, one for C++ and another for JavaScript.In libuv, the callback function will take over the control when job is done. A C style callback is a plaint function. A C++ wrapper of libuv must handle these callbacks and transform them into C++ style. In JavaScript, because of its closure mechanism, life becomes much easier than C++.
C++ Callback
Thanks for C++14, it makes callback a piece of case. We can play the callback function around anywhere. Here is a simple example:// For C++14 #include <iostream> #include <function> using namespace std; ... class A { public: void fork() { cout<<"Hello,World, This is A::fork"<<endl; } }; // Make a short name using callback_type=std::function<void(int)>; class B { public: void fork2(int val, const callback_type& cb) { cout<<"Pretend to do something..."<<endl; cout<<"Fire the callback:"<<endl; cb(val); } }; int main() { using namespace std::placeholders; A a; callback_type cb = std::bind(&A::fork, &a, _1); cb(100); B b; b.fork2(200, cb); b.fork2(200, [&](int x) { cout<<"Try lambda as the callback, just likes JavaScript does."<<x<<endl; }); return 0; }
JavaScript Callback
There is nothing more than function, for callback in js.Closure
A good thing is, from C++11, we do have the closure now, even it’s limited. An article about C++ closure can be found here. The bad thing is, it’s too limited to access the resources as will. The worse thing is, as crossing thread boundary, capturing the resource will fail. There is the worst thing: the compiler won’t tell you, everything looks fine, the syntax, the calling , until you get an access violation or other odd errors.NOTE:
Explicitly declare the resources in the capture specification(in the []) if they will probably be used in another thread.
Closure When inter-operating C++ and JavaScript
When accessing js variables from C++ code in different thread, the context, which is crucial for js(or v8 engine), has changed. Then any access to these js variables involving the context using will fail. Extra effort must be needed to keep the variables information and build the running context.Assuming the following js code:
// A is a node add-on var a = new A(); // A::fork is a pure C++ function a.fork(11, function(x) { console.log('This is pure js callback'); });
And the implementation of
A::forkis:
void fork(int x, const std::function<void(int)>& cb) { /// Do something and fire cb in another thread. cb(x); }
Here is the node add-on for class A:
static void callFork(FunctionCallbackInfo<Value>& args) { Isolate* iso = args.GetIsolate(); int x = args[0]->Int32Value(); Local<Value> cb_val = args[1]; // We need an extra structure to hold callback info struct callback_info_struc { Persistent<Function> cb; }; // Have to use pointer form; Otherwise the cb will call // constructor without parameters, and then compiler fails. callback_info_struc* pcb_info = new callback_info_struc(); // Save the callback info. pcb_info->cb.Reset(iso, cb_val); // pa is a pointer to A object. // Explicitly declare pcb_info in capture specification. pa->fork(x, [&, pcb_info](int v) { // Rebuild context Isolate* iso = Isolate::GetCurrent(); HandleScope scope(iso); // Prepare parameters. Local<Value> params[1] = { Integer::New(iso, x) }; // Fire callback pcb_info->cb->Call(iso->GetCurrentContext()->Global(), 1, params); // Release persistent variable. pcb_info->cb.Reset(); // Release callback info structure delete pcb_info; }); }
相关文章推荐
- node-haystack Episode 12: problem of C++ closure
- Inside The C++ Object Model(Note):sizeof in an object
- Inside in C++ Object Model Notes(1)
- node-haystack Episode-4: Wrapper of libuv
- node-haystack Episode 9: Manipulate Volume
- node-haystack Episode 8: Simple Recovery And Verification
- CALLBACKS IN C++ USING TEMPLATE FUNCTORS
- node-haystack Episode 1: What is it and why
- leetcode_c++:树:Populating Next Right Pointers in Each Node II(117)
- node-haystack Episode 11: node object of Volume
- Leetcode_populating-next-right-pointers-in-each-node(updated c++ and python version)
- LeetCode 之 Delete Node in a Linked List — C++ 实现
- LeetCode 之 Populating Next Right Pointers in Each Node I II — C++ 实现
- node-haystack Episode 2: Asynchronous and Threading
- leetcode 237 Delete Node in a Linked List C++
- Callback in NodeJS
- [C++]LeetCode: 124 Populating Next Right Pointers in Each Node II(链接二叉树)
- [leetcode-117]Populating Next Right Pointers in Each Node II(c++)
- node-haystack Episode 6: Data Structure And Constants
- leetcode之237. Delete Node in a Linked List(C++解法)