@@ -82,7 +82,7 @@ New(napi_env env,
82
82
calling `uv_thread_join()`. It is important that, aside from the main loop
83
83
thread, there be no threads left using the thread-safe function after the
84
84
finalize callback completes. Must implement `void operator()(Env env,
85
- DataType * data, ContextType* hint)`.
85
+ FinalizerDataType * data, ContextType* hint)`.
86
86
- `[optional] data`: Data to be passed to `finalizeCallback`.
87
87
88
88
Returns a non-empty `Napi::ThreadSafeFunctionEx` instance.
@@ -182,56 +182,109 @@ Returns one of:
182
182
- ` napi_generic_failure ` : A generic error occurred when attemping to add to the
183
183
queue.
184
184
185
+
185
186
## Example
186
187
187
- For an in-line documented example, please see the ThreadSafeFunctionEx CI tests hosted here.
188
- - [ test/threadsafe_function_ex/test/example.js] ( ../test/threadsafe_function_ex/test/example.js )
189
- - [ test/threadsafe_function_ex/test/example.cc] ( ../test/threadsafe_function_ex/test/example.cc )
188
+ ``` cpp
189
+ #include < chrono>
190
+ #include < thread>
191
+ #include < napi.h>
192
+
193
+ using namespace Napi ;
194
+
195
+ std::thread nativeThread;
196
+ ThreadSafeFunction tsfn;
197
+
198
+ Value Start ( const CallbackInfo& info )
199
+ {
200
+ Napi::Env env = info.Env();
201
+
202
+ if ( info.Length() < 2 )
203
+ {
204
+ throw TypeError::New( env, "Expected two arguments" );
205
+ }
206
+ else if ( !info[ 0] .IsFunction() )
207
+ {
208
+ throw TypeError::New( env, "Expected first arg to be function" );
209
+ }
210
+ else if ( !info[ 1] .IsNumber() )
211
+ {
212
+ throw TypeError::New( env, "Expected second arg to be number" );
213
+ }
214
+
215
+ int count = info[ 1] .As<Number >().Int32Value();
216
+
217
+ // Create a ThreadSafeFunction
218
+ tsfn = ThreadSafeFunction::New(
219
+ env,
220
+ info[ 0] .As<Function >(), // JavaScript function called asynchronously
221
+ "Resource Name", // Name
222
+ 0, // Unlimited queue
223
+ 1, // Only one thread will use this initially
224
+ [ ] ( Napi::Env ) { // Finalizer used to clean threads up
225
+ nativeThread.join();
226
+ } );
227
+
228
+ // Create a native thread
229
+ nativeThread = std::thread( [ count] {
230
+ auto callback = [ ] ( Napi::Env env, Function jsCallback, int* value ) {
231
+ // Transform native data into JS data, passing it to the provided
232
+ // ` jsCallback ` -- the TSFN's JavaScript function.
233
+ jsCallback.Call( {Number::New( env, * value )} );
234
+
235
+ // We're finished with the data.
236
+ delete value;
237
+ };
238
+
239
+ for ( int i = 0; i < count; i++ )
240
+ {
241
+ // Create new data
242
+ int* value = new int( clock() );
243
+
244
+ // Perform a blocking call
245
+ napi_status status = tsfn.BlockingCall( value, callback );
246
+ if ( status != napi_ok )
247
+ {
248
+ // Handle error
249
+ break;
250
+ }
251
+
252
+ std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
253
+ }
254
+
255
+ // Release the thread-safe function
256
+ tsfn.Release();
257
+ } );
258
+
259
+ return Boolean::New(env, true);
260
+ }
261
+
262
+ Napi::Object Init( Napi::Env env, Object exports )
263
+ {
264
+ exports.Set( "start", Function::New( env, Start ) );
265
+ return exports;
266
+ }
267
+
268
+ NODE_API_MODULE( clock, Init )
269
+ ```
270
+
271
+ The above code can be used from JavaScript as follows:
272
+
273
+ ```js
274
+ const { start } = require('bindings')('clock');
190
275
191
- The example will create multiple set of threads. Each thread calls into
192
- JavaScript with a numeric ` base ` value (deterministically calculated by the
193
- thread id), with Node returning either a ` number ` or ` Promise<number> ` that
194
- resolves to ` base * base ` .
276
+ start(function () {
277
+ console.log("JavaScript callback called with arguments", Array.from(arguments));
278
+ }, 5);
279
+ ```
195
280
196
- From the root of the ` node-addon-api ` repository:
281
+ When executed, the output will show the value of ` clock() ` five times at one
282
+ second intervals:
197
283
198
284
```
199
- Usage: node ./test/threadsafe_function_ex/test/example.js [options]
200
-
201
- -c, --calls <calls> The number of calls each thread should make (number[]).
202
- -a, --acquire [factor] Acquire a new set of `factor` call threads, using the
203
- same `calls` definition.
204
- -d, --call-delay <call-delays> The delay on callback resolution that each thread should
205
- have (number[]). This is achieved via a delayed Promise
206
- resolution in the JavaScript callback provided to the
207
- TSFN. Using large delays here will cause all threads to
208
- bottle-neck.
209
- -D, --thread-delay <thread-delays> The delay that each thread should have prior to making a
210
- call (number[]). Using large delays here will cause the
211
- individual thread to bottle-neck.
212
- -l, --log-call Display console.log-based logging messages.
213
- -L, --log-thread Display std::cout-based logging messages.
214
- -n, --no-callback Do not use a JavaScript callback.
215
- -e, --callback-error [thread[.call]] Cause an error to occur in the JavaScript callback for
216
- the given thread's call (if provided; first thread's
217
- first call otherwise).
218
-
219
- When not provided:
220
- - <calls> defaults to [1,2,3,4,5]
221
- - [factor] defaults to 1
222
- - <call-delays> defaults to [400,200,100,50,0]
223
- - <thread-delays> defaults to [400,200,100,50,0]
224
-
225
-
226
- Examples:
227
-
228
- -c [1,2,3] -l -L
229
-
230
- Creates three threads that makes one, two, and three calls each, respectively.
231
-
232
- -c [5,5] -d [5000,5000] -D [0,0] -l -L
233
-
234
- Creates two threads that make five calls each. In this scenario, the threads will be
235
- blocked primarily on waiting for the callback to resolve, as each thread's call takes
236
- 5000 milliseconds.
285
+ JavaScript callback called with arguments [ 84745 ]
286
+ JavaScript callback called with arguments [ 103211 ]
287
+ JavaScript callback called with arguments [ 104516 ]
288
+ JavaScript callback called with arguments [ 105104 ]
289
+ JavaScript callback called with arguments [ 105691 ]
237
290
```
0 commit comments