Skip to content

Commit 4b461ad

Browse files
committed
initial pass of async example, Monte Carlo π est
1 parent c779cc0 commit 4b461ad

File tree

4 files changed

+147
-0
lines changed

4 files changed

+147
-0
lines changed

9_async_work/addon.cc

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#include <node.h>
2+
#include <cstdlib>
3+
4+
using namespace v8;
5+
6+
double Estimate (int points) {
7+
int i = points;
8+
int inside = 0;
9+
unsigned int seed = rand();
10+
double r1, r2;
11+
12+
while (i-- > 0) {
13+
r1 = rand_r(&seed) / (double)RAND_MAX;
14+
r2 = rand_r(&seed) / (double)RAND_MAX;
15+
16+
if ((r1 * r1) + (r2 * r2) <= 1)
17+
inside++;
18+
}
19+
20+
21+
return (inside / (double)points) * 4;
22+
}
23+
24+
Handle<Value> CalculateSync(const Arguments& args) {
25+
Isolate* isolate = Isolate::GetCurrent();
26+
HandleScope scope(isolate);
27+
28+
int points = args[0]->Uint32Value();
29+
double est = Estimate(points);
30+
31+
return scope.Close(Number::New(est));
32+
}
33+
34+
typedef struct AsyncData {
35+
int points;
36+
Persistent<Function> callback;
37+
double estimate;
38+
} AsyncData;
39+
40+
void AsyncWork(uv_work_t *req) {
41+
AsyncData *asyncData = (AsyncData *)req->data;
42+
asyncData->estimate = Estimate(asyncData->points);
43+
}
44+
45+
void AsyncAfter(uv_work_t *req) {
46+
Isolate* isolate = Isolate::GetCurrent();
47+
HandleScope scope(isolate);
48+
49+
AsyncData *asyncData = (AsyncData *)req->data;
50+
Handle<Value> argv[] = {
51+
Null(),
52+
Number::New(isolate, asyncData->estimate)
53+
};
54+
55+
TryCatch try_catch;
56+
asyncData->callback->Call(Context::GetCurrent()->Global(), 2, argv);
57+
asyncData->callback.Dispose(isolate);
58+
delete asyncData;
59+
delete req;
60+
if (try_catch.HasCaught())
61+
node::FatalException(try_catch);
62+
}
63+
64+
Handle<Value> CalculateAsync(const Arguments& args) {
65+
Isolate* isolate = Isolate::GetCurrent();
66+
HandleScope scope(isolate);
67+
68+
uv_work_t *req = new uv_work_t;
69+
AsyncData *asyncData = new AsyncData;
70+
req->data = asyncData;
71+
asyncData->points = args[0]->Uint32Value();
72+
Local<Function> callback = Local<Function>::Cast(args[1]);
73+
asyncData->callback = Persistent<Function>::New(isolate, callback);
74+
75+
uv_queue_work(
76+
uv_default_loop()
77+
, req
78+
, AsyncWork
79+
, (uv_after_work_cb)AsyncAfter
80+
);
81+
82+
return scope.Close(Undefined());
83+
}
84+
85+
void InitAll(Handle<Object> exports) {
86+
exports->Set(String::NewSymbol("calculateSync"),
87+
FunctionTemplate::New(CalculateSync)->GetFunction());
88+
89+
exports->Set(String::NewSymbol("calculateAsync"),
90+
FunctionTemplate::New(CalculateAsync)->GetFunction());
91+
}
92+
93+
NODE_MODULE(addon, InitAll)

9_async_work/addon.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
var addon = require('./build/Release/addon');
2+
var calculations = process.argv[2] || 100000000;
3+
4+
function printResult(type, pi, ms) {
5+
console.log(type, 'method:')
6+
console.log('\tπ ≈ ' + pi
7+
+ ' (' + Math.abs(pi - Math.PI) + ' away from actual)')
8+
console.log('\tTook ' + ms + 'ms');
9+
console.log()
10+
}
11+
12+
function runSync () {
13+
var start = Date.now();
14+
var result = addon.calculateSync(calculations);
15+
printResult('Sync', result, Date.now() - start)
16+
}
17+
18+
function runAsync () {
19+
var batches = process.argv[3] || 16;
20+
var ended = 0;
21+
var total = 0;
22+
var start = Date.now();
23+
24+
function done (err, result) {
25+
total += result;
26+
27+
if (++ended == batches) {
28+
printResult('Async', total / batches, Date.now() - start)
29+
}
30+
}
31+
32+
for (var i = 0; i < batches; i++) {
33+
addon.calculateAsync(calculations / batches, done);
34+
}
35+
}
36+
37+
runSync()
38+
runAsync()

9_async_work/binding.gyp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"targets": [
3+
{
4+
"target_name": "addon",
5+
"sources": [ "addon.cc" ]
6+
}
7+
]
8+
}

9_async_work/package.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "async_work",
3+
"version": "0.0.0",
4+
"description": "Node.js Addons Example #9",
5+
"main": "addon.js",
6+
"private": true,
7+
"gypfile": true
8+
}

0 commit comments

Comments
 (0)