TBB need condition_variable for task synchronization - task

I'm using tbb for some project, and i'm forced to use tbb tasks.
My program has N tasks, who are interact.
Pseudo code goes like this:
class Task;
Task* t[N];
class Task {
startTask(Task &t) {
t.notify();
}
execute() {
while(!end){
if(some condition 1)
wait();
for(i = 0; i < N; ++i)
if(some condition 2)
startTask(*t[i]);
if(some condition 3)
end = true;
}
}
};
N >> cores
If I use condition_variable for this job, then thread stop and thread stops all tasks.
Is there some method what I can use to make my job done?
I've trying to use recycle, but only CORE_NUMBER task's working, and other N-CORE_NUMBER tasks never start to execute.
Best regards,
Goran

(Disclaimer: I work for Intel and on Intel® Threading Building Blocks)
Yes, TBB tasks are non-preemptive and they are scheduled on to a fixed number of worker threads. So if you have tasks on all of the worker threads and all of these tasks are waiting, then you will deadlock. No other task can be scheduled to wake up the others, since all worker threads are busy executing (blocked) tasks.
A few things that I can think of:
Can you restructure your application so that a task is spawned only when the condition it will wait on is satisfied? Your pseudo-code seems to indicate that you spawn the task and then it checks whether it can proceed. Instead of blocking in the task, can you only schedule the task when it is able to complete?
If you know the order in which the tasks are allowed to execute, you might create a graph of tasks ( http://software.intel.com/sites/products/documentation/doclib/tbb_sa/help/hh_goto.htm#tbb_userguide/General_Acyclic_Graphs_of_Tasks.htm ).
You can use the flow graph to implement streaming and reactive applications in TBB. Is it possible to implement it as a flow graph? ( http://www.drdobbs.com/tools/the-intel-threading-building-blocks-flow/231900177 )
Can you provide any more details on what the conditions look like? Your pseudo-code is very abstract, so my suggestions might be way off the mark…

Related

How to restore runOn Scheduler used in previous operator?

Folks, is it possible to obtain currently used Scheduler within an operator?
The problem that I have is that Mono.fromFuture() is being executed on a native thread (AWS CRT Http Client in my case). As result all subsequent operators are also executed on that thread. And later code wants to obtain class loader context that is obviously null. I realize that I can call .publishOn(originalScheduler) after .fromFuture() but I don't know what scheduler is used to materialize Mono returned by my function.
Is there elegant way to deal with this?
fun myFunction(): Mono<String> {
return Mono.just("example")
.flatMap { value ->
Mono.fromFuture {
// invocation of 3rd party library that executes Future on the thread created in native code.
}
}
.map {
val resource = Thread.currentThread().getContextClassLoader().getResources("META-INF/services/blah_blah");
// NullPointerException because Thread.currentThread().getContextClassLoader() returns NULL
resource.asSequence().first().toString()
}
}
It is not possible, because there's no guarantee that there is a Scheduler at all.
The place where the subscription is made and the data starts flowing could simply be a Thread. There is no mechanism in Java that allows an external actor to submit a task to an arbitrary thread (you have to provide the Runnable at Thread construction).
So no, there's no way of "returning to the previous Scheduler".
Usually, this shouldn't be an issue at all. If your your code is reactive it should also be non-blocking and thus able to "share" whichever thread it currently runs on with other computations.
If your code is blocking, it should off-load the work to a blocking-compatible Scheduler anyway, which you should explicitly chose. Typically: publishOn(Schedulers.boundedElastic()). This is also true for CPU-intensive tasks btw.

Does async operation in iOS create a new thread internally, and allocate task to it?

Does async operation in iOS, internally create a new thread, and allocate task to it ?
An async operation is capable to internally create a new thread and allocate task to it. But in order for this to happen you need to run an async operation which creates a new thread and allocates task to it. Or in other words: There is no direct correlation.
I assume that by async you mean something like DispatchQueue.main.async { <#code here#> }. This does not create a new thread as main thread should already be present. How and why does this work can be (if oversimplified) explained with an array of operations and an endless loop which is basically what RunLoop is there for. Imagine the following:
Array<Operations> allOperations;
int main() {
bool continueRunning = true;
for(;continueRunning;) {
allOperations.forEach { $0.run(); }
allOperations.clear();
}
return 0;
}
And when you call something like DispatchQueue.main.async it basically creates a new operation and inserts it into allOperations. The same thread will eventually go into a new loop (within for-loop) and call your operation asynchronously. Again keep in mind that this is all over-simplified just to illustrate the idea behind all of it. You can from this also imagine how for instance timers work; the operation will evaluate if current time is greater then the one of next scheduled execution and if so it will trigger the operation on timer. That is also why timers can not be very precise since they depend on rest of execution and thread may be busy.
A new thread on the other hand may be spawned when you create a new queue DispatchQueue(label: "Will most likely run on a new thread"). When(if) exactly will a thread be made is not something that needs to be fixed. It may vary from implementations and systems being run on. The tool will only guarantee to perform what it is designed for but not how it will do it.
And then there is also Thread class which can generate a new thread. But the deal is same as for previous one; it might internally instantly create a new thread or it might do it later, lazily. All it guarantees is that it will work for it's public interface.
I am not saying that these things change over time, implementation or system they run on. I am only saying that they potentially could and they might have had.

Shuld be a delay in a FreeRTOS task main loop?

Is it necessary to add some delay into the infinite loop inside a FreeRTOS task (created by xTaskCreatePinnedToCore())? Also, in my case, since the function aws_iot_mqtt_yield already takes a timeout (100) I tend to think the extra task delay is unnecessary.
My task looks like:
...
while(1) {
error = aws_iot_mqtt_yield(&m_client, 100);
check error...
vTaskDelay(10 / portTICK_RATE_MS);
}
...
No. You shouldn't need to add a delay. In fact in my opinion it is bad practice as it means you could be suspended at two different points in the task which can lead to very confusing program flow and is hard to debug.

A proper way to wait for an event from a concurrent thread

I've got an occasional crash that has to do with the improperly finished task on a concurrent thread while an app is transitioning to background.
So I have 3 threads:
A (main).
B (managed by GCD).
C (manually created to process intensive socket operations).
The scenario is the following:
In the applicationDidEnterBackground: handler (which is certainly executed on thread A) a long-running task is begun on thread B to complete all ongoing operations (save an application state, close a socket, etc.). In this task I need to wait until a socket properly finishes its work on thread C and only after that to continue with this long-running task.
Below is simplified code:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Some synchronous task.
[stateManager saveState];
// Here I need to wait until the socket finishes its task.
...
// Continuing of the long-running task.
...
}
What is the acceptable way to accomplish this task. Is it OK if I do something like this?
while (socket.isConnected)
{
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
// Continuing of the long-running task.
Or maybe something wrong in my current architecture and I need to use NSOperation to serialize asynchronous tasks somehow for example?
update: The problem has been solved by using dispatch_semaphore APIs as #Rob Napier suggested.
First, do not think of these as threads, and if you're creating a thread with NSThread or performSelectorInBackground: (or even worse, pthreads), don't do that. Use GCD. GCD creates queues. Queues order blocks, which eventually do run on threads, but the threads are an implementation detail and there is not a 1:1 mapping of queues to threads. See Migrating Away from Threads for more discussion on that.
To the question of how to wait for some other operation, the tool you probably want is a dispatch_semaphore. You create the semaphore and hand it to both operations. Then you call dispatch_semaphore_wait when you want to wait for something, and dispatch_sempahore_signal when you want to indicate that that something has happened. See Using Dispatch Semaphores to Regulate the Use of Finite Resources for more example code. The "finite resource" in this case is "the socket." You want to wait until the other part is done using it and returned it to the pool.
Semaphores will work even if you are using manual threading, but I can't emphasize enough that you should not be doing manual threading. All your concurrency should be managed through GCD. This is an important tool to overall concurrency management in iOS.
I would use NSOperation with dependencies.
So, you have tasks
A - main thread - aka 'entry point'
B - heavy boy to run in background
C - something else heavy to run after socket finished
Your heavy task from "B" is OperationB
Assume your socket framework capable of running syncronous in current thread? - then this is your OperationSend
Do the rest to do in background - OperationC
there you have a chain of operations, dependent on each other:
OperationB -> OperationSend -> OperationC

Resart a task in FreeRTOS

I have a specific task routine which performs some operations in a specific order, and these operations handle few volatile variables. There is a specific interrupt which updates these volatile variables asynchronously. Hence, the task routine should restart if such an interrupt occurs. Normally FreeRTOS will resume the task, but this will result in wrong derived values, hence the requirement for restarting the routine. I also cannot keep the task routine under critical section, because I should not be missing any interrupts.
Is there a way in FreeRTOS with which I can achieve this? Like a vtaskRestart API. I could have deleted the task and re-created it, but this adds a lot of memory management complications, which I would like to avoid. Currently my only option is to add checks in the routine on a flag to see if a context switch have occured and if yes, restart, else continue.
Googling did not fetch any clue on this. Seems like people never faced such a problem or may be its that this design is poor. In FreeRTOS forum, few who asked for a task-restart didn't seem to have this same problem. stackOverflow didn't have a result on freertos + task + restart. So, this could be the first post with this tag combination ;)
Can someone please tell me if this is directly possible in FreeRTOS?
You can use semaphore for this purpose. If you decide using semaphore, you should do the steps below.
Firstly, you should create a binary semaphore.
The semaphore must be given in the interrupt routine with
xSemaphoreGiveFromISR( Example_xSemaphore, &xHigherPriorityTaskWoken
);
And, you must check taking semaphore in the task.
void vExample_Task( void * pvParameters )
{
for( ;; )
{
if (xSemaphoreTake( Example_xSemaphore, Example_PROCESS_TIME)==pdTRUE)
{
}
}
}
For this purpose you should use a queue and use the queue peek function to yield at your volatile data.
I'm using it as I have a real time timer and this way I make the time available to all my task, without any blocking.
Here it how it goes:
Declare the queue:
xQueueHandle RTC_Time_Queue;
Create the queue of 1 element:
RTC_Time_Queue = xQueueCreate( 1, sizeof(your volatile struct) );
Overwrite the queue everytime your interrupt occurs:
xQueueOverwriteFromISR(RTC_Time_Queue, (void*) &time);
And from other task peek the queue:
xQueuePeek(RTC_GetReadQueue(), (void*) &TheTime, 0);
The 0 at the end of xQueuePeek means you don't want to wait if the queue is empty. The queue peek won't delete the value in the queue so it will be present every time you peek and the code will never stop.
Also you should avoid having variable being accessed from ISR and the RTOS code as you may get unexpected corruption.

Resources