231103.1 · 7f4a9ed91bbecb84e39f4bc8030247ce5116ddf8
Reorganize examples into categorized folders (#341)
* refactor: create directory structure to organize exmaples
* test: update test_all to work with new directory structure
* fix: bug in test_all if no package.json scripts
* test: cleanup output of test_all
* fix: remove default test script that throws from thread_safe_function_with_object_wrap
* fix: remove build_with_cmake from .gitignore
* fix: swith to ' from " and remove subdir from getAllTests call
* test: add extra test cases for npm start and just running the pkgJson.main with node
* refactor: move all examples to src directory
* refactor: add numbers to categories so they are ordered in the src folder
* refactor: simplify getAllExamples in test_all.js
* docs: add directory structure to README.md
* docs: update directory structure to README.md
* docs: update directory structure to README.md
* docs: update directory structure to README.md
* docs: update directory structure example in readme
* add back build_with_cmake
---------
Co-authored-by: legendecas <legendecas@gmail.com>
reading declarations
Changes to src/6-threadsafe-function/thread_safe_function_counting/. All files
src/6-threadsafe-function/thread_safe_function_counting/node-addon-api/addon.cc
@@ -0,0 +1,106 @@+#include <chrono>+#include <thread>+#include "napi.h"++constexpr size_t ARRAY_LENGTH = 10;++// Data structure representing our thread-safe function context.+struct TsfnContext {+ TsfnContext(Napi::Env env) : deferred(Napi::Promise::Deferred::New(env)) {+ for (size_t i = 0; i < ARRAY_LENGTH; ++i) ints[i] = i;+ };++ // Native Promise returned to JavaScript+ Napi::Promise::Deferred deferred;++ // Native thread+ std::thread nativeThread;++ // Some data to pass around+ int ints[ARRAY_LENGTH];++ Napi::ThreadSafeFunction tsfn;+};++// The thread entry point. This takes as its arguments the specific+// threadsafe-function context created inside the main thread.+void threadEntry(TsfnContext* context);++// The thread-safe function finalizer callback. This callback executes+// at destruction of thread-safe function, taking as arguments the finalizer+// data and threadsafe-function context.+void FinalizerCallback(Napi::Env env, void* finalizeData, TsfnContext* context);++// Exported JavaScript function. Creates the thread-safe function and native+// thread. Promise is resolved in the thread-safe function's finalizer.+Napi::Value CreateTSFN(const Napi::CallbackInfo& info) {+ Napi::Env env = info.Env();++ // Construct context data+ auto testData = new TsfnContext(env);++ // Create a new ThreadSafeFunction.+ testData->tsfn = Napi::ThreadSafeFunction::New(+ env, // Environment+ info[0].As<Napi::Function>(), // JS function from caller+ "TSFN", // Resource name+ 0, // Max queue size (0 = unlimited).+ 1, // Initial thread count+ testData, // Context,+ FinalizerCallback, // Finalizer+ (void*)nullptr // Finalizer data+ );+ testData->nativeThread = std::thread(threadEntry, testData);++ // Return the deferred's Promise. This Promise is resolved in the thread-safe+ // function's finalizer callback.+ return testData->deferred.Promise();+}++// The thread entry point. This takes as its arguments the specific+// threadsafe-function context created inside the main thread.+void threadEntry(TsfnContext* context) {+ // This callback transforms the native addon data (int *data) to JavaScript+ // values. It also receives the treadsafe-function's registered callback, and+ // may choose to call it.+ auto callback = [](Napi::Env env, Napi::Function jsCallback, int* data) {+ jsCallback.Call({Napi::Number::New(env, *data)});+ };++ for (size_t index = 0; index < ARRAY_LENGTH; ++index) {+ // Perform a call into JavaScript.+ napi_status status =+ context->tsfn.BlockingCall(&context->ints[index], callback);++ if (status != napi_ok) {+ Napi::Error::Fatal(+ "ThreadEntry",+ "Napi::ThreadSafeNapi::Function.BlockingCall() failed");+ }+ // Sleep for some time.+ std::this_thread::sleep_for(std::chrono::milliseconds(200));+ }++ // Release the thread-safe function. This decrements the internal thread+ // count, and will perform finalization since the count will reach 0.+ context->tsfn.Release();+}++void FinalizerCallback(Napi::Env env,+ void* finalizeData,+ TsfnContext* context) {+ // Join the thread+ context->nativeThread.join();++ // Resolve the Promise previously returned to JS via the CreateTSFN method.+ context->deferred.Resolve(Napi::Boolean::New(env, true));+ delete context;+}++// Addon entry point+Napi::Object Init(Napi::Env env, Napi::Object exports) {+ exports["createTSFN"] = Napi::Function::New(env, CreateTSFN);+ return exports;+}++NODE_API_MODULE(addon, Init)
src/6-threadsafe-function/thread_safe_function_counting/node-addon-api/addon.js
@@ -0,0 +1,9 @@+const { createTSFN } = require('bindings')('addon');++const callback = (...args) => { + console.log(new Date, ...args); +};++void async function() {+ console.log(await createTSFN(callback));+}();
src/6-threadsafe-function/thread_safe_function_counting/node-addon-api/binding.gyp
@@ -0,0 +1,21 @@+{+ 'targets': [{+ 'target_name': 'addon',+ 'defines': ['V8_DEPRECATION_WARNINGS=1'],+ 'sources': ['addon.cc'],+ 'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],+ 'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],+ 'cflags!': ['-fno-exceptions'],+ 'cflags_cc!': ['-fno-exceptions'],+ 'xcode_settings': {+ 'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',+ 'CLANG_CXX_LIBRARY': 'libc++',+ 'MACOSX_DEPLOYMENT_TARGET': '10.7',+ },+ 'msvs_settings': {+ 'VCCLCompilerTool': {+ 'ExceptionHandling': 1+ },+ },+ }]+}
src/6-threadsafe-function/thread_safe_function_counting/node-addon-api/package.json
@@ -0,0 +1,15 @@+{+ "name": "tsfn-counting",+ "version": "0.0.0",+ "description": "Thread-safe Function Example",+ "main": "addon.js",+ "private": true,+ "gypfile": true,+ "dependencies": {+ "node-addon-api": "*",+ "bindings": "*"+ },+ "engines": {+ "node": ">= 10.16.0"+ }+}