Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.
2465 Discussions

20100406 stable open-source release is available

Vladimir_P_1234567890
440 Views

20100406 open-source release

Changes (w.r.t. 20100310 open-source release):

- Added support for Microsoft* Visual Studio* 2010, including binaries.
- Added parallel_pipeline function and companion classes and functions
that provide a strongly typed lambda-friendly pipeline interface.
- Reworked enumerable_thread_specific to use a custom implementation of
hash map that is more efficient for ETS usage models.
- Added example for class task_group; see examples/task_group/sudoku.
- Removed two examples, as they were long outdated and superceded:
pipeline/text_filter (use pipeline/square);
parallel_while/parallel_preorder (use parallel_do/parallel_preorder).
-
- Other fixes and changes in code, tests, and examples.

Bugs fixed:

- Eliminated build errors with MinGW32.
- Fixed post-build step and other issues in VS projects for examples.
- Fixed discrepancy between scalable_realloc and scalable_msize that
caused crashes with malloc replacement on Windows.


--Vladimir

0 Kudos
9 Replies
nagy
New Contributor I
440 Views
Why doesconcrete_filter store the "my_body" by value and not reference or pointer? Could be a problem when one wants to reference the body externally.

I guess this functionality is mostly for lambdas.... but would be nice if one could use function objects and the like.
e.g
class MyClass
{
public:
public RunMyFilters
{
auto chain = tbb::make_filter(tbb::filter::serial_in_order,myInputFuncObject_) &
tbb::make_filter(tbb::filter::serial_in_order,myOutputFuncObject_);
tbb::parallel_pipeline(4, chain);
}
size_t SomeCount()
{
returnmyInputFilter_.SomeCount(); // Will this work???
}
private:
InputFunc myInputFuncObject_;
OutputFunc myOutputFuncObject_;
};
EDIT:
The changes document also mention "Added a PDF file with recommended Design Patterns for TBB.". But I cannot find such a file.
EDIT2:
I would also like to ask about the rationale behind flow_control. Previously as stated in the reference,
"It should return NULL if there are no more items inthe stream.". However when using the parallel_pipeline this is no longer the case, it continues even if NULL was returned, it will only be stopped if the flow_control.stop() is called. Whats the reason behind this?
0 Kudos
ARCH_R_Intel
Employee
440 Views

Yes, the functors are copied by value in order to support lambdas. Using move constructors would have been better, but that requires C++0x support.

We had long debates over the flow_control feature. We needed some way for the first filter to indicate end-of-stream. Returning NULL was no longer an option because the functors can return a value of any type, not just pointer types. Proposed solutions were:

  • Have the filter return a std::pair, where the bool indicated whether end-of-file had been reached.
  • Have the filter return some kind of wrapper that would hold either the value or a special bool value.
  • Have the filter return a special value marking end of file, and let the user specific the special value.
  • The flow_control feature.

The flow_control variant seemed to be the least evil.

0 Kudos
nagy
New Contributor I
440 Views
Yes, I was just reading up on rvalue references and moveconstructors before I would do such a suggestion. Wouldn't it be possible to implement C++0x moveconstructors and disable them with a define? e.g #ifdef C++0x
0 Kudos
nagy
New Contributor I
440 Views
I would like to suggest that make_filter takes the "body" by value instead of reference to make it explicit that a copy is used. Currently the only way to find this out is to go into the implementation. Implicitbehavior like thiscould in my opinion cause somemisunderstandingsand users might potentiallycreate bugs.
0 Kudos
Alexey-Kukanov
Employee
440 Views
Quoting nagy
Why doesconcrete_filter store the "my_body" by value and not reference or pointer? Could be a problem when one wants to reference the body externally.
I guess this functionality is mostly for lambdas.... but would be nice if one could use function objects and the like.


The reason for storing a copy is that the filter can be constructed using a temporary object (not necessary a lambda but a function objects as well) outside of the expression that starts parallel_pipeline:

auto chain = tbb::make_filter(tbb::filter::serial_in_order,InputFunc()) &
tbb::make_filter(tbb::filter::serial_in_order,OutputFunc());
tbb::parallel_pipeline(4, chain);

If body is stored by reference, this won't work because the temporaries are destroyed before the call to parallel_pipeline. Actually, I am not sure how rvalue references would help in this usage scenario. We do the same in class tbb_thread; the auxiliary thread_closure class holds a copy of function object in order to pass it to another OS thread.

Anyway, I think it should not be a huge issue. Generally, function objects are supposed to be small and copy-constructible easily; all heavy and/or changing state should better be kept in separate instances referenced from the function object.

0 Kudos
Alexey-Kukanov
Employee
440 Views
The reason for storing a copy is that the filter can be constructed using a temporary object (not necessary a lambda but a function objects as well) outside of the expression that starts parallel_pipeline:
auto chain = tbb::make_filter(tbb::filter::serial_in_order,InputFunc()) &
tbb::make_filter(tbb::filter::serial_in_order,OutputFunc());
tbb::parallel_pipeline(4, chain);

If body is stored by reference, this won't work because the temporaries are destroyed before the call to parallel_pipeline.


Actually, looking at the code I see that we do have this problem! Because the copies are createdexactly in the call to parallel_pipeline, not earlier. Surprise surprise :)
0 Kudos
Alexey-Kukanov
Employee
440 Views
Quoting nagy
I would like to suggest that make_filter takes the "body" by value instead of reference to make it explicit that a copy is used. Currently the only way to find this out is to go into the implementation. Implicitbehavior like thiscould in my opinion cause somemisunderstandingsand users might potentiallycreate bugs.


Or go into the documentation instead (which is not yet available but will be, soon).
Passing by value could cause creation ofanother, excessivecopy. I am not sure all compilers would be able to eliminate it.

0 Kudos
Dmitry_Vyukov
Valued Contributor I
440 Views
The reason is simple. If a functor is passed by value, then a user can always put a pointer to a shared body into it and get shared functors.
And if a functor is passed by pointer, then a user has no choice.
Plus pass by value is safer in a single-threaded context, and a way safer and faster in a multi-threaded context.

Wrt misunderstandings, pass by value functors/allocators are used in C++ for years. So IMVHO in the context of C++ it's quite expected behavior.


0 Kudos
Vladimir_P_1234567890
440 Views
Quoting nagy
EDIT:
The changes document also mention "Added a PDF file with recommended Design Patterns for TBB.". But I cannot find such a file.
File has been recently uploaded to the site. you can find on the documentation page.

--Vladimir
0 Kudos
Reply