Permalink
Browse files

Add async callback example

  • Loading branch information...
1 parent 425d326 commit 9d226b25aedae4174a8af4b4f3cac836c3f893eb @nikhilm committed Jan 20, 2012
Showing with 169 additions and 0 deletions.
  1. +146 −0 async/main.cc
  2. +10 −0 async/test.js
  3. +13 −0 async/wscript
View
146 async/main.cc
@@ -0,0 +1,146 @@
+#include <unistd.h>
+#include <v8.h>
+#include <node.h>
+#include <node_object_wrap.h>
+using namespace v8;
+using namespace node;
+
+namespace Library {
+class Inventory {
+public:
+ Inventory() : items(0) {}
+
+ void addStock(int n) {
+ items += n;
+ }
+
+ int ship(int orders) {
+ if (orders > items)
+ return -1;
+
+ items -= orders;
+ return 0;
+ }
+
+ int getItems() {
+ return items;
+ }
+
+ void reshelve() {
+ sleep(5);
+ }
+
+private:
+ int items;
+};
+}
+
+namespace binding {
+
+class Inventory;
+struct ReshelveBaton {
+ uv_work_t request;
+ Persistent<Function> callback;
+ Inventory *wrapper;
+ // any other data that has to be sent to the callback
+ // or for async processing.
+};
+
+class Inventory : public ObjectWrap {
+public:
+ Inventory() : ObjectWrap()
+ , inv(new Library::Inventory()) {};
+
+ ~Inventory() { delete inv; }
+
+ static Handle<Value> New(const Arguments &args) {
+ Inventory *wrapper = new Inventory();
+ wrapper->Wrap(args.Holder());
+ return args.Holder();
+ }
+
+ static Handle<Value> AddStock(const Arguments &args) {
+ Inventory *wrapper = Unwrap<Inventory>(args.Holder());
+ int n = args[0]->Uint32Value();
+
+ wrapper->inv->addStock(n);
+ return Undefined();
+ }
+
+ static Handle<Value> Ship(const Arguments &args) {
+ Inventory *wrapper = Unwrap<Inventory>(args.Holder());
+ int orders = args[0]->Uint32Value();
+ int result = wrapper->inv->ship(orders);
+
+ if (result == -1)
+ return ThrowException(String::New("Not enough items"));
+
+ return Undefined();
+ }
+
+ static Handle<Value> GetItems(Local<String> property, const AccessorInfo &info) {
+ Inventory *wrapper = Unwrap<Inventory>(info.Holder());
+ return Integer::New(wrapper->inv->getItems());
+ }
+
+ static Handle<Value> Reshelve(const Arguments &args) {
+ Inventory *wrapper = Unwrap<Inventory>(args.Holder());
+
+ Handle<Function> cb = Handle<Function>::Cast(args[0]);
+
+ ReshelveBaton *baton = new ReshelveBaton();
+ baton->request.data = baton;
+ baton->callback = Persistent<Function>::New(cb);
+ baton->wrapper = wrapper;
+
+ uv_queue_work(Loop(), &baton->request, ReshelveAsync, ReshelveAsyncAfter);
+
+ return Undefined();
+ }
+
+ static void ReshelveAsync(uv_work_t *req) {
+ // This runs in a separate thread
+ // NO V8 interaction should be done
+ ReshelveBaton *baton = static_cast<ReshelveBaton*>(req->data);
+ // if you want to modify baton values
+ // do synchronous work here
+ baton->wrapper->inv->reshelve();
+ }
+
+ static void ReshelveAsyncAfter(uv_work_t *req) {
+ ReshelveBaton *baton = static_cast<ReshelveBaton*>(req->data);
+ Handle<Value> argv[] = { Null() }; // no error
+ baton->callback->Call(Context::GetCurrent()->Global(), 1, argv);
+
+ baton->callback.Dispose();
+ delete baton;
+ }
+
+private:
+ Library::Inventory *inv;
+};
+
+extern "C" {
+ static void Init(Handle<Object> target) {
+ HandleScope scope;
+
+ Handle<FunctionTemplate> inventoryTpl =
+ FunctionTemplate::New(Inventory::New);
+
+ Handle<ObjectTemplate> instance =
+ inventoryTpl->InstanceTemplate();
+
+ instance->SetInternalFieldCount(1);
+
+ instance->SetAccessor(String::New("items"), Inventory::GetItems);
+
+ NODE_SET_PROTOTYPE_METHOD(inventoryTpl, "addStock", Inventory::AddStock);
+ NODE_SET_PROTOTYPE_METHOD(inventoryTpl, "ship", Inventory::Ship);
+ NODE_SET_PROTOTYPE_METHOD(inventoryTpl, "reshelve", Inventory::Reshelve);
+
+ target->Set(String::NewSymbol("Inventory"),
+ inventoryTpl->GetFunction());
+ }
+ NODE_MODULE(async, Init)
+}
+}
View
10 async/test.js
@@ -0,0 +1,10 @@
+var inv = new (require('./build/Release/async')).Inventory()
+
+inv.reshelve(function() {
+ console.log("Reshelving done");
+})
+console.log("After reshelve in source");
+for (var i = 1; i < 5; i++)
+ setTimeout(function() {
+ console.log("Tick");
+ }, i*1000);
View
13 async/wscript
@@ -0,0 +1,13 @@
+import Options
+
+def set_options(opt):
+ opt.tool_options("compiler_cxx")
+
+def configure(conf):
+ conf.check_tool("compiler_cxx")
+ conf.check_tool("node_addon")
+
+def build(bld):
+ obj = bld.new_task_gen("cxx", "shlib", "node_addon")
+ obj.target = "async"
+ obj.source = "main.cc"

0 comments on commit 9d226b2

Please sign in to comment.