-
Notifications
You must be signed in to change notification settings - Fork 4
/
delay.cc
117 lines (91 loc) · 3 KB
/
delay.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <unistd.h>
#include <node.h>
#include <string.h>
#include <v8.h>
#include <chrono>
#include <uv.h>
#include <sys/types.h>
#include <unistd.h>
using namespace v8;
unsigned long long count = 0;
// native blocking/compute intensive function
void delay(int seconds) {
int i;
int j;
// a long computation
for(i=0;i<2000000;++i) {
for(j=0;j<400;++j) {
count = count * seconds;
}
}
/**
* or a blocking call
* sleep(seconds);
*/
}
// the 'baton' is the carrier for data between functions
struct DelayBaton
{
// required
uv_work_t request; // libuv
Persistent<Function> callback; // javascript callback
// optional : data goes here.
// data that doesn't go back to javascript can be any typedef
// data that goes back to javascript needs to be a supported type
int seconds;
char greeting[256];
};
// called by libuv worker in separate thread
static void DelayAsync(uv_work_t *req)
{
DelayBaton *baton = static_cast<DelayBaton *>(req->data);
delay(baton->seconds);
}
// called by libuv in event loop when async function completes
static void DelayAsyncAfter(uv_work_t *req,int status)
{
// get the reference to the baton from the request
DelayBaton *baton = static_cast<DelayBaton *>(req->data);
// set up return arguments
Handle<Value> argv[] =
{
Handle<Value>(Int32::New(baton->seconds)),
Handle<Value>(String::New(baton->greeting))
};
// execute the callback
baton->callback->Call(Isolate::GetCurrent()->GetCurrentContext()->Global(),2,argv);
// dispose the callback object from the baton
baton->callback.Dispose();
// delete the baton object
delete baton;
}
// javascript callable function
Handle<Value> Delay(const Arguments &args)
{
// create 'baton' data carrier
DelayBaton *baton = new DelayBaton;
// get callback argument
Handle<Function> cb = Handle<Function>::Cast(args[2]);
// attach baton to uv work request
baton->request.data = baton;
// assign incoming arguments to baton
baton->seconds = args[0]->Int32Value();
// point at the argument as a string, then copy it to the baton
v8::String::Utf8Value str(args[1]);
strncpy(baton->greeting,*str,sizeof(baton->greeting));
// assign callback to baton
baton->callback = Persistent<Function>::New(cb);
// queue the async function to the event loop
// the uv default loop is the node.js event loop
uv_queue_work(uv_default_loop(),&baton->request,DelayAsync,DelayAsyncAfter);
// nothing returned
return Undefined();
}
void init(Handle<Object> exports) {
// add the async function to the exports for this object
exports->Set(
String::NewSymbol("delay"), // javascript function name
FunctionTemplate::New(Delay)->GetFunction() // attach 'Delay' function to javascript name
);
}
NODE_MODULE(delay, init)