@@ -118,9 +118,9 @@ To assign the hooks call:
118
118
119
119
``` javascript
120
120
asyncWrap .setupHooks (init, pre, post, destroy);
121
- function init (provider , uid , parent ) { /* consumer code */ }
122
- function pre () { /* consumer code */ }
123
- function post () { /* consumer code */ }
121
+ function init (uid , provider , parentUid , parentHandle ) { /* consumer code */ }
122
+ function pre (uid ) { /* consumer code */ }
123
+ function post (uid ) { /* consumer code */ }
124
124
function destroy (uid ) { /* consumer code */ }
125
125
```
126
126
@@ -153,21 +153,21 @@ asyncWrap.disable();
153
153
#### The Hooks
154
154
155
155
Currently there are 4 hooks: ` init ` , ` pre ` , ` post ` ` destroy ` . The ` this `
156
- variable refers to the handle object. The ` init ` hook has three extra arguments
157
- ` provider ` , ` uid ` and ` parent ` . The ` destroy ` hook also has the ` uid ` argument .
156
+ variable refers to the handle object, they all have a ` uid ` argument, finally
157
+ ` init ` provides extra information about the creation of the handle object .
158
158
159
159
``` javascript
160
- function init (provider , uid , parent ) { }
161
- function pre () { }
162
- function post () { }
160
+ function init (uid , provider , parentUid , parentHandle ) { }
161
+ function pre (uid ) { }
162
+ function post (uid ) { }
163
163
function destroy (uid ) { }
164
164
```
165
165
166
166
##### this
167
167
168
168
In the ` init ` , ` pre ` and ` post ` cases the ` this ` variable is the handle object.
169
169
Users may read properties from this object such as ` port ` and ` address ` in the
170
- ` TCPConnectWrap ` case, or set user specific properties .
170
+ ` TCPConnectWrap ` case.
171
171
172
172
In the ` init ` hook the handle object is not yet fully constructed, thus some
173
173
properties are not safe to read. This causes problems when doing
@@ -211,16 +211,20 @@ At the time of writing this is the current list:
211
211
212
212
##### uid
213
213
214
- The ` uid ` is a unique integer that identify each handle object. Because the
215
- ` destroy ` hook isn't called with the handle object, this is particular useful
216
- for storing information related to the handle object, that the user require in
217
- the ` destroy ` hook.
214
+ The ` uid ` is a unique integer that identifies each handle object. You can use
215
+ the ` uid ` to store information related to the handle object, by using it as
216
+ a key for a shared ` Map ` object.
218
217
219
- ##### parent
218
+ As such the user could also store information on the ` this ` object, but this
219
+ may be unsafe since the user could accidentally overwrite an undocumented
220
+ property. The ` this ` object is also not available in the ` destroy ` hook, thus
221
+ the ` uid ` is generally the recommended choice.
222
+
223
+ ##### parentUid
220
224
221
225
In some cases the handle was created from another handle object. In those
222
- cases the ` parent ` argument is set the creating handle object. If there is
223
- no parent handle then it is just ` null ` .
226
+ cases the ` parentUid ` argument is set to the uid of the creating handle object.
227
+ If there is no parent then it is just ` null ` .
224
228
225
229
The most common case is the TCP server. The TCP server itself is a ` TCP ` handle,
226
230
but when receiving new connection it creates another ` TCP ` handle that is
@@ -235,7 +239,11 @@ post // TCP (server)
235
239
236
240
This means it is not possible to know in what handle context the new socket
237
241
handle was created using the ` pre ` and ` post ` hooks. However the
238
- ` parent ` argument provides this information.
242
+ ` parentUid ` argument provides this information.
243
+
244
+ ##### parentHandle
245
+
246
+ This is similar to parentUid but is the actual parent handle object.
239
247
240
248
## Example
241
249
@@ -244,38 +252,47 @@ A classic use case for AsyncWrap is to create a long-stack-trace tool.
244
252
``` javascript
245
253
const asyncWrap = process .binding (' async_wrap' );
246
254
247
- asyncWrap .setupHooks (init, pre, post );
255
+ asyncWrap .setupHooks (init, before, after, destroy );
248
256
asyncWrap .enable ();
249
257
250
- // global state variable, that contains the current stack trace
251
- let currentStack = ' ' ;
258
+ // global state variable, that contains the stack traces and the current uid
259
+ const stack = new Map ();
260
+ stack .set (- 1 , ' ' );
252
261
253
- function init (provider , uid , parent ) {
262
+ let currentUid = - 1 ;
263
+
264
+ function init (uid , provider , parentUid , parentHandle ) {
254
265
// When a handle is created, collect the stack trace such that we later
255
266
// can see what involved the handle constructor.
256
267
const localStack = (new Error ()).stack .split (' \n ' ).slice (1 ).join (' \n ' );
257
268
258
- // Compute the full stack and store it as a property on the handle object,
259
- // such that it can be fetched later.
260
- const extraStack = parent ? parent ._full_init_stack : currentStack;
261
- this ._full_init_stack = localStack + ' \n ' + extraStack;
269
+ // Compute the full stack and store on the `Map` using the `uid` as key.
270
+ const extraStack = stack .get (parentUid || currentUid);
271
+ stack .set (uid, localStack + ' \n ' + extraStack);
262
272
}
263
- function pre ( ) {
264
- // A callback is about to be called, update the `currentStack ` such that
273
+ function before ( uid ) {
274
+ // A callback is about to be called, update the `currentUid ` such that
265
275
// it is correct for when another handle is initialized or `getStack` is
266
276
// called.
267
- currentStack = this . _full_init_stack ;
277
+ currentUid = uid ;
268
278
}
269
- function post ( ) {
279
+ function after ( uid ) {
270
280
// At the time of writing there are some odd cases where there is no handle
271
281
// context, this line prevents that from resulting in wrong stack trace. But
272
282
// the stack trace will be shorter compared to what ideally should happen.
273
- currentStack = ' ' ;
283
+ currentUid = - 1 ;
284
+ }
285
+
286
+ function destroy (uid ) {
287
+ // Once the handle is destroyed no other handle objects can be created with
288
+ // this handle as its immediate context. Thus its associated stack can be
289
+ // deleted.
290
+ stack .delete (uid);
274
291
}
275
292
276
293
function getStack (message ) {
277
294
const localStack = new Error (message);
278
- return localStack .stack + ' \n ' + currentStack ;
295
+ return localStack .stack + ' \n ' + stack . get (currentUid) ;
279
296
}
280
297
module .exports = getStack;
281
298
```
0 commit comments