@@ -241,6 +241,12 @@ NODE_MODULE_INIT(/* exports, module, context */) {
241
241
242
242
#### Worker support
243
243
244
+ In order to be loaded from multiple Node.js environments,
245
+ such as a main thread and a Worker thread, an add-on needs to either:
246
+
247
+ * Be an N-API addon, or
248
+ * Be declared as context-aware using ` NODE_MODULE_INIT() ` as described above
249
+
244
250
In order to support [ ` Worker ` ] [ ] threads, addons need to clean up any resources
245
251
they may have allocated when such a thread exists. This can be achieved through
246
252
the usage of the ` AddEnvironmentCleanupHook() ` function:
@@ -254,13 +260,62 @@ void AddEnvironmentCleanupHook(v8::Isolate* isolate,
254
260
This function adds a hook that will run before a given Node.js instance shuts
255
261
down. If necessary, such hooks can be removed using
256
262
`RemoveEnvironmentCleanupHook()` before they are run, which has the same
257
- signature.
263
+ signature. Callbacks are run in last-in first-out order.
258
264
259
- In order to be loaded from multiple Node.js environments,
260
- such as a main thread and a Worker thread, an add-on needs to either:
265
+ The following `addon.cc` uses `AddEnvironmentCleanupHook`:
261
266
262
- * Be an N-API addon, or
263
- * Be declared as context-aware using `NODE_MODULE_INIT()` as described above
267
+ ```cpp
268
+ // addon.cc
269
+ #include <assert.h>
270
+ #include <stdlib.h>
271
+ #include <node.h>
272
+
273
+ using node::AddEnvironmentCleanupHook;
274
+ using v8::HandleScope;
275
+ using v8::Isolate;
276
+ using v8::Local;
277
+ using v8::Object;
278
+
279
+ // Note: In a real-world application, do not rely on static/global data.
280
+ static char cookie[] = "yum yum";
281
+ static int cleanup_cb1_called = 0;
282
+ static int cleanup_cb2_called = 0;
283
+
284
+ static void cleanup_cb1(void* arg) {
285
+ Isolate* isolate = static_cast<Isolate*>(arg);
286
+ HandleScope scope(isolate);
287
+ Local<Object> obj = Object::New(isolate);
288
+ assert(!obj.IsEmpty()); // assert VM is still alive
289
+ assert(obj->IsObject());
290
+ cleanup_cb1_called++;
291
+ }
292
+
293
+ static void cleanup_cb2(void* arg) {
294
+ assert(arg == static_cast<void*>(cookie));
295
+ cleanup_cb2_called++;
296
+ }
297
+
298
+ static void sanity_check(void*) {
299
+ assert(cleanup_cb1_called == 1);
300
+ assert(cleanup_cb2_called == 1);
301
+ }
302
+
303
+ // Initialize this addon to be context-aware.
304
+ NODE_MODULE_INIT(/* exports, module, context */) {
305
+ Isolate* isolate = context->GetIsolate();
306
+
307
+ AddEnvironmentCleanupHook(isolate, sanity_check, nullptr);
308
+ AddEnvironmentCleanupHook(isolate, cleanup_cb2, cookie);
309
+ AddEnvironmentCleanupHook(isolate, cleanup_cb1, isolate);
310
+ }
311
+ ```
312
+
313
+ Test in JavaScript by running:
314
+
315
+ ``` js
316
+ // test.js
317
+ require (' ./build/Release/addon' );
318
+ ```
264
319
265
320
### Building
266
321
@@ -1293,85 +1348,6 @@ console.log(result);
1293
1348
// Prints: 30
1294
1349
```
1295
1350
1296
- ### AtExit hooks
1297
-
1298
- An ` AtExit ` hook is a function that is invoked after the Node.js event loop
1299
- has ended but before the JavaScript VM is terminated and Node.js shuts down.
1300
- ` AtExit ` hooks are registered using the ` node::AtExit ` API.
1301
-
1302
- #### void AtExit(callback, args)
1303
-
1304
- * ` callback ` <span class =" type " >< ; void (\* )(void\* )> ; </span >
1305
- A pointer to the function to call at exit.
1306
- * ` args ` <span class =" type " >< ; void\* > ; </span >
1307
- A pointer to pass to the callback at exit.
1308
-
1309
- Registers exit hooks that run after the event loop has ended but before the VM
1310
- is killed.
1311
-
1312
- ` AtExit ` takes two parameters: a pointer to a callback function to run at exit,
1313
- and a pointer to untyped context data to be passed to that callback.
1314
-
1315
- Callbacks are run in last-in first-out order.
1316
-
1317
- The following ` addon.cc ` implements ` AtExit ` :
1318
-
1319
- ``` cpp
1320
- // addon.cc
1321
- #include < assert.h>
1322
- #include < stdlib.h>
1323
- #include < node.h>
1324
-
1325
- namespace demo {
1326
-
1327
- using node::AtExit;
1328
- using v8::HandleScope;
1329
- using v8::Isolate;
1330
- using v8::Local;
1331
- using v8::Object;
1332
-
1333
- static char cookie[ ] = "yum yum";
1334
- static int at_exit_cb1_called = 0;
1335
- static int at_exit_cb2_called = 0;
1336
-
1337
- static void at_exit_cb1(void* arg) {
1338
- Isolate* isolate = static_cast<Isolate* >(arg);
1339
- HandleScope scope(isolate);
1340
- Local<Object > obj = Object::New(isolate);
1341
- assert(!obj.IsEmpty()); // assert VM is still alive
1342
- assert(obj->IsObject());
1343
- at_exit_cb1_called++;
1344
- }
1345
-
1346
- static void at_exit_cb2(void* arg) {
1347
- assert(arg == static_cast<void* >(cookie));
1348
- at_exit_cb2_called++;
1349
- }
1350
-
1351
- static void sanity_check(void* ) {
1352
- assert(at_exit_cb1_called == 1);
1353
- assert(at_exit_cb2_called == 2);
1354
- }
1355
-
1356
- void init(Local<Object > exports) {
1357
- AtExit(sanity_check);
1358
- AtExit(at_exit_cb2, cookie);
1359
- AtExit(at_exit_cb2, cookie);
1360
- AtExit(at_exit_cb1, exports->GetIsolate());
1361
- }
1362
-
1363
- NODE_MODULE(NODE_GYP_MODULE_NAME, init)
1364
-
1365
- } // namespace demo
1366
- ```
1367
-
1368
- Test in JavaScript by running:
1369
-
1370
- ```js
1371
- // test.js
1372
- require('./build/Release/addon');
1373
- ```
1374
-
1375
1351
[ `Worker`]: worker_threads.html#worker_threads_class_worker
1376
1352
[Electron]: https:// electronjs.org/
1377
1353
[Embedder' s Guide]: https://github.com/v8/v8/wiki/Embedder' s%20Guide
0 commit comments