- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I changed the example from TBB Tutorial section 11.5.4 so that FibTask::execute() spawns the recycled task instead of returning this pointer. When the code is compiled and run in debug mode it causes assertion failure with the message task in READY state upon return from method execute(). Can someone help me to figure out what it is going on? Thank you.
Below is the complete example.
[cpp]// // example from TBB tutorial section 11.5.4 // #include#include "tbb/task.h" const long CutOff = 5; long SerialFib(long n) { if(n<2) return n; else return SerialFib(n-1)+SerialFib(n-2); } struct FibContinuation : public tbb::task { long* const sum; long x, y; FibContinuation(long* sum_): sum(sum_) {} task* execute() { *sum = x + y; return NULL; } }; struct FibTask : public tbb::task { long n; long* sum; FibTask(long n_, long* sum_): n(n_), sum(sum_) {} task* execute() { if(n
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is an unfortunate trap that exists in TBB when recycling tasks. There is a poorly documented restriction that while t.execute() is running, task t must not be spawned. The reason is after t.execute() returns, the scheduler inspects some state internal to t. But if t has been spawned in the meantime, all kinds of asynchronous actions may be occuring to t, including deletion!
We did not notice the trap for a few years because we were always using thetrick where t.execute() returns a pointer to the recycled task instead of spawning it.(The trick exists to simulate tail-call). Then after a few releases, some users were falling into a similar trap where a task t recycled as a continuation started running before t.execute() returned. Hence the invention of task::recycle_as_safe_continuation(), which avoids the problem in that case. In theory we could add a similar task::recycle_as_safe_child_of(), and an internal rule that if such a recycled task is spawned, it is not really spawned until t.execute() returns. But that burdens everyone (performance wise) with yet-another-internal-branch and complication to explain, and wouldn't solve the problem completely because users could still trap themselves by spawning such a recycled task and then waiting for it to complete.
So the basic rule is that a task object t cannot be put in jeopardy of having two simultaneous invocations of t.execute(). The assertion detects a case of such jeopardy.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page