3

Is there anything similar to PPL's task continuations in TBB? I am aware of the low level TBB method of manuall allocating tbb::tasks and manually allocating continuation tasks too and managing ref counts manually for them:

struct FibContinuation: public task {
    long* const sum;
    long x, y;
    FibContinuation( long* sum_ ) : sum(sum_) {}
    task* execute() {
        *sum = x+y;
        return NULL;
    }
};

struct FibTask: public task {
    const long n;
    long* const sum;
    FibTask( long n_, long* sum_ ) :
        n(n_), sum(sum_)
    {}
    task* execute() {
        if( n<CutOff ) {
            *sum = SerialFib(n);
            return NULL;
        } else {
            // long x, y; This line removed 
            FibContinuation& c = 
                *new( allocate_continuation() ) FibContinuation(sum);
            FibTask& a = *new( c.allocate_child() ) FibTask(n-2,&c.x);
            FibTask& b = *new( c.allocate_child() ) FibTask(n-1,&c.y);
            // Set ref_count to "two children plus one for the wait".
            c.set_ref_count(2);
            spawn( b );
            spawn( a );
        // *sum = x+y; This line removed
            return NULL;
        }
    }
};

That's simply horrible. You have to in advance know how many child tasks you will spawn, and manually set the reference count appropriately. This is very fragile coding...

PPL's way of specifying continuations is just so straightforward:

create_task([]()->bool
{
  // compute something then return a bool result
  return true
}).then([](bool aComputedResult)
{
  // do something with aComputedResult
});

How do you achieve that in TBB?

Ed Rowlett-Barbu
  • 1,489
  • 9
  • 24
  • 1
    Just some random thoughts. Boost futures have `then`, I think since 1.53, probably not all methods are implemented while others might have some bugs. Check the docs. TBB doesn't have something similar, one thing which comes close is the TBB flow-graph. You can create a flow scheme for your messages, TBB will parallelize wherever possible. While this is not as simple as a `then`, it is also way more powerful. Lastly, I want to mention that TBB isn't focused on task-based parallelism but on algorithm-patterns which abstract data-parallel problems away. – Stephan Dollberg Apr 15 '13 at 15:03
  • @bamboon hmm, I'll give that a thought, thanks for answering – Ed Rowlett-Barbu Apr 16 '13 at 11:16
  • The question is comparing implementations in two different language dialects, and complaining about the fragility of the the problem-specific details present in one and not the other... The TBB example could loop over new-increment-spawn twice and now the fragility is gone. There's probably a more efficient spawn_all() or something, too! – mabraham Nov 23 '13 at 15:21

2 Answers2

4

Yes, there are several recommended TBB continuation styles you can read about at http://www.threadingbuildingblocks.org/docs/help/reference/task_scheduler/catalog_of_recommended_task_patterns.htm. However, by design of the TBB library, none of them use C++11 constructs like your PPL example.

If your question is really "does TBB have a C++11 interface for task continuation," then the answer is "no."

Anton
  • 5,863
  • 1
  • 18
  • 49
mabraham
  • 2,318
  • 1
  • 25
  • 23
1

There isn't anything directly, I posted an example of how to do this with task_group (which is in tbb) ages ago on my blog here.

The syntax is similar but not 100% the same since it was posted before task existed.

void SimpleContinuation()
{
    auto task1 = run_task([](){ContinueableTask(1);});
    //task 2 depends on task 1
    auto task2 = run_when(task1, [](){ContinueableTask(2);});
    wait_for_all(task1, task2);
}
Rick
  • 3,145
  • 15
  • 17
  • It does not answer the question regarding how is it in TBB. TBB has no 'run_task' and 'run_when' methods – Anton Apr 30 '14 at 09:07
  • Sorry, I didn't get that these functions are implemented in your blog on top of the task_group – Anton Apr 30 '14 at 12:00