Skip to content

Commit cc8de12

Browse files
committed
implement optional function callback
1 parent 8fcdb4d commit cc8de12

File tree

5 files changed

+466
-87
lines changed

5 files changed

+466
-87
lines changed

common.gypi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
'variables': {
3-
'NAPI_VERSION%': "<!(node -p \"process.versions.napi\")",
3+
'NAPI_VERSION%': "<!(node -p \"process.env['NAPI_VERSION'] || process.versions.napi\")",
44
'disable_deprecated': "<!(node -p \"process.env['npm_config_disable_deprecated']\")"
55
},
66
'conditions': [

napi-inl.h

Lines changed: 307 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4317,7 +4317,241 @@ inline void AsyncWorker::OnWorkComplete(Napi::Env /*env*/, napi_status status) {
43174317
// ThreadSafeFunctionEx<ContextType,DataType,CallJs> class
43184318
////////////////////////////////////////////////////////////////////////////////
43194319

4320-
// static
4320+
// Starting with NAPI 4, the JavaScript function `func` parameter of
4321+
// `napi_create_threadsafe_function` is optional.
4322+
#if NAPI_VERSION > 4
4323+
// static, with Callback [missing] Resource [missing] Finalizer [missing]
4324+
template <typename ContextType, typename DataType,
4325+
void (*CallJs)(Napi::Env, Napi::Function, ContextType *, DataType *)>
4326+
template <typename ResourceString>
4327+
inline ThreadSafeFunctionEx<ContextType, DataType, CallJs>
4328+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>::New(
4329+
napi_env env, ResourceString resourceName, size_t maxQueueSize,
4330+
size_t initialThreadCount, ContextType *context) {
4331+
ThreadSafeFunctionEx<ContextType, DataType, CallJs> tsfn;
4332+
4333+
napi_status status = napi_create_threadsafe_function(
4334+
env, nullptr, nullptr, String::From(env, resourceName), maxQueueSize,
4335+
initialThreadCount, nullptr, nullptr, context,
4336+
CallJsInternal, &tsfn._tsfn);
4337+
if (status != napi_ok) {
4338+
NAPI_THROW_IF_FAILED(env, status,
4339+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>());
4340+
}
4341+
4342+
return tsfn;
4343+
}
4344+
4345+
// static, with Callback [nullptr] Resource [missing] Finalizer [missing]
4346+
template <typename ContextType, typename DataType,
4347+
void (*CallJs)(Napi::Env, Napi::Function, ContextType *, DataType *)>
4348+
template <typename ResourceString>
4349+
inline ThreadSafeFunctionEx<ContextType, DataType, CallJs>
4350+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>::New(
4351+
napi_env env, std::nullptr_t callback, ResourceString resourceName, size_t maxQueueSize,
4352+
size_t initialThreadCount, ContextType *context) {
4353+
ThreadSafeFunctionEx<ContextType, DataType, CallJs> tsfn;
4354+
4355+
napi_status status = napi_create_threadsafe_function(
4356+
env, nullptr, nullptr, String::From(env, resourceName), maxQueueSize,
4357+
initialThreadCount, nullptr, nullptr, context,
4358+
CallJsInternal, &tsfn._tsfn);
4359+
if (status != napi_ok) {
4360+
NAPI_THROW_IF_FAILED(env, status,
4361+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>());
4362+
}
4363+
4364+
return tsfn;
4365+
}
4366+
4367+
// static, with Callback [missing] Resource [passed] Finalizer [missing]
4368+
template <typename ContextType, typename DataType,
4369+
void (*CallJs)(Napi::Env, Napi::Function, ContextType *, DataType *)>
4370+
template <typename ResourceString>
4371+
inline ThreadSafeFunctionEx<ContextType, DataType, CallJs>
4372+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>::New(
4373+
napi_env env, const Object &resource, ResourceString resourceName,
4374+
size_t maxQueueSize, size_t initialThreadCount, ContextType *context) {
4375+
ThreadSafeFunctionEx<ContextType, DataType, CallJs> tsfn;
4376+
4377+
napi_status status = napi_create_threadsafe_function(
4378+
env, nullptr, resource, String::From(env, resourceName), maxQueueSize,
4379+
initialThreadCount, nullptr, nullptr, context, CallJsInternal,
4380+
&tsfn._tsfn);
4381+
if (status != napi_ok) {
4382+
NAPI_THROW_IF_FAILED(env, status,
4383+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>());
4384+
}
4385+
4386+
return tsfn;
4387+
}
4388+
4389+
// static, with Callback [nullptr] Resource [passed] Finalizer [missing]
4390+
template <typename ContextType, typename DataType,
4391+
void (*CallJs)(Napi::Env, Napi::Function, ContextType *, DataType *)>
4392+
template <typename ResourceString>
4393+
inline ThreadSafeFunctionEx<ContextType, DataType, CallJs>
4394+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>::New(
4395+
napi_env env, std::nullptr_t callback, const Object &resource, ResourceString resourceName,
4396+
size_t maxQueueSize, size_t initialThreadCount, ContextType *context) {
4397+
ThreadSafeFunctionEx<ContextType, DataType, CallJs> tsfn;
4398+
4399+
napi_status status = napi_create_threadsafe_function(
4400+
env, nullptr, resource, String::From(env, resourceName), maxQueueSize,
4401+
initialThreadCount, nullptr, nullptr, context, CallJsInternal,
4402+
&tsfn._tsfn);
4403+
if (status != napi_ok) {
4404+
NAPI_THROW_IF_FAILED(env, status,
4405+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>());
4406+
}
4407+
4408+
return tsfn;
4409+
}
4410+
4411+
// static, with Callback [missing] Resource [missing] Finalizer [passed]
4412+
template <typename ContextType, typename DataType,
4413+
void (*CallJs)(Napi::Env, Napi::Function, ContextType *, DataType *)>
4414+
template <typename ResourceString, typename Finalizer,
4415+
typename FinalizerDataType>
4416+
inline ThreadSafeFunctionEx<ContextType, DataType, CallJs>
4417+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>::New(
4418+
napi_env env, ResourceString resourceName, size_t maxQueueSize,
4419+
size_t initialThreadCount, ContextType *context, Finalizer finalizeCallback,
4420+
FinalizerDataType *data) {
4421+
ThreadSafeFunctionEx<ContextType, DataType, CallJs> tsfn;
4422+
4423+
auto *finalizeData = new details::ThreadSafeFinalize<ContextType, Finalizer,
4424+
FinalizerDataType>(
4425+
{data, finalizeCallback});
4426+
napi_status status = napi_create_threadsafe_function(
4427+
env, nullptr, nullptr, String::From(env, resourceName), maxQueueSize,
4428+
initialThreadCount, finalizeData,
4429+
details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
4430+
FinalizeFinalizeWrapperWithDataAndContext,
4431+
context, CallJsInternal, &tsfn._tsfn);
4432+
if (status != napi_ok) {
4433+
delete finalizeData;
4434+
NAPI_THROW_IF_FAILED(env, status,
4435+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>());
4436+
}
4437+
4438+
return tsfn;
4439+
}
4440+
4441+
// static, with Callback [nullptr] Resource [missing] Finalizer [passed]
4442+
template <typename ContextType, typename DataType,
4443+
void (*CallJs)(Napi::Env, Napi::Function, ContextType *, DataType *)>
4444+
template <typename ResourceString, typename Finalizer,
4445+
typename FinalizerDataType>
4446+
inline ThreadSafeFunctionEx<ContextType, DataType, CallJs>
4447+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>::New(
4448+
napi_env env, std::nullptr_t callback, ResourceString resourceName, size_t maxQueueSize,
4449+
size_t initialThreadCount, ContextType *context, Finalizer finalizeCallback,
4450+
FinalizerDataType *data) {
4451+
ThreadSafeFunctionEx<ContextType, DataType, CallJs> tsfn;
4452+
4453+
auto *finalizeData = new details::ThreadSafeFinalize<ContextType, Finalizer,
4454+
FinalizerDataType>(
4455+
{data, finalizeCallback});
4456+
napi_status status = napi_create_threadsafe_function(
4457+
env, nullptr, nullptr, String::From(env, resourceName), maxQueueSize,
4458+
initialThreadCount, finalizeData,
4459+
details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
4460+
FinalizeFinalizeWrapperWithDataAndContext,
4461+
context, CallJsInternal, &tsfn._tsfn);
4462+
if (status != napi_ok) {
4463+
delete finalizeData;
4464+
NAPI_THROW_IF_FAILED(env, status,
4465+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>());
4466+
}
4467+
4468+
return tsfn;
4469+
}
4470+
4471+
// static, with Callback [missing] Resource [passed] Finalizer [passed]
4472+
template <typename ContextType, typename DataType,
4473+
void (*CallJs)(Napi::Env, Napi::Function, ContextType *, DataType *)>
4474+
template <typename ResourceString, typename Finalizer,
4475+
typename FinalizerDataType>
4476+
inline ThreadSafeFunctionEx<ContextType, DataType, CallJs>
4477+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>::New(
4478+
napi_env env, const Object &resource, ResourceString resourceName,
4479+
size_t maxQueueSize, size_t initialThreadCount, ContextType *context,
4480+
Finalizer finalizeCallback, FinalizerDataType *data) {
4481+
ThreadSafeFunctionEx<ContextType, DataType, CallJs> tsfn;
4482+
4483+
auto *finalizeData = new details::ThreadSafeFinalize<ContextType, Finalizer,
4484+
FinalizerDataType>(
4485+
{data, finalizeCallback});
4486+
napi_status status = napi_create_threadsafe_function(
4487+
env, nullptr, resource, String::From(env, resourceName), maxQueueSize,
4488+
initialThreadCount, finalizeData,
4489+
details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
4490+
FinalizeFinalizeWrapperWithDataAndContext,
4491+
context, CallJsInternal, &tsfn._tsfn);
4492+
if (status != napi_ok) {
4493+
delete finalizeData;
4494+
NAPI_THROW_IF_FAILED(env, status,
4495+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>());
4496+
}
4497+
4498+
return tsfn;
4499+
}
4500+
4501+
// static, with Callback [nullptr] Resource [passed] Finalizer [passed]
4502+
template <typename ContextType, typename DataType,
4503+
void (*CallJs)(Napi::Env, Napi::Function, ContextType *, DataType *)>
4504+
template <typename ResourceString, typename Finalizer,
4505+
typename FinalizerDataType>
4506+
inline ThreadSafeFunctionEx<ContextType, DataType, CallJs>
4507+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>::New(
4508+
napi_env env, std::nullptr_t callback, const Object &resource, ResourceString resourceName,
4509+
size_t maxQueueSize, size_t initialThreadCount, ContextType *context,
4510+
Finalizer finalizeCallback, FinalizerDataType *data) {
4511+
ThreadSafeFunctionEx<ContextType, DataType, CallJs> tsfn;
4512+
4513+
auto *finalizeData = new details::ThreadSafeFinalize<ContextType, Finalizer,
4514+
FinalizerDataType>(
4515+
{data, finalizeCallback});
4516+
napi_status status = napi_create_threadsafe_function(
4517+
env, nullptr, resource, String::From(env, resourceName), maxQueueSize,
4518+
initialThreadCount, finalizeData,
4519+
details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
4520+
FinalizeFinalizeWrapperWithDataAndContext,
4521+
context, CallJsInternal, &tsfn._tsfn);
4522+
if (status != napi_ok) {
4523+
delete finalizeData;
4524+
NAPI_THROW_IF_FAILED(env, status,
4525+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>());
4526+
}
4527+
4528+
return tsfn;
4529+
}
4530+
#endif
4531+
4532+
// static, with Callback [passed] Resource [missing] Finalizer [missing]
4533+
template <typename ContextType, typename DataType,
4534+
void (*CallJs)(Napi::Env, Napi::Function, ContextType *, DataType *)>
4535+
template <typename ResourceString>
4536+
inline ThreadSafeFunctionEx<ContextType, DataType, CallJs>
4537+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>::New(
4538+
napi_env env, const Function &callback, ResourceString resourceName,
4539+
size_t maxQueueSize, size_t initialThreadCount, ContextType *context) {
4540+
ThreadSafeFunctionEx<ContextType, DataType, CallJs> tsfn;
4541+
4542+
napi_status status = napi_create_threadsafe_function(
4543+
env, callback, nullptr, String::From(env, resourceName), maxQueueSize,
4544+
initialThreadCount, nullptr, nullptr, context, CallJsInternal,
4545+
&tsfn._tsfn);
4546+
if (status != napi_ok) {
4547+
NAPI_THROW_IF_FAILED(env, status,
4548+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>());
4549+
}
4550+
4551+
return tsfn;
4552+
}
4553+
4554+
// static, with Callback [x] Resource [x] Finalizer [missing]
43214555
template <typename ContextType, typename DataType,
43224556
void (*CallJs)(Napi::Env, Napi::Function, ContextType *, DataType *)>
43234557
template <typename ResourceString>
@@ -4326,12 +4560,51 @@ ThreadSafeFunctionEx<ContextType, DataType, CallJs>::New(
43264560
napi_env env, const Function &callback, const Object &resource,
43274561
ResourceString resourceName, size_t maxQueueSize, size_t initialThreadCount,
43284562
ContextType *context) {
4329-
return New(
4330-
env, callback, resource, resourceName, maxQueueSize, initialThreadCount,
4331-
context, [](Env, void *, ContextType *) {}, static_cast<void *>(nullptr));
4563+
ThreadSafeFunctionEx<ContextType, DataType, CallJs> tsfn;
4564+
4565+
napi_status status = napi_create_threadsafe_function(
4566+
env, callback, resource, String::From(env, resourceName), maxQueueSize,
4567+
initialThreadCount, nullptr, nullptr, context, CallJsInternal,
4568+
&tsfn._tsfn);
4569+
if (status != napi_ok) {
4570+
NAPI_THROW_IF_FAILED(env, status,
4571+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>());
4572+
}
4573+
4574+
return tsfn;
43324575
}
43334576

4334-
// static
4577+
// static, with Callback [x] Resource [missing ] Finalizer [x]
4578+
template <typename ContextType, typename DataType,
4579+
void (*CallJs)(Napi::Env, Napi::Function, ContextType *, DataType *)>
4580+
template <typename ResourceString, typename Finalizer,
4581+
typename FinalizerDataType>
4582+
inline ThreadSafeFunctionEx<ContextType, DataType, CallJs>
4583+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>::New(
4584+
napi_env env, const Function &callback, ResourceString resourceName,
4585+
size_t maxQueueSize, size_t initialThreadCount, ContextType *context,
4586+
Finalizer finalizeCallback, FinalizerDataType *data) {
4587+
ThreadSafeFunctionEx<ContextType, DataType, CallJs> tsfn;
4588+
4589+
auto *finalizeData = new details::ThreadSafeFinalize<ContextType, Finalizer,
4590+
FinalizerDataType>(
4591+
{data, finalizeCallback});
4592+
napi_status status = napi_create_threadsafe_function(
4593+
env, callback, nullptr, String::From(env, resourceName), maxQueueSize,
4594+
initialThreadCount, finalizeData,
4595+
details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
4596+
FinalizeFinalizeWrapperWithDataAndContext,
4597+
context, CallJsInternal, &tsfn._tsfn);
4598+
if (status != napi_ok) {
4599+
delete finalizeData;
4600+
NAPI_THROW_IF_FAILED(env, status,
4601+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>());
4602+
}
4603+
4604+
return tsfn;
4605+
}
4606+
4607+
// static, with: Callback [x] Resource [x] Finalizer [x]
43354608
template <typename ContextType, typename DataType,
43364609
void (*CallJs)(Napi::Env, Napi::Function, ContextType *, DataType *)>
43374610
template <typename ResourceString, typename Finalizer,
@@ -4341,11 +4614,24 @@ ThreadSafeFunctionEx<ContextType, DataType, CallJs>::New(
43414614
napi_env env, const Function &callback, const Object &resource,
43424615
ResourceString resourceName, size_t maxQueueSize, size_t initialThreadCount,
43434616
ContextType *context, Finalizer finalizeCallback, FinalizerDataType *data) {
4344-
return New(
4345-
env, callback, resource, resourceName, maxQueueSize, initialThreadCount,
4346-
context, finalizeCallback, data,
4617+
ThreadSafeFunctionEx<ContextType, DataType, CallJs> tsfn;
4618+
4619+
auto *finalizeData = new details::ThreadSafeFinalize<ContextType, Finalizer,
4620+
FinalizerDataType>(
4621+
{data, finalizeCallback});
4622+
napi_status status = napi_create_threadsafe_function(
4623+
env, callback, resource, String::From(env, resourceName), maxQueueSize,
4624+
initialThreadCount, finalizeData,
43474625
details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
4348-
FinalizeFinalizeWrapperWithDataAndContext);
4626+
FinalizeFinalizeWrapperWithDataAndContext,
4627+
context, CallJsInternal, &tsfn._tsfn);
4628+
if (status != napi_ok) {
4629+
delete finalizeData;
4630+
NAPI_THROW_IF_FAILED(env, status,
4631+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>());
4632+
}
4633+
4634+
return tsfn;
43494635
}
43504636

43514637
template <typename ContextType, typename DataType,
@@ -4438,43 +4724,23 @@ ThreadSafeFunctionEx<ContextType, DataType, CallJs>::GetContext() const {
44384724
// static
44394725
template <typename ContextType, typename DataType,
44404726
void (*CallJs)(Napi::Env, Napi::Function, ContextType *, DataType *)>
4441-
template <typename ResourceString, typename Finalizer,
4442-
typename FinalizerDataType>
4443-
inline ThreadSafeFunctionEx<ContextType, DataType, CallJs>
4444-
ThreadSafeFunctionEx<ContextType, DataType, CallJs>::New(
4445-
napi_env env, const Function &callback, const Object &resource,
4446-
ResourceString resourceName, size_t maxQueueSize, size_t initialThreadCount,
4447-
ContextType *context, Finalizer finalizeCallback, FinalizerDataType *data,
4448-
napi_finalize wrapper) {
4449-
static_assert(details::can_make_string<ResourceString>::value ||
4450-
std::is_convertible<ResourceString, napi_value>::value,
4451-
"Resource name should be convertible to the string type");
4452-
4453-
ThreadSafeFunctionEx<ContextType, DataType, CallJs> tsfn;
4454-
4455-
auto *finalizeData = new details::ThreadSafeFinalize<ContextType, Finalizer,
4456-
FinalizerDataType>(
4457-
{data, finalizeCallback});
4458-
napi_status status = napi_create_threadsafe_function(
4459-
env, callback, resource, Value::From(env, resourceName), maxQueueSize,
4460-
initialThreadCount, finalizeData, wrapper, context, CallJsInternal,
4461-
&tsfn._tsfn);
4462-
if (status != napi_ok) {
4463-
delete finalizeData;
4464-
NAPI_THROW_IF_FAILED(env, status,
4465-
ThreadSafeFunctionEx<ContextType, DataType, CallJs>());
4466-
}
4467-
4468-
return tsfn;
4727+
void ThreadSafeFunctionEx<ContextType, DataType, CallJs>::CallJsInternal(
4728+
napi_env env, napi_value jsCallback, void *context, void *data) {
4729+
details::CallJsWrapper<ContextType, DataType, decltype(CallJs), CallJs>(
4730+
env, jsCallback, context, data);
44694731
}
44704732

44714733
// static
44724734
template <typename ContextType, typename DataType,
44734735
void (*CallJs)(Napi::Env, Napi::Function, ContextType *, DataType *)>
4474-
void ThreadSafeFunctionEx<ContextType, DataType, CallJs>::CallJsInternal(
4475-
napi_env env, napi_value jsCallback, void *context, void *data) {
4476-
details::CallJsWrapper<ContextType, DataType, decltype(CallJs), CallJs>(
4477-
env, jsCallback, context, data);
4736+
typename ThreadSafeFunctionEx<ContextType, DataType, CallJs>::DefaultFunctionType
4737+
ThreadSafeFunctionEx<ContextType, DataType, CallJs>::DefaultFunctionFactory(
4738+
Napi::Env env) {
4739+
#if NAPI_VERSION > 4
4740+
return nullptr;
4741+
#else
4742+
return Function::New(env, [](const CallbackInfo &cb) {});
4743+
#endif
44784744
}
44794745

44804746
////////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)