Synchronous and ASynchronous APIs - c++

I am developing a library, which provides some time consuming services. I need to have two versions of each API, one for synchronous function call and the other for asynchronous.
Library user should decide which version to use, a service result might be crucial for continue of system operation (synch call). The same operation might be needed to be done in different worker thread as it result is not needed to continue (asynch call).
What are the problems of this approach?
Is there any better way?
Are there popular libraries which provides both sync/async for the same API (Without using external events or threads) ?
Here is an example of what I am going to provide:
enum StuffStatus
{
SUCCEED,
FAILED,
STILL_RUNNING
};
class IServiceCallback
{
public:
void lengthyStuffCallback(StuffStatus status);
};
class MyServiceClass
{
public:
StuffStatus doSomeLengthStuff(IServiceCallback* callback)
{
if( callback == NULL ) // user wants sync. call
{
// do all operations in caller context
return SUCCEED;
}else{
// save the callback, queue the request in a separate worker thread.
// and after the worker thread finishes the job it calls callback->lengthyStuffCallback(SUCCEED) from its context.
return STILL_RUNNING;
}
}
};
EDIT:
As ' Matthieu M.' mentioned, In my service I need asynchronous with Continuation Passing Style (callback after API finish).

You might want to consider to provide only the synchronous operation and advise users to use std::future<...> (or a similar facility if you can't use C++ 2011) if they want an asynchronous version of the call!
std::future<StuffStatus> async(std::async(&MyServiceClass::doSomeLengthyStuff,
&service));
// do other stuff
StuffStatus status = async.get(); // get the result, possibly using a blocking wait

Related

Blocking calls in a Node.js Addon

I'm developing a Node.js application that incorporates a Windows DLL. The DLL manages scientific equipment, for context.
My interface from Node to the DLL is going well, however the DLL has some non-deterministic calls that depend on the network topology and RF signals in the room. These calls can take anywhere from 10 seconds to 10 minutes.
I'd like to get these calls off Node's event loop, and even avoid AsyncWorkers. I'd like to put them in their own C++ threads. I'm worried that I don't know enough Node/V8 to approach the problem correctly, though I've attempted twice now.
Below is my attempt at spawning a thread to call a js callback, though I'm not sure if this is a good approach. I need the result of the call, and what I have so far is a 'daemon' in my node app that checks on a regular interval to retrieve results for completed tasks.
mTp in the snippet below is a threadpool implementation I've written. Runtask takes a C++ lambda as a parameter to be pushed onto my worker thread queue. mThreadStatus is a map from my thread 'handle', which is a string, to thread_status_t enum. mThreadResults is another map from the thread handle to a v8::Value that gets returned by the callback.
void
MyObj::SpawnThread(functionInput info) {
MyObj* obj = ObjectWrap::Unwrap<MyObj>(info.Holder());
obj->mTp.RunTask([&]() {
v8::Isolate::CreateParams cp;
v8::Isolate* tpIsolate = v8::Isolate::New(cp);
v8::Locker locker(tpIsolate);
v8::Isolate::Scope isolateScope(tpIsolate);
Nan::HandleScope scope;
auto global = obj->mContext.Get(tpIsolate)->Global();
auto handle = std::string(*v8::String::Utf8Value(info[0]->ToString()));
{
std::unique_lock<std::shared_mutex> lock(obj->mThreadStatusMutex);
obj->mThreadStatus[handle] = thread_status_t::running;
}
v8::Handle<v8::Function> f = v8::Handle<v8::Function>::Cast(info[1]);
v8::TryCatch trycatch(tpIsolate);
v8::Handle<v8::Value> result = f->Call(global, 0, nullptr);
if (result.IsEmpty()) {
v8::Local<v8::Value> exception = trycatch.Exception();
std::unique_lock<std::shared_mutex> lock(obj->mThreadStatusMutex);
obj->mThreadStatus[handle] = thread_status_t::error;
return;
}
{
std::unique_lock<std::shared_mutex> resultLock(obj->mThreadResultsMutex);
obj->mThreadResults[handle] = result;
}
std::unique_lock<std::shared_mutex> lock(obj->mThreadStatusMutex);
obj->mThreadStatus[handle] = completed;
tpIsolate->Dispose();
});
I'm envisioning my js looking like this to spawn a thread:
var ctx = this
this.myObj.spawnThread('startMeasurements', () => {
return ctx.myObj.startMeasurements()
})
And like this to get the result, in my 'daemon':
var status = this.myObj.getThreadStatus('startMeasurements')
if ( status === 'complete') {
// Publish returned information to front-end
}
else if (status === 'error') {
// Handle error
}
Has anyone solved this problem before? Does this look like a decent approach? Help with v8 is greatly appreciated. Thank you!
I have not solved a similar problem before, but the general way I would go about it is:
let the JavaScript code be oblivious of the threading
expose a function getMeasurements(callback) to JavaScript, implemented in C++
when the function is called, it gets itself a thread (either newly created, or from the pool) and instructs it to do the blocking external call; when that call is completed the thread signals its result to the main thread, which invokes the callback with it.
that way all communication with JavaScript code (i.e. all interaction with V8) happens on the main thread, and you only use background threads for the blocking calls.
I hope this helps!

Reading all available messages from mpsc UnboundedReceiver without blocking unnecessarily

I have an futures::sync::mpsc::unbounded channel. I can send messages to the UnboundedSender<T> but have problems receiving them from the UnboundedReciever<T>.
I use the channel to send messages to the UI thread, and I have a function that gets called every frame, and I'd like to read all the available messages from the channel on each frame, without blocking the thread when there are no available messages.
From what I've read the Future::poll method is kind of what I need, I just poll, and if I get Async::Ready, I do something with the message, and if not, I just return from the function.
The problem is the poll panics when there is no task context (I'm not sure what that means or what to do about it).
What I tried:
let (sender, receiver) = unbounded(); // somewhere in the code, doesn't matter
// ...
let fut = match receiver.by_ref().collect().poll() {
Async::Ready(items_vec) => // do something on UI with items,
_ => return None
}
this panics because I don't have a task context.
Also tried:
let (sender, receiver) = unbounded(); // somewhere in the code, doesn't matter
// ...
let fut = receiver.by_ref().collect(); // how do I run the future?
tokio::runtime::current_thread::Runtime::new().unwrap().block_on(fut); // this blocks the thread when there are no items in the receiver
I would like help with reading the UnboundedReceiver<T> without blocking the thread when there are no items in the stream (just do nothing then).
Thanks!
You are using futures incorrectly -- you need a Runtime and a bit more boilerplate to get this to work:
extern crate tokio;
extern crate futures;
use tokio::prelude::*;
use futures::future::{lazy, ok};
use futures::sync::mpsc::unbounded;
use tokio::runtime::Runtime;
fn main() {
let (sender, receiver) = unbounded::<i64>();
let receiver = receiver.for_each(|result| {
println!("Got: {}", result);
Ok(())
});
let rt = Runtime::new().unwrap();
rt.executor().spawn(receiver);
let lazy_future = lazy(move || {
sender.unbounded_send(1).unwrap();
sender.unbounded_send(2).unwrap();
sender.unbounded_send(3).unwrap();
ok::<(), ()>(())
});
rt.block_on_all(lazy_future).unwrap();
}
Further reading, from Tokio's runtime model:
[...]in order to use Tokio and successfully execute tasks, an application must start an executor and the necessary drivers for the resources that the application’s tasks depend on. This requires significant boilerplate. To manage the boilerplate, Tokio offers a couple of runtime options. A runtime is an executor bundled with all necessary drivers to power Tokio’s resources. Instead of managing all the various Tokio components individually, a runtime is created and started in a single call.
Tokio offers a concurrent runtime and a single-threaded runtime. The concurrent runtime is backed by a multi-threaded, work-stealing executor. The single-threaded runtime executes all tasks and drivers on thee current thread. The user may pick the runtime with characteristics best suited for the application.

Correct way to stop asynchronous ISearchJob

I am going to use WUA API and begin execution of an asynchronous search for updates in this way:
CComPtr<SearchCallbackImpl> iscc_; <<-- Note you need to CreateInstance
CComPtr<ISearchJob> pUpJob_;
pUpJob_ = NULL;
pUpSearcher_->BeginSearch(
CComVariant(criteria.c_str()).bstrVal,
iscc_,
CComVariant(L"Scanning"),
&pUpJob_);
When I need to stop my program, but ISearchJob has not completed yet, I use this code:
if (pUpJob_)
{
CComVariant isStopped;
pUpJob_->get_IsCompleted(&isStopped.boolVal);
if (isStopped.boolVal == VARIANT_FALSE)
{
if (SUCCEEDED(pUpJob_->RequestAbort()))
{
pUpJob_->CleanUp();
pUpJob_.Release();
}
}
}
Generally this code works but sometime it hangs on pUpJob_->CleanUp(); and I do not have ability to stop my programm correctly.
So my questions are:
What is the correct way to stop asynchronous search job for updates?
Also i misunderstood what is difference between ISearchJob::CleanUp and ISearchJob::RequestAbort and how to use this methods to stop asynchronous search correctly?
Should this methods be used together or separately?
RequestAbort() is also asynchronous (the hint to that is in the name). After calling it, you should call pUpSearcher_->EndSearch(); it will return an ISearchResult with ResultCode equal to orcAborted if the abort was successful. Then you can free your resources.
I'm not fully sure how CleanUp() is supposed to be used, but this page seems to imply it's intended for scripts that have callbacks, and that you're not supposed to call CleanUp() from within a callback. Not sure where your code for cancelling is run.

How to shutdown gRPC server from Client (using RPC function)

I'm using gRPC for inter-process communication between C++ App (gRPC Server) and Java App (gRPC Client). Everything run on one machine. I want to provide client possibility to shut down the server. My idea is to add RPC function to service in proto which would do it.
The C++ Implementation would be:
class Service : public grpcGeneratedService
{
public:
......
private:
grpc::Server* m_pServer;
};
grpc::Status Service::ShutDown(grpc::ServerContext* pContext, const ShutDownRequest* pRequest, ShutDownResponse* pResponse)
{
if (m_pServer)
m_pServer->Shutdown();
return grpc::Status(grpc::StatusCode::OK, "");
}
However the ShutDown blocks until all RPC calls are processed what means dead-lock. Is there any elegant way how to implement it?
I'm using a std::promise with a method almost exactly like yours.
// Somewhere in the global scope :/
std::promise<void> exit_requested;
// My method looks nearly identical to yours
Status CoreServiceImpl::shutdown(ServerContext *context, const SystemRequest *request, Empty*)
{
LOG(INFO) << context->peer() << " - Shutdown request acknowledged.";
exit_requested.set_value();
return Status::OK;
}
In order to make this work, I call server->Wait() in a second thread and wait on the future for the exit_requested promise to block a shutdown call:
auto serveFn = [&]() {
server->Wait();
};
std::thread serving_thread(serveFn);
auto f = exit_requested.get_future();
f.wait();
server->Shutdown();
serving_thread.join();
Once I had this I was also able to support a clean shutdown via signal handlers as well:
auto handler = [](int s) {
exit_requested.set_value();
};
std::signal(SIGINT, handler);
std::signal(SIGTERM, handler);
std::signal(SIGQUIT, handler);
I've been satisfied with this approach so far and it's kept me within the bounds of gRPC and the standard c++ libs. Rather than use some globally scoped promise (I have to declare it as an external in my service implementation source) I should probably think of something more elegant.
One thing to note here is that setting the value of the promise more than once will throw an exception. This could happen if you somehow send the shutdown message and also pkill -2 my_awesome_service at the same time. I actually ran into this when there was a deadlock in my persistence layer preventing shutdown from finishing, when I tried to send a SIGINT again the service aborted instead! For my needs this is still an acceptable solution but I'd love to hear about alternatives that work around or solve that little problem.
You can create an std::function from the ShutDown() handler and run that function in a separate thread (or threadpool). This will allow decoupling the handling of the RPC from the execution of the shutdown logic and eliminate the deadlock.

How to specify a callback method for IAsyncOperation

Is it possible to specify a method to be called after finishing an async operation?
Platform : C++, Windows Phone 8
I need to implement non-blocking method for sending UDP packets asynchronously. And them have my method:
onWriteComplete(int errorCode)
called back when the operation completes.
Here's what I've tried:
res = await asyncWrite();
onWriteComplete( res );
But no luck.
Asynchronous operations work in similar ways across all languages in Windows Phone 8 and Windows RT applications. The asynchronous operation returns an IAsyncOperation result which you can use to chain a function to run when the operation completes.
In C++ you can create tasks and chain them in a way similar to C# using the create_task and task::then functions. Check Asynchronous Programming in C++ (Windows Store Apps) for an example.
The sample creates a task from an IAsyncOperation result and schedules another task to execute when the first task completes:
auto deviceEnumTask = create_task(deviceOp);
// Call the task’s .then member function, and provide
// the lambda to be invoked when the async operation completes.
deviceEnumTask.then( [this] (DeviceInformationCollection^ devices )
{
for(int i = 0; i < devices->Size; i++)
{
DeviceInformation^ di = devices->GetAt(i);
// Do something with di...
}
}); // end lambda