Skip to content

Commit

Permalink
Rename to TypedThreadSafeFunction
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinEady committed Nov 24, 2020
1 parent 4abe7cf commit c24c455
Show file tree
Hide file tree
Showing 20 changed files with 196 additions and 196 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ The following is the documentation for node-addon-api.
- [AsyncWorker Variants](doc/async_worker_variants.md)
- [Thread-safe Functions](doc/threadsafe.md)
- [ThreadSafeFunction](doc/threadsafe_function.md)
- [ThreadSafeFunctionEx](doc/threadsafe_function_ex.md)
- [TypedThreadSafeFunction](doc/typed_threadsafe_function.md)
- [Promises](doc/promises.md)
- [Version management](doc/version_management.md)

Expand Down
58 changes: 29 additions & 29 deletions doc/threadsafe.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,40 +11,40 @@ communicate with the addon's main thread so that the main thread can invoke the
JavaScript function on their behalf. The thread-safe function APIs provide an
easy way to do this. These APIs provide two types --
[`Napi::ThreadSafeFunction`](threadsafe_function.md) and
[`Napi::ThreadSafeFunctionEx`](threadsafe_function_ex.md) -- as well as APIs to
create, destroy, and call objects of this type. The differences between the two
are subtle and are [highlighted below](#implementation-differences). Regardless
of which type you choose, the APIs between the two are similar.
[`Napi::TypedThreadSafeFunction`](typed_threadsafe_function.md) -- as well as
APIs to create, destroy, and call objects of this type. The differences between
the two are subtle and are [highlighted below](#implementation-differences).
Regardless of which type you choose, the APIs between the two are similar.

`Napi::ThreadSafeFunction[Ex]::New()` creates a persistent reference that holds
a JavaScript function which can be called from multiple threads. The calls
`Napi::[Typed]ThreadSafeFunction::New()` creates a persistent reference that
holds a JavaScript function which can be called from multiple threads. The calls
happen asynchronously. This means that values with which the JavaScript callback
is to be called will be placed in a queue, and, for each value in the queue, a
call will eventually be made to the JavaScript function.

`Napi::ThreadSafeFunction[Ex]` objects are destroyed when every thread which
`Napi::[Typed]ThreadSafeFunction` objects are destroyed when every thread which
uses the object has called `Release()` or has received a return status of
`napi_closing` in response to a call to `BlockingCall()` or `NonBlockingCall()`.
The queue is emptied before the `Napi::ThreadSafeFunction[Ex]` is destroyed. It
is important that `Release()` be the last API call made in conjunction with a
given `Napi::ThreadSafeFunction[Ex]`, because after the call completes, there is
no guarantee that the `Napi::ThreadSafeFunction[Ex]` is still allocated. For the
same reason it is also important that no more use be made of a thread-safe
function after receiving a return value of `napi_closing` in response to a call
to `BlockingCall()` or `NonBlockingCall()`. Data associated with the
`Napi::ThreadSafeFunction[Ex]` can be freed in its `Finalizer` callback which
was passed to `ThreadSafeFunction[Ex]::New()`.

Once the number of threads making use of a `Napi::ThreadSafeFunction[Ex]`
The queue is emptied before the `Napi::[Typed]ThreadSafeFunction` is destroyed.
It is important that `Release()` be the last API call made in conjunction with a
given `Napi::[Typed]ThreadSafeFunction`, because after the call completes, there
is no guarantee that the `Napi::[Typed]ThreadSafeFunction` is still allocated.
For the same reason it is also important that no more use be made of a
thread-safe function after receiving a return value of `napi_closing` in
response to a call to `BlockingCall()` or `NonBlockingCall()`. Data associated
with the `Napi::[Typed]ThreadSafeFunction` can be freed in its `Finalizer`
callback which was passed to `[Typed]ThreadSafeFunction::New()`.

Once the number of threads making use of a `Napi::[Typed]ThreadSafeFunction`
reaches zero, no further threads can start making use of it by calling
`Acquire()`. In fact, all subsequent API calls associated with it, except
`Release()`, will return an error value of `napi_closing`.

## Implementation Differences

The choice between `Napi::ThreadSafeFunction` and `Napi::ThreadSafeFunctionEx`
depends largely on how you plan to execute your native C++ code (the "callback")
on the Node.js thread.
The choice between `Napi::ThreadSafeFunction` and
`Napi::TypedThreadSafeFunction` depends largely on how you plan to execute your
native C++ code (the "callback") on the Node.js thread.

### [`Napi::ThreadSafeFunction`](threadsafe_function.md)

Expand All @@ -64,13 +64,13 @@ This API has some dynamic functionality, in that:

Note that this functionality comes with some **additional overhead** and
situational **memory leaks**:
- The API acts as a "broker" between the underlying
`napi_threadsafe_function`, and dynamically constructs a wrapper for your
callback on the heap for every call to `[Non]BlockingCall()`.
- The API acts as a "broker" between the underlying `napi_threadsafe_function`,
and dynamically constructs a wrapper for your callback on the heap for every
call to `[Non]BlockingCall()`.
- In acting in this "broker" fashion, the API will call the underlying "make
call" N-API method on this packaged item. If the API has determined the
thread-safe function is no longer accessible (eg. all threads have released yet
there are still items on the queue), **the callback passed to
thread-safe function is no longer accessible (eg. all threads have released
yet there are still items on the queue), **the callback passed to
[Non]BlockingCall will not execute**. This means it is impossible to perform
clean-up for calls that never execute their `CallJs` callback. **This may lead
to memory leaks** if you are dynamically allocating memory.
Expand All @@ -81,9 +81,9 @@ situational **memory leaks**:
_type-safe_, as the method returns an object that can be "any-casted", instead
of having a static type.

### [`Napi::ThreadSafeFunctionEx`](threadsafe_function_ex.md)
### [`Napi::TypedThreadSafeFunction`](typed_threadsafe_function.md)

The `ThreadSafeFunctionEx` class is a new implementation to address the
The `TypedThreadSafeFunction` class is a new implementation to address the
drawbacks listed above. The API is designed with N-API 5's support of an
optional function callback. The API will correctly allow developers to pass
`std::nullptr` instead of a `const Function&` for the callback function
Expand Down Expand Up @@ -112,7 +112,7 @@ The removal of the dynamic call functionality has the following implications:

### Usage Suggestions

In summary, it may be best to use `Napi::ThreadSafeFunctionEx` if:
In summary, it may be best to use `Napi::TypedThreadSafeFunction` if:

- static, compile-time support for targeting N-API 4 or 5+ with an optional
JavaScript callback feature is desired;
Expand Down
74 changes: 37 additions & 37 deletions doc/threadsafe_function_ex.md → doc/typed_threadsafe_function.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# ThreadSafeFunctionEx

The `Napi::ThreadSafeFunctionEx` type provides APIs for threads to communicate
with the addon's main thread to invoke JavaScript functions on their behalf. The
type is a three-argument templated class, each argument representing the type
of:
- `ContextType = std::nullptr_t`: The thread-safe function's context. By default,
a TSFN has no context.
# TypedThreadSafeFunction

The `Napi::TypedThreadSafeFunction` type provides APIs for threads to
communicate with the addon's main thread to invoke JavaScript functions on their
behalf. The type is a three-argument templated class, each argument representing
the type of:
- `ContextType = std::nullptr_t`: The thread-safe function's context. By
default, a TSFN has no context.
- `DataType = void*`: The data to use in the native callback. By default, a TSFN
can accept any data type.
- `Callback = void(*)(Napi::Env, Napi::Function jsCallback, ContextType*,
Expand All @@ -21,31 +21,31 @@ APIs](threadsafe.md#implementation-differences).

### Constructor

Creates a new empty instance of `Napi::ThreadSafeFunctionEx`.
Creates a new empty instance of `Napi::TypedThreadSafeFunction`.

```cpp
Napi::Function::ThreadSafeFunctionEx<ContextType, DataType, Callback>::ThreadSafeFunctionEx();
Napi::Function::TypedThreadSafeFunction<ContextType, DataType, Callback>::TypedThreadSafeFunction();
```

### Constructor

Creates a new instance of the `Napi::ThreadSafeFunctionEx` object.
Creates a new instance of the `Napi::TypedThreadSafeFunction` object.

```cpp
Napi::ThreadSafeFunctionEx<ContextType, DataType, Callback>::ThreadSafeFunctionEx(napi_threadsafe_function tsfn);
Napi::TypedThreadSafeFunction<ContextType, DataType, Callback>::TypedThreadSafeFunction(napi_threadsafe_function tsfn);
```

- `tsfn`: The `napi_threadsafe_function` which is a handle for an existing
thread-safe function.

Returns a non-empty `Napi::ThreadSafeFunctionEx` instance. To ensure the API
Returns a non-empty `Napi::TypedThreadSafeFunction` instance. To ensure the API
statically handles the correct return type for `GetContext()` and
`[Non]BlockingCall()`, pass the proper template arguments to
`Napi::ThreadSafeFunctionEx`.
`Napi::TypedThreadSafeFunction`.

### New

Creates a new instance of the `Napi::ThreadSafeFunctionEx` object. The `New`
Creates a new instance of the `Napi::TypedThreadSafeFunction` object. The `New`
function has several overloads for the various optional parameters: skip the
optional parameter for that specific overload.

Expand All @@ -72,11 +72,11 @@ New(napi_env env,
- `maxQueueSize`: Maximum size of the queue. `0` for no limit.
- `initialThreadCount`: The initial number of threads, including the main
thread, which will be making use of this function.
- `[optional] context`: Data to attach to the resulting `ThreadSafeFunction`.
It can be retreived via `GetContext()`.
- `[optional] context`: Data to attach to the resulting `ThreadSafeFunction`. It
can be retreived via `GetContext()`.
- `[optional] finalizeCallback`: Function to call when the
`ThreadSafeFunctionEx` is being destroyed. This callback will be invoked on
the main thread when the thread-safe function is about to be destroyed. It
`TypedThreadSafeFunction` is being destroyed. This callback will be invoked
on the main thread when the thread-safe function is about to be destroyed. It
receives the context and the finalize data given during construction (if
given), and provides an opportunity for cleaning up after the threads e.g. by
calling `uv_thread_join()`. It is important that, aside from the main loop
Expand All @@ -85,15 +85,15 @@ New(napi_env env,
FinalizerDataType* data, ContextType* hint)`.
- `[optional] data`: Data to be passed to `finalizeCallback`.
Returns a non-empty `Napi::ThreadSafeFunctionEx` instance.
Returns a non-empty `Napi::TypedThreadSafeFunction` instance.
Depending on the targetted `NAPI_VERSION`, the API has different implementations
for `CallbackType callback`.
When targetting version 4, `callback` may be:
- of type `const Function&`
- not provided as a parameter, in which case the API creates a new no-op
`Function`
`Function`
When targetting version 5+, `callback` may be:
- of type `const Function&`
Expand All @@ -106,7 +106,7 @@ Adds a thread to this thread-safe function object, indicating that a new thread
will start making use of the thread-safe function.
```cpp
napi_status Napi::ThreadSafeFunctionEx<ContextType, DataType, Callback>::Acquire()
napi_status Napi::TypedThreadSafeFunction<ContextType, DataType, Callback>::Acquire()
```

Returns one of:
Expand All @@ -124,7 +124,7 @@ has undefined results in the current thread, as the thread-safe function may
have been destroyed.

```cpp
napi_status Napi::ThreadSafeFunctionEx<ContextType, DataType, Callback>::Release()
napi_status Napi::TypedThreadSafeFunction<ContextType, DataType, Callback>::Release()
```

Returns one of:
Expand All @@ -135,18 +135,18 @@ Returns one of:

### Abort

"Aborts" the thread-safe function. This will cause all subsequent APIs associated
with the thread-safe function except `Release()` to return `napi_closing` even
before its reference count reaches zero. In particular, `BlockingCall` and
`NonBlockingCall()` will return `napi_closing`, thus informing the threads that
it is no longer possible to make asynchronous calls to the thread-safe function.
This can be used as a criterion for terminating the thread. Upon receiving a
return value of `napi_closing` from a thread-safe function call a thread must
make no further use of the thread-safe function because it is no longer
guaranteed to be allocated.
"Aborts" the thread-safe function. This will cause all subsequent APIs
associated with the thread-safe function except `Release()` to return
`napi_closing` even before its reference count reaches zero. In particular,
`BlockingCall` and `NonBlockingCall()` will return `napi_closing`, thus
informing the threads that it is no longer possible to make asynchronous calls
to the thread-safe function. This can be used as a criterion for terminating the
thread. Upon receiving a return value of `napi_closing` from a thread-safe
function call a thread must make no further use of the thread-safe function
because it is no longer guaranteed to be allocated.

```cpp
napi_status Napi::ThreadSafeFunctionEx<ContextType, DataType, Callback>::Abort()
napi_status Napi::TypedThreadSafeFunction<ContextType, DataType, Callback>::Abort()
```

Returns one of:
Expand All @@ -165,13 +165,13 @@ Calls the Javascript function in either a blocking or non-blocking fashion.
preventing data from being successfully added to the queue.

```cpp
napi_status Napi::ThreadSafeFunctionEx<ContextType, DataType, Callback>::BlockingCall(DataType* data = nullptr) const
napi_status Napi::TypedThreadSafeFunction<ContextType, DataType, Callback>::BlockingCall(DataType* data = nullptr) const

napi_status Napi::ThreadSafeFunctionEx<ContextType, DataType, Callback>::NonBlockingCall(DataType* data = nullptr) const
napi_status Napi::TypedThreadSafeFunction<ContextType, DataType, Callback>::NonBlockingCall(DataType* data = nullptr) const
```

- `[optional] data`: Data to pass to the callback which was passed to
`ThreadSafeFunctionEx::New()`.
`TypedThreadSafeFunction::New()`.

Returns one of:
- `napi_ok`: `data` was successfully added to the queue.
Expand All @@ -196,7 +196,7 @@ using namespace Napi;
using Context = Reference<Value>;
using DataType = int;
void CallJs(Napi::Env env, Function callback, Context *context, DataType *data);
using TSFN = ThreadSafeFunctionEx<Context, DataType, CallJs>;
using TSFN = TypedThreadSafeFunction<Context, DataType, CallJs>;
using FinalizerDataType = void;

std::thread nativeThread;
Expand Down
Loading

0 comments on commit c24c455

Please sign in to comment.