Skip to content

Commit

Permalink
Documentation for generic_subscription_wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
Markus Klemm committed Sep 24, 2020
1 parent 5b77a85 commit fe02642
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 2 deletions.
48 changes: 48 additions & 0 deletions doc/generic_subscription_wrapper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# GenericSubscriptionWrapper

`Napi::GenericSubscriptionWrapper<T>` is a class with one template parameter `T`,
which is intended to allow you to call a JavaScript callback with `T` as parameter repeatedly
from a C++ function (subscribe) running arbitrary async i.e. concurrency/timer regimes like `boost::asio` via a `Napi::Promise`
until a callback in JavaScript is called (unsubscribe).

Overall this Object is quite similar to [GenericCallbackWrapper](generic_callback_wrapper.md) but intended to be used
for efficient repeatedly data push pattern, for example pushing device states triggered by arbitrary timers to maybe
multiple javascript callbacks. To give satisfying freedom for such house keeping, the unsubscribe function
is also promised, for cases where the according native facilities has also to be looked up or messaged first.

`Napi::GenericSubscriptionWrapper<T>` requires C++ exceptions enabled, so works by default.

## Self managed thread example

```cpp
Napi::Value convert_int(const Napi::Env &env, const std::shared_future<std::uint32_t> & future) {
return Napi::Number::From(env, future.get());
}

std::uint32_t pull_some_device_state();

Napi::Value SubScribeFor10Calls(const Napi::CallbackInfo& info) {
Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(info.Env());

auto wrapper = Napi::GenericSubscriptionWrapper<std::uint32_t>(
deferred, &convert_int, info[0].As<Napi::Function>());


auto t = std::thread([wrapper = std::move(wrapper)]() mutable {
std::atomic<bool> run{true};
wrapper.set_unsubscription_function([&run]() {
run = false;
});
for (std::uint32_t counter{}; run; ++counter) {
auto future = std::async(std::launch::deferred, []() {
return pull_some_device_state();
});
wrapper.get_native_callback()(future.share());
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
});
t.detach();

return deferred.Promise();
}
```
6 changes: 4 additions & 2 deletions test/generic_subscription_wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ async function testNormal10TimesCallAndUnsubscribe(bindingFunction) {
this.countsLeft = 10;
this.callCounter = 0;
this.finish = finish;
this.checkSum = 0;
}
iteration(input) {
++this.callCounter;
if (--this.countsLeft === 0) {
this.finish();
}
this.checkSum += input;
}
}

Expand All @@ -28,10 +30,10 @@ async function testNormal10TimesCallAndUnsubscribe(bindingFunction) {
});

await p;
assert.equal(handler.callCounter, 10);
assert.equal(handler.checkSum, 45);
await unsub.then(u => (u()));


assert.equal(handler.callCounter, 10);
}

async function test(binding) {
Expand Down

0 comments on commit fe02642

Please sign in to comment.