18c339a94Sopenharmony_ci# Thread-safe Functions 28c339a94Sopenharmony_ci 38c339a94Sopenharmony_ciJavaScript functions can normally only be called from a native addon's main 48c339a94Sopenharmony_cithread. If an addon creates additional threads, then node-addon-api functions 58c339a94Sopenharmony_cithat require a `Napi::Env`, `Napi::Value`, or `Napi::Reference` must not be 68c339a94Sopenharmony_cicalled from those threads. 78c339a94Sopenharmony_ci 88c339a94Sopenharmony_ciWhen an addon has additional threads and JavaScript functions need to be invoked 98c339a94Sopenharmony_cibased on the processing completed by those threads, those threads must 108c339a94Sopenharmony_cicommunicate with the addon's main thread so that the main thread can invoke the 118c339a94Sopenharmony_ciJavaScript function on their behalf. The thread-safe function APIs provide an 128c339a94Sopenharmony_cieasy way to do this. These APIs provide two types -- 138c339a94Sopenharmony_ci[`Napi::ThreadSafeFunction`](threadsafe_function.md) and 148c339a94Sopenharmony_ci[`Napi::TypedThreadSafeFunction`](typed_threadsafe_function.md) -- as well as 158c339a94Sopenharmony_ciAPIs to create, destroy, and call objects of this type. The differences between 168c339a94Sopenharmony_cithe two are subtle and are [highlighted below](#implementation-differences). 178c339a94Sopenharmony_ciRegardless of which type you choose, the APIs between the two are similar. 188c339a94Sopenharmony_ci 198c339a94Sopenharmony_ci`Napi::[Typed]ThreadSafeFunction::New()` creates a persistent reference that 208c339a94Sopenharmony_ciholds a JavaScript function which can be called from multiple threads. The calls 218c339a94Sopenharmony_cihappen asynchronously. This means that values with which the JavaScript callback 228c339a94Sopenharmony_ciis to be called will be placed in a queue, and, for each value in the queue, a 238c339a94Sopenharmony_cicall will eventually be made to the JavaScript function. 248c339a94Sopenharmony_ci 258c339a94Sopenharmony_ci`Napi::[Typed]ThreadSafeFunction` objects are destroyed when every thread which 268c339a94Sopenharmony_ciuses the object has called `Release()` or has received a return status of 278c339a94Sopenharmony_ci`napi_closing` in response to a call to `BlockingCall()` or `NonBlockingCall()`. 288c339a94Sopenharmony_ciThe queue is emptied before the `Napi::[Typed]ThreadSafeFunction` is destroyed. 298c339a94Sopenharmony_ciIt is important that `Release()` be the last API call made in conjunction with a 308c339a94Sopenharmony_cigiven `Napi::[Typed]ThreadSafeFunction`, because after the call completes, there 318c339a94Sopenharmony_ciis no guarantee that the `Napi::[Typed]ThreadSafeFunction` is still allocated. 328c339a94Sopenharmony_ciFor the same reason it is also important that no more use be made of a 338c339a94Sopenharmony_cithread-safe function after receiving a return value of `napi_closing` in 348c339a94Sopenharmony_ciresponse to a call to `BlockingCall()` or `NonBlockingCall()`. Data associated 358c339a94Sopenharmony_ciwith the `Napi::[Typed]ThreadSafeFunction` can be freed in its `Finalizer` 368c339a94Sopenharmony_cicallback which was passed to `[Typed]ThreadSafeFunction::New()`. 378c339a94Sopenharmony_ci 388c339a94Sopenharmony_ciOnce the number of threads making use of a `Napi::[Typed]ThreadSafeFunction` 398c339a94Sopenharmony_cireaches zero, no further threads can start making use of it by calling 408c339a94Sopenharmony_ci`Acquire()`. In fact, all subsequent API calls associated with it, except 418c339a94Sopenharmony_ci`Release()`, will return an error value of `napi_closing`. 428c339a94Sopenharmony_ci 438c339a94Sopenharmony_ci## Implementation Differences 448c339a94Sopenharmony_ci 458c339a94Sopenharmony_ciThe choice between `Napi::ThreadSafeFunction` and 468c339a94Sopenharmony_ci`Napi::TypedThreadSafeFunction` depends largely on how you plan to execute your 478c339a94Sopenharmony_cinative C++ code (the "callback") on the Node.js thread. 488c339a94Sopenharmony_ci 498c339a94Sopenharmony_ci### [`Napi::ThreadSafeFunction`](threadsafe_function.md) 508c339a94Sopenharmony_ci 518c339a94Sopenharmony_ciThis API is designed without Node-API 5 native support for [the optional JavaScript 528c339a94Sopenharmony_ci function callback feature](/node/commit/53297e66cb). 538c339a94Sopenharmony_ci 548c339a94Sopenharmony_ciThis API has some dynamic functionality, in that: 558c339a94Sopenharmony_ci- The `[Non]BlockingCall()` methods provide a `Napi::Function` parameter as the 568c339a94Sopenharmony_ci callback to run when processing the data item on the main thread -- the 578c339a94Sopenharmony_ci `CallJs` callback. Since the callback is a parameter, it can be changed for 588c339a94Sopenharmony_ci every call. 598c339a94Sopenharmony_ci- Different C++ data types may be passed with each call of `[Non]BlockingCall()` 608c339a94Sopenharmony_ci to match the specific data type as specified in the `CallJs` callback. 618c339a94Sopenharmony_ci 628c339a94Sopenharmony_ciNote that this functionality comes with some **additional overhead** and 638c339a94Sopenharmony_cisituational **memory leaks**: 648c339a94Sopenharmony_ci- The API acts as a "broker" between the underlying `napi_threadsafe_function`, 658c339a94Sopenharmony_ci and dynamically constructs a wrapper for your callback on the heap for every 668c339a94Sopenharmony_ci call to `[Non]BlockingCall()`. 678c339a94Sopenharmony_ci- In acting in this "broker" fashion, the API will call the underlying "make 688c339a94Sopenharmony_ci call" Node-API method on this packaged item. If the API has determined the 698c339a94Sopenharmony_ci thread-safe function is no longer accessible (eg. all threads have released 708c339a94Sopenharmony_ci yet there are still items on the queue), **the callback passed to 718c339a94Sopenharmony_ci [Non]BlockingCall will not execute**. This means it is impossible to perform 728c339a94Sopenharmony_ci clean-up for calls that never execute their `CallJs` callback. **This may lead 738c339a94Sopenharmony_ci to memory leaks** if you are dynamically allocating memory. 748c339a94Sopenharmony_ci- The `CallJs` does not receive the thread-safe function's context as a 758c339a94Sopenharmony_ci parameter. In order for the callback to access the context, it must have a 768c339a94Sopenharmony_ci reference to either (1) the context directly, or (2) the thread-safe function 778c339a94Sopenharmony_ci to call `GetContext()`. Furthermore, the `GetContext()` method is not 788c339a94Sopenharmony_ci _type-safe_, as the method returns an object that can be "any-casted", instead 798c339a94Sopenharmony_ci of having a static type. 808c339a94Sopenharmony_ci 818c339a94Sopenharmony_ci### [`Napi::TypedThreadSafeFunction`](typed_threadsafe_function.md) 828c339a94Sopenharmony_ci 838c339a94Sopenharmony_ciThe `TypedThreadSafeFunction` class is a new implementation to address the 848c339a94Sopenharmony_cidrawbacks listed above. The API is designed with Node-API 5's support of an 858c339a94Sopenharmony_cioptional function callback. The API will correctly allow developers to pass 868c339a94Sopenharmony_ci`std::nullptr` instead of a `const Function&` for the callback function 878c339a94Sopenharmony_cispecified in `::New`. It also provides helper APIs to _target_ Node-API 4 and 888c339a94Sopenharmony_ciconstruct a no-op `Function` **or** to target Node-API 5 and "construct" a 898c339a94Sopenharmony_ci`std::nullptr` callback. This allows a single codebase to use the same APIs, 908c339a94Sopenharmony_ciwith just a switch of the `NAPI_VERSION` compile-time constant. 918c339a94Sopenharmony_ci 928c339a94Sopenharmony_ciThe removal of the dynamic call functionality has the following implications: 938c339a94Sopenharmony_ci- The API does _not_ act as a "broker" compared to the 948c339a94Sopenharmony_ci `Napi::ThreadSafeFunction`. Once Node.js finalizes the thread-safe function, 958c339a94Sopenharmony_ci the `CallJs` callback will execute with an empty `Napi::Env` for any remaining 968c339a94Sopenharmony_ci items on the queue. This provides the ability to handle any necessary cleanup 978c339a94Sopenharmony_ci of the item's data. 988c339a94Sopenharmony_ci- The callback _does_ receive the context as a parameter, so a call to 998c339a94Sopenharmony_ci `GetContext()` is _not_ necessary. This context type is specified as the 1008c339a94Sopenharmony_ci **first template argument** specified to `::New`, ensuring type safety. 1018c339a94Sopenharmony_ci- The `New()` constructor accepts the `CallJs` callback as the **second type 1028c339a94Sopenharmony_ci argument**. The callback must be statically defined for the API to access it. 1038c339a94Sopenharmony_ci This affords the ability to statically pass the context as the correct type 1048c339a94Sopenharmony_ci across all methods. 1058c339a94Sopenharmony_ci- Only one C++ data type may be specified to every call to `[Non]BlockingCall()` 1068c339a94Sopenharmony_ci -- the **third template argument** specified to `::New`. Any "dynamic call 1078c339a94Sopenharmony_ci data" must be implemented by the user. 1088c339a94Sopenharmony_ci 1098c339a94Sopenharmony_ci 1108c339a94Sopenharmony_ci### Usage Suggestions 1118c339a94Sopenharmony_ci 1128c339a94Sopenharmony_ciIn summary, it may be best to use `Napi::TypedThreadSafeFunction` if: 1138c339a94Sopenharmony_ci 1148c339a94Sopenharmony_ci- static, compile-time support for targeting Node-API 4 or 5+ with an optional 1158c339a94Sopenharmony_ci JavaScript callback feature is desired; 1168c339a94Sopenharmony_ci- the callback can have `static` storage class and will not change across calls 1178c339a94Sopenharmony_ci to `[Non]BlockingCall()`; 1188c339a94Sopenharmony_ci- cleanup of items' data is required (eg. deleting dynamically-allocated data 1198c339a94Sopenharmony_ci that is created at the caller level). 1208c339a94Sopenharmony_ci 1218c339a94Sopenharmony_ciOtherwise, `Napi::ThreadSafeFunction` may be a better choice. 122