Skip to content

Commit ad9333e

Browse files
committed
test: tsfnex uses ported tsfn tests
1 parent fd6a2b4 commit ad9333e

25 files changed

+945
-2102
lines changed

doc/threadsafe_function_ex.md

Lines changed: 100 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ New(napi_env env,
8282
calling `uv_thread_join()`. It is important that, aside from the main loop
8383
thread, there be no threads left using the thread-safe function after the
8484
finalize callback completes. Must implement `void operator()(Env env,
85-
DataType* data, ContextType* hint)`.
85+
FinalizerDataType* data, ContextType* hint)`.
8686
- `[optional] data`: Data to be passed to `finalizeCallback`.
8787
8888
Returns a non-empty `Napi::ThreadSafeFunctionEx` instance.
@@ -182,56 +182,109 @@ Returns one of:
182182
- `napi_generic_failure`: A generic error occurred when attemping to add to the
183183
queue.
184184

185+
185186
## Example
186187

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');
190275
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+
```
195280

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:
197283

198284
```
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 ]
237290
```

test/binding.cc

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,12 @@ Object InitThreadSafeFunctionPtr(Env env);
4949
Object InitThreadSafeFunctionSum(Env env);
5050
Object InitThreadSafeFunctionUnref(Env env);
5151
Object InitThreadSafeFunction(Env env);
52-
Object InitThreadSafeFunctionExBasic(Env env);
53-
Object InitThreadSafeFunctionExExample(Env env);
54-
Object InitThreadSafeFunctionExThreadSafe(Env env);
52+
Object InitThreadSafeFunctionExCtx(Env env);
53+
Object InitThreadSafeFunctionExExistingTsfn(Env env);
54+
Object InitThreadSafeFunctionExPtr(Env env);
55+
Object InitThreadSafeFunctionExSum(Env env);
56+
Object InitThreadSafeFunctionExUnref(Env env);
57+
Object InitThreadSafeFunctionEx(Env env);
5558
#endif
5659
Object InitTypedArray(Env env);
5760
Object InitObjectWrap(Env env);
@@ -111,10 +114,13 @@ Object Init(Env env, Object exports) {
111114
exports.Set("threadsafe_function_ptr", InitThreadSafeFunctionPtr(env));
112115
exports.Set("threadsafe_function_sum", InitThreadSafeFunctionSum(env));
113116
exports.Set("threadsafe_function_unref", InitThreadSafeFunctionUnref(env));
114-
exports.Set("threadsafe_function", InitThreadSafeFunction(env));
115-
exports.Set("threadsafe_function_ex_basic", InitThreadSafeFunctionExBasic(env));
116-
exports.Set("threadsafe_function_ex_example", InitThreadSafeFunctionExExample(env));
117-
exports.Set("threadsafe_function_ex_threadsafe", InitThreadSafeFunctionExThreadSafe(env));
117+
exports.Set("threadsafe_function", InitThreadSafeFunctionEx(env));
118+
exports.Set("threadsafe_function_ex_ctx", InitThreadSafeFunctionExCtx(env));
119+
exports.Set("threadsafe_function_ex_existing_tsfn", InitThreadSafeFunctionExExistingTsfn(env));
120+
exports.Set("threadsafe_function_ex_ptr", InitThreadSafeFunctionExPtr(env));
121+
exports.Set("threadsafe_function_ex_sum", InitThreadSafeFunctionExSum(env));
122+
exports.Set("threadsafe_function_ex_unref", InitThreadSafeFunctionExUnref(env));
123+
exports.Set("threadsafe_function_ex", InitThreadSafeFunctionEx(env));
118124
#endif
119125
exports.Set("typedarray", InitTypedArray(env));
120126
exports.Set("objectwrap", InitObjectWrap(env));

test/binding.gyp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,12 @@
3636
'object/set_property.cc',
3737
'promise.cc',
3838
'run_script.cc',
39-
'threadsafe_function_ex/test/basic.cc',
40-
'threadsafe_function_ex/test/example.cc',
41-
'threadsafe_function_ex/test/threadsafe.cc',
39+
'threadsafe_function_ex/threadsafe_function_ctx.cc',
40+
'threadsafe_function_ex/threadsafe_function_existing_tsfn.cc',
41+
'threadsafe_function_ex/threadsafe_function_ptr.cc',
42+
'threadsafe_function_ex/threadsafe_function_sum.cc',
43+
'threadsafe_function_ex/threadsafe_function_unref.cc',
44+
'threadsafe_function_ex/threadsafe_function.cc',
4245
'threadsafe_function/threadsafe_function_ctx.cc',
4346
'threadsafe_function/threadsafe_function_existing_tsfn.cc',
4447
'threadsafe_function/threadsafe_function_ptr.cc',

test/index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,12 @@ let testModules = [
4343
'object/set_property',
4444
'promise',
4545
'run_script',
46-
'threadsafe_function_ex',
46+
'threadsafe_function_ex/threadsafe_function_ctx',
47+
'threadsafe_function_ex/threadsafe_function_existing_tsfn',
48+
'threadsafe_function_ex/threadsafe_function_ptr',
49+
'threadsafe_function_ex/threadsafe_function_sum',
50+
'threadsafe_function_ex/threadsafe_function_unref',
51+
'threadsafe_function_ex/threadsafe_function',
4752
'threadsafe_function/threadsafe_function_ctx',
4853
'threadsafe_function/threadsafe_function_existing_tsfn',
4954
'threadsafe_function/threadsafe_function_ptr',

test/threadsafe_function_ex/README.md

Lines changed: 0 additions & 3 deletions
This file was deleted.

test/threadsafe_function_ex/index.js

Lines changed: 0 additions & 13 deletions
This file was deleted.

0 commit comments

Comments
 (0)