
"Oliver Kowalke" <k-oli@gmx.de> writes:
It's OK if the nested task was spawned by this task. If the nested task was spawned by an unrelated task, then these things become real issues.
Sorry I don't know the semantic of an 'urelated task'. Do you mean a task created by another worker-thread?
Some (user-level) thread does pool.submit(task1), and another (user-level) thread does pool.submit(task2). These tasks are unrelated: one was not spawned by the other. They may also not share any data: one may be spawned by the GUI thread, and another by a network thread.
Also, if your thread runs an unrelated task the condition it was waiting for might become ready, but the task is unable to resume because the new unrelated task is still running. This is why you might choose to migrate fibers between threads:
1. task A spawns tasks B 2. task B gets picked up by other worker threads 3. task N is submitted to the queue, but there are no free workers 4. task A blocks on task B 5. the thread running task A picks up task N 6. task B completes. * task A is now ready to run, but its thread is running task N. * Migrate task A to the thread that just completed task B, and resume task A (easily done with SwitchToFiber). Everything is fine and dandy.... except the thread-local variables and thread ID for task A just changed :-(
I got it. This happens if migration of fibered tasks between worker-threads happens.
The problem (changed thread ID) happens if you migrate fibered tasks between threads once they've started, yes. That problem was an aside: I was trying to explain why you might do that in the first place.
But what about executing fibered tasks only in the worker-thread which has created the fiber?
There is still a problem (just different).
Then a new task is dequeued from the local worker-queue, then from the global -queue and then from worker-queues of other threads.
Here's the problem: if you take a task from the global queue or the worker queue of another thread and *don't* do thread migration, then you risk delaying a task and potentially deadlocking the pool. Consider the sequence above: at step 5, task A is blocked, and the only task it is waiting for (B) has been picked up by an idle worker thread. The thread running task A now takes a new task from the global queue (task N). Suppose this is a really long-running task (calculate PI to 3 million digits, defrag a hard disk, etc.). Without thread migration, task A cannot resume until task N is complete. Obviously, if task N blocks on a future you can then reschedule task A, but if it doesn't then you don't get that opportunity. If task N waits for another event to be triggered from task A (e.g. a notify on a condition variable) then it will never get it because task A is suspended, and so the pool thread will deadlock *even when task A is ready to run*. Anthony -- Anthony Williams Author of C++ Concurrency in Action | http://www.manning.com/williams Custom Software Development | http://www.justsoftwaresolutions.co.uk Just Software Solutions Ltd, Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK