Windows PPL(C++): Is this the correct way to test if a task is done? - windows

Is this the correct way to test if a task is done?
const concurrency::task<void> voidTask;
if (voidTask != m_getInfoAsync)
{
if (!m_getInfoAsync.is_done())
{
return 0;
}
}
if (voidTask != m_getRangeAsync)
{
if (!m_getRangeAsync.is_done())
{
return 0;
}
}

although task::is_done is the correct way to test if the task is done, I suggest not using it. if is_done returns false, by the time you started acting on that fact, the task may be already done. this function is very racy, not to mention that this function probably requires some synchronization which may slow down the program.
instead, just chain a continuation or use co_await. handle finished task there.

Related

How to enforce only 1 subscriber per multiple instances of a same Single/Observable?

I have this sync modeled as a Single, and only 1 sync can be running at a time.
I'm trying to subscribe the "job" on a Schedulers.single() which mostly works, but inside the chain there are schedulers hops (to db writes scheduler), which unblocks the natural queue created by single()
Then I looked at flatMap(maxConcurrency=1) but this won't work, as that requires always the same instance. I.e. from what I understand, some sort of a Subject of sync requests, which however is uncomposable as my usecase mostly looks like this
fun someAction1AndSync(): Single<Unit> {
return someAction1()
.flatMap { sync() }
}
fun someAction2AndSync(): Single<Unit> {
return someAction2()
.flatMap { sync() }
}
...
as you can see, its separate sync Single instances :/
Also note someActionXAndSync should not emit until the sync is also done
Basically I'm looking for coroutines Semaphore
I can think of three ways:
use a single thread for whole sync operation (decoupling through queue)
use semaphore to protect sync method from entering multiple times (not recommended, because will block callee)
fast return, when sync is in progress (AtomicBoolean)
There might by other solutions, which I am not aware of.
fast return, when sync is in progress
Also note someActionXAndSync should not emit until the sync is also done
This solution will not queue up sync requests, but will fail fast. The callee must handle the error appropriately
SyncService
class SyncService {
val isSync: AtomicBoolean = AtomicBoolean(false)
fun sync(): Completable {
return if (isSync.compareAndSet(false, true)) {
Completable.fromCallable { "" }.doOnEvent { isSync.set(false) }
} else {
Completable.error(IllegalStateException("whatever"))
}
}
}
Handling
When sync process is already happening, you will receive an onError. This issue must be handled somehow, because the onError will be emitted to the subscriber. Either you are fine with it, or you could just ignore it with onErrorComplete
fun someAction1AndSync(): Completable {
return Single.just("")
.flatMapCompletable {
sync().onErrorComplete()
}
}
use a single thread for whole sync operation
You have to make sure, that the whole sync-process is processed in a single job. When the sync-process is composed of multiple reactive steps on other threads, it could happen, that another sync process is started, while one sync process is already in progress.
How?
You have to have a scheduler with one thread. Each sync invocation must be invoked from given scheduler. The sync operation must complete sync in one running job.
I would use this:
fun Observable<Unit>.forceOnlyOneSubscriber(): Observable<Unit> {
val subscriberCount = AtomicInteger(0)
return doOnSubscribe { subscriberCount.incrementAndGet() }
.doFinally { subscriberCount.decrementAndGet() }
.doOnSubscribe { check(subscriberCount.get() <= 1) }
}
You can always generify Unit using generics if you need.

Task status changed to RanToCompletion while stille running

I created a method which handles a few checks before starting a Task passed as a parameter.
My issue is that the task created there do not behave as expected and are quickly considered as RanToCompletion despite code is still running.
Here is an example:
public Task Main(CancellationToken localToken)
{
try
{
AddToTasker(new Task(async () => await ExtractAllOffer(localToken), localToken), TaskTypes.Extractor);
//this allows to extract only the task for the given task type through the list created in AddToTasker, actual code is not necessary the returned array is correct
Task.WaitAll(GetTasksArray(new TaskTypes[]{TaskTypes.Extractor}), localToken);
IsRunning = false;
}
}
public void AddToTasker(Task task, TaskTypes taskstype)
{
/*
* Whatever code to perform few check before starting the task
* among which referencing the task within a list which holds also the taskstype
*/
task.Start();
}
async private Task ExtractAllOffer(CancellationToken localToken)
{
// *** Do very long Stuff ***
}
The ExtractAllOffer method is a loop, with a few moment where i await external code completion. At the first await the Task.WaiAll terminates and it goes to IsRunning = false
I checked this thread but it does not seem to be the same issue as I correctly use an async task and not an async void.
Also, the code use to run properly before I shifted the Task execution within the AddToTasker method. Before I used to do like this AddToTasker(Task.Run(() => ExtractAllOffer(localToken), localToken), TaskTypes.Extractor); but I realized I needed to perform checks before starting the Task and needed to factor the checks within the AddToTasker method (I have many calls to this method).
I kind of understand that there is a flaw in how I declare or start my Task but can't figure what.
Help greatly appreciated
Thanks to #pere57 and this other thread I see that the wait only wait until the action that creates the Task finishes... which is quite fast.
I have to declare it as a Task< Task> in order to the unwrap the first Task (the action) to access the inner Task (the actual method that gets executed).
So here it goes :
public Task Main(CancellationToken localToken)
{
try
{
AddToTasker(new Task<Task>(() => ExtractAllOffer(localToken), localToken), TaskTypes.Extractor);
//this allows to extract only the task for the given task type through the list created in AddToTasker, actual code is not necessary the returned array is correct
Task.WaitAll(GetTasksArray(new TaskTypes[]{TaskTypes.Extractor}), localToken);
IsRunning = false;
}
}
public void AddToTasker(Task<Task> task, TaskTypes taskstype)
{
/*
* Whatever code to perform few check before starting the task
* among which referencing the task within a list which holds also the taskstype
*/
mylistoftask.Add(task.Unwrap()); //I have now to unwrap the task to add the inner one in my list
task.Start();
}
async private Task ExtractAllOffer(CancellationToken localToken)
{
// *** Do very long Stuff ***
}

Is it possible to cancel a blocking call in C++ 11 or 14?

My gcc compiler supports C++ 14.
Scenario:
I want to know if there is a way I can force cancel out of a blocking call and stop my std::thread safely.
Code:
// Member vars declared in MyClass.hpp
std::atomic<bool> m_continue_polling = false;
std::thread m_thread;
StartThread() {
m_continue_polling = true;
m_thread = std::thread { [this] {
while (m_continue_polling) {
int somevalue = ReadValue(); // This is a blocking call and can take minutes
}
}};
}
StopThread() {
m_continue_polling = false;
try {
if (m_thread.joinable()) {
m_thread.join();
}
}
catch(const std::exception & /*e*/) {
// Log it out
}
}
In above code ReadValue is a blocking call which goes into a library and reads on a fd which some device driver related code which I have no control on.
Question:
I need StopThread to be able to stop the thread and cancel the call that is blocking on ReadValue. How can I do this? Is there some way in C++11 or 14?
PS:
Probably std::async could be a solution? But I wish to know if there are better ways. If std::async is the best approach then how to effectively use it this scenario without causing bad side effects.
On Linux, you can get the native thread handle and use pthread_cancel function. Provided the thread did not disable cancelability and that the thread is blocked in a cancellation point. You will have to read the documentation carefully to understand all the caveats.

How to implement kind of global try..finally in TPL?

I have async method that returns Task. From time to time my process is recycling/restarting. Work is interruping in the middle of the Task. Is there more or less general approach in TPL that I can at least log that Task was interruped?
I am hosting in ASP.NET, so I can use IRegisteredObject to cancel tasks with CancellationToken. I do not like this however. I need to pass CancellationToken in all methods and I have many of them.
try..finally in each method does not seem even to raise. ContinueWith also does not work
Any advice?
I have single place I start my async tasks, however each task can have any number of child tasks. To get an idea:
class CommandRunner
{
public Task Execute(object cmd, Func<object, Task> handler)
{
return handler(cmd).ContinueWith(t =>
{
if (t.State = == TaskStatus.Faulted)
{
// Handle faultes, log them
}
else if (x.Status == TaskStatus.RanToCompletion)
{
// Audit
}
})
}
}
Tasks don't just get "interrupted" somehow. They always get completed, faulted or cancelled. There is no global hook to find out about those completions. So the only option to do your logging is to either instrument the bodies of your tasks or hook up continuations for everything.

Handling more than 2 possible returned values?

When a function returns a boolean you can easily
if (task()){
// it worked!
}else{
// it failed.
}
But when it returns multiple different values it gets messier
var status = task();
if (status == 1){
// hmm
}else if (status == 2){
// hmmmmm
}else if (status == 3){
// hmmmmmmmm!
}
..is there a neater way of handling it?
Edit: In response to the answers that recommend switch statements, yes I know about those. I was asking for something neater than even that?
I can't tell what language you are using (JavaScript?) but I generally write code like this:
var result = task();
switch (result)
{
case 1:
handleStatus1();
break;
case 2:
handleStatus2();
break;
default:
handleEverythingElse();
break;
}
Depends on a language's possibilities, but I'd do something like this in JavaScript:
var handle_task_1 = function () {
// handle task 1
};
var handle_task_2 = function () {
// handle task 2
};
var tasks = {
1: handle_task_1,
2: handle_task_2,
"default": function() {},
};
tasks[task()]();
// Or, with a default action. But it may be too much for some people :)
(tasks[task()] || tasks["default"])();
Most languages have a switch statement, something like:
switch (task()) {
case 1: // do stuff
break;
case 2: // other stuff
break;
/// etc.
default: // what?!
Error("Unhandleable status code");
}
If you have many chained if commands each executing a unique block of code, you might consider using a map of simple functor classes. Ideally, the application's startup would populate that map and you can just call the actions from an instance of that map
The code would look like this
Action action = (Action) contextMap.get(task());
action.do();
This has the advantage that adding new tasks requires only defining a new class for that task and adding it to the contextMap on startup.
There are some other nice things about this approach
taskA() and taskB() can share the same contextMap and even some of the same Actions so you have less code duplication
Actions can be unit tested more easily (usually)
Sharing of code between actions will be easy without ending up with spaghetti code or complex if(status > 2 && status !=7 ) statements
And of course, interfaces, varargs and other syntactic sugar helps here.
If you're talking about an integer or other primitive return type, the best approach I know is the switch statement.
switch (status)
{
case 1:
// hmm
break;
case 2:
// hmmm
break;
}
However, if you're returning an object that defines the behavior following the method call things become much neater.
Say you have an interface ISomething and two (or more) objects that implement that interface (ASomething and BSomething). If the method's return type is ISomething, the code becomes:
ISomething result = task();
result.DoSomething();
Maybe you are looking for exceptions?
Then you don't need to clutter your code for the successful case, and for the various error cases you can throw different exceptions as necessary.

Resources