_aggregator_impl.h   _aggregator_impl.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB__aggregator_impl_H #ifndef __TBB__aggregator_impl_H
#define __TBB__aggregator_impl_H #define __TBB__aggregator_impl_H
#include "../atomic.h" #include "../atomic.h"
#if !__TBBMALLOC_BUILD #if !__TBBMALLOC_BUILD
#include "../tbb_profiling.h" #include "../tbb_profiling.h"
#endif #endif
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 _concurrent_queue_impl.h   _concurrent_queue_impl.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB__concurrent_queue_impl_H #ifndef __TBB__concurrent_queue_impl_H
#define __TBB__concurrent_queue_impl_H #define __TBB__concurrent_queue_impl_H
#ifndef __TBB_concurrent_queue_H #ifndef __TBB_concurrent_queue_H
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#include "../tbb_stddef.h" #include "../tbb_stddef.h"
#include "../tbb_machine.h" #include "../tbb_machine.h"
#include "../atomic.h" #include "../atomic.h"
#include "../spin_mutex.h" #include "../spin_mutex.h"
#include "../cache_aligned_allocator.h" #include "../cache_aligned_allocator.h"
#include "../tbb_exception.h" #include "../tbb_exception.h"
#include "../tbb_profiling.h" #include "../tbb_profiling.h"
#include <new> #include <new>
#include <utility>
#if !TBB_USE_EXCEPTIONS && _MSC_VER #if !TBB_USE_EXCEPTIONS && _MSC_VER
// Suppress "C++ exception handler used, but unwind semantics are not e nabled" warning in STL headers // Suppress "C++ exception handler used, but unwind semantics are not e nabled" warning in STL headers
#pragma warning (push) #pragma warning (push)
#pragma warning (disable: 4530) #pragma warning (disable: 4530)
#endif #endif
#include <iterator> #include <iterator>
#if !TBB_USE_EXCEPTIONS && _MSC_VER #if !TBB_USE_EXCEPTIONS && _MSC_VER
skipping to change at line 68 skipping to change at line 61
#if !__TBB_TEMPLATE_FRIENDS_BROKEN #if !__TBB_TEMPLATE_FRIENDS_BROKEN
// forward declaration // forward declaration
namespace strict_ppl { namespace strict_ppl {
template<typename T, typename A> class concurrent_queue; template<typename T, typename A> class concurrent_queue;
} }
template<typename T, typename A> class concurrent_bounded_queue; template<typename T, typename A> class concurrent_bounded_queue;
namespace deprecated {
template<typename T, typename A> class concurrent_queue;
}
#endif #endif
//! For internal use only. //! For internal use only.
namespace strict_ppl { namespace strict_ppl {
//! @cond INTERNAL //! @cond INTERNAL
namespace internal { namespace internal {
using namespace tbb::internal; using namespace tbb::internal;
typedef size_t ticket; typedef size_t ticket;
template<typename T> class micro_queue ; template<typename T> class micro_queue ;
template<typename T> class micro_queue_pop_finalizer ; template<typename T> class micro_queue_pop_finalizer ;
template<typename T> class concurrent_queue_base_v3; template<typename T> class concurrent_queue_base_v3;
template<typename T> struct concurrent_queue_rep;
//! parts of concurrent_queue_rep that do not have references to micro_queu e //! parts of concurrent_queue_rep that do not have references to micro_queu e
/** /**
* For internal use only. * For internal use only.
*/ */
struct concurrent_queue_rep_base : no_copy { struct concurrent_queue_rep_base : no_copy {
template<typename T> friend class micro_queue; template<typename T> friend class micro_queue;
template<typename T> friend class concurrent_queue_base_v3; template<typename T> friend class concurrent_queue_base_v3;
protected: protected:
skipping to change at line 156 skipping to change at line 147
// unary minus operator applied to unsigned type, result still unsigned // unary minus operator applied to unsigned type, result still unsigned
#pragma warning( push ) #pragma warning( push )
#pragma warning( disable: 4146 ) #pragma warning( disable: 4146 )
#endif #endif
//! A queue using simple locking. //! A queue using simple locking.
/** For efficiency, this class has no constructor. /** For efficiency, this class has no constructor.
The caller is expected to zero-initialize it. */ The caller is expected to zero-initialize it. */
template<typename T> template<typename T>
class micro_queue : no_copy { class micro_queue : no_copy {
public:
typedef void (*item_constructor_t)(T* location, const void* src);
private:
typedef concurrent_queue_rep_base::page page; typedef concurrent_queue_rep_base::page page;
//! Class used to ensure exception-safety of method "pop" //! Class used to ensure exception-safety of method "pop"
class destroyer: no_copy { class destroyer: no_copy {
T& my_value; T& my_value;
public: public:
destroyer( T& value ) : my_value(value) {} destroyer( T& value ) : my_value(value) {}
~destroyer() {my_value.~T();} ~destroyer() {my_value.~T();}
}; };
void copy_item( page& dst, size_t index, const void* src ) { void copy_item( page& dst, size_t dindex, const void* src, item_constru
new( &get_ref(dst,index) ) T(*static_cast<const T*>(src)); ctor_t construct_item ) {
construct_item( &get_ref(dst, dindex), src );
} }
void copy_item( page& dst, size_t dindex, const page& src, size_t sinde void copy_item( page& dst, size_t dindex, const page& src, size_t sinde
x ) { x,
new( &get_ref(dst,dindex) ) T( get_ref(const_cast<page&>(src),sinde item_constructor_t construct_item )
x) ); {
T& src_item = get_ref( const_cast<page&>(src), sindex );
construct_item( &get_ref(dst, dindex), static_cast<const void*>(&sr
c_item) );
} }
void assign_and_destroy_item( void* dst, page& src, size_t index ) { void assign_and_destroy_item( void* dst, page& src, size_t index ) {
T& from = get_ref(src,index); T& from = get_ref(src,index);
destroyer d(from); destroyer d(from);
*static_cast<T*>(dst) = from; *static_cast<T*>(dst) = tbb::internal::move( from );
} }
void spin_wait_until_my_turn( atomic<ticket>& counter, ticket k, concur rent_queue_rep_base& rb ) const ; void spin_wait_until_my_turn( atomic<ticket>& counter, ticket k, concur rent_queue_rep_base& rb ) const ;
public: public:
friend class micro_queue_pop_finalizer<T>; friend class micro_queue_pop_finalizer<T>;
struct padded_page: page { struct padded_page: page {
//! Not defined anywhere - exists to quiet warnings. //! Not defined anywhere - exists to quiet warnings.
padded_page(); padded_page();
skipping to change at line 206 skipping to change at line 203
} }
atomic<page*> head_page; atomic<page*> head_page;
atomic<ticket> head_counter; atomic<ticket> head_counter;
atomic<page*> tail_page; atomic<page*> tail_page;
atomic<ticket> tail_counter; atomic<ticket> tail_counter;
spin_mutex page_mutex; spin_mutex page_mutex;
void push( const void* item, ticket k, concurrent_queue_base_v3<T>& bas void push( const void* item, ticket k, concurrent_queue_base_v3<T>& bas
e ) ; e,
item_constructor_t construct_item ) ;
bool pop( void* dst, ticket k, concurrent_queue_base_v3<T>& base ) ; bool pop( void* dst, ticket k, concurrent_queue_base_v3<T>& base ) ;
micro_queue& assign( const micro_queue& src, concurrent_queue_base_v3<T micro_queue& assign( const micro_queue& src, concurrent_queue_base_v3<T
>& base ) ; >& base,
item_constructor_t construct_item ) ;
page* make_copy( concurrent_queue_base_v3<T>& base, const page* src_pag page* make_copy( concurrent_queue_base_v3<T>& base, const page* src_pag
e, size_t begin_in_page, size_t end_in_page, ticket& g_index ) ; e, size_t begin_in_page,
size_t end_in_page, ticket& g_index, item_constructor_t construct_i
tem ) ;
void invalidate_page_and_rethrow( ticket k ) ; void invalidate_page_and_rethrow( ticket k ) ;
}; };
template<typename T> template<typename T>
void micro_queue<T>::spin_wait_until_my_turn( atomic<ticket>& counter, tick et k, concurrent_queue_rep_base& rb ) const { void micro_queue<T>::spin_wait_until_my_turn( atomic<ticket>& counter, tick et k, concurrent_queue_rep_base& rb ) const {
for( atomic_backoff b(true);;b.pause() ) { for( atomic_backoff b(true);;b.pause() ) {
ticket c = counter; ticket c = counter;
if( c==k ) return; if( c==k ) return;
else if( c&1 ) { else if( c&1 ) {
++rb.n_invalid_entries; ++rb.n_invalid_entries;
throw_exception( eid_bad_last_alloc ); throw_exception( eid_bad_last_alloc );
} }
} }
} }
template<typename T> template<typename T>
void micro_queue<T>::push( const void* item, ticket k, concurrent_queue_bas void micro_queue<T>::push( const void* item, ticket k, concurrent_queue_bas
e_v3<T>& base ) { e_v3<T>& base,
item_constructor_t construct_item )
{
k &= -concurrent_queue_rep_base::n_queue; k &= -concurrent_queue_rep_base::n_queue;
page* p = NULL; page* p = NULL;
size_t index = modulo_power_of_two( k/concurrent_queue_rep_base::n_queu e, base.my_rep->items_per_page); size_t index = modulo_power_of_two( k/concurrent_queue_rep_base::n_queu e, base.my_rep->items_per_page);
if( !index ) { if( !index ) {
__TBB_TRY { __TBB_TRY {
concurrent_queue_page_allocator& pa = base; concurrent_queue_page_allocator& pa = base;
p = pa.allocate_page(); p = pa.allocate_page();
} __TBB_CATCH (...) { } __TBB_CATCH (...) {
++base.my_rep->n_invalid_entries; ++base.my_rep->n_invalid_entries;
invalidate_page_and_rethrow( k ); invalidate_page_and_rethrow( k );
} }
p->mask = 0; p->mask = 0;
p->next = NULL; p->next = NULL;
} }
if( tail_counter!=k ) spin_wait_until_my_turn( tail_counter, k, *base.m y_rep ); if( tail_counter != k ) spin_wait_until_my_turn( tail_counter, k, *base .my_rep );
call_itt_notify(acquired, &tail_counter); call_itt_notify(acquired, &tail_counter);
if( p ) { if( p ) {
spin_mutex::scoped_lock lock( page_mutex ); spin_mutex::scoped_lock lock( page_mutex );
page* q = tail_page; page* q = tail_page;
if( is_valid_page(q) ) if( is_valid_page(q) )
q->next = p; q->next = p;
else else
head_page = p; head_page = p;
tail_page = p; tail_page = p;
} else { } else {
p = tail_page; p = tail_page;
} }
__TBB_TRY { __TBB_TRY {
copy_item( *p, index, item ); copy_item( *p, index, item, construct_item );
// If no exception was thrown, mark item as present. // If no exception was thrown, mark item as present.
itt_hide_store_word(p->mask, p->mask | uintptr_t(1)<<index); itt_hide_store_word(p->mask, p->mask | uintptr_t(1)<<index);
call_itt_notify(releasing, &tail_counter); call_itt_notify(releasing, &tail_counter);
tail_counter += concurrent_queue_rep_base::n_queue; tail_counter += concurrent_queue_rep_base::n_queue;
} __TBB_CATCH (...) { } __TBB_CATCH (...) {
++base.my_rep->n_invalid_entries; ++base.my_rep->n_invalid_entries;
call_itt_notify(releasing, &tail_counter); call_itt_notify(releasing, &tail_counter);
tail_counter += concurrent_queue_rep_base::n_queue; tail_counter += concurrent_queue_rep_base::n_queue;
__TBB_RETHROW(); __TBB_RETHROW();
} }
skipping to change at line 298 skipping to change at line 301
success = true; success = true;
assign_and_destroy_item( dst, p, index ); assign_and_destroy_item( dst, p, index );
} else { } else {
--base.my_rep->n_invalid_entries; --base.my_rep->n_invalid_entries;
} }
} }
return success; return success;
} }
template<typename T> template<typename T>
micro_queue<T>& micro_queue<T>::assign( const micro_queue<T>& src, concurre micro_queue<T>& micro_queue<T>::assign( const micro_queue<T>& src, concurre
nt_queue_base_v3<T>& base ) { nt_queue_base_v3<T>& base,
item_constructor_t construct_item )
{
head_counter = src.head_counter; head_counter = src.head_counter;
tail_counter = src.tail_counter; tail_counter = src.tail_counter;
page_mutex = src.page_mutex;
const page* srcp = src.head_page; const page* srcp = src.head_page;
if( is_valid_page(srcp) ) { if( is_valid_page(srcp) ) {
ticket g_index = head_counter; ticket g_index = head_counter;
__TBB_TRY { __TBB_TRY {
size_t n_items = (tail_counter-head_counter)/concurrent_queue_ rep_base::n_queue; size_t n_items = (tail_counter-head_counter)/concurrent_queue_ rep_base::n_queue;
size_t index = modulo_power_of_two( head_counter/concurrent_que ue_rep_base::n_queue, base.my_rep->items_per_page ); size_t index = modulo_power_of_two( head_counter/concurrent_que ue_rep_base::n_queue, base.my_rep->items_per_page );
size_t end_in_first_page = (index+n_items<base.my_rep->items_pe r_page)?(index+n_items):base.my_rep->items_per_page; size_t end_in_first_page = (index+n_items<base.my_rep->items_pe r_page)?(index+n_items):base.my_rep->items_per_page;
head_page = make_copy( base, srcp, index, end_in_first_page, g_ index ); head_page = make_copy( base, srcp, index, end_in_first_page, g_ index, construct_item );
page* cur_page = head_page; page* cur_page = head_page;
if( srcp != src.tail_page ) { if( srcp != src.tail_page ) {
for( srcp = srcp->next; srcp!=src.tail_page; srcp=srcp->nex t ) { for( srcp = srcp->next; srcp!=src.tail_page; srcp=srcp->nex t ) {
cur_page->next = make_copy( base, srcp, 0, base.my_rep- >items_per_page, g_index ); cur_page->next = make_copy( base, srcp, 0, base.my_rep- >items_per_page, g_index, construct_item );
cur_page = cur_page->next; cur_page = cur_page->next;
} }
__TBB_ASSERT( srcp==src.tail_page, NULL ); __TBB_ASSERT( srcp==src.tail_page, NULL );
size_t last_index = modulo_power_of_two( tail_counter/concu rrent_queue_rep_base::n_queue, base.my_rep->items_per_page ); size_t last_index = modulo_power_of_two( tail_counter/concu rrent_queue_rep_base::n_queue, base.my_rep->items_per_page );
if( last_index==0 ) last_index = base.my_rep->items_per_pag e; if( last_index==0 ) last_index = base.my_rep->items_per_pag e;
cur_page->next = make_copy( base, srcp, 0, last_index, g_in dex ); cur_page->next = make_copy( base, srcp, 0, last_index, g_in dex, construct_item );
cur_page = cur_page->next; cur_page = cur_page->next;
} }
tail_page = cur_page; tail_page = cur_page;
} __TBB_CATCH (...) { } __TBB_CATCH (...) {
invalidate_page_and_rethrow( g_index ); invalidate_page_and_rethrow( g_index );
} }
} else { } else {
head_page = tail_page = NULL; head_page = tail_page = NULL;
} }
return *this; return *this;
skipping to change at line 355 skipping to change at line 359
if( is_valid_page(q) ) if( is_valid_page(q) )
q->next = invalid_page; q->next = invalid_page;
else else
head_page = invalid_page; head_page = invalid_page;
tail_page = invalid_page; tail_page = invalid_page;
} }
__TBB_RETHROW(); __TBB_RETHROW();
} }
template<typename T> template<typename T>
concurrent_queue_rep_base::page* micro_queue<T>::make_copy( concurrent_queu concurrent_queue_rep_base::page* micro_queue<T>::make_copy( concurrent_queu
e_base_v3<T>& base, const concurrent_queue_rep_base::page* src_page, size_t e_base_v3<T>& base,
begin_in_page, size_t end_in_page, ticket& g_index ) { const concurrent_queue_rep_base::page* src_page, size_t begin_in_page,
size_t end_in_page,
ticket& g_index, item_constructor_t construct_item )
{
concurrent_queue_page_allocator& pa = base; concurrent_queue_page_allocator& pa = base;
page* new_page = pa.allocate_page(); page* new_page = pa.allocate_page();
new_page->next = NULL; new_page->next = NULL;
new_page->mask = src_page->mask; new_page->mask = src_page->mask;
for( ; begin_in_page!=end_in_page; ++begin_in_page, ++g_index ) for( ; begin_in_page!=end_in_page; ++begin_in_page, ++g_index )
if( new_page->mask & uintptr_t(1)<<begin_in_page ) if( new_page->mask & uintptr_t(1)<<begin_in_page )
copy_item( *new_page, begin_in_page, *src_page, begin_in_page ) ; copy_item( *new_page, begin_in_page, *src_page, begin_in_page, construct_item );
return new_page; return new_page;
} }
template<typename T> template<typename T>
class micro_queue_pop_finalizer: no_copy { class micro_queue_pop_finalizer: no_copy {
typedef concurrent_queue_rep_base::page page; typedef concurrent_queue_rep_base::page page;
ticket my_ticket; ticket my_ticket;
micro_queue<T>& my_queue; micro_queue<T>& my_queue;
page* my_page; page* my_page;
concurrent_queue_page_allocator& allocator; concurrent_queue_page_allocator& allocator;
skipping to change at line 443 skipping to change at line 450
friend struct concurrent_queue_rep<T>; friend struct concurrent_queue_rep<T>;
friend class micro_queue<T>; friend class micro_queue<T>;
friend class concurrent_queue_iterator_rep<T>; friend class concurrent_queue_iterator_rep<T>;
friend class concurrent_queue_iterator_base_v3<T>; friend class concurrent_queue_iterator_base_v3<T>;
protected: protected:
typedef typename concurrent_queue_rep<T>::page page; typedef typename concurrent_queue_rep<T>::page page;
private: private:
typedef typename micro_queue<T>::padded_page padded_page; typedef typename micro_queue<T>::padded_page padded_page;
typedef typename micro_queue<T>::item_constructor_t item_constructor_t;
/* override */ virtual page *allocate_page() { /* override */ virtual page *allocate_page() {
concurrent_queue_rep<T>& r = *my_rep; concurrent_queue_rep<T>& r = *my_rep;
size_t n = sizeof(padded_page) + (r.items_per_page-1)*sizeof(T); size_t n = sizeof(padded_page) + (r.items_per_page-1)*sizeof(T);
return reinterpret_cast<page*>(allocate_block ( n )); return reinterpret_cast<page*>(allocate_block ( n ));
} }
/* override */ virtual void deallocate_page( concurrent_queue_rep_base: :page *p ) { /* override */ virtual void deallocate_page( concurrent_queue_rep_base: :page *p ) {
concurrent_queue_rep<T>& r = *my_rep; concurrent_queue_rep<T>& r = *my_rep;
size_t n = sizeof(padded_page) + (r.items_per_page-1)*sizeof(T); size_t n = sizeof(padded_page) + (r.items_per_page-1)*sizeof(T);
skipping to change at line 475 skipping to change at line 483
/* override */ virtual ~concurrent_queue_base_v3() { /* override */ virtual ~concurrent_queue_base_v3() {
#if TBB_USE_ASSERT #if TBB_USE_ASSERT
size_t nq = my_rep->n_queue; size_t nq = my_rep->n_queue;
for( size_t i=0; i<nq; i++ ) for( size_t i=0; i<nq; i++ )
__TBB_ASSERT( my_rep->array[i].tail_page==NULL, "pages were not freed properly" ); __TBB_ASSERT( my_rep->array[i].tail_page==NULL, "pages were not freed properly" );
#endif /* TBB_USE_ASSERT */ #endif /* TBB_USE_ASSERT */
cache_aligned_allocator<concurrent_queue_rep<T> >().deallocate(my_r ep,1); cache_aligned_allocator<concurrent_queue_rep<T> >().deallocate(my_r ep,1);
} }
//! Enqueue item at tail of queue //! Enqueue item at tail of queue
void internal_push( const void* src ) { void internal_push( const void* src, item_constructor_t construct_item
concurrent_queue_rep<T>& r = *my_rep; ) {
ticket k = r.tail_counter++; concurrent_queue_rep<T>& r = *my_rep;
r.choose(k).push( src, k, *this ); ticket k = r.tail_counter++;
r.choose(k).push( src, k, *this, construct_item );
} }
//! Attempt to dequeue item from queue. //! Attempt to dequeue item from queue.
/** NULL if there was no item to dequeue. */ /** NULL if there was no item to dequeue. */
bool internal_try_pop( void* dst ) ; bool internal_try_pop( void* dst ) ;
//! Get size of queue; result may be invalid if queue is modified concu rrently //! Get size of queue; result may be invalid if queue is modified concu rrently
size_t internal_size() const ; size_t internal_size() const ;
//! check if the queue is empty; thread safe //! check if the queue is empty; thread safe
skipping to change at line 500 skipping to change at line 508
//! free any remaining pages //! free any remaining pages
/* note that the name may be misleading, but it remains so due to a his torical accident. */ /* note that the name may be misleading, but it remains so due to a his torical accident. */
void internal_finish_clear() ; void internal_finish_clear() ;
//! Obsolete //! Obsolete
void internal_throw_exception() const { void internal_throw_exception() const {
throw_exception( eid_bad_alloc ); throw_exception( eid_bad_alloc );
} }
//! copy internal representation //! copy or move internal representation
void assign( const concurrent_queue_base_v3& src ) ; void assign( const concurrent_queue_base_v3& src, item_constructor_t co
nstruct_item ) ;
#if __TBB_CPP11_RVALUE_REF_PRESENT
//! swap internal representation
void internal_swap( concurrent_queue_base_v3& src ) {
std::swap( my_rep, src.my_rep );
}
#endif /* __TBB_CPP11_RVALUE_REF_PRESENT */
}; };
template<typename T> template<typename T>
concurrent_queue_base_v3<T>::concurrent_queue_base_v3() { concurrent_queue_base_v3<T>::concurrent_queue_base_v3() {
const size_t item_size = sizeof(T); const size_t item_size = sizeof(T);
my_rep = cache_aligned_allocator<concurrent_queue_rep<T> >().allocate(1 ); my_rep = cache_aligned_allocator<concurrent_queue_rep<T> >().allocate(1 );
__TBB_ASSERT( (size_t)my_rep % NFS_GetLineSize()==0, "alignment error" ); __TBB_ASSERT( (size_t)my_rep % NFS_GetLineSize()==0, "alignment error" );
__TBB_ASSERT( (size_t)&my_rep->head_counter % NFS_GetLineSize()==0, "al ignment error" ); __TBB_ASSERT( (size_t)&my_rep->head_counter % NFS_GetLineSize()==0, "al ignment error" );
__TBB_ASSERT( (size_t)&my_rep->tail_counter % NFS_GetLineSize()==0, "al ignment error" ); __TBB_ASSERT( (size_t)&my_rep->tail_counter % NFS_GetLineSize()==0, "al ignment error" );
__TBB_ASSERT( (size_t)&my_rep->array % NFS_GetLineSize()==0, "alignment error" ); __TBB_ASSERT( (size_t)&my_rep->array % NFS_GetLineSize()==0, "alignment error" );
skipping to change at line 588 skipping to change at line 603
if( is_valid_page(tp) ) { if( is_valid_page(tp) ) {
__TBB_ASSERT( r.array[i].head_page==tp, "at most one page shoul d remain" ); __TBB_ASSERT( r.array[i].head_page==tp, "at most one page shoul d remain" );
deallocate_page( tp ); deallocate_page( tp );
r.array[i].tail_page = NULL; r.array[i].tail_page = NULL;
} else } else
__TBB_ASSERT( !is_valid_page(r.array[i].head_page), "head page pointer corrupt?" ); __TBB_ASSERT( !is_valid_page(r.array[i].head_page), "head page pointer corrupt?" );
} }
} }
template<typename T> template<typename T>
void concurrent_queue_base_v3<T>::assign( const concurrent_queue_base_v3& s void concurrent_queue_base_v3<T>::assign( const concurrent_queue_base_v3& s
rc ) { rc,
item_constructor_t construct_item )
{
concurrent_queue_rep<T>& r = *my_rep; concurrent_queue_rep<T>& r = *my_rep;
r.items_per_page = src.my_rep->items_per_page; r.items_per_page = src.my_rep->items_per_page;
// copy concurrent_queue_rep. // copy concurrent_queue_rep data
r.head_counter = src.my_rep->head_counter; r.head_counter = src.my_rep->head_counter;
r.tail_counter = src.my_rep->tail_counter; r.tail_counter = src.my_rep->tail_counter;
r.n_invalid_entries = src.my_rep->n_invalid_entries; r.n_invalid_entries = src.my_rep->n_invalid_entries;
// copy micro_queues // copy or move micro_queues
for( size_t i = 0; i<r.n_queue; ++i ) for( size_t i = 0; i < r.n_queue; ++i )
r.array[i].assign( src.my_rep->array[i], *this); r.array[i].assign( src.my_rep->array[i], *this, construct_item);
__TBB_ASSERT( r.head_counter==src.my_rep->head_counter && r.tail_counte r==src.my_rep->tail_counter, __TBB_ASSERT( r.head_counter==src.my_rep->head_counter && r.tail_counte r==src.my_rep->tail_counter,
"the source concurrent queue should not be concurrently modifie d." ); "the source concurrent queue should not be concurrently modifie d." );
} }
template<typename Container, typename Value> class concurrent_queue_iterato r; template<typename Container, typename Value> class concurrent_queue_iterato r;
template<typename T> template<typename T>
class concurrent_queue_iterator_rep: no_assign { class concurrent_queue_iterator_rep: no_assign {
typedef typename micro_queue<T>::padded_page padded_page; typedef typename micro_queue<T>::padded_page padded_page;
skipping to change at line 840 skipping to change at line 857
//! Capacity of the queue //! Capacity of the queue
ptrdiff_t my_capacity; ptrdiff_t my_capacity;
//! Always a power of 2 //! Always a power of 2
size_t items_per_page; size_t items_per_page;
//! Size of an item //! Size of an item
size_t item_size; size_t item_size;
enum copy_specifics { copy, move };
#if __TBB_PROTECTED_NESTED_CLASS_BROKEN #if __TBB_PROTECTED_NESTED_CLASS_BROKEN
public: public:
#endif #endif
template<typename T> template<typename T>
struct padded_page: page { struct padded_page: page {
//! Not defined anywhere - exists to quiet warnings. //! Not defined anywhere - exists to quiet warnings.
padded_page(); padded_page();
//! Not defined anywhere - exists to quiet warnings. //! Not defined anywhere - exists to quiet warnings.
void operator=( const padded_page& ); void operator=( const padded_page& );
//! Must be last field. //! Must be last field.
T last; T last;
}; };
private: private:
virtual void copy_item( page& dst, size_t index, const void* src ) = 0; virtual void copy_item( page& dst, size_t index, const void* src ) = 0;
virtual void assign_and_destroy_item( void* dst, page& src, size_t inde x ) = 0; virtual void assign_and_destroy_item( void* dst, page& src, size_t inde x ) = 0;
protected: protected:
__TBB_EXPORTED_METHOD concurrent_queue_base_v3( size_t item_size ); __TBB_EXPORTED_METHOD concurrent_queue_base_v3( size_t item_size );
virtual __TBB_EXPORTED_METHOD ~concurrent_queue_base_v3(); virtual __TBB_EXPORTED_METHOD ~concurrent_queue_base_v3();
//! Enqueue item at tail of queue //! Enqueue item at tail of queue using copy operation
void __TBB_EXPORTED_METHOD internal_push( const void* src ); void __TBB_EXPORTED_METHOD internal_push( const void* src );
//! Dequeue item from head of queue //! Dequeue item from head of queue
void __TBB_EXPORTED_METHOD internal_pop( void* dst ); void __TBB_EXPORTED_METHOD internal_pop( void* dst );
//! Abort all pending queue operations //! Abort all pending queue operations
void __TBB_EXPORTED_METHOD internal_abort(); void __TBB_EXPORTED_METHOD internal_abort();
//! Attempt to enqueue item onto queue. //! Attempt to enqueue item onto queue using copy operation
bool __TBB_EXPORTED_METHOD internal_push_if_not_full( const void* src ) ; bool __TBB_EXPORTED_METHOD internal_push_if_not_full( const void* src ) ;
//! Attempt to dequeue item from queue. //! Attempt to dequeue item from queue.
/** NULL if there was no item to dequeue. */ /** NULL if there was no item to dequeue. */
bool __TBB_EXPORTED_METHOD internal_pop_if_present( void* dst ); bool __TBB_EXPORTED_METHOD internal_pop_if_present( void* dst );
//! Get size of queue //! Get size of queue
ptrdiff_t __TBB_EXPORTED_METHOD internal_size() const; ptrdiff_t __TBB_EXPORTED_METHOD internal_size() const;
//! Check if the queue is emtpy //! Check if the queue is emtpy
skipping to change at line 901 skipping to change at line 920
//! free any remaining pages //! free any remaining pages
/* note that the name may be misleading, but it remains so due to a his torical accident. */ /* note that the name may be misleading, but it remains so due to a his torical accident. */
void __TBB_EXPORTED_METHOD internal_finish_clear() ; void __TBB_EXPORTED_METHOD internal_finish_clear() ;
//! throw an exception //! throw an exception
void __TBB_EXPORTED_METHOD internal_throw_exception() const; void __TBB_EXPORTED_METHOD internal_throw_exception() const;
//! copy internal representation //! copy internal representation
void __TBB_EXPORTED_METHOD assign( const concurrent_queue_base_v3& src ) ; void __TBB_EXPORTED_METHOD assign( const concurrent_queue_base_v3& src ) ;
#if __TBB_CPP11_RVALUE_REF_PRESENT
//! swap queues
void internal_swap( concurrent_queue_base_v3& src ) {
std::swap( my_capacity, src.my_capacity );
std::swap( items_per_page, src.items_per_page );
std::swap( item_size, src.item_size );
std::swap( my_rep, src.my_rep );
}
#endif /* __TBB_CPP11_RVALUE_REF_PRESENT */
//! Enqueues item at tail of queue using specified operation (copy or m
ove)
void internal_insert_item( const void* src, copy_specifics op_type );
//! Attempts to enqueue at tail of queue using specified operation (cop
y or move)
bool internal_insert_if_not_full( const void* src, copy_specifics op_ty
pe );
//! Assigns one queue to another using specified operation (copy or mov
e)
void internal_assign( const concurrent_queue_base_v3& src, copy_specifi
cs op_type );
private: private:
virtual void copy_page_item( page& dst, size_t dindex, const page& src, size_t sindex ) = 0; virtual void copy_page_item( page& dst, size_t dindex, const page& src, size_t sindex ) = 0;
}; };
//! For internal use only.
/** Backward compatible modification of concurrent_queue_base_v3
@ingroup containers */
class concurrent_queue_base_v8: public concurrent_queue_base_v3 {
protected:
concurrent_queue_base_v8( size_t item_sz ) : concurrent_queue_base_v3(
item_sz ) {}
//! move items
void __TBB_EXPORTED_METHOD move_content( concurrent_queue_base_v8& src
) ;
//! Attempt to enqueue item onto queue using move operation
bool __TBB_EXPORTED_METHOD internal_push_move_if_not_full( const void*
src );
//! Enqueue item at tail of queue using move operation
void __TBB_EXPORTED_METHOD internal_push_move( const void* src );
private:
friend struct micro_queue;
virtual void move_page_item( page& dst, size_t dindex, const page& src,
size_t sindex ) = 0;
virtual void move_item( page& dst, size_t index, const void* src ) = 0;
};
//! Type-independent portion of concurrent_queue_iterator. //! Type-independent portion of concurrent_queue_iterator.
/** @ingroup containers */ /** @ingroup containers */
class concurrent_queue_iterator_base_v3 { class concurrent_queue_iterator_base_v3 {
//! concurrent_queue over which we are iterating. //! concurrent_queue over which we are iterating.
/** NULL if one past last element in queue. */ /** NULL if one past last element in queue. */
concurrent_queue_iterator_rep* my_rep; concurrent_queue_iterator_rep* my_rep;
template<typename C, typename T, typename U> template<typename C, typename T, typename U>
friend bool operator==( const concurrent_queue_iterator<C,T>& i, const concurrent_queue_iterator<C,U>& j ); friend bool operator==( const concurrent_queue_iterator<C,T>& i, const concurrent_queue_iterator<C,U>& j );
skipping to change at line 960 skipping to change at line 1018
//! Meets requirements of a forward iterator for STL. //! Meets requirements of a forward iterator for STL.
/** Value is either the T or const T type of the container. /** Value is either the T or const T type of the container.
@ingroup containers */ @ingroup containers */
template<typename Container, typename Value> template<typename Container, typename Value>
class concurrent_queue_iterator: public concurrent_queue_iterator_base, class concurrent_queue_iterator: public concurrent_queue_iterator_base,
public std::iterator<std::forward_iterator_tag,Value> { public std::iterator<std::forward_iterator_tag,Value> {
#if !defined(_MSC_VER) || defined(__INTEL_COMPILER) #if !defined(_MSC_VER) || defined(__INTEL_COMPILER)
template<typename T, class A> template<typename T, class A>
friend class ::tbb::concurrent_bounded_queue; friend class ::tbb::concurrent_bounded_queue;
template<typename T, class A>
friend class ::tbb::deprecated::concurrent_queue;
#else #else
public: // workaround for MSVC public: // workaround for MSVC
#endif #endif
//! Construct iterator pointing to head of queue. //! Construct iterator pointing to head of queue.
concurrent_queue_iterator( const concurrent_queue_base_v3& queue ) : concurrent_queue_iterator( const concurrent_queue_base_v3& queue ) :
concurrent_queue_iterator_base_v3(queue,__TBB_offsetof(concurrent_q ueue_base_v3::padded_page<Value>,last)) concurrent_queue_iterator_base_v3(queue,__TBB_offsetof(concurrent_q ueue_base_v3::padded_page<Value>,last))
{ {
} }
public: public:
concurrent_queue_iterator() {} concurrent_queue_iterator() {}
/** If Value==Container::value_type, then this routine is the copy cons tructor. /** If Value==Container::value_type, then this routine is the copy cons tructor.
 End of changes. 35 change blocks. 
75 lines changed or deleted 153 lines changed or added


 _concurrent_unordered_impl.h   _concurrent_unordered_impl.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
/* Container implementations in this header are based on PPL implementation s /* Container implementations in this header are based on PPL implementation s
provided by Microsoft. */ provided by Microsoft. */
#ifndef __TBB__concurrent_unordered_impl_H #ifndef __TBB__concurrent_unordered_impl_H
#define __TBB__concurrent_unordered_impl_H #define __TBB__concurrent_unordered_impl_H
#if !defined(__TBB_concurrent_unordered_map_H) && !defined(__TBB_concurrent _unordered_set_H) && !defined(__TBB_concurrent_hash_map_H) #if !defined(__TBB_concurrent_unordered_map_H) && !defined(__TBB_concurrent _unordered_set_H) && !defined(__TBB_concurrent_hash_map_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
skipping to change at line 281 skipping to change at line 273
new(static_cast<void*>(&pnode->my_element)) T(value); new(static_cast<void*>(&pnode->my_element)) T(value);
pnode->init(order_key); pnode->init(order_key);
} __TBB_CATCH(...) { } __TBB_CATCH(...) {
my_node_allocator.deallocate(pnode, 1); my_node_allocator.deallocate(pnode, 1);
__TBB_RETHROW(); __TBB_RETHROW();
} }
return (pnode); return (pnode);
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT
//TODO: try to combine both implementations using poor man forward
//TODO: use RAII scoped guard instead of explicit catch
// Allocate a new node with the given order key and value
nodeptr_t create_node(sokey_t order_key, T &&value) {
nodeptr_t pnode = my_node_allocator.allocate(1);
__TBB_TRY {
new(static_cast<void*>(&pnode->my_element)) T(std::move(value))
;
pnode->init(order_key);
} __TBB_CATCH(...) {
my_node_allocator.deallocate(pnode, 1);
__TBB_RETHROW();
}
return (pnode);
}
#endif //__TBB_CPP11_RVALUE_REF_PRESENT
// Allocate a new node with the given order key; used to allocate dummy nodes // Allocate a new node with the given order key; used to allocate dummy nodes
nodeptr_t create_node(sokey_t order_key) { nodeptr_t create_node(sokey_t order_key) {
nodeptr_t pnode = my_node_allocator.allocate(1); nodeptr_t pnode = my_node_allocator.allocate(1);
pnode->init(order_key); pnode->init(order_key);
return (pnode); return (pnode);
} }
split_ordered_list(allocator_type a = allocator_type()) split_ordered_list(allocator_type a = allocator_type())
: my_node_allocator(a), my_element_count(0) : my_node_allocator(a), my_element_count(0)
{ {
skipping to change at line 604 skipping to change at line 615
nodeptr_t dummy_node = pnode->is_dummy() ? create_node(pnode->g et_order_key()) : create_node(pnode->get_order_key(), pnode->my_element); nodeptr_t dummy_node = pnode->is_dummy() ? create_node(pnode->g et_order_key()) : create_node(pnode->get_order_key(), pnode->my_element);
previous_node = try_insert(previous_node, dummy_node, NULL); previous_node = try_insert(previous_node, dummy_node, NULL);
__TBB_ASSERT(previous_node != NULL, "Insertion must succeed"); __TBB_ASSERT(previous_node != NULL, "Insertion must succeed");
raw_const_iterator where = it++; raw_const_iterator where = it++;
source.erase_node(get_iterator(begin_iterator), where); source.erase_node(get_iterator(begin_iterator), where);
} }
check_range(); check_range();
} }
private: private:
//Need to setup private fields of split_ordered_list in move constructo
r and assignment of concurrent_unordered_base
template <typename Traits>
friend class concurrent_unordered_base;
// Check the list for order violations // Check the list for order violations
void check_range() void check_range()
{ {
#if TBB_USE_ASSERT #if TBB_USE_ASSERT
for (raw_iterator it = raw_begin(); it != raw_end(); ++it) for (raw_iterator it = raw_begin(); it != raw_end(); ++it)
{ {
raw_iterator next_iterator = it; raw_iterator next_iterator = it;
++next_iterator; ++next_iterator;
skipping to change at line 629 skipping to change at line 643
typename allocator_type::template rebind<node>::other my_node_allocator ; // allocator object for nodes typename allocator_type::template rebind<node>::other my_node_allocator ; // allocator object for nodes
size_type my_element_count; // Total item count, not counting dummy nodes size_type my_element_count; // Total item count, not counting dummy nodes
nodeptr_t my_head; // pointer to head node nodeptr_t my_head; // pointer to head node
}; };
// Template class for hash compare // Template class for hash compare
template<typename Key, typename Hasher, typename Key_equality> template<typename Key, typename Hasher, typename Key_equality>
class hash_compare class hash_compare
{ {
public: public:
typedef Hasher hasher;
typedef Key_equality key_equal;
hash_compare() {} hash_compare() {}
hash_compare(Hasher a_hasher) : my_hash_object(a_hasher) {} hash_compare(Hasher a_hasher) : my_hash_object(a_hasher) {}
hash_compare(Hasher a_hasher, Key_equality a_keyeq) : my_hash_object(a_ hasher), my_key_compare_object(a_keyeq) {} hash_compare(Hasher a_hasher, Key_equality a_keyeq) : my_hash_object(a_ hasher), my_key_compare_object(a_keyeq) {}
size_t operator()(const Key& key) const { size_t operator()(const Key& key) const {
return ((size_t)my_hash_object(key)); return ((size_t)my_hash_object(key));
} }
bool operator()(const Key& key1, const Key& key2) const { bool operator()(const Key& key1, const Key& key2) const {
return (!my_key_compare_object(key1, key2)); return (!my_key_compare_object(key1, key2));
} }
Hasher my_hash_object; // The hash object Hasher my_hash_object; // The hash object
Key_equality my_key_compare_object; // The equality comparator object Key_equality my_key_compare_object; // The equality comparator object
}; };
#if _MSC_VER #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#pragma warning(push) #pragma warning(push)
#pragma warning(disable: 4127) // warning 4127 -- while (true) has a consta nt expression in it (for allow_multimapping) #pragma warning(disable: 4127) // warning C4127: conditional expression is constant
#endif #endif
template <typename Traits> template <typename Traits>
class concurrent_unordered_base : public Traits class concurrent_unordered_base : public Traits
{ {
protected: protected:
// Type definitions // Type definitions
typedef concurrent_unordered_base<Traits> self_type; typedef concurrent_unordered_base<Traits> self_type;
typedef typename Traits::value_type value_type; typedef typename Traits::value_type value_type;
typedef typename Traits::key_type key_type; typedef typename Traits::key_type key_type;
typedef typename Traits::hash_compare hash_compare; typedef typename Traits::hash_compare hash_compare;
typedef typename Traits::value_compare value_compare; typedef typename Traits::value_compare value_compare;
typedef typename Traits::allocator_type allocator_type; typedef typename Traits::allocator_type allocator_type;
typedef typename hash_compare::hasher hasher;
typedef typename hash_compare::key_equal key_equal;
typedef typename allocator_type::pointer pointer; typedef typename allocator_type::pointer pointer;
typedef typename allocator_type::const_pointer const_pointer; typedef typename allocator_type::const_pointer const_pointer;
typedef typename allocator_type::reference reference; typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference; typedef typename allocator_type::const_reference const_reference;
typedef typename allocator_type::size_type size_type; typedef typename allocator_type::size_type size_type;
typedef typename allocator_type::difference_type difference_type; typedef typename allocator_type::difference_type difference_type;
typedef split_ordered_list<value_type, typename Traits::allocator_type> solist_t; typedef split_ordered_list<value_type, typename Traits::allocator_type> solist_t;
typedef typename solist_t::nodeptr_t nodeptr_t; typedef typename solist_t::nodeptr_t nodeptr_t;
// Iterators that walk the entire split-order list, including dummy nod es // Iterators that walk the entire split-order list, including dummy nod es
typedef typename solist_t::raw_iterator raw_iterator; typedef typename solist_t::raw_iterator raw_iterator;
typedef typename solist_t::raw_const_iterator raw_const_iterator; typedef typename solist_t::raw_const_iterator raw_const_iterator;
typedef typename solist_t::iterator iterator; // TODO: restore const it erator for unordered_sets typedef typename solist_t::iterator iterator; // TODO: restore const it erator for unordered_sets
typedef typename solist_t::const_iterator const_iterator; typedef typename solist_t::const_iterator const_iterator;
typedef iterator local_iterator; typedef iterator local_iterator;
typedef const_iterator const_local_iterator; typedef const_iterator const_local_iterator;
using Traits::my_hash_compare; using Traits::my_hash_compare;
using Traits::get_key; using Traits::get_key;
using Traits::allow_multimapping; using Traits::allow_multimapping;
static const size_type initial_bucket_number = 8; // Initial number of buckets
private: private:
typedef std::pair<iterator, iterator> pairii_t; typedef std::pair<iterator, iterator> pairii_t;
typedef std::pair<const_iterator, const_iterator> paircc_t; typedef std::pair<const_iterator, const_iterator> paircc_t;
static size_type const pointers_per_table = sizeof(size_type) * 8; // One bucket segment per bit static size_type const pointers_per_table = sizeof(size_type) * 8; // One bucket segment per bit
static const size_type initial_bucket_number = 8; // Initial number of buckets
static const size_type initial_bucket_load = 4; // Initial maximum number of elements per bucket static const size_type initial_bucket_load = 4; // Initial maximum number of elements per bucket
struct call_internal_clear_on_exit{
concurrent_unordered_base* my_instance;
call_internal_clear_on_exit(concurrent_unordered_base* instance) :
my_instance(instance) {}
void dismiss(){ my_instance = NULL;}
~call_internal_clear_on_exit(){
if (my_instance){
my_instance->internal_clear();
}
}
};
protected: protected:
// Constructors/Destructors // Constructors/Destructors
concurrent_unordered_base(size_type n_of_buckets = initial_bucket_numbe r, concurrent_unordered_base(size_type n_of_buckets = initial_bucket_numbe r,
const hash_compare& hc = hash_compare(), const allocator_type& a = allocator_type()) const hash_compare& hc = hash_compare(), const allocator_type& a = allocator_type())
: Traits(hc), my_solist(a), : Traits(hc), my_solist(a),
my_allocator(a), my_maximum_bucket_size((float) initial_bucket_lo ad) my_allocator(a), my_maximum_bucket_size((float) initial_bucket_lo ad)
{ {
if( n_of_buckets == 0) ++n_of_buckets; if( n_of_buckets == 0) ++n_of_buckets;
my_number_of_buckets = 1<<__TBB_Log2((uintptr_t)n_of_buckets*2-1); // round up to power of 2 my_number_of_buckets = 1<<__TBB_Log2((uintptr_t)n_of_buckets*2-1); // round up to power of 2
internal_init(); internal_init();
skipping to change at line 712 skipping to change at line 741
concurrent_unordered_base(const concurrent_unordered_base& right, const allocator_type& a) concurrent_unordered_base(const concurrent_unordered_base& right, const allocator_type& a)
: Traits(right.my_hash_compare), my_solist(a), my_allocator(a) : Traits(right.my_hash_compare), my_solist(a), my_allocator(a)
{ {
internal_init(); internal_init();
internal_copy(right); internal_copy(right);
} }
concurrent_unordered_base(const concurrent_unordered_base& right) concurrent_unordered_base(const concurrent_unordered_base& right)
: Traits(right.my_hash_compare), my_solist(right.get_allocator()), my_allocator(right.get_allocator()) : Traits(right.my_hash_compare), my_solist(right.get_allocator()), my_allocator(right.get_allocator())
{ {
//FIXME:exception safety seems to be broken here
internal_init(); internal_init();
internal_copy(right); internal_copy(right);
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT
concurrent_unordered_base(concurrent_unordered_base&& right)
: Traits(right.my_hash_compare), my_solist(right.get_allocator()),
my_allocator(right.get_allocator())
{
internal_init();
swap(right);
}
concurrent_unordered_base(concurrent_unordered_base&& right, const allo
cator_type& a)
: Traits(right.my_hash_compare), my_solist(a), my_allocator(a)
{
call_internal_clear_on_exit clear_buckets_on_exception(this);
internal_init();
if (a == right.get_allocator()){
this->swap(right);
}else{
my_maximum_bucket_size = right.my_maximum_bucket_size;
my_number_of_buckets = right.my_number_of_buckets;
my_solist.my_element_count = right.my_solist.my_element_count;
if (! right.my_solist.empty()){
nodeptr_t previous_node = my_solist.my_head;
// Move all elements one by one, including dummy ones
for (raw_const_iterator it = ++(right.my_solist.raw_begin()
), last = right.my_solist.raw_end(); it != last; ++it)
{
const nodeptr_t pnode = it.get_node_ptr();
nodeptr_t node;
if (pnode->is_dummy()) {
node = my_solist.create_node(pnode->get_order_key()
);
size_type bucket = __TBB_ReverseBits(pnode->get_ord
er_key()) % my_number_of_buckets;
set_bucket(bucket, node);
}else{
node = my_solist.create_node(pnode->get_order_key()
, std::move(pnode->my_element));
}
previous_node = my_solist.try_insert(previous_node, nod
e, NULL);
__TBB_ASSERT(previous_node != NULL, "Insertion of node
failed. Concurrent inserts in constructor ?");
}
my_solist.check_range();
}
}
clear_buckets_on_exception.dismiss();
}
#endif //__TBB_CPP11_RVALUE_REF_PRESENT
concurrent_unordered_base& operator=(const concurrent_unordered_base& r ight) { concurrent_unordered_base& operator=(const concurrent_unordered_base& r ight) {
if (this != &right) if (this != &right)
internal_copy(right); internal_copy(right);
return (*this); return (*this);
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT
concurrent_unordered_base& operator=(concurrent_unordered_base&& other)
{
if(this != &other){
typedef typename tbb::internal::allocator_traits<allocator_type
>::propagate_on_container_move_assignment pocma_t;
if(pocma_t::value || this->my_allocator == other.my_allocator)
{
concurrent_unordered_base trash (std::move(*this));
swap(other);
if (pocma_t::value) {
using std::swap;
//TODO: swapping allocators here may be a problem, repl
ace with single direction moving
swap(this->my_solist.my_node_allocator, other.my_solist
.my_node_allocator);
swap(this->my_allocator, other.my_allocator);
}
} else {
concurrent_unordered_base moved_copy(std::move(other),this-
>my_allocator);
this->swap(moved_copy);
}
}
return *this;
}
#endif //__TBB_CPP11_RVALUE_REF_PRESENT
#if __TBB_INITIALIZER_LISTS_PRESENT #if __TBB_INITIALIZER_LISTS_PRESENT
//! assignment operator from initializer_list //! assignment operator from initializer_list
concurrent_unordered_base& operator=(std::initializer_list<value_type> const& il) concurrent_unordered_base& operator=(std::initializer_list<value_type> il)
{ {
this->clear(); this->clear();
this->insert(il.begin(),il.end()); this->insert(il.begin(),il.end());
return (*this); return (*this);
} }
#endif //# __TBB_INITIALIZER_LISTS_PRESENT #endif //# __TBB_INITIALIZER_LISTS_PRESENT
~concurrent_unordered_base() { ~concurrent_unordered_base() {
// Delete all node segments // Delete all node segments
internal_clear(); internal_clear();
skipping to change at line 887 skipping to change at line 990
// Ignore hint // Ignore hint
return insert(value).first; return insert(value).first;
} }
template<class Iterator> template<class Iterator>
void insert(Iterator first, Iterator last) { void insert(Iterator first, Iterator last) {
for (Iterator it = first; it != last; ++it) for (Iterator it = first; it != last; ++it)
insert(*it); insert(*it);
} }
#if __TBB_INITIALIZER_LISTS_PRESENT
//! Insert initializer list
void insert(std::initializer_list<value_type> il) {
insert(il.begin(), il.end());
}
#endif
iterator unsafe_erase(const_iterator where) { iterator unsafe_erase(const_iterator where) {
return internal_erase(where); return internal_erase(where);
} }
iterator unsafe_erase(const_iterator first, const_iterator last) { iterator unsafe_erase(const_iterator first, const_iterator last) {
while (first != last) while (first != last)
unsafe_erase(first++); unsafe_erase(first++);
return my_solist.get_iterator(first); return my_solist.get_iterator(first);
} }
skipping to change at line 915 skipping to change at line 1025
if (this != &right) { if (this != &right) {
std::swap(my_hash_compare, right.my_hash_compare); // TODO: che ck what ADL meant here std::swap(my_hash_compare, right.my_hash_compare); // TODO: che ck what ADL meant here
my_solist.swap(right.my_solist); my_solist.swap(right.my_solist);
internal_swap_buckets(right); internal_swap_buckets(right);
std::swap(my_number_of_buckets, right.my_number_of_buckets); std::swap(my_number_of_buckets, right.my_number_of_buckets);
std::swap(my_maximum_bucket_size, right.my_maximum_bucket_size) ; std::swap(my_maximum_bucket_size, right.my_maximum_bucket_size) ;
} }
} }
// Observers // Observers
hasher hash_function() const {
return my_hash_compare.my_hash_object;
}
key_equal key_eq() const {
return my_hash_compare.my_key_compare_object;
}
void clear() { void clear() {
// Clear list // Clear list
my_solist.clear(); my_solist.clear();
// Clear buckets // Clear buckets
internal_clear(); internal_clear();
// Initialize bucket 0 // Initialize bucket 0
__TBB_ASSERT(my_buckets[0] == NULL, NULL); __TBB_ASSERT(my_buckets[0] == NULL, NULL);
raw_iterator dummy_node = my_solist.raw_begin(); raw_iterator dummy_node = my_solist.raw_begin();
skipping to change at line 1034 skipping to change at line 1152
raw_const_iterator it = get_bucket(bucket); raw_const_iterator it = get_bucket(bucket);
// Find the end of the bucket, denoted by the dummy element // Find the end of the bucket, denoted by the dummy element
do ++it; do ++it;
while(it != my_solist.raw_end() && !it.get_node_ptr()->is_dummy()); while(it != my_solist.raw_end() && !it.get_node_ptr()->is_dummy());
// Return the first real element past the end of the bucket // Return the first real element past the end of the bucket
return my_solist.first_real_iterator(it); return my_solist.first_real_iterator(it);
} }
const_local_iterator unsafe_cbegin(size_type /*bucket*/) const { const_local_iterator unsafe_cbegin(size_type bucket) const {
return ((const self_type *) this)->begin(); return ((const self_type *) this)->unsafe_begin(bucket);
} }
const_local_iterator unsafe_cend(size_type /*bucket*/) const { const_local_iterator unsafe_cend(size_type bucket) const {
return ((const self_type *) this)->end(); return ((const self_type *) this)->unsafe_end(bucket);
} }
// Hash policy // Hash policy
float load_factor() const { float load_factor() const {
return (float) size() / (float) unsafe_bucket_count(); return (float) size() / (float) unsafe_bucket_count();
} }
float max_load_factor() const { float max_load_factor() const {
return my_maximum_bucket_size; return my_maximum_bucket_size;
} }
skipping to change at line 1117 skipping to change at line 1235
{ {
// Swap all node segments // Swap all node segments
for (size_type index = 0; index < pointers_per_table; ++index) for (size_type index = 0; index < pointers_per_table; ++index)
{ {
raw_iterator * iterator_pointer = my_buckets[index]; raw_iterator * iterator_pointer = my_buckets[index];
my_buckets[index] = right.my_buckets[index]; my_buckets[index] = right.my_buckets[index];
right.my_buckets[index] = iterator_pointer; right.my_buckets[index] = iterator_pointer;
} }
} }
//TODO: why not use std::distance?
// Hash APIs // Hash APIs
size_type internal_distance(const_iterator first, const_iterator last) const size_type internal_distance(const_iterator first, const_iterator last) const
{ {
size_type num = 0; size_type num = 0;
for (const_iterator it = first; it != last; ++it) for (const_iterator it = first; it != last; ++it)
++num; ++num;
return num; return num;
} }
skipping to change at line 1394 skipping to change at line 1513
return __TBB_ReverseBits(order_key) & ~sokey_t(0x1); return __TBB_ReverseBits(order_key) & ~sokey_t(0x1);
} }
// Shared variables // Shared variables
atomic<size_type> my_number _of_buckets; // Current table size atomic<size_type> my_number _of_buckets; // Current table size
solist_t my_solist ; // List where all the elements are kept solist_t my_solist ; // List where all the elements are kept
typename allocator_type::template rebind<raw_iterator>::other my_alloca tor; // Allocator object for segments typename allocator_type::template rebind<raw_iterator>::other my_alloca tor; // Allocator object for segments
float my_maximu m_bucket_size; // Maximum size of the bucket float my_maximu m_bucket_size; // Maximum size of the bucket
atomic<raw_iterator*> my_bucket s[pointers_per_table]; // The segment table atomic<raw_iterator*> my_bucket s[pointers_per_table]; // The segment table
}; };
#if _MSC_VER #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#pragma warning(pop) // warning 4127 -- while (true) has a constant express #pragma warning(pop) // warning 4127 is back
ion in it
#endif #endif
//! Hash multiplier //! Hash multiplier
static const size_t hash_multiplier = tbb::internal::select_size_t_constant <2654435769U, 11400714819323198485ULL>::value; static const size_t hash_multiplier = tbb::internal::select_size_t_constant <2654435769U, 11400714819323198485ULL>::value;
} // namespace internal } // namespace internal
//! @endcond //! @endcond
//! Hasher functions //! Hasher functions
template<typename T> template<typename T>
inline size_t tbb_hasher( const T& t ) { inline size_t tbb_hasher( const T& t ) {
return static_cast<size_t>( t ) * internal::hash_multiplier; return static_cast<size_t>( t ) * internal::hash_multiplier;
 End of changes. 20 change blocks. 
39 lines changed or deleted 182 lines changed or added


 _flow_graph_impl.h   _flow_graph_impl.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB__flow_graph_impl_H #ifndef __TBB__flow_graph_impl_H
#define __TBB__flow_graph_impl_H #define __TBB__flow_graph_impl_H
#ifndef __TBB_flow_graph_H #ifndef __TBB_flow_graph_H
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
namespace internal { namespace internal {
skipping to change at line 51 skipping to change at line 43
// -------------- function_body containers ---------------------- // -------------- function_body containers ----------------------
//! A functor that takes no input and generates a value of type Output //! A functor that takes no input and generates a value of type Output
template< typename Output > template< typename Output >
class source_body : tbb::internal::no_assign { class source_body : tbb::internal::no_assign {
public: public:
virtual ~source_body() {} virtual ~source_body() {}
virtual bool operator()(Output &output) = 0; virtual bool operator()(Output &output) = 0;
virtual source_body* clone() = 0; virtual source_body* clone() = 0;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
virtual void reset_body() = 0;
#endif
}; };
//! The leaf for source_body //! The leaf for source_body
template< typename Output, typename Body> template< typename Output, typename Body>
class source_body_leaf : public source_body<Output> { class source_body_leaf : public source_body<Output> {
public: public:
source_body_leaf( const Body &_body ) : body(_body), init_body(_bod y) { } source_body_leaf( const Body &_body ) : body(_body), init_body(_bod y) { }
/*override*/ bool operator()(Output &output) { return body( output ); } /*override*/ bool operator()(Output &output) { return body( output ); }
/*override*/ source_body_leaf* clone() { /*override*/ source_body_leaf* clone() {
return new source_body_leaf< Output, Body >(init_body); return new source_body_leaf< Output, Body >(init_body);
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
/*override*/ void reset_body() {
body = init_body;
}
#endif
Body get_body() { return body; } Body get_body() { return body; }
private: private:
Body body; Body body;
Body init_body; Body init_body;
}; };
//! A functor that takes an Input and generates an Output //! A functor that takes an Input and generates an Output
template< typename Input, typename Output > template< typename Input, typename Output >
class function_body : tbb::internal::no_assign { class function_body : tbb::internal::no_assign {
public: public:
virtual ~function_body() {} virtual ~function_body() {}
virtual Output operator()(const Input &input) = 0; virtual Output operator()(const Input &input) = 0;
virtual function_body* clone() = 0; virtual function_body* clone() = 0;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
virtual void reset_body() = 0;
#endif
}; };
//! the leaf for function_body //! the leaf for function_body
template <typename Input, typename Output, typename B> template <typename Input, typename Output, typename B>
class function_body_leaf : public function_body< Input, Output > { class function_body_leaf : public function_body< Input, Output > {
public: public:
function_body_leaf( const B &_body ) : body(_body), init_body(_body ) { } function_body_leaf( const B &_body ) : body(_body), init_body(_body ) { }
Output operator()(const Input &i) { return body(i); } Output operator()(const Input &i) { return body(i); }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
/*override*/ void reset_body() {
body = init_body;
}
#endif
B get_body() { return body; } B get_body() { return body; }
/*override*/ function_body_leaf* clone() { /*override*/ function_body_leaf* clone() {
return new function_body_leaf< Input, Output, B >(init_body); return new function_body_leaf< Input, Output, B >(init_body);
} }
private: private:
B body; B body;
B init_body; B init_body;
}; };
//! the leaf for function_body specialized for Input and output of cont inue_msg //! the leaf for function_body specialized for Input and output of cont inue_msg
template <typename B> template <typename B>
class function_body_leaf< continue_msg, continue_msg, B> : public funct ion_body< continue_msg, continue_msg > { class function_body_leaf< continue_msg, continue_msg, B> : public funct ion_body< continue_msg, continue_msg > {
public: public:
function_body_leaf( const B &_body ) : body(_body), init_body(_body ) { } function_body_leaf( const B &_body ) : body(_body), init_body(_body ) { }
continue_msg operator()( const continue_msg &i ) { continue_msg operator()( const continue_msg &i ) {
body(i); body(i);
return i; return i;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
/*override*/ void reset_body() {
body = init_body;
}
#endif
B get_body() { return body; } B get_body() { return body; }
/*override*/ function_body_leaf* clone() { /*override*/ function_body_leaf* clone() {
return new function_body_leaf< continue_msg, continue_msg, B >(i nit_body); return new function_body_leaf< continue_msg, continue_msg, B >(i nit_body);
} }
private: private:
B body; B body;
B init_body; B init_body;
}; };
//! the leaf for function_body specialized for Output of continue_msg //! the leaf for function_body specialized for Output of continue_msg
template <typename Input, typename B> template <typename Input, typename B>
class function_body_leaf< Input, continue_msg, B> : public function_bod y< Input, continue_msg > { class function_body_leaf< Input, continue_msg, B> : public function_bod y< Input, continue_msg > {
public: public:
function_body_leaf( const B &_body ) : body(_body), init_body(_body ) { } function_body_leaf( const B &_body ) : body(_body), init_body(_body ) { }
continue_msg operator()(const Input &i) { continue_msg operator()(const Input &i) {
body(i); body(i);
return continue_msg(); return continue_msg();
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
/*override*/ void reset_body() {
body = init_body;
}
#endif
B get_body() { return body; } B get_body() { return body; }
/*override*/ function_body_leaf* clone() { /*override*/ function_body_leaf* clone() {
return new function_body_leaf< Input, continue_msg, B >(init_bo dy); return new function_body_leaf< Input, continue_msg, B >(init_bo dy);
} }
private: private:
B body; B body;
B init_body; B init_body;
}; };
//! the leaf for function_body specialized for Input of continue_msg //! the leaf for function_body specialized for Input of continue_msg
template <typename Output, typename B> template <typename Output, typename B>
class function_body_leaf< continue_msg, Output, B > : public function_b ody< continue_msg, Output > { class function_body_leaf< continue_msg, Output, B > : public function_b ody< continue_msg, Output > {
public: public:
function_body_leaf( const B &_body ) : body(_body), init_body(_body ) { } function_body_leaf( const B &_body ) : body(_body), init_body(_body ) { }
Output operator()(const continue_msg &i) { Output operator()(const continue_msg &i) {
return body(i); return body(i);
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
/*override*/ void reset_body() {
body = init_body;
}
#endif
B get_body() { return body; } B get_body() { return body; }
/*override*/ function_body_leaf* clone() { /*override*/ function_body_leaf* clone() {
return new function_body_leaf< continue_msg, Output, B >(init_b ody); return new function_body_leaf< continue_msg, Output, B >(init_b ody);
} }
private: private:
B body; B body;
B init_body; B init_body;
}; };
//! function_body that takes an Input and a set of output ports //! function_body that takes an Input and a set of output ports
template<typename Input, typename OutputSet> template<typename Input, typename OutputSet>
class multifunction_body { class multifunction_body : tbb::internal::no_assign {
public: public:
virtual ~multifunction_body () {} virtual ~multifunction_body () {}
virtual void operator()(const Input &/* input*/, OutputSet &/*oset* /) = 0; virtual void operator()(const Input &/* input*/, OutputSet &/*oset* /) = 0;
virtual multifunction_body* clone() = 0; virtual multifunction_body* clone() = 0;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
virtual void reset_body() = 0;
#endif
}; };
//! leaf for multifunction. OutputSet can be a std::tuple or a vector. //! leaf for multifunction. OutputSet can be a std::tuple or a vector.
template<typename Input, typename OutputSet, typename B> template<typename Input, typename OutputSet, typename B>
class multifunction_body_leaf : public multifunction_body<Input, Output Set> { class multifunction_body_leaf : public multifunction_body<Input, Output Set> {
public: public:
multifunction_body_leaf(const B &_body) : body(_body), init_body(_b ody) { } multifunction_body_leaf(const B &_body) : body(_body), init_body(_b ody) { }
void operator()(const Input &input, OutputSet &oset) { void operator()(const Input &input, OutputSet &oset) {
body(input, oset); // body may explicitly put() to one or more of oset. body(input, oset); // body may explicitly put() to one or more of oset.
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
/*override*/ void reset_body() {
body = init_body;
}
#endif
B get_body() { return body; } B get_body() { return body; }
/*override*/ multifunction_body_leaf* clone() { /*override*/ multifunction_body_leaf* clone() {
return new multifunction_body_leaf<Input, OutputSet,B>(init_bod y); return new multifunction_body_leaf<Input, OutputSet,B>(init_bod y);
} }
private: private:
B body; B body;
B init_body; B init_body;
}; };
// --------------------------- end of function_body containers ------------ ------------ // --------------------------- end of function_body containers ------------ ------------
skipping to change at line 257 skipping to change at line 288
void add( T &n ) { void add( T &n ) {
typename my_mutex_type::scoped_lock lock( my_mutex ); typename my_mutex_type::scoped_lock lock( my_mutex );
internal_push(n); internal_push(n);
} }
void remove( T &n ) { void remove( T &n ) {
typename my_mutex_type::scoped_lock lock( my_mutex ); typename my_mutex_type::scoped_lock lock( my_mutex );
for ( size_t i = internal_size(); i != 0; --i ) { for ( size_t i = internal_size(); i != 0; --i ) {
T &s = internal_pop(); T &s = internal_pop();
if ( &s != &n ) { if ( &s == &n ) return; // only remove one predecessor pe
internal_push(s); r request
} internal_push(s);
} }
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<T *> predecessor_vector_type;
void internal_add_built_predecessor( T &n ) {
typename my_mutex_type::scoped_lock lock( my_mutex );
my_built_predecessors.add_edge(n);
}
void internal_delete_built_predecessor( T &n ) {
typename my_mutex_type::scoped_lock lock( my_mutex );
my_built_predecessors.delete_edge(n);
}
void copy_predecessors( predecessor_vector_type &v) {
typename my_mutex_type::scoped_lock lock( my_mutex );
my_built_predecessors.copy_edges(v);
}
size_t predecessor_count() {
typename my_mutex_type::scoped_lock lock(my_mutex);
return (size_t)(my_built_predecessors.edge_count());
}
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
protected: protected:
typedef M my_mutex_type; typedef M my_mutex_type;
my_mutex_type my_mutex; my_mutex_type my_mutex;
std::queue< T * > my_q; std::queue< T * > my_q;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
edge_container<T> my_built_predecessors;
#endif
// Assumes lock is held // Assumes lock is held
inline bool internal_empty( ) { inline bool internal_empty( ) {
return my_q.empty(); return my_q.empty();
} }
// Assumes lock is held // Assumes lock is held
inline size_type internal_size( ) { inline size_type internal_size( ) {
return my_q.size(); return my_q.size();
} }
skipping to change at line 335 skipping to change at line 391
if ( my_owner) if ( my_owner)
src->register_successor( *my_owner ); src->register_successor( *my_owner );
} else { } else {
// Retain ownership of the edge // Retain ownership of the edge
this->add(*src); this->add(*src);
} }
} while ( msg == false ); } while ( msg == false );
return msg; return msg;
} }
void reset() { void reset( __TBB_PFG_RESET_ARG(reset_flags f)) {
if(!my_owner) { if(my_owner) {
return; // retain ownership of edges for(;;) {
} predecessor_type *src;
for(;;) { {
predecessor_type *src; if(this->internal_empty()) break;
{ src = &this->internal_pop();
typename my_mutex_type::scoped_lock lock(this->my_mutex }
); src->register_successor( *my_owner);
if(this->internal_empty()) break;
src = &this->internal_pop();
} }
src->register_successor( *my_owner);
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
if (f&rf_extract && my_owner)
my_built_predecessors.receiver_extract(*my_owner);
__TBB_ASSERT(!(f&rf_extract) || this->internal_empty(), "predec
essor cache not empty");
#endif
} }
protected: protected:
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
using node_cache< sender<T>, M >::my_built_predecessors;
#endif
successor_type *my_owner; successor_type *my_owner;
}; };
//! An cache of predecessors that supports requests and reservations //! An cache of predecessors that supports requests and reservations
template< typename T, typename M=spin_mutex > template< typename T, typename M=spin_mutex >
class reservable_predecessor_cache : public predecessor_cache< T, M > { class reservable_predecessor_cache : public predecessor_cache< T, M > {
public: public:
typedef M my_mutex_type; typedef M my_mutex_type;
typedef T output_type; typedef T output_type;
typedef sender<T> predecessor_type; typedef sender<T> predecessor_type;
skipping to change at line 410 skipping to change at line 472
return true; return true;
} }
bool bool
try_consume( ) { try_consume( ) {
reserved_src->try_consume( ); reserved_src->try_consume( );
reserved_src = NULL; reserved_src = NULL;
return true; return true;
} }
void reset() { void reset( __TBB_PFG_RESET_ARG(reset_flags f)) {
reserved_src = NULL; reserved_src = NULL;
predecessor_cache<T,M>::reset(); predecessor_cache<T,M>::reset(__TBB_PFG_RESET_ARG(f));
} }
private: private:
predecessor_type *reserved_src; predecessor_type *reserved_src;
}; };
//! An abstract cache of successors //! An abstract cache of successors
template<typename T, typename M=spin_rw_mutex > template<typename T, typename M=spin_rw_mutex >
class successor_cache : tbb::internal::no_copy { class successor_cache : tbb::internal::no_copy {
protected: protected:
typedef M my_mutex_type; typedef M my_mutex_type;
my_mutex_type my_mutex; my_mutex_type my_mutex;
typedef std::list< receiver<T> * > my_successors_type; typedef receiver<T> *pointer_type;
typedef std::list< pointer_type > my_successors_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
edge_container<receiver<T> > my_built_successors;
#endif
my_successors_type my_successors; my_successors_type my_successors;
sender<T> *my_owner; sender<T> *my_owner;
public: public:
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<pointer_type> successor_vector_type;
void internal_add_built_successor( receiver<T> &r) {
typename my_mutex_type::scoped_lock l(my_mutex, true);
my_built_successors.add_edge( r );
}
void internal_delete_built_successor( receiver<T> &r) {
typename my_mutex_type::scoped_lock l(my_mutex, true);
my_built_successors.delete_edge(r);
}
void copy_successors( successor_vector_type &v) {
typename my_mutex_type::scoped_lock l(my_mutex, false);
my_built_successors.copy_edges(v);
}
size_t successor_count() {
typename my_mutex_type::scoped_lock l(my_mutex,false);
return my_built_successors.edge_count();
}
void reset( __TBB_PFG_RESET_ARG(reset_flags f)) {
if (f&rf_extract && my_owner)
my_built_successors.sender_extract(*my_owner);
}
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
successor_cache( ) : my_owner(NULL) {} successor_cache( ) : my_owner(NULL) {}
void set_owner( sender<T> *owner ) { my_owner = owner; } void set_owner( sender<T> *owner ) { my_owner = owner; }
virtual ~successor_cache() {} virtual ~successor_cache() {}
void register_successor( receiver<T> &r ) { void register_successor( receiver<T> &r ) {
typename my_mutex_type::scoped_lock l(my_mutex, true); typename my_mutex_type::scoped_lock l(my_mutex, true);
my_successors.push_back( &r ); my_successors.push_back( &r );
skipping to change at line 461 skipping to change at line 554
break; break;
} }
} }
} }
bool empty() { bool empty() {
typename my_mutex_type::scoped_lock l(my_mutex, false); typename my_mutex_type::scoped_lock l(my_mutex, false);
return my_successors.empty(); return my_successors.empty();
} }
void clear() {
my_successors.clear();
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
my_built_successors.clear();
#endif
}
virtual task * try_put_task( const T &t ) = 0; virtual task * try_put_task( const T &t ) = 0;
}; };
//! An abstract cache of succesors, specialized to continue_msg //! An abstract cache of successors, specialized to continue_msg
template<> template<>
class successor_cache< continue_msg > : tbb::internal::no_copy { class successor_cache< continue_msg > : tbb::internal::no_copy {
protected: protected:
typedef spin_rw_mutex my_mutex_type; typedef spin_rw_mutex my_mutex_type;
my_mutex_type my_mutex; my_mutex_type my_mutex;
typedef std::list< receiver<continue_msg> * > my_successors_type; typedef receiver<continue_msg> *pointer_type;
typedef std::list< pointer_type > my_successors_type;
my_successors_type my_successors; my_successors_type my_successors;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
edge_container<receiver<continue_msg> > my_built_successors;
#endif
sender<continue_msg> *my_owner; sender<continue_msg> *my_owner;
public: public:
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<pointer_type> successor_vector_type;
void internal_add_built_successor( receiver<continue_msg> &r) {
my_mutex_type::scoped_lock l(my_mutex, true);
my_built_successors.add_edge( r );
}
void internal_delete_built_successor( receiver<continue_msg> &r) {
my_mutex_type::scoped_lock l(my_mutex, true);
my_built_successors.delete_edge(r);
}
void copy_successors( successor_vector_type &v) {
my_mutex_type::scoped_lock l(my_mutex, false);
my_built_successors.copy_edges(v);
}
size_t successor_count() {
my_mutex_type::scoped_lock l(my_mutex,false);
return my_built_successors.edge_count();
}
void reset( __TBB_PFG_RESET_ARG(reset_flags f)) {
if (f&rf_extract && my_owner)
my_built_successors.sender_extract(*my_owner);
}
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
successor_cache( ) : my_owner(NULL) {} successor_cache( ) : my_owner(NULL) {}
void set_owner( sender<continue_msg> *owner ) { my_owner = owner; } void set_owner( sender<continue_msg> *owner ) { my_owner = owner; }
virtual ~successor_cache() {} virtual ~successor_cache() {}
void register_successor( receiver<continue_msg> &r ) { void register_successor( receiver<continue_msg> &r ) {
my_mutex_type::scoped_lock l(my_mutex, true); my_mutex_type::scoped_lock l(my_mutex, true);
my_successors.push_back( &r ); my_successors.push_back( &r );
if ( my_owner && r.is_continue_receiver() ) { if ( my_owner && r.is_continue_receiver() ) {
r.register_predecessor( *my_owner ); r.register_predecessor( *my_owner );
} }
} }
void remove_successor( receiver<continue_msg> &r ) { void remove_successor( receiver<continue_msg> &r ) {
my_mutex_type::scoped_lock l(my_mutex, true); my_mutex_type::scoped_lock l(my_mutex, true);
for ( my_successors_type::iterator i = my_successors.begin(); for ( my_successors_type::iterator i = my_successors.begin();
i != my_successors.end(); ++i ) { i != my_successors.end(); ++i ) {
if ( *i == & r ) { if ( *i == & r ) {
// TODO: Check if we need to test for continue_receiver
before
// removing from r.
if ( my_owner ) if ( my_owner )
r.remove_predecessor( *my_owner ); r.remove_predecessor( *my_owner );
my_successors.erase(i); my_successors.erase(i);
break; break;
} }
} }
} }
bool empty() { bool empty() {
my_mutex_type::scoped_lock l(my_mutex, false); my_mutex_type::scoped_lock l(my_mutex, false);
return my_successors.empty(); return my_successors.empty();
} }
void clear() {
my_successors.clear();
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
my_built_successors.clear();
#endif
}
virtual task * try_put_task( const continue_msg &t ) = 0; virtual task * try_put_task( const continue_msg &t ) = 0;
}; };
//! A cache of successors that are broadcast to //! A cache of successors that are broadcast to
template<typename T, typename M=spin_rw_mutex> template<typename T, typename M=spin_rw_mutex>
class broadcast_cache : public successor_cache<T, M> { class broadcast_cache : public successor_cache<T, M> {
typedef M my_mutex_type; typedef M my_mutex_type;
typedef std::list< receiver<T> * > my_successors_type; typedef std::list< receiver<T> * > my_successors_type;
skipping to change at line 551 skipping to change at line 692
upgraded = true; upgraded = true;
} }
i = this->my_successors.erase(i); i = this->my_successors.erase(i);
} else { } else {
++i; ++i;
} }
} }
} }
return last_task; return last_task;
} }
}; };
//! A cache of successors that are put in a round-robin fashion //! A cache of successors that are put in a round-robin fashion
template<typename T, typename M=spin_rw_mutex > template<typename T, typename M=spin_rw_mutex >
class round_robin_cache : public successor_cache<T, M> { class round_robin_cache : public successor_cache<T, M> {
typedef size_t size_type; typedef size_t size_type;
typedef M my_mutex_type; typedef M my_mutex_type;
typedef std::list< receiver<T> * > my_successors_type; typedef std::list< receiver<T> * > my_successors_type;
public: public:
 End of changes. 30 change blocks. 
49 lines changed or deleted 202 lines changed or added


 _flow_graph_indexer_impl.h   _flow_graph_indexer_impl.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB__flow_graph_indexer_impl_H #ifndef __TBB__flow_graph_indexer_impl_H
#define __TBB__flow_graph_indexer_impl_H #define __TBB__flow_graph_indexer_impl_H
#ifndef __TBB_flow_graph_H #ifndef __TBB_flow_graph_H
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#if TBB_PREVIEW_GRAPH_NODES
#include "tbb/internal/_flow_graph_types_impl.h" #include "tbb/internal/_flow_graph_types_impl.h"
namespace internal { namespace internal {
// Output of the indexer_node is a tbb::flow::tagged_msg, and will be o f // Output of the indexer_node is a tbb::flow::tagged_msg, and will be o f
// the form tagged_msg<tag, result> // the form tagged_msg<tag, result>
// where the value of tag will indicate which result was put to the // where the value of tag will indicate which result was put to the
// successor. // successor.
template<typename IndexerNodeBaseType, typename T, size_t K> template<typename IndexerNodeBaseType, typename T, size_t K>
skipping to change at line 61 skipping to change at line 52
template<typename TupleTypes,int N> template<typename TupleTypes,int N>
struct indexer_helper { struct indexer_helper {
template<typename IndexerNodeBaseType, typename PortTuple> template<typename IndexerNodeBaseType, typename PortTuple>
static inline void set_indexer_node_pointer(PortTuple &my_input, In dexerNodeBaseType *p) { static inline void set_indexer_node_pointer(PortTuple &my_input, In dexerNodeBaseType *p) {
typedef typename tuple_element<N-1, TupleTypes>::type T; typedef typename tuple_element<N-1, TupleTypes>::type T;
task *(*indexer_node_put_task)(const T&, void *) = do_try_put<I ndexerNodeBaseType, T, N-1>; task *(*indexer_node_put_task)(const T&, void *) = do_try_put<I ndexerNodeBaseType, T, N-1>;
tbb::flow::get<N-1>(my_input).set_up(p, indexer_node_put_task); tbb::flow::get<N-1>(my_input).set_up(p, indexer_node_put_task);
indexer_helper<TupleTypes,N-1>::template set_indexer_node_point er<IndexerNodeBaseType,PortTuple>(my_input, p); indexer_helper<TupleTypes,N-1>::template set_indexer_node_point er<IndexerNodeBaseType,PortTuple>(my_input, p);
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
template<typename InputTuple>
static inline void reset_inputs(InputTuple &my_input, reset_flags f
) {
join_helper<N-1>::reset_inputs(my_input, f);
tbb::flow::get<N-1>(my_input).reset_receiver(f);
}
#endif
}; };
template<typename TupleTypes> template<typename TupleTypes>
struct indexer_helper<TupleTypes,1> { struct indexer_helper<TupleTypes,1> {
template<typename IndexerNodeBaseType, typename PortTuple> template<typename IndexerNodeBaseType, typename PortTuple>
static inline void set_indexer_node_pointer(PortTuple &my_input, In dexerNodeBaseType *p) { static inline void set_indexer_node_pointer(PortTuple &my_input, In dexerNodeBaseType *p) {
typedef typename tuple_element<0, TupleTypes>::type T; typedef typename tuple_element<0, TupleTypes>::type T;
task *(*indexer_node_put_task)(const T&, void *) = do_try_put<I ndexerNodeBaseType, T, 0>; task *(*indexer_node_put_task)(const T&, void *) = do_try_put<I ndexerNodeBaseType, T, 0>;
tbb::flow::get<0>(my_input).set_up(p, indexer_node_put_task); tbb::flow::get<0>(my_input).set_up(p, indexer_node_put_task);
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
template<typename InputTuple>
static inline void reset_inputs(InputTuple &my_input, reset_flags f
) {
tbb::flow::get<0>(my_input).reset_receiver(f);
}
#endif
}; };
template<typename T> template<typename T>
class indexer_input_port : public receiver<T> { class indexer_input_port : public receiver<T> {
private: private:
void* my_indexer_ptr; void* my_indexer_ptr;
typedef task* (* forward_function_ptr)(T const &, void* ); typedef task* (* forward_function_ptr)(T const &, void* );
forward_function_ptr my_try_put_task; forward_function_ptr my_try_put_task;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
spin_mutex my_pred_mutex;
edge_container<sender<T> > my_built_predecessors;
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
public: public:
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
indexer_input_port() : my_pred_mutex() {}
indexer_input_port( const indexer_input_port & /*other*/ ) : receiv
er<T>(), my_pred_mutex() {
}
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
void set_up(void *p, forward_function_ptr f) { void set_up(void *p, forward_function_ptr f) {
my_indexer_ptr = p; my_indexer_ptr = p;
my_try_put_task = f; my_try_put_task = f;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<sender<T> *> predecessor_vector_type;
/*override*/size_t predecessor_count() {
spin_mutex::scoped_lock l(my_pred_mutex);
return my_built_predecessors.edge_count();
}
/*override*/void internal_add_built_predecessor(sender<T> &p) {
spin_mutex::scoped_lock l(my_pred_mutex);
my_built_predecessors.add_edge(p);
}
/*override*/void internal_delete_built_predecessor(sender<T> &p) {
spin_mutex::scoped_lock l(my_pred_mutex);
my_built_predecessors.delete_edge(p);
}
/*override*/void copy_predecessors( predecessor_vector_type &v) {
spin_mutex::scoped_lock l(my_pred_mutex);
return my_built_predecessors.copy_edges(v);
}
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
protected: protected:
template< typename R, typename B > friend class run_and_put_task; template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_c ache; template<typename X, typename Y> friend class internal::broadcast_c ache;
template<typename X, typename Y> friend class internal::round_robin _cache; template<typename X, typename Y> friend class internal::round_robin _cache;
task *try_put_task(const T &v) { task *try_put_task(const T &v) {
return my_try_put_task(v, my_indexer_ptr); return my_try_put_task(v, my_indexer_ptr);
} }
/*override*/void reset_receiver() {}
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
public:
/*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags f))
{
if(f&rf_extract) my_built_predecessors.receiver_extract(*this);
}
#else
/*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags /*f
*/)) { }
#endif
}; };
template<typename InputTuple, typename OutputType, typename StructTypes > template<typename InputTuple, typename OutputType, typename StructTypes >
class indexer_node_FE { class indexer_node_FE {
public: public:
static const int N = tbb::flow::tuple_size<InputTuple>::value; static const int N = tbb::flow::tuple_size<InputTuple>::value;
typedef OutputType output_type; typedef OutputType output_type;
typedef InputTuple input_type; typedef InputTuple input_type;
input_type &input_ports() { return my_inputs; } input_type &input_ports() { return my_inputs; }
skipping to change at line 118 skipping to change at line 159
class indexer_node_base : public graph_node, public indexer_node_FE<Inp utTuple, OutputType,StructTypes>, class indexer_node_base : public graph_node, public indexer_node_FE<Inp utTuple, OutputType,StructTypes>,
public sender<OutputType> { public sender<OutputType> {
protected: protected:
using graph_node::my_graph; using graph_node::my_graph;
public: public:
static const size_t N = tbb::flow::tuple_size<InputTuple>::value; static const size_t N = tbb::flow::tuple_size<InputTuple>::value;
typedef OutputType output_type; typedef OutputType output_type;
typedef StructTypes tuple_types; typedef StructTypes tuple_types;
typedef receiver<output_type> successor_type; typedef receiver<output_type> successor_type;
typedef indexer_node_FE<InputTuple, output_type,StructTypes> input_ ports_type; typedef indexer_node_FE<InputTuple, output_type,StructTypes> input_ ports_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<successor_type *> successor_vector_type;
#endif
private: private:
// ----------- Aggregator ------------ // ----------- Aggregator ------------
enum op_type { reg_succ, rem_succ, try__put_task }; enum op_type { reg_succ, rem_succ, try__put_task
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
, add_blt_succ, del_blt_succ,
blt_succ_cnt, blt_succ_cpy
#endif
};
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
typedef indexer_node_base<InputTuple,output_type,StructTypes> my_cl ass; typedef indexer_node_base<InputTuple,output_type,StructTypes> my_cl ass;
class indexer_node_base_operation : public aggregated_operation<ind exer_node_base_operation> { class indexer_node_base_operation : public aggregated_operation<ind exer_node_base_operation> {
public: public:
char type; char type;
union { union {
output_type const *my_arg; output_type const *my_arg;
successor_type *my_succ; successor_type *my_succ;
task *bypass_t; task *bypass_t;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
size_t cnt_val;
successor_vector_type *succv;
#endif
}; };
indexer_node_base_operation(const output_type* e, op_type t) : indexer_node_base_operation(const output_type* e, op_type t) :
type(char(t)), my_arg(e) {} type(char(t)), my_arg(e) {}
indexer_node_base_operation(const successor_type &s, op_type t) : type(char(t)), indexer_node_base_operation(const successor_type &s, op_type t) : type(char(t)),
my_succ(const_cast<successor_type *>(&s)) {} my_succ(const_cast<successor_type *>(&s)) {}
indexer_node_base_operation(op_type t) : type(char(t)) {} indexer_node_base_operation(op_type t) : type(char(t)) {}
}; };
typedef internal::aggregating_functor<my_class, indexer_node_base_o peration> my_handler; typedef internal::aggregating_functor<my_class, indexer_node_base_o peration> my_handler;
friend class internal::aggregating_functor<my_class, indexer_node_b ase_operation>; friend class internal::aggregating_functor<my_class, indexer_node_b ase_operation>;
skipping to change at line 165 skipping to change at line 218
case rem_succ: case rem_succ:
my_successors.remove_successor(*(current->my_succ)); my_successors.remove_successor(*(current->my_succ));
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case try__put_task: { case try__put_task: {
current->bypass_t = my_successors.try_put_task(*(cu rrent->my_arg)); current->bypass_t = my_successors.try_put_task(*(cu rrent->my_arg));
__TBB_store_with_release(current->status, SUCCEEDED ); // return of try_put_task actual return value __TBB_store_with_release(current->status, SUCCEEDED ); // return of try_put_task actual return value
} }
break; break;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
case add_blt_succ:
my_successors.internal_add_built_successor(*(current->m
y_succ));
__TBB_store_with_release(current->status, SUCCEEDED);
break;
case del_blt_succ:
my_successors.internal_delete_built_successor(*(current
->my_succ));
__TBB_store_with_release(current->status, SUCCEEDED);
break;
case blt_succ_cnt:
current->cnt_val = my_successors.successor_count();
__TBB_store_with_release(current->status, SUCCEEDED);
break;
case blt_succ_cpy:
my_successors.copy_successors(*(current->succv));
__TBB_store_with_release(current->status, SUCCEEDED);
break;
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
} }
} }
} }
// ---------- end aggregator ----------- // ---------- end aggregator -----------
public: public:
indexer_node_base(graph& g) : graph_node(g), input_ports_type() { indexer_node_base(graph& g) : graph_node(g), input_ports_type() {
indexer_helper<StructTypes,N>::set_indexer_node_pointer(this->m y_inputs, this); indexer_helper<StructTypes,N>::set_indexer_node_pointer(this->m y_inputs, this);
my_successors.set_owner(this); my_successors.set_owner(this);
my_aggregator.initialize_handler(my_handler(this)); my_aggregator.initialize_handler(my_handler(this));
} }
skipping to change at line 200 skipping to change at line 271
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.status == SUCCEEDED; return op_data.status == SUCCEEDED;
} }
task * try_put_task(output_type const *v) { task * try_put_task(output_type const *v) {
indexer_node_base_operation op_data(v, try__put_task); indexer_node_base_operation op_data(v, try__put_task);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.bypass_t; return op_data.bypass_t;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
void internal_add_built_successor( successor_type &r) {
indexer_node_base_operation op_data(r, add_blt_succ);
my_aggregator.execute(&op_data);
}
void internal_delete_built_successor( successor_type &r) {
indexer_node_base_operation op_data(r, del_blt_succ);
my_aggregator.execute(&op_data);
}
size_t successor_count() {
indexer_node_base_operation op_data(blt_succ_cnt);
my_aggregator.execute(&op_data);
return op_data.cnt_val;
}
void copy_successors( successor_vector_type &v) {
indexer_node_base_operation op_data(blt_succ_cpy);
op_data.succv = &v;
my_aggregator.execute(&op_data);
}
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
protected: protected:
/*override*/void reset() {} /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) {
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
my_successors.reset(f);
indexer_helper<StructTypes,N>::reset_inputs(this->my_inputs, f)
;
#endif
}
private: private:
broadcast_cache<output_type, null_rw_mutex> my_successors; broadcast_cache<output_type, null_rw_mutex> my_successors;
}; //indexer_node_base }; //indexer_node_base
template<int N, typename InputTuple> struct input_types; template<int N, typename InputTuple> struct input_types;
template<typename InputTuple> template<typename InputTuple>
struct input_types<1, InputTuple> { struct input_types<1, InputTuple> {
typedef typename tuple_element<0, InputTuple>::type first_type; typedef typename tuple_element<0, InputTuple>::type first_type;
skipping to change at line 350 skipping to change at line 449
typedef OutputTuple tuple_types; typedef OutputTuple tuple_types;
typedef typename indexer_types<OutputTuple>::output_type output_typ e; typedef typename indexer_types<OutputTuple>::output_type output_typ e;
private: private:
typedef typename indexer_types<OutputTuple>::indexer_base_type base _type; typedef typename indexer_types<OutputTuple>::indexer_base_type base _type;
public: public:
unfolded_indexer_node(graph& g) : base_type(g) {} unfolded_indexer_node(graph& g) : base_type(g) {}
unfolded_indexer_node(const unfolded_indexer_node &other) : base_ty pe(other) {} unfolded_indexer_node(const unfolded_indexer_node &other) : base_ty pe(other) {}
}; };
} /* namespace internal */ } /* namespace internal */
#endif // TBB_PREVIEW_GRAPH_NODES
#endif /* __TBB__flow_graph_indexer_impl_H */ #endif /* __TBB__flow_graph_indexer_impl_H */
 End of changes. 15 change blocks. 
33 lines changed or deleted 148 lines changed or added


 _flow_graph_item_buffer_impl.h   _flow_graph_item_buffer_impl.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB__flow_graph_item_buffer_impl_H #ifndef __TBB__flow_graph_item_buffer_impl_H
#define __TBB__flow_graph_item_buffer_impl_H #define __TBB__flow_graph_item_buffer_impl_H
#ifndef __TBB_flow_graph_H #ifndef __TBB_flow_graph_H
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#include "tbb/internal/_flow_graph_types_impl.h" // for aligned_pair
// in namespace tbb::flow::interface7 (included in _flow_graph_node_impl.h)
//! Expandable buffer of items. The possible operations are push, pop, //! Expandable buffer of items. The possible operations are push, pop,
//* tests for empty and so forth. No mutual exclusion is built in. //* tests for empty and so forth. No mutual exclusion is built in.
//* objects are constructed into and explicitly-destroyed. get_my_item
gives
// a read-only reference to the item in the buffer. set_my_item may be
called
// with either an empty or occupied slot.
using internal::aligned_pair;
using internal::alignment_of;
namespace internal {
template <typename T, typename A=cache_aligned_allocator<T> > template <typename T, typename A=cache_aligned_allocator<T> >
class item_buffer { class item_buffer {
public: public:
typedef T input_type; typedef T item_type;
typedef T output_type; enum buffer_item_state { no_item=0, has_item=1, reserved_item=2 };
protected: protected:
typedef size_t size_type; typedef size_t size_type;
typedef std::pair< T, bool > item_type; typedef typename aligned_pair<item_type, buffer_item_state>::type b
typedef typename A::template rebind<item_type>::other allocator_typ uffer_item_type;
e; typedef typename A::template rebind<buffer_item_type>::other alloca
tor_type;
item_type *my_array; buffer_item_type *my_array;
size_type my_array_size; size_type my_array_size;
static const size_type initial_buffer_size = 4; static const size_type initial_buffer_size = 4;
size_type my_head; size_type my_head;
size_type my_tail; size_type my_tail;
bool buffer_empty() { return my_head == my_tail; } bool buffer_empty() { return my_head == my_tail; }
item_type &item(size_type i) { return my_array[i & (my_array_size - buffer_item_type &item(size_type i) {
1) ]; } // may not be marked valid __TBB_ASSERT(!(size_type(&(my_array[i&(my_array_size-1)].second
))%alignment_of<buffer_item_state>::value),NULL);
__TBB_ASSERT(!(size_type(&(my_array[i&(my_array_size-1)].first)
)%alignment_of<item_type>::value), NULL);
return my_array[i & (my_array_size - 1) ];
}
bool my_item_valid(size_type i) { return item(i).second != no_item;
}
bool my_item_reserved(size_type i) { return item(i).second == reser
ved_item; }
bool item_valid(size_type i) { return item(i).second; } // object management in buffer
const item_type &get_my_item(size_t i) {
__TBB_ASSERT(my_item_valid(i),"attempt to get invalid item");
item_type *itm = (tbb::internal::punned_cast<item_type *>(&(ite
m(i).first)));
return *(const item_type *)itm;
}
// may be called with an empty slot or a slot that has already been
constructed into.
void set_my_item(size_t i, const item_type &o) {
if(item(i).second != no_item) {
destroy_item(i);
}
new(&(item(i).first)) item_type(o);
item(i).second = has_item;
}
void fetch_front(T &v) { __TBB_ASSERT(item_valid(my_head), "front n // destructively-fetch an object from the buffer
ot valid"); v = item(my_head).first; } void fetch_item(size_t i, item_type &o) {
void fetch_back(T &v) { __TBB_ASSERT(item_valid(my_tail-1), "back n __TBB_ASSERT(my_item_valid(i), "Trying to fetch an empty slot")
ot valid"); v = item(my_tail-1).first; } ;
o = get_my_item(i); // could have std::move assign semantics
destroy_item(i);
}
void invalidate(size_type i) { __TBB_ASSERT(item_valid(i), "Item no // move an existing item from one slot to another. The moved-to sl
t valid"); item(i).second = false; } ot must be unoccupied,
void validate(size_type i) { __TBB_ASSERT(!item_valid(i), "Item alr // the moved-from slot must exist and not be reserved. The after,
eady valid"); item(i).second = true; } from will be empty,
// to will be occupied but not reserved
void move_item(size_t to, size_t from) {
__TBB_ASSERT(!my_item_valid(to), "Trying to move to a non-empty
slot");
__TBB_ASSERT(my_item_valid(from), "Trying to move from an empty
slot");
set_my_item(to, get_my_item(from)); // could have std::move s
emantics
destroy_item(from);
void invalidate_front() { invalidate(my_head); } }
void validate_front() { validate(my_head); }
void invalidate_back() { invalidate(my_tail-1); }
size_type size() { return my_tail - my_head; } // put an item in an empty slot. Return true if successful, else f
alse
bool place_item(size_t here, const item_type &me) {
#if !TBB_DEPRECATED_SEQUENCER_DUPLICATES
if(my_item_valid(here)) return false;
#endif
set_my_item(here, me);
return true;
}
// could be implemented with std::move semantics
void swap_items(size_t i, size_t j) {
__TBB_ASSERT(my_item_valid(i) && my_item_valid(j), "attempt to
swap invalid item(s)");
item_type temp = get_my_item(i);
set_my_item(i, get_my_item(j));
set_my_item(j, temp);
}
void destroy_item(size_type i) {
__TBB_ASSERT(my_item_valid(i), "destruction of invalid item");
(tbb::internal::punned_cast<item_type *>(&(item(i).first)))->~i
tem_type();
item(i).second = no_item;
}
// returns a copy of the front
void copy_front(item_type &v) {
__TBB_ASSERT(my_item_valid(my_head), "attempt to fetch head non
-item");
v = get_my_item(my_head);
}
// returns a copy of the back
void copy_back(item_type &v) {
__TBB_ASSERT(my_item_valid(my_tail-1), "attempt to fetch head n
on-item");
v = get_my_item(my_tail-1);
}
// following methods are for reservation of the front of a bufffer.
void reserve_item(size_type i) { __TBB_ASSERT(my_item_valid(i) && !
my_item_reserved(i), "item cannot be reserved"); item(i).second = reserved_
item; }
void release_item(size_type i) { __TBB_ASSERT(my_item_reserved(i),
"item is not reserved"); item(i).second = has_item; }
void destroy_front() { destroy_item(my_head); ++my_head; }
void destroy_back() { destroy_item(my_tail-1); --my_tail; }
// we have to be able to test against a new tail value without chan
ging my_tail
// grow_array doesn't work if we change my_tail when the old array
is too small
size_type size(size_t new_tail = 0) { return (new_tail ? new_tail :
my_tail) - my_head; }
size_type capacity() { return my_array_size; } size_type capacity() { return my_array_size; }
bool buffer_full() { return size() == capacity(); } // sequencer_node does not use this method, so we don't
// need a version that passes in the new_tail value.
bool buffer_full() { return size() >= capacity(); }
//! Grows the internal array. //! Grows the internal array.
void grow_my_array( size_t minimum_size ) { void grow_my_array( size_t minimum_size ) {
size_type old_size = my_array_size; // test that we haven't made the structure inconsistent.
size_type new_size = old_size ? 2*old_size : initial_buffer_siz __TBB_ASSERT(capacity() >= my_tail - my_head, "total items exce
e; ed capacity");
size_type new_size = my_array_size ? 2*my_array_size : initial_
buffer_size;
while( new_size<minimum_size ) while( new_size<minimum_size )
new_size*=2; new_size*=2;
item_type* new_array = allocator_type().allocate(new_size); buffer_item_type* new_array = allocator_type().allocate(new_siz
item_type* old_array = my_array; e);
// initialize validity to "no"
for( size_type i=0; i<new_size; ++i ) { new_array[i].second = n
o_item; }
for( size_type i=0; i<new_size; ++i ) { for( size_type i=my_head; i<my_tail; ++i) {
new (&(new_array[i].first)) input_type; if(my_item_valid(i)) { // sequencer_node may have empty sl
new_array[i].second = false; ots
// placement-new copy-construct; could be std::move
char *new_space = (char *)&(new_array[i&(new_size-1)].f
irst);
(void)new(new_space) item_type(get_my_item(i));
new_array[i&(new_size-1)].second = item(i).second;
}
} }
size_t t=my_head; clean_up_buffer(/*reset_pointers*/false);
for( size_type i=0; i<old_size; ++i, ++t )
new_array[t&(new_size-1)] = old_array[t&(old_size-1)];
my_array = new_array; my_array = new_array;
my_array_size = new_size; my_array_size = new_size;
if( old_array ) {
for( size_type i=0; i<old_size; ++i, ++t )
old_array[i].first.~input_type();
allocator_type().deallocate(old_array,old_size);
}
} }
bool push_back(T &v) { bool push_back(item_type &v) {
if(buffer_full()) { if(buffer_full()) {
grow_my_array(size() + 1); grow_my_array(size() + 1);
} }
item(my_tail) = std::make_pair( v, true ); set_my_item(my_tail, v);
++my_tail; ++my_tail;
return true; return true;
} }
bool pop_back(T &v) { bool pop_back(item_type &v) {
if (!item_valid(my_tail-1)) { if (!my_item_valid(my_tail-1)) {
return false; return false;
} }
fetch_back(v); copy_back(v);
invalidate_back(); destroy_back();
--my_tail;
return true; return true;
} }
bool pop_front(T &v) { bool pop_front(item_type &v) {
if(!item_valid(my_head)) { if(!my_item_valid(my_head)) {
return false; return false;
} }
fetch_front(v); copy_front(v);
invalidate_front(); destroy_front();
++my_head;
return true; return true;
} }
void clean_up_buffer() { // This is used both for reset and for grow_my_array. In the case
of grow_my_array
// we want to retain the values of the head and tail.
void clean_up_buffer(bool reset_pointers) {
if (my_array) { if (my_array) {
for( size_type i=0; i<my_array_size; ++i ) { for( size_type i=0; i<my_array_size; ++i ) {
my_array[i].first.~input_type(); if(my_item_valid(i))
destroy_item(i);
} }
allocator_type().deallocate(my_array,my_array_size); allocator_type().deallocate(my_array,my_array_size);
} }
my_array = NULL; my_array = NULL;
my_head = my_tail = my_array_size = 0; if(reset_pointers) {
my_head = my_tail = my_array_size = 0;
}
} }
public: public:
//! Constructor //! Constructor
item_buffer( ) : my_array(NULL), my_array_size(0), item_buffer( ) : my_array(NULL), my_array_size(0),
my_head(0), my_tail(0) { my_head(0), my_tail(0) {
grow_my_array(initial_buffer_size); grow_my_array(initial_buffer_size);
} }
~item_buffer() { ~item_buffer() {
clean_up_buffer(); clean_up_buffer(/*reset_pointers*/true);
} }
void reset() { clean_up_buffer(); grow_my_array(initial_buffer_size ); } void reset() { clean_up_buffer(/*reset_pointers*/true); grow_my_arr ay(initial_buffer_size); }
}; };
//! item_buffer with reservable front-end. NOTE: if reserving, do not //! item_buffer with reservable front-end. NOTE: if reserving, do not
//* complete operation with pop_front(); use consume_front(). //* complete operation with pop_front(); use consume_front().
//* No synchronization built-in. //* No synchronization built-in.
template<typename T, typename A=cache_aligned_allocator<T> > template<typename T, typename A=cache_aligned_allocator<T> >
class reservable_item_buffer : public item_buffer<T, A> { class reservable_item_buffer : public item_buffer<T, A> {
protected: protected:
using item_buffer<T, A>::buffer_empty; using item_buffer<T, A>::my_item_valid;
using item_buffer<T, A>::fetch_front;
using item_buffer<T, A>::invalidate_front;
using item_buffer<T, A>::validate_front;
using item_buffer<T, A>::item_valid;
using item_buffer<T, A>::my_head; using item_buffer<T, A>::my_head;
public: public:
reservable_item_buffer() : item_buffer<T, A>(), my_reserved(false) {} reservable_item_buffer() : item_buffer<T, A>(), my_reserved(false) {}
void reset() {my_reserved = false; item_buffer<T,A>::reset(); } void reset() {my_reserved = false; item_buffer<T,A>::reset(); }
protected: protected:
bool reserve_front(T &v) { bool reserve_front(T &v) {
if(my_reserved || !item_valid(my_head)) return false; if(my_reserved || !my_item_valid(my_head)) return false;
my_reserved = true; my_reserved = true;
// reserving the head // reserving the head
fetch_front(v); this->copy_front(v);
// invalidate the head, but don't commit until consume is calle this->reserve_item(this->my_head);
d
invalidate_front();
return true; return true;
} }
void consume_front() { void consume_front() {
__TBB_ASSERT(my_reserved, "Attempt to consume a non-reserved it em"); __TBB_ASSERT(my_reserved, "Attempt to consume a non-reserved it em");
++my_head; this->destroy_front();
my_reserved = false; my_reserved = false;
} }
void release_front() { void release_front() {
__TBB_ASSERT(my_reserved, "Attempt to release a non-reserved it em"); __TBB_ASSERT(my_reserved, "Attempt to release a non-reserved it em");
validate_front(); this->release_item(this->my_head);
my_reserved = false; my_reserved = false;
} }
bool my_reserved; bool my_reserved;
}; };
} // namespace internal
#endif // __TBB__flow_graph_item_buffer_impl_H #endif // __TBB__flow_graph_item_buffer_impl_H
 End of changes. 35 change blocks. 
95 lines changed or deleted 210 lines changed or added


 _flow_graph_join_impl.h   _flow_graph_join_impl.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB__flow_graph_join_impl_H #ifndef __TBB__flow_graph_join_impl_H
#define __TBB__flow_graph_join_impl_H #define __TBB__flow_graph_join_impl_H
#ifndef __TBB_flow_graph_H #ifndef __TBB_flow_graph_H
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#include "_flow_graph_types_impl.h" #include "_flow_graph_types_impl.h"
skipping to change at line 131 skipping to change at line 123
template< typename TagFuncTuple1, typename TagFuncTuple2> template< typename TagFuncTuple1, typename TagFuncTuple2>
static inline void copy_tag_functors(TagFuncTuple1 &my_inputs, TagF uncTuple2 &other_inputs) { static inline void copy_tag_functors(TagFuncTuple1 &my_inputs, TagF uncTuple2 &other_inputs) {
if(tbb::flow::get<N-1>(other_inputs).my_original_func()) { if(tbb::flow::get<N-1>(other_inputs).my_original_func()) {
tbb::flow::get<N-1>(my_inputs).set_my_tag_func(tbb::flow::g et<N-1>(other_inputs).my_original_func()->clone()); tbb::flow::get<N-1>(my_inputs).set_my_tag_func(tbb::flow::g et<N-1>(other_inputs).my_original_func()->clone());
tbb::flow::get<N-1>(my_inputs).set_my_original_tag_func(tbb ::flow::get<N-1>(other_inputs).my_original_func()->clone()); tbb::flow::get<N-1>(my_inputs).set_my_original_tag_func(tbb ::flow::get<N-1>(other_inputs).my_original_func()->clone());
} }
join_helper<N-1>::copy_tag_functors(my_inputs, other_inputs); join_helper<N-1>::copy_tag_functors(my_inputs, other_inputs);
} }
template<typename InputTuple> template<typename InputTuple>
static inline void reset_inputs(InputTuple &my_input) { static inline void reset_inputs(InputTuple &my_input __TBB_PFG_RESE
join_helper<N-1>::reset_inputs(my_input); T_ARG(__TBB_COMMA reset_flags f)) {
tbb::flow::get<N-1>(my_input).reinitialize_port(); join_helper<N-1>::reset_inputs(my_input __TBB_PFG_RESET_ARG(__T
BB_COMMA f));
tbb::flow::get<N-1>(my_input).reset_receiver(__TBB_PFG_RESET_AR
G(f));
} }
}; };
template< > template< >
struct join_helper<1> { struct join_helper<1> {
template< typename TupleType, typename PortType > template< typename TupleType, typename PortType >
static inline void set_join_node_pointer(TupleType &my_input, PortT ype *port) { static inline void set_join_node_pointer(TupleType &my_input, PortT ype *port) {
tbb::flow::get<0>( my_input ).set_join_node_pointer(port); tbb::flow::get<0>( my_input ).set_join_node_pointer(port);
} }
skipping to change at line 200 skipping to change at line 192
} }
template< typename TagFuncTuple1, typename TagFuncTuple2> template< typename TagFuncTuple1, typename TagFuncTuple2>
static inline void copy_tag_functors(TagFuncTuple1 &my_inputs, TagF uncTuple2 &other_inputs) { static inline void copy_tag_functors(TagFuncTuple1 &my_inputs, TagF uncTuple2 &other_inputs) {
if(tbb::flow::get<0>(other_inputs).my_original_func()) { if(tbb::flow::get<0>(other_inputs).my_original_func()) {
tbb::flow::get<0>(my_inputs).set_my_tag_func(tbb::flow::get <0>(other_inputs).my_original_func()->clone()); tbb::flow::get<0>(my_inputs).set_my_tag_func(tbb::flow::get <0>(other_inputs).my_original_func()->clone());
tbb::flow::get<0>(my_inputs).set_my_original_tag_func(tbb:: flow::get<0>(other_inputs).my_original_func()->clone()); tbb::flow::get<0>(my_inputs).set_my_original_tag_func(tbb:: flow::get<0>(other_inputs).my_original_func()->clone());
} }
} }
template<typename InputTuple> template<typename InputTuple>
static inline void reset_inputs(InputTuple &my_input) { static inline void reset_inputs(InputTuple &my_input __TBB_PFG_RESE
tbb::flow::get<0>(my_input).reinitialize_port(); T_ARG(__TBB_COMMA reset_flags f)) {
tbb::flow::get<0>(my_input).reset_receiver(__TBB_PFG_RESET_ARG(
f));
} }
}; };
//! The two-phase join port //! The two-phase join port
template< typename T > template< typename T >
class reserving_port : public receiver<T> { class reserving_port : public receiver<T> {
public: public:
typedef T input_type; typedef T input_type;
typedef sender<T> predecessor_type; typedef sender<T> predecessor_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<predecessor_type *> predecessor_vector_type;
#endif
private: private:
// ----------- Aggregator ------------ // ----------- Aggregator ------------
enum op_type { reg_pred, rem_pred, res_item, rel_res, con_res }; enum op_type { reg_pred, rem_pred, res_item, rel_res, con_res
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
, add_blt_pred, del_blt_pred, blt_pred_cnt, blt_pred_cpy
#endif
};
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
typedef reserving_port<T> my_class; typedef reserving_port<T> my_class;
class reserving_port_operation : public aggregated_operation<reserv ing_port_operation> { class reserving_port_operation : public aggregated_operation<reserv ing_port_operation> {
public: public:
char type; char type;
union { union {
T *my_arg; T *my_arg;
predecessor_type *my_pred; predecessor_type *my_pred;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
size_t cnt_val;
predecessor_vector_type *pvec;
#endif
}; };
reserving_port_operation(const T& e, op_type t) : reserving_port_operation(const T& e, op_type t) :
type(char(t)), my_arg(const_cast<T*>(&e)) {} type(char(t)), my_arg(const_cast<T*>(&e)) {}
reserving_port_operation(const predecessor_type &s, op_type t) : type(char(t)), reserving_port_operation(const predecessor_type &s, op_type t) : type(char(t)),
my_pred(const_cast<predecessor_type *>(&s)) {} my_pred(const_cast<predecessor_type *>(&s)) {}
reserving_port_operation(op_type t) : type(char(t)) {} reserving_port_operation(op_type t) : type(char(t)) {}
}; };
typedef internal::aggregating_functor<my_class, reserving_port_oper ation> my_handler; typedef internal::aggregating_functor<my_class, reserving_port_oper ation> my_handler;
friend class internal::aggregating_functor<my_class, reserving_port _operation>; friend class internal::aggregating_functor<my_class, reserving_port _operation>;
skipping to change at line 279 skipping to change at line 282
case rel_res: case rel_res:
reserved = false; reserved = false;
my_predecessors.try_release( ); my_predecessors.try_release( );
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case con_res: case con_res:
reserved = false; reserved = false;
my_predecessors.try_consume( ); my_predecessors.try_consume( );
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
case add_blt_pred:
my_predecessors.internal_add_built_predecessor(*(curren
t->my_pred));
__TBB_store_with_release(current->status, SUCCEEDED);
break;
case del_blt_pred:
my_predecessors.internal_delete_built_predecessor(*(cur
rent->my_pred));
__TBB_store_with_release(current->status, SUCCEEDED);
break;
case blt_pred_cnt:
current->cnt_val = my_predecessors.predecessor_count();
__TBB_store_with_release(current->status, SUCCEEDED);
break;
case blt_pred_cpy:
my_predecessors.copy_predecessors(*(current->pvec));
__TBB_store_with_release(current->status, SUCCEEDED);
break;
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
} }
} }
} }
protected: protected:
template< typename R, typename B > friend class run_and_put_task; template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_c ache; template<typename X, typename Y> friend class internal::broadcast_c ache;
template<typename X, typename Y> friend class internal::round_robin _cache; template<typename X, typename Y> friend class internal::round_robin _cache;
task *try_put_task( const T & ) { task *try_put_task( const T & ) {
return NULL; return NULL;
skipping to change at line 345 skipping to change at line 366
reserving_port_operation op_data(rel_res); reserving_port_operation op_data(rel_res);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
//! Complete use of the port //! Complete use of the port
void consume( ) { void consume( ) {
reserving_port_operation op_data(con_res); reserving_port_operation op_data(con_res);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
void reinitialize_port() { #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
my_predecessors.reset(); /*override*/void internal_add_built_predecessor(predecessor_type &s
reserved = false; rc) {
reserving_port_operation op_data(src, add_blt_pred);
my_aggregator.execute(&op_data);
} }
protected: /*override*/void internal_delete_built_predecessor(predecessor_type
&src) {
reserving_port_operation op_data(src, del_blt_pred);
my_aggregator.execute(&op_data);
}
/*override*/void reset_receiver() { /*override*/size_t predecessor_count() {
my_predecessors.reset(); reserving_port_operation op_data(blt_pred_cnt);
my_aggregator.execute(&op_data);
return op_data.cnt_val;
}
/*override*/void copy_predecessors(predecessor_vector_type &v) {
reserving_port_operation op_data(blt_pred_cpy);
op_data.pvec = &v;
my_aggregator.execute(&op_data);
}
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
/*override*/void reset_receiver( __TBB_PFG_RESET_ARG(reset_flags f)
) {
my_predecessors.reset(__TBB_PFG_RESET_ARG(f));
reserved = false;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
__TBB_ASSERT(!(f&rf_extract) || my_predecessors.empty(), "port
edges not removed");
#endif
} }
private: private:
forwarding_base *my_join; forwarding_base *my_join;
reservable_predecessor_cache< T, null_mutex > my_predecessors; reservable_predecessor_cache< T, null_mutex > my_predecessors;
bool reserved; bool reserved;
}; };
//! queueing join_port //! queueing join_port
template<typename T> template<typename T>
class queueing_port : public receiver<T>, public item_buffer<T> { class queueing_port : public receiver<T>, public item_buffer<T> {
public: public:
typedef T input_type; typedef T input_type;
typedef sender<T> predecessor_type; typedef sender<T> predecessor_type;
typedef queueing_port<T> my_node_type; typedef queueing_port<T> my_node_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<predecessor_type *> predecessor_vector_type;
#endif
// ----------- Aggregator ------------ // ----------- Aggregator ------------
private: private:
enum op_type { get__item, res_port, try__put_task }; enum op_type { get__item, res_port, try__put_task
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
, add_blt_pred, del_blt_pred, blt_pred_cnt, blt_pred_cpy
#endif
};
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
typedef queueing_port<T> my_class; typedef queueing_port<T> my_class;
class queueing_port_operation : public aggregated_operation<queuein g_port_operation> { class queueing_port_operation : public aggregated_operation<queuein g_port_operation> {
public: public:
char type; char type;
T my_val; T my_val;
T *my_arg; T *my_arg;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
sender<T> *pred;
size_t cnt_val;
predecessor_vector_type *pvec;
#endif
task * bypass_t; task * bypass_t;
// constructor for value parameter // constructor for value parameter
queueing_port_operation(const T& e, op_type t) : queueing_port_operation(const T& e, op_type t) :
type(char(t)), my_val(e) type(char(t)), my_val(e)
, bypass_t(NULL) , bypass_t(NULL)
{} {}
// constructor for pointer parameter // constructor for pointer parameter
queueing_port_operation(const T* p, op_type t) : queueing_port_operation(const T* p, op_type t) :
type(char(t)), my_arg(const_cast<T*>(p)) type(char(t)), my_arg(const_cast<T*>(p))
, bypass_t(NULL) , bypass_t(NULL)
skipping to change at line 422 skipping to change at line 476
this->push_back(current->my_val); this->push_back(current->my_val);
if (was_empty) rtask = my_join->decrement_port_coun t(false); if (was_empty) rtask = my_join->decrement_port_coun t(false);
else else
rtask = SUCCESSFULLY_ENQUEUED; rtask = SUCCESSFULLY_ENQUEUED;
current->bypass_t = rtask; current->bypass_t = rtask;
__TBB_store_with_release(current->status, SUCCEEDED ); __TBB_store_with_release(current->status, SUCCEEDED );
} }
break; break;
case get__item: case get__item:
if(!this->buffer_empty()) { if(!this->buffer_empty()) {
this->fetch_front(*(current->my_arg)); this->copy_front(*(current->my_arg));
__TBB_store_with_release(current->status, SUCCEEDED ); __TBB_store_with_release(current->status, SUCCEEDED );
} }
else { else {
__TBB_store_with_release(current->status, FAILED); __TBB_store_with_release(current->status, FAILED);
} }
break; break;
case res_port: case res_port:
__TBB_ASSERT(this->item_valid(this->my_head), "No item __TBB_ASSERT(this->my_item_valid(this->my_head), "No it
to reset"); em to reset");
this->invalidate_front(); ++(this->my_head); this->destroy_front();
if(this->item_valid(this->my_head)) { if(this->my_item_valid(this->my_head)) {
(void)my_join->decrement_port_count(true); (void)my_join->decrement_port_count(true);
} }
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
case add_blt_pred:
my_built_predecessors.add_edge(*(current->pred));
__TBB_store_with_release(current->status, SUCCEEDED);
break;
case del_blt_pred:
my_built_predecessors.delete_edge(*(current->pred));
__TBB_store_with_release(current->status, SUCCEEDED);
break;
case blt_pred_cnt:
current->cnt_val = my_built_predecessors.edge_count();
__TBB_store_with_release(current->status, SUCCEEDED);
break;
case blt_pred_cpy:
my_built_predecessors.copy_edges(*(current->pvec));
__TBB_store_with_release(current->status, SUCCEEDED);
break;
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
} }
} }
} }
// ------------ End Aggregator --------------- // ------------ End Aggregator ---------------
protected: protected:
template< typename R, typename B > friend class run_and_put_task; template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_c ache; template<typename X, typename Y> friend class internal::broadcast_c ache;
template<typename X, typename Y> friend class internal::round_robin _cache; template<typename X, typename Y> friend class internal::round_robin _cache;
/*override*/task *try_put_task(const T &v) { /*override*/task *try_put_task(const T &v) {
skipping to change at line 487 skipping to change at line 559
} }
// reset_port is called when item is accepted by successor, but // reset_port is called when item is accepted by successor, but
// is initiated by join_node. // is initiated by join_node.
void reset_port() { void reset_port() {
queueing_port_operation op_data(res_port); queueing_port_operation op_data(res_port);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return; return;
} }
void reinitialize_port() { #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
item_buffer<T>::reset(); /*override*/void internal_add_built_predecessor(sender<T> &p) {
queueing_port_operation op_data(add_blt_pred);
op_data.pred = &p;
my_aggregator.execute(&op_data);
} }
protected: /*override*/void internal_delete_built_predecessor(sender<T> &p) {
queueing_port_operation op_data(del_blt_pred);
op_data.pred = &p;
my_aggregator.execute(&op_data);
}
/*override*/void reset_receiver() { /*override*/size_t predecessor_count() {
// nothing to do. We queue, so no predecessor cache queueing_port_operation op_data(blt_pred_cnt);
my_aggregator.execute(&op_data);
return op_data.cnt_val;
} }
/*override*/void copy_predecessors(predecessor_vector_type &v) {
queueing_port_operation op_data(blt_pred_cpy);
op_data.pvec = &v;
my_aggregator.execute(&op_data);
}
/*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags f))
{
item_buffer<T>::reset();
if (f & rf_extract)
my_built_predecessors.receiver_extract(*this);
}
#else
/*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags /*f
*/)) { item_buffer<T>::reset(); }
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
private: private:
forwarding_base *my_join; forwarding_base *my_join;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
edge_container<sender<T> > my_built_predecessors;
#endif
}; };
#include "_flow_graph_tagged_buffer_impl.h" #include "_flow_graph_tagged_buffer_impl.h"
template< typename T > template< typename T >
class tag_matching_port : public receiver<T>, public tagged_buffer< tag _value, T, NO_TAG > { class tag_matching_port : public receiver<T>, public tagged_buffer< tag _value, T, NO_TAG > {
public: public:
typedef T input_type; typedef T input_type;
typedef sender<T> predecessor_type; typedef sender<T> predecessor_type;
typedef tag_matching_port<T> my_node_type; // for forwarding, if n eeded typedef tag_matching_port<T> my_node_type; // for forwarding, if n eeded
typedef function_body<input_type, tag_value> my_tag_func_type; typedef function_body<input_type, tag_value> my_tag_func_type;
typedef tagged_buffer<tag_value,T,NO_TAG> my_buffer_type; typedef tagged_buffer<tag_value,T,NO_TAG> my_buffer_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<predecessor_type *> predecessor_vector_type;
#endif
private: private:
// ----------- Aggregator ------------ // ----------- Aggregator ------------
private: private:
enum op_type { try__put, get__item, res_port }; enum op_type { try__put, get__item, res_port,
add_blt_pred, del_blt_pred, blt_pred_cnt, blt_pred_cpy
};
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
typedef tag_matching_port<T> my_class; typedef tag_matching_port<T> my_class;
class tag_matching_port_operation : public aggregated_operation<tag _matching_port_operation> { class tag_matching_port_operation : public aggregated_operation<tag _matching_port_operation> {
public: public:
char type; char type;
T my_val; T my_val;
T *my_arg; T *my_arg;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
predecessor_type *pred;
size_t cnt_val;
predecessor_vector_type *pvec;
#endif
tag_value my_tag_value; tag_value my_tag_value;
// constructor for value parameter // constructor for value parameter
tag_matching_port_operation(const T& e, op_type t) : tag_matching_port_operation(const T& e, op_type t) :
type(char(t)), my_val(e) {} type(char(t)), my_val(e) {}
// constructor for pointer parameter // constructor for pointer parameter
tag_matching_port_operation(const T* p, op_type t) : tag_matching_port_operation(const T* p, op_type t) :
type(char(t)), my_arg(const_cast<T*>(p)) {} type(char(t)), my_arg(const_cast<T*>(p)) {}
// constructor with no parameter // constructor with no parameter
tag_matching_port_operation(op_type t) : type(char(t)) {} tag_matching_port_operation(op_type t) : type(char(t)) {}
}; };
skipping to change at line 562 skipping to change at line 671
if(!this->tagged_find(my_join->current_tag, *(current-> my_arg))) { if(!this->tagged_find(my_join->current_tag, *(current-> my_arg))) {
__TBB_ASSERT(false, "Failed to find item correspond ing to current_tag."); __TBB_ASSERT(false, "Failed to find item correspond ing to current_tag.");
} }
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case res_port: case res_port:
// use current_tag from FE for item // use current_tag from FE for item
this->tagged_delete(my_join->current_tag); this->tagged_delete(my_join->current_tag);
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
case add_blt_pred:
my_built_predecessors.add_edge(*(current->pred));
__TBB_store_with_release(current->status, SUCCEEDED);
break;
case del_blt_pred:
my_built_predecessors.delete_edge(*(current->pred));
__TBB_store_with_release(current->status, SUCCEEDED);
break;
case blt_pred_cnt:
current->cnt_val = my_built_predecessors.edge_count();
__TBB_store_with_release(current->status, SUCCEEDED);
break;
case blt_pred_cpy:
my_built_predecessors.copy_edges(*(current->pvec));
__TBB_store_with_release(current->status, SUCCEEDED);
break;
#endif
} }
} }
} }
// ------------ End Aggregator --------------- // ------------ End Aggregator ---------------
protected: protected:
template< typename R, typename B > friend class run_and_put_task; template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_c ache; template<typename X, typename Y> friend class internal::broadcast_c ache;
template<typename X, typename Y> friend class internal::round_robin _cache; template<typename X, typename Y> friend class internal::round_robin _cache;
/*override*/task *try_put_task(const T& v) { /*override*/task *try_put_task(const T& v) {
tag_matching_port_operation op_data(v, try__put); tag_matching_port_operation op_data(v, try__put);
skipping to change at line 624 skipping to change at line 751
void set_my_tag_func(my_tag_func_type *f) { void set_my_tag_func(my_tag_func_type *f) {
my_tag_func = f; my_tag_func = f;
} }
bool get_item( T &v ) { bool get_item( T &v ) {
tag_matching_port_operation op_data(&v, get__item); tag_matching_port_operation op_data(&v, get__item);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.status == SUCCEEDED; return op_data.status == SUCCEEDED;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
/*override*/void internal_add_built_predecessor(sender<T> &p) {
tag_matching_port_operation op_data(add_blt_pred);
op_data.pred = &p;
my_aggregator.execute(&op_data);
}
/*override*/void internal_delete_built_predecessor(sender<T> &p) {
tag_matching_port_operation op_data(del_blt_pred);
op_data.pred = &p;
my_aggregator.execute(&op_data);
}
/*override*/size_t predecessor_count() {
tag_matching_port_operation op_data(blt_pred_cnt);
my_aggregator.execute(&op_data);
return op_data.cnt_val;
}
/*override*/void copy_predecessors(predecessor_vector_type &v) {
tag_matching_port_operation op_data(blt_pred_cpy);
op_data.pvec = &v;
my_aggregator.execute(&op_data);
}
#endif
// reset_port is called when item is accepted by successor, but // reset_port is called when item is accepted by successor, but
// is initiated by join_node. // is initiated by join_node.
void reset_port() { void reset_port() {
tag_matching_port_operation op_data(res_port); tag_matching_port_operation op_data(res_port);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return; return;
} }
my_tag_func_type *my_func() { return my_tag_func; } my_tag_func_type *my_func() { return my_tag_func; }
my_tag_func_type *my_original_func() { return my_original_tag_func; } my_tag_func_type *my_original_func() { return my_original_tag_func; }
void reinitialize_port() { #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
/*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags f))
{
my_buffer_type::reset(); my_buffer_type::reset();
if (f & rf_extract)
my_built_predecessors.receiver_extract(*this);
} }
#else
protected: /*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags /*f
*/)) { my_buffer_type::reset(); }
/*override*/void reset_receiver() { #endif
// nothing to do. We queue, so no predecessor cache
}
private: private:
// need map of tags to values // need map of tags to values
forwarding_base *my_join; forwarding_base *my_join;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
edge_container<predecessor_type> my_built_predecessors;
#endif
my_tag_func_type *my_tag_func; my_tag_func_type *my_tag_func;
my_tag_func_type *my_original_tag_func; my_tag_func_type *my_original_tag_func;
}; // tag_matching_port }; // tag_matching_port
using namespace graph_policy_namespace; using namespace graph_policy_namespace;
template<graph_buffer_policy JP, typename InputTuple, typename OutputTu ple> template<graph_buffer_policy JP, typename InputTuple, typename OutputTu ple>
class join_node_base; class join_node_base;
//! join_node_FE : implements input port policy //! join_node_FE : implements input port policy
skipping to change at line 703 skipping to change at line 859
FLOW_SPAWN(*rtask); FLOW_SPAWN(*rtask);
} }
} }
return NULL; return NULL;
} }
input_type &input_ports() { return my_inputs; } input_type &input_ports() { return my_inputs; }
protected: protected:
void reset() { void reset( __TBB_PFG_RESET_ARG( reset_flags f)) {
// called outside of parallel contexts // called outside of parallel contexts
ports_with_no_inputs = N; ports_with_no_inputs = N;
join_helper<N>::reset_inputs(my_inputs); join_helper<N>::reset_inputs(my_inputs __TBB_PFG_RESET_ARG( __T BB_COMMA f));
} }
// all methods on input ports should be called under mutual exclusi on from join_node_base. // all methods on input ports should be called under mutual exclusi on from join_node_base.
bool tuple_build_may_succeed() { bool tuple_build_may_succeed() {
return !ports_with_no_inputs; return !ports_with_no_inputs;
} }
bool try_to_make_tuple(output_type &out) { bool try_to_make_tuple(output_type &out) {
if(ports_with_no_inputs) return false; if(ports_with_no_inputs) return false;
skipping to change at line 778 skipping to change at line 934
} }
return NULL; return NULL;
} }
void increment_port_count() { __TBB_ASSERT(false, NULL); } // shou ld never be called void increment_port_count() { __TBB_ASSERT(false, NULL); } // shou ld never be called
input_type &input_ports() { return my_inputs; } input_type &input_ports() { return my_inputs; }
protected: protected:
void reset() { void reset( __TBB_PFG_RESET_ARG( reset_flags f)) {
reset_port_count(); reset_port_count();
join_helper<N>::reset_inputs(my_inputs); join_helper<N>::reset_inputs(my_inputs __TBB_PFG_RESET_ARG( __T BB_COMMA f) );
} }
// all methods on input ports should be called under mutual exclusi on from join_node_base. // all methods on input ports should be called under mutual exclusi on from join_node_base.
bool tuple_build_may_succeed() { bool tuple_build_may_succeed() {
return !ports_with_no_items; return !ports_with_no_items;
} }
bool try_to_make_tuple(output_type &out) { bool try_to_make_tuple(output_type &out) {
if(ports_with_no_items) return false; if(ports_with_no_items) return false;
skipping to change at line 890 skipping to change at line 1046
} }
void handle_operations(tag_matching_FE_operation* op_list) { void handle_operations(tag_matching_FE_operation* op_list) {
tag_matching_FE_operation *current; tag_matching_FE_operation *current;
while(op_list) { while(op_list) {
current = op_list; current = op_list;
op_list = op_list->next; op_list = op_list->next;
switch(current->type) { switch(current->type) {
case res_count: // called from BE case res_count: // called from BE
{ {
output_type l_out; this->destroy_front();
this->pop_front(l_out); // don't care about return
ed value.
__TBB_store_with_release(current->status, SUCCEEDED ); __TBB_store_with_release(current->status, SUCCEEDED );
} }
break; break;
case inc_count: { // called from input ports case inc_count: { // called from input ports
size_t *p = 0; size_t *p = 0;
tag_value t = current->my_val; tag_value t = current->my_val;
bool do_enqueue = current->enqueue_task; bool do_enqueue = current->enqueue_task;
if(!(this->tagged_find_ref(t,p))) { if(!(this->tagged_find_ref(t,p))) {
this->tagged_insert(t, 0); this->tagged_insert(t, 0);
if(!(this->tagged_find_ref(t,p))) { if(!(this->tagged_find_ref(t,p))) {
skipping to change at line 921 skipping to change at line 1076
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case may_succeed: // called from BE case may_succeed: // called from BE
__TBB_store_with_release(current->status, this->buffer_ empty() ? FAILED : SUCCEEDED); __TBB_store_with_release(current->status, this->buffer_ empty() ? FAILED : SUCCEEDED);
break; break;
case try_make: // called from BE case try_make: // called from BE
if(this->buffer_empty()) { if(this->buffer_empty()) {
__TBB_store_with_release(current->status, FAILED); __TBB_store_with_release(current->status, FAILED);
} }
else { else {
this->fetch_front(*(current->my_output)); this->copy_front(*(current->my_output));
__TBB_store_with_release(current->status, SUCCEEDED ); __TBB_store_with_release(current->status, SUCCEEDED );
} }
break; break;
} }
} }
} }
// ------------ End Aggregator --------------- // ------------ End Aggregator ---------------
public: public:
template<typename FunctionTuple> template<typename FunctionTuple>
skipping to change at line 971 skipping to change at line 1126
} }
/*override*/ task *decrement_port_count(bool /*handle_task*/) { __T BB_ASSERT(false, NULL); return NULL; } /*override*/ task *decrement_port_count(bool /*handle_task*/) { __T BB_ASSERT(false, NULL); return NULL; }
void increment_port_count() { __TBB_ASSERT(false, NULL); } // shou ld never be called void increment_port_count() { __TBB_ASSERT(false, NULL); } // shou ld never be called
input_type &input_ports() { return my_inputs; } input_type &input_ports() { return my_inputs; }
protected: protected:
void reset() { void reset( __TBB_PFG_RESET_ARG( reset_flags f )) {
// called outside of parallel contexts // called outside of parallel contexts
join_helper<N>::reset_inputs(my_inputs); join_helper<N>::reset_inputs(my_inputs __TBB_PFG_RESET_ARG( __T BB_COMMA f));
my_tag_buffer::reset(); // have to reset the tag counts my_tag_buffer::reset(); // have to reset the tag counts
output_buffer_type::reset(); // also the queue of outputs output_buffer_type::reset(); // also the queue of outputs
my_node->current_tag = NO_TAG; my_node->current_tag = NO_TAG;
} }
// all methods on input ports should be called under mutual exclusi on from join_node_base. // all methods on input ports should be called under mutual exclusi on from join_node_base.
bool tuple_build_may_succeed() { // called from back-end bool tuple_build_may_succeed() { // called from back-end
tag_matching_FE_operation op_data(may_succeed); tag_matching_FE_operation op_data(may_succeed);
skipping to change at line 1023 skipping to change at line 1178
using graph_node::my_graph; using graph_node::my_graph;
public: public:
typedef OutputTuple output_type; typedef OutputTuple output_type;
typedef receiver<output_type> successor_type; typedef receiver<output_type> successor_type;
typedef join_node_FE<JP, InputTuple, OutputTuple> input_ports_type; typedef join_node_FE<JP, InputTuple, OutputTuple> input_ports_type;
using input_ports_type::tuple_build_may_succeed; using input_ports_type::tuple_build_may_succeed;
using input_ports_type::try_to_make_tuple; using input_ports_type::try_to_make_tuple;
using input_ports_type::tuple_accepted; using input_ports_type::tuple_accepted;
using input_ports_type::tuple_rejected; using input_ports_type::tuple_rejected;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<successor_type *> successor_vector_type;
#endif
private: private:
// ----------- Aggregator ------------ // ----------- Aggregator ------------
enum op_type { reg_succ, rem_succ, try__get, do_fwrd, do_fwrd_bypas enum op_type { reg_succ, rem_succ, try__get, do_fwrd, do_fwrd_bypas
s }; s
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
, add_blt_succ, del_blt_succ, blt_succ_cnt, blt_succ_cpy
#endif
};
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
typedef join_node_base<JP,InputTuple,OutputTuple> my_class; typedef join_node_base<JP,InputTuple,OutputTuple> my_class;
class join_node_base_operation : public aggregated_operation<join_n ode_base_operation> { class join_node_base_operation : public aggregated_operation<join_n ode_base_operation> {
public: public:
char type; char type;
union { union {
output_type *my_arg; output_type *my_arg;
successor_type *my_succ; successor_type *my_succ;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
size_t cnt_val;
successor_vector_type *svec;
#endif
}; };
task *bypass_t; task *bypass_t;
join_node_base_operation(const output_type& e, op_type t) : typ e(char(t)), join_node_base_operation(const output_type& e, op_type t) : typ e(char(t)),
my_arg(const_cast<output_type*>(&e)), bypass_t(NULL) {} my_arg(const_cast<output_type*>(&e)), bypass_t(NULL) {}
join_node_base_operation(const successor_type &s, op_type t) : type(char(t)), join_node_base_operation(const successor_type &s, op_type t) : type(char(t)),
my_succ(const_cast<successor_type *>(&s)), bypass_t(NULL) { } my_succ(const_cast<successor_type *>(&s)), bypass_t(NULL) { }
join_node_base_operation(op_type t) : type(char(t)), bypass_t(N ULL) {} join_node_base_operation(op_type t) : type(char(t)), bypass_t(N ULL) {}
}; };
typedef internal::aggregating_functor<my_class, join_node_base_oper ation> my_handler; typedef internal::aggregating_functor<my_class, join_node_base_oper ation> my_handler;
skipping to change at line 1108 skipping to change at line 1274
build_succeeded = false; build_succeeded = false;
} }
} }
} while(build_succeeded); } while(build_succeeded);
} }
current->bypass_t = last_task; current->bypass_t = last_task;
__TBB_store_with_release(current->status, SUCCEEDED ); __TBB_store_with_release(current->status, SUCCEEDED );
forwarder_busy = false; forwarder_busy = false;
} }
break; break;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
case add_blt_succ:
my_successors.internal_add_built_successor(*(current->m
y_succ));
__TBB_store_with_release(current->status, SUCCEEDED);
break;
case del_blt_succ:
my_successors.internal_delete_built_successor(*(current
->my_succ));
__TBB_store_with_release(current->status, SUCCEEDED);
break;
case blt_succ_cnt:
current->cnt_val = my_successors.successor_count();
__TBB_store_with_release(current->status, SUCCEEDED);
break;
case blt_succ_cpy:
my_successors.copy_successors(*(current->svec));
__TBB_store_with_release(current->status, SUCCEEDED);
break;
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
} }
} }
} }
// ---------- end aggregator ----------- // ---------- end aggregator -----------
public: public:
join_node_base(graph &g) : graph_node(g), input_ports_type(g), forw arder_busy(false) { join_node_base(graph &g) : graph_node(g), input_ports_type(g), forw arder_busy(false) {
my_successors.set_owner(this); my_successors.set_owner(this);
input_ports_type::set_my_node(this); input_ports_type::set_my_node(this);
my_aggregator.initialize_handler(my_handler(this)); my_aggregator.initialize_handler(my_handler(this));
} }
skipping to change at line 1152 skipping to change at line 1336
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.status == SUCCEEDED; return op_data.status == SUCCEEDED;
} }
bool try_get( output_type &v) { bool try_get( output_type &v) {
join_node_base_operation op_data(v, try__get); join_node_base_operation op_data(v, try__get);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.status == SUCCEEDED; return op_data.status == SUCCEEDED;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
/*override*/void internal_add_built_successor( successor_type &r) {
join_node_base_operation op_data(r, add_blt_succ);
my_aggregator.execute(&op_data);
}
/*override*/void internal_delete_built_successor( successor_type &r
) {
join_node_base_operation op_data(r, del_blt_succ);
my_aggregator.execute(&op_data);
}
/*override*/size_t successor_count() {
join_node_base_operation op_data(blt_succ_cnt);
my_aggregator.execute(&op_data);
return op_data.cnt_val;
}
/*override*/ void copy_successors(successor_vector_type &v) {
join_node_base_operation op_data(blt_succ_cpy);
op_data.svec = &v;
my_aggregator.execute(&op_data);
}
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
protected: protected:
/*override*/void reset() { /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) {
input_ports_type::reset(); input_ports_type::reset(__TBB_PFG_RESET_ARG(f));
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
my_successors.reset(f);
#endif
} }
private: private:
broadcast_cache<output_type, null_rw_mutex> my_successors; broadcast_cache<output_type, null_rw_mutex> my_successors;
friend class forward_task_bypass< join_node_base<JP, InputTuple, Ou tputTuple> >; friend class forward_task_bypass< join_node_base<JP, InputTuple, Ou tputTuple> >;
task *forward_task() { task *forward_task() {
join_node_base_operation op_data(do_fwrd_bypass); join_node_base_operation op_data(do_fwrd_bypass);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.bypass_t; return op_data.bypass_t;
 End of changes. 44 change blocks. 
73 lines changed or deleted 310 lines changed or added


 _flow_graph_node_impl.h   _flow_graph_node_impl.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB__flow_graph_node_impl_H #ifndef __TBB__flow_graph_node_impl_H
#define __TBB__flow_graph_node_impl_H #define __TBB__flow_graph_node_impl_H
#ifndef __TBB_flow_graph_H #ifndef __TBB_flow_graph_H
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#include "_flow_graph_item_buffer_impl.h" #include "_flow_graph_item_buffer_impl.h"
skipping to change at line 62 skipping to change at line 54
bool push( T& t ) { bool push( T& t ) {
return this->push_back( t ); return this->push_back( t );
} }
}; };
//! Input and scheduling for a function node that takes a type Input as input //! Input and scheduling for a function node that takes a type Input as input
// The only up-ref is apply_body_impl, which should implement the func tion // The only up-ref is apply_body_impl, which should implement the func tion
// call and any handling of the result. // call and any handling of the result.
template< typename Input, typename A, typename ImplType > template< typename Input, typename A, typename ImplType >
class function_input_base : public receiver<Input>, tbb::internal::no_a ssign { class function_input_base : public receiver<Input>, tbb::internal::no_a ssign {
typedef sender<Input> predecessor_type;
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
enum op_type {reg_pred, rem_pred, app_body, try_fwd, tryput_bypass, enum op_type {reg_pred, rem_pred, app_body, try_fwd, tryput_bypass,
app_body_bypass }; app_body_bypass
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
, add_blt_pred, del_blt_pred,
blt_pred_cnt, blt_pred_cpy // create vector copies of preds a
nd succs
#endif
};
typedef function_input_base<Input, A, ImplType> my_class; typedef function_input_base<Input, A, ImplType> my_class;
public: public:
//! The input type of this receiver //! The input type of this receiver
typedef Input input_type; typedef Input input_type;
typedef sender<Input> predecessor_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<predecessor_type *> predecessor_vector_type;
#endif
//! Constructor for function_input_base //! Constructor for function_input_base
function_input_base( graph &g, size_t max_concurrency, function_inp ut_queue<input_type,A> *q = NULL ) function_input_base( graph &g, size_t max_concurrency, function_inp ut_queue<input_type,A> *q = NULL )
: my_graph(g), my_max_concurrency(max_concurrency), my_concurre ncy(0), : my_graph(g), my_max_concurrency(max_concurrency), my_concurre ncy(0),
my_queue(q), forwarder_busy(false) { my_queue(q), forwarder_busy(false) {
my_predecessors.set_owner(this); my_predecessors.set_owner(this);
my_aggregator.initialize_handler(my_handler(this)); my_aggregator.initialize_handler(my_handler(this));
} }
//! Copy constructor //! Copy constructor
skipping to change at line 125 skipping to change at line 126
} }
//! Removes src from the list of cached predecessors. //! Removes src from the list of cached predecessors.
/* override */ bool remove_predecessor( predecessor_type &src ) { /* override */ bool remove_predecessor( predecessor_type &src ) {
my_operation op_data(rem_pred); my_operation op_data(rem_pred);
op_data.r = &src; op_data.r = &src;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return true; return true;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
//! Adds to list of predecessors added by make_edge
/*override*/ void internal_add_built_predecessor( predecessor_type
&src) {
my_operation op_data(add_blt_pred);
op_data.r = &src;
my_aggregator.execute(&op_data);
}
//! removes from to list of predecessors (used by remove_edge)
/*override*/ void internal_delete_built_predecessor( predecessor_ty
pe &src) {
my_operation op_data(del_blt_pred);
op_data.r = &src;
my_aggregator.execute(&op_data);
}
/*override*/ size_t predecessor_count() {
my_operation op_data(blt_pred_cnt);
my_aggregator.execute(&op_data);
return op_data.cnt_val;
}
/*override*/ void copy_predecessors(predecessor_vector_type &v) {
my_operation op_data(blt_pred_cpy);
op_data.predv = &v;
my_aggregator.execute(&op_data);
}
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
protected: protected:
void reset_function_input_base() { void reset_function_input_base( __TBB_PFG_RESET_ARG(reset_flags f)) {
my_concurrency = 0; my_concurrency = 0;
if(my_queue) { if(my_queue) {
my_queue->reset(); my_queue->reset();
} }
my_predecessors.reset(); reset_receiver(__TBB_PFG_RESET_ARG(f));
forwarder_busy = false; forwarder_busy = false;
} }
graph& my_graph; graph& my_graph;
const size_t my_max_concurrency; const size_t my_max_concurrency;
size_t my_concurrency; size_t my_concurrency;
function_input_queue<input_type, A> *my_queue; function_input_queue<input_type, A> *my_queue;
predecessor_cache<input_type, null_mutex > my_predecessors; predecessor_cache<input_type, null_mutex > my_predecessors;
/*override*/void reset_receiver() { /*override*/void reset_receiver( __TBB_PFG_RESET_ARG(reset_flags f)
my_predecessors.reset(); ) {
my_predecessors.reset(__TBB_PFG_RESET_ARG(f));
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
__TBB_ASSERT(!(f & rf_extract) || my_predecessors.empty(), "fun
ction_input_base reset failed");
#endif
} }
private: private:
friend class apply_body_task_bypass< my_class, input_type >; friend class apply_body_task_bypass< my_class, input_type >;
friend class forward_task_bypass< my_class >; friend class forward_task_bypass< my_class >;
class my_operation : public aggregated_operation< my_operation > { class my_operation : public aggregated_operation< my_operation > {
public: public:
char type; char type;
union { union {
input_type *elem; input_type *elem;
predecessor_type *r; predecessor_type *r;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
size_t cnt_val;
predecessor_vector_type *predv;
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
}; };
tbb::task *bypass_t; tbb::task *bypass_t;
my_operation(const input_type& e, op_type t) : my_operation(const input_type& e, op_type t) :
type(char(t)), elem(const_cast<input_type*>(&e)) {} type(char(t)), elem(const_cast<input_type*>(&e)) {}
my_operation(op_type t) : type(char(t)), r(NULL) {} my_operation(op_type t) : type(char(t)), r(NULL) {}
}; };
bool forwarder_busy; bool forwarder_busy;
typedef internal::aggregating_functor<my_class, my_operation> my_ha ndler; typedef internal::aggregating_functor<my_class, my_operation> my_ha ndler;
friend class internal::aggregating_functor<my_class, my_operation>; friend class internal::aggregating_functor<my_class, my_operation>;
skipping to change at line 226 skipping to change at line 262
++my_concurrency; ++my_concurrency;
new_task = create_body_task(i); new_task = create_body_task(i);
} }
} }
tmp->bypass_t = new_task; tmp->bypass_t = new_task;
__TBB_store_with_release(tmp->status, SUCCEEDED); __TBB_store_with_release(tmp->status, SUCCEEDED);
} }
break; break;
case tryput_bypass: internal_try_put_task(tmp); break; case tryput_bypass: internal_try_put_task(tmp); break;
case try_fwd: internal_forward(tmp); break; case try_fwd: internal_forward(tmp); break;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
case add_blt_pred: {
my_predecessors.internal_add_built_predecessor(*(t
mp->r));
__TBB_store_with_release(tmp->status, SUCCEEDED);
} }
break;
case del_blt_pred:
my_predecessors.internal_delete_built_predecessor(*(tmp
->r));
__TBB_store_with_release(tmp->status, SUCCEEDED);
break;
case blt_pred_cnt:
tmp->cnt_val = my_predecessors.predecessor_count();
__TBB_store_with_release(tmp->status, SUCCEEDED);
break;
case blt_pred_cpy:
my_predecessors.copy_predecessors( *(tmp->predv) );
__TBB_store_with_release(tmp->status, SUCCEEDED);
break;
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
}
} }
} }
//! Put to the node, but return the task instead of enqueueing it //! Put to the node, but return the task instead of enqueueing it
void internal_try_put_task(my_operation *op) { void internal_try_put_task(my_operation *op) {
__TBB_ASSERT(my_max_concurrency != 0, NULL); __TBB_ASSERT(my_max_concurrency != 0, NULL);
if (my_concurrency < my_max_concurrency) { if (my_concurrency < my_max_concurrency) {
++my_concurrency; ++my_concurrency;
task * new_task = create_body_task(*(op->elem)); task * new_task = create_body_task(*(op->elem));
op->bypass_t = new_task; op->bypass_t = new_task;
skipping to change at line 391 skipping to change at line 446
tbb::internal::fgt_end_body( my_body ); tbb::internal::fgt_end_body( my_body );
task * new_task = successors().try_put_task( v ); task * new_task = successors().try_put_task( v );
#else #else
task * new_task = successors().try_put_task( (*my_body)(i) ); task * new_task = successors().try_put_task( (*my_body)(i) );
#endif #endif
return new_task; return new_task;
} }
protected: protected:
void reset_function_input() { void reset_function_input(__TBB_PFG_RESET_ARG(reset_flags f)) {
base_type::reset_function_input_base(); base_type::reset_function_input_base(__TBB_PFG_RESET_ARG(f));
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
if(f & rf_reset_bodies) my_body->reset_body();
#endif
} }
function_body<input_type, output_type> *my_body; function_body<input_type, output_type> *my_body;
virtual broadcast_cache<output_type > &successors() = 0; virtual broadcast_cache<output_type > &successors() = 0;
}; // function_input }; // function_input
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
// helper templates to reset the successor edges of the output ports of
an multifunction_node
template<int N>
struct reset_element {
template<typename P>
static void reset_this(P &p, reset_flags f) {
(void)tbb::flow::get<N-1>(p).successors().reset(f);
reset_element<N-1>::reset_this(p, f);
}
template<typename P>
static bool this_empty(P &p) {
if(tbb::flow::get<N-1>(p).successors().empty())
return reset_element<N-1>::this_empty(p);
return false;
}
};
template<>
struct reset_element<1> {
template<typename P>
static void reset_this(P &p, reset_flags f) {
(void)tbb::flow::get<0>(p).successors().reset(f);
}
template<typename P>
static bool this_empty(P &p) {
return tbb::flow::get<0>(p).successors().empty();
}
};
#endif
//! Implements methods for a function node that takes a type Input as i nput //! Implements methods for a function node that takes a type Input as i nput
// and has a tuple of output ports specified. // and has a tuple of output ports specified.
template< typename Input, typename OutputPortSet, typename A> template< typename Input, typename OutputPortSet, typename A>
class multifunction_input : public function_input_base<Input, A, multif unction_input<Input,OutputPortSet,A> > { class multifunction_input : public function_input_base<Input, A, multif unction_input<Input,OutputPortSet,A> > {
public: public:
static const int N = tbb::flow::tuple_size<OutputPortSet>::value;
typedef Input input_type; typedef Input input_type;
typedef OutputPortSet output_ports_type; typedef OutputPortSet output_ports_type;
typedef multifunction_input<Input,OutputPortSet,A> my_class; typedef multifunction_input<Input,OutputPortSet,A> my_class;
typedef function_input_base<Input, A, my_class> base_type; typedef function_input_base<Input, A, my_class> base_type;
typedef function_input_queue<input_type, A> input_queue_type; typedef function_input_queue<input_type, A> input_queue_type;
// constructor // constructor
template<typename Body> template<typename Body>
multifunction_input( multifunction_input(
graph &g, graph &g,
skipping to change at line 452 skipping to change at line 541
(*my_body)(i, my_output_ports); (*my_body)(i, my_output_ports);
tbb::internal::fgt_end_body( my_body ); tbb::internal::fgt_end_body( my_body );
task * new_task = SUCCESSFULLY_ENQUEUED; task * new_task = SUCCESSFULLY_ENQUEUED;
return new_task; return new_task;
} }
output_ports_type &output_ports(){ return my_output_ports; } output_ports_type &output_ports(){ return my_output_ports; }
protected: protected:
void reset() { /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) {
base_type::reset_function_input_base(); base_type::reset_function_input_base(__TBB_PFG_RESET_ARG(f));
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
reset_element<N>::reset_this(my_output_ports, f);
if(f & rf_reset_bodies) my_body->reset_body();
__TBB_ASSERT(!(f & rf_extract) || reset_element<N>::this_empty(
my_output_ports), "multifunction_node reset failed");
#endif
} }
multifunction_body<input_type, output_ports_type> *my_body; multifunction_body<input_type, output_ports_type> *my_body;
output_ports_type my_output_ports; output_ports_type my_output_ports;
}; // multifunction_input }; // multifunction_input
// template to refer to an output port of a multifunction_node // template to refer to an output port of a multifunction_node
template<size_t N, typename MOP> template<size_t N, typename MOP>
typename tbb::flow::tuple_element<N, typename MOP::output_ports_type>:: type &output_port(MOP &op) { typename tbb::flow::tuple_element<N, typename MOP::output_ports_type>:: type &output_port(MOP &op) {
skipping to change at line 519 skipping to change at line 613
~continue_input() { ~continue_input() {
delete my_body; delete my_body;
} }
template< typename Body > template< typename Body >
Body copy_function_object() { Body copy_function_object() {
internal::function_body<input_type, output_type> &body_ref = *m y_body; internal::function_body<input_type, output_type> &body_ref = *m y_body;
return dynamic_cast< internal::function_body_leaf<input_type, o utput_type, Body> & >(body_ref).get_body(); return dynamic_cast< internal::function_body_leaf<input_type, o utput_type, Body> & >(body_ref).get_body();
} }
/*override*/void reset_receiver( __TBB_PFG_RESET_ARG(reset_flags f)
) {
continue_receiver::reset_receiver(__TBB_PFG_RESET_ARG(f));
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
if(f & rf_reset_bodies) my_body->reset_body();
#endif
}
protected: protected:
graph* my_graph_ptr; graph* my_graph_ptr;
function_body<input_type, output_type> *my_body; function_body<input_type, output_type> *my_body;
virtual broadcast_cache<output_type > &successors() = 0; virtual broadcast_cache<output_type > &successors() = 0;
friend class apply_body_task_bypass< continue_input< Output >, cont inue_msg >; friend class apply_body_task_bypass< continue_input< Output >, cont inue_msg >;
//! Applies the body to the provided input //! Applies the body to the provided input
skipping to change at line 558 skipping to change at line 659
NULL; NULL;
} }
}; // continue_input }; // continue_input
//! Implements methods for both executable and function nodes that puts Output to its successors //! Implements methods for both executable and function nodes that puts Output to its successors
template< typename Output > template< typename Output >
class function_output : public sender<Output> { class function_output : public sender<Output> {
public: public:
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
template<int N> friend struct reset_element;
#endif
typedef Output output_type; typedef Output output_type;
typedef receiver<output_type> successor_type;
typedef broadcast_cache<output_type> broadcast_cache_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<successor_type *> successor_vector_type;
#endif
function_output() { my_successors.set_owner(this); } function_output() { my_successors.set_owner(this); }
function_output(const function_output & /*other*/) : sender<output_ type>() { function_output(const function_output & /*other*/) : sender<output_ type>() {
my_successors.set_owner(this); my_successors.set_owner(this);
} }
//! Adds a new successor to this node //! Adds a new successor to this node
/* override */ bool register_successor( receiver<output_type> &r ) { /* override */ bool register_successor( receiver<output_type> &r ) {
successors().register_successor( r ); successors().register_successor( r );
return true; return true;
} }
//! Removes a successor from this node //! Removes a successor from this node
/* override */ bool remove_successor( receiver<output_type> &r ) { /* override */ bool remove_successor( receiver<output_type> &r ) {
successors().remove_successor( r ); successors().remove_successor( r );
return true; return true;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
/*override*/ void internal_add_built_successor( receiver<output_typ
e> &r) {
successors().internal_add_built_successor( r );
}
/*override*/ void internal_delete_built_successor( receiver<output_
type> &r) {
successors().internal_delete_built_successor( r );
}
/*override*/ size_t successor_count() {
return successors().successor_count();
}
/*override*/ void copy_successors( successor_vector_type &v) {
successors().copy_successors(v);
}
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
// for multifunction_node. The function_body that implements // for multifunction_node. The function_body that implements
// the node will have an input and an output tuple of ports. To pu t // the node will have an input and an output tuple of ports. To pu t
// an item to a successor, the body should // an item to a successor, the body should
// //
// get<I>(output_ports).try_put(output_value); // get<I>(output_ports).try_put(output_value);
// //
// return value will be bool returned from successors.try_put. // return value will be bool returned from successors.try_put.
task *try_put_task(const output_type &i) { return my_successors.try _put_task(i); } task *try_put_task(const output_type &i) { return my_successors.try _put_task(i); }
protected: protected:
broadcast_cache<output_type> my_successors; broadcast_cache_type my_successors;
broadcast_cache<output_type > &successors() { return my_successors; broadcast_cache_type &successors() { return my_successors; }
}
}; // function_output }; // function_output
template< typename Output > template< typename Output >
class multifunction_output : public function_output<Output> { class multifunction_output : public function_output<Output> {
public: public:
typedef Output output_type; typedef Output output_type;
typedef function_output<output_type> base_type; typedef function_output<output_type> base_type;
using base_type::my_successors; using base_type::my_successors;
 End of changes. 20 change blocks. 
42 lines changed or deleted 189 lines changed or added


 _flow_graph_tagged_buffer_impl.h   _flow_graph_tagged_buffer_impl.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
// tagged buffer that can expand, and can support as many deletions as addi tions // tagged buffer that can expand, and can support as many deletions as addi tions
// list-based, with elements of list held in std::vector (for destruction m anagement), // list-based, with elements of list held in array (for destruction managem ent),
// multiplicative hashing (like ets). No synchronization built-in. // multiplicative hashing (like ets). No synchronization built-in.
// //
#ifndef __TBB__flow_graph_tagged_buffer_impl_H #ifndef __TBB__flow_graph_tagged_buffer_impl_H
#define __TBB__flow_graph_tagged_buffer_impl_H #define __TBB__flow_graph_tagged_buffer_impl_H
#ifndef __TBB_flow_graph_H #ifndef __TBB_flow_graph_H
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
// included in namespace tbb::flow::interface7::internal
template<typename T, typename U, size_t NoTagMark>
struct otherData {
T t;
U next;
otherData() : t(NoTagMark), next(NULL) {}
};
template<typename TagType, typename ValueType, size_t NoTagMark> template<typename TagType, typename ValueType, size_t NoTagMark>
struct buffer_element { struct buffer_element_type {
TagType t; // the second parameter below is void * because we can't forward-declar
ValueType v; e the type
buffer_element *next; // itself, so we just reinterpret_cast below.
buffer_element() : t(NoTagMark), next(NULL) {} typedef typename aligned_pair<ValueType, otherData<TagType, void *, NoT
agMark> >::type type;
}; };
template template
< <
typename TagType, typename TagType,
typename ValueType, typename ValueType,
size_t NoTagMark = 0, size_t NoTagMark = 0,
typename Allocator=tbb::cache_aligned_allocator< buffer_element<TagTyp e,ValueType,NoTagMark> > typename Allocator=tbb::cache_aligned_allocator< typename buffer_eleme nt_type<TagType, ValueType, NoTagMark>::type >
> >
class tagged_buffer { class tagged_buffer {
public: public:
static const size_t INITIAL_SIZE = 8; // initial size of the hash poin ter table static const size_t INITIAL_SIZE = 8; // initial size of the hash poin ter table
static const TagType NO_TAG = TagType(NoTagMark); static const TagType NO_TAG = TagType(NoTagMark);
typedef ValueType value_type; typedef ValueType value_type;
typedef buffer_element<TagType,ValueType, NO_TAG> element_type; typedef typename buffer_element_type<TagType, ValueType, NO_TAG>::type element_type;
typedef value_type *pointer_type; typedef value_type *pointer_type;
typedef std::vector<element_type, Allocator> list_array_type; typedef element_type *list_array_type; // array we manage manually
typedef typename Allocator::template rebind<element_type*>::other point typedef list_array_type *pointer_array_type;
er_array_allocator_type; typedef typename Allocator::template rebind<list_array_type>::other poi
typedef typename Allocator::template rebind<list_array_type>::other lis nter_array_allocator_type;
t_array_allocator; typedef typename Allocator::template rebind<element_type>::other elemen
ts_array_allocator;
private: private:
size_t my_size; size_t my_size;
size_t nelements; size_t nelements;
element_type** array; pointer_array_type pointer_array; // pointer_array[my_size]
std::vector<element_type, Allocator> *lists; list_array_type elements_array; // elements_array[my_size / 2]
element_type* free_list; element_type* free_list;
size_t mask() { return my_size - 1; } size_t mask() { return my_size - 1; }
static size_t hash(TagType t) { static size_t hash(TagType t) {
return uintptr_t(t)*tbb::internal::select_size_t_constant<0x9E3779B 9,0x9E3779B97F4A7C15ULL>::value; return uintptr_t(t)*tbb::internal::select_size_t_constant<0x9E3779B 9,0x9E3779B97F4A7C15ULL>::value;
} }
void set_up_free_list( element_type **p_free_list, list_array_type *la, size_t sz) { void set_up_free_list( element_type **p_free_list, list_array_type la, size_t sz) {
for(size_t i=0; i < sz - 1; ++i ) { // construct free list for(size_t i=0; i < sz - 1; ++i ) { // construct free list
(*la)[i].next = &((*la)[i+1]); la[i].second.next = &(la[i+1]);
(*la)[i].t = NO_TAG; la[i].second.t = NO_TAG;
} }
(*la)[sz-1].next = NULL; la[sz-1].second.next = NULL;
*p_free_list = &((*la)[0]); *p_free_list = &(la[0]);
} }
void grow_array() { // cleanup for exceptions
// make the pointer array larger struct DoCleanup {
element_type **new_array; pointer_array_type *my_pa;
element_type **old_array = array; list_array_type *my_elements;
size_t old_size = my_size; size_t my_size;
my_size *=2;
new_array = pointer_array_allocator_type().allocate(my_size); DoCleanup(pointer_array_type &pa, list_array_type &my_els, size_t s
for(size_t i=0; i < my_size; ++i) new_array[i] = NULL; z) :
list_array_type *new_list_array = new list_array_type(old_size, ele my_pa(&pa), my_elements(&my_els), my_size(sz) { }
ment_type(), Allocator()); ~DoCleanup() {
set_up_free_list(&free_list, new_list_array, old_size ); if(my_pa) {
size_t dont_care = 0;
for(size_t i=0; i < old_size; ++i) { internal_free_buffer(*my_pa, *my_elements, my_size, dont_ca
for( element_type* op = old_array[i]; op; op = op->next) { re);
internal_tagged_insert(new_array, my_size, op->t, op->v);
} }
} }
pointer_array_allocator_type().deallocate(old_array, old_size); };
delete lists; // destroy and deallocate instead // exception-safety requires we do all the potentially-throwing operati
array = new_array; ons first
lists = new_list_array; void grow_array() {
} size_t new_size = my_size*2;
size_t new_nelements = nelements; // internal_free_buffer zeroes t
his
list_array_type new_elements_array = NULL;
pointer_array_type new_pointer_array = NULL;
list_array_type new_free_list = NULL;
{
DoCleanup my_cleanup(new_pointer_array, new_elements_array, new
_size);
new_elements_array = elements_array_allocator().allocate(my_siz
e);
new_pointer_array = pointer_array_allocator_type().allocate(new
_size);
for(size_t i=0; i < new_size; ++i) new_pointer_array[i] = NULL;
set_up_free_list(&new_free_list, new_elements_array, my_size );
for(size_t i=0; i < my_size; ++i) {
for( element_type* op = pointer_array[i]; op; op = (element
_type *)(op->second.next)) {
value_type *ov = reinterpret_cast<value_type *>(&(op->f
irst));
// could have std::move semantics
internal_tagged_insert(new_pointer_array, new_size, new
_free_list, op->second.t, *ov);
}
}
my_cleanup.my_pa = NULL;
my_cleanup.my_elements = NULL;
}
void internal_tagged_insert( element_type **ar, size_t sz, TagType t, v internal_free_buffer(pointer_array, elements_array, my_size, neleme
alue_type v) { nts);
size_t l_mask = sz-1; free_list = new_free_list;
pointer_array = new_pointer_array;
elements_array = new_elements_array;
my_size = new_size;
nelements = new_nelements;
}
// v should have perfect forwarding if std::move implemented.
// we use this method to move elements in grow_array, so can't use clas
s fields
void internal_tagged_insert( element_type **p_pointer_array, size_t p_s
z, list_array_type &p_free_list,
const TagType t, const value_type &v) {
size_t l_mask = p_sz-1;
size_t h = hash(t) & l_mask; size_t h = hash(t) & l_mask;
__TBB_ASSERT(free_list, "Error: free list not set up."); __TBB_ASSERT(p_free_list, "Error: free list not set up.");
element_type* my_elem = free_list; free_list = free_list->next; element_type* my_elem = p_free_list; p_free_list = (element_type *)
my_elem->t = t; (p_free_list->second.next);
my_elem->v = v; my_elem->second.t = t;
my_elem->next = ar[h]; (void) new(&(my_elem->first)) value_type(v);
ar[h] = my_elem; my_elem->second.next = p_pointer_array[h];
p_pointer_array[h] = my_elem;
} }
void internal_initialize_buffer() { void internal_initialize_buffer() {
array = pointer_array_allocator_type().allocate(my_size); pointer_array = pointer_array_allocator_type().allocate(my_size);
for(size_t i = 0; i < my_size; ++i) array[i] = NULL; for(size_t i = 0; i < my_size; ++i) pointer_array[i] = NULL;
lists = new list_array_type(INITIAL_SIZE/2, element_type(), Allocat elements_array = elements_array_allocator().allocate(my_size / 2);
or()); set_up_free_list(&free_list, elements_array, my_size / 2);
set_up_free_list(&free_list, lists, INITIAL_SIZE/2); }
}
// made static so an enclosed class can use to properly dispose of the
void internal_free_buffer() { internals
if(array) { static void internal_free_buffer( pointer_array_type &pa, list_array_ty
pointer_array_allocator_type().deallocate(array, my_size); pe &el, size_t &sz, size_t &ne ) {
array = NULL; if(pa) {
} for(size_t i = 0; i < sz; ++i ) {
if(lists) { element_type *p_next;
delete lists; for( element_type *p = pa[i]; p; p = p_next) {
lists = NULL; p_next = (element_type *)p->second.next;
value_type *vp = reinterpret_cast<value_type *>(&(p->fi
rst));
vp->~value_type();
}
}
pointer_array_allocator_type().deallocate(pa, sz);
pa = NULL;
}
// Separate test (if allocation of pa throws, el may be allocated.
// but no elements will be constructed.)
if(el) {
elements_array_allocator().deallocate(el, sz / 2);
el = NULL;
} }
my_size = INITIAL_SIZE; sz = INITIAL_SIZE;
nelements = 0; ne = 0;
} }
public: public:
tagged_buffer() : my_size(INITIAL_SIZE), nelements(0) { tagged_buffer() : my_size(INITIAL_SIZE), nelements(0) {
internal_initialize_buffer(); internal_initialize_buffer();
} }
~tagged_buffer() { ~tagged_buffer() {
internal_free_buffer(); internal_free_buffer(pointer_array, elements_array, my_size, neleme nts);
} }
void reset() { void reset() {
internal_free_buffer(); internal_free_buffer(pointer_array, elements_array, my_size, neleme nts);
internal_initialize_buffer(); internal_initialize_buffer();
} }
bool tagged_insert(TagType t, value_type v) { bool tagged_insert(const TagType t, const value_type &v) {
pointer_type p; pointer_type p;
if(tagged_find_ref(t, p)) { if(tagged_find_ref(t, p)) {
*p = v; // replace the value p->~value_type();
(void) new(p) value_type(v); // copy-construct into the space
return false; return false;
} }
++nelements; ++nelements;
if(nelements*2 > my_size) grow_array(); if(nelements*2 > my_size) grow_array();
internal_tagged_insert(array, my_size, t, v); internal_tagged_insert(pointer_array, my_size, free_list, t, v);
return true; return true;
} }
// returns reference to array element.v // returns reference to array element.v
bool tagged_find_ref(TagType t, pointer_type &v) { bool tagged_find_ref(const TagType t, pointer_type &v) {
size_t i = hash(t) & mask(); size_t i = hash(t) & mask();
for(element_type* p = array[i]; p; p = p->next) { for(element_type* p = pointer_array[i]; p; p = (element_type *)(p->
if(p->t == t) { second.next)) {
v = &(p->v); if(p->second.t == t) {
v = reinterpret_cast<pointer_type>(&(p->first));
return true; return true;
} }
} }
return false; return false;
} }
bool tagged_find( TagType t, value_type &v) { bool tagged_find( const TagType t, value_type &v) {
value_type *p; value_type *p;
if(tagged_find_ref(t, p)) { if(tagged_find_ref(t, p)) {
v = *p; v = *p;
return true; return true;
} }
else else
return false; return false;
} }
void tagged_delete(TagType t) { void tagged_delete(const TagType t) {
size_t h = hash(t) & mask(); size_t h = hash(t) & mask();
element_type* prev = NULL; element_type* prev = NULL;
for(element_type* p = array[h]; p; prev = p, p = p->next) { for(element_type* p = pointer_array[h]; p; prev = p, p = (element_t
if(p->t == t) { ype *)(p->second.next)) {
p->t = NO_TAG; if(p->second.t == t) {
if(prev) prev->next = p->next; value_type *vp = reinterpret_cast<value_type *>(&(p->first)
else array[h] = p->next; );
p->next = free_list; vp->~value_type();
p->second.t = NO_TAG;
if(prev) prev->second.next = p->second.next;
else pointer_array[h] = (element_type *)(p->second.next);
p->second.next = free_list;
free_list = p; free_list = p;
--nelements; --nelements;
return; return;
} }
} }
__TBB_ASSERT(false, "tag not found for delete"); __TBB_ASSERT(false, "tag not found for delete");
} }
// search for v in the array; if found {set t, return true} else return
false
// we use this in join_node_FE to find if a tag's items are all availab
le.
bool find_value_tag( TagType &t, value_type v) {
for(size_t i= 0; i < my_size / 2; ++i) { // remember the vector is
half the size of the hash array
if( (*lists)[i].t != NO_TAG && (*lists)[i].v == v) {
t = (*lists)[i].t;
return true;
}
}
return false;
}
}; };
#endif // __TBB__flow_graph_tagged_buffer_impl_H #endif // __TBB__flow_graph_tagged_buffer_impl_H
 End of changes. 30 change blocks. 
127 lines changed or deleted 183 lines changed or added


 _flow_graph_trace_impl.h   _flow_graph_trace_impl.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef _FGT_GRAPH_TRACE_IMPL_H #ifndef _FGT_GRAPH_TRACE_IMPL_H
#define _FGT_GRAPH_TRACE_IMPL_H #define _FGT_GRAPH_TRACE_IMPL_H
#include "../tbb_profiling.h" #include "../tbb_profiling.h"
namespace tbb { namespace tbb {
namespace internal { namespace internal {
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 _flow_graph_types_impl.h   _flow_graph_types_impl.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB__flow_graph_types_impl_H #ifndef __TBB__flow_graph_types_impl_H
#define __TBB__flow_graph_types_impl_H #define __TBB__flow_graph_types_impl_H
#ifndef __TBB_flow_graph_H #ifndef __TBB_flow_graph_H
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
// included in namespace tbb::flow::interface7
namespace internal { namespace internal {
// wrap each element of a tuple in a template, and make a tuple of the resu lt. // wrap each element of a tuple in a template, and make a tuple of the resu lt.
template<int N, template<class> class PT, typename TypeTuple> template<int N, template<class> class PT, typename TypeTuple>
struct wrap_tuple_elements; struct wrap_tuple_elements;
template<template<class> class PT, typename TypeTuple> template<template<class> class PT, typename TypeTuple>
struct wrap_tuple_elements<1, PT, TypeTuple> { struct wrap_tuple_elements<1, PT, TypeTuple> {
typedef typename tbb::flow::tuple< typedef typename tbb::flow::tuple<
PT<typename tbb::flow::tuple_element<0,TypeTuple>::type> > PT<typename tbb::flow::tuple_element<0,TypeTuple>::type> >
skipping to change at line 167 skipping to change at line 161
PT<typename tbb::flow::tuple_element<4,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<4,TypeTuple>::type>,
PT<typename tbb::flow::tuple_element<5,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<5,TypeTuple>::type>,
PT<typename tbb::flow::tuple_element<6,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<6,TypeTuple>::type>,
PT<typename tbb::flow::tuple_element<7,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<7,TypeTuple>::type>,
PT<typename tbb::flow::tuple_element<8,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<8,TypeTuple>::type>,
PT<typename tbb::flow::tuple_element<9,TypeTuple>::type> > PT<typename tbb::flow::tuple_element<9,TypeTuple>::type> >
type; type;
}; };
#endif #endif
#if TBB_PREVIEW_GRAPH_NODES //! type mimicking std::pair but with trailing fill to ensure each element
of an array
//* will have the correct alignment
template<typename T1, typename T2, size_t REM>
struct type_plus_align {
char first[sizeof(T1)];
T2 second;
char fill1[REM];
};
template<typename T1, typename T2>
struct type_plus_align<T1,T2,0> {
char first[sizeof(T1)];
T2 second;
};
template<class U> struct alignment_of {
typedef struct { char t; U padded; } test_alignment;
static const size_t value = sizeof(test_alignment) - sizeof(U);
};
// T1, T2 are actual types stored. The space defined for T1 in the typ
e returned
// is a char array of the correct size. Type T2 should be trivially-co
nstructible,
// T1 must be explicitly managed.
template<typename T1, typename T2>
struct aligned_pair {
static const size_t t1_align = alignment_of<T1>::value;
static const size_t t2_align = alignment_of<T2>::value;
typedef type_plus_align<T1, T2, 0 > just_pair;
static const size_t max_align = t1_align < t2_align ? t2_align : t1
_align;
static const size_t extra_bytes = sizeof(just_pair) % max_align;
static const size_t remainder = extra_bytes ? max_align - extra_byt
es : 0;
public:
typedef type_plus_align<T1,T2,remainder> type;
}; // aligned_pair
// support for variant type // support for variant type
// type we use when we're not storing a value // type we use when we're not storing a value
struct default_constructed { }; struct default_constructed { };
// type which contains another type, tests for what type is contained, and references to it. // type which contains another type, tests for what type is contained, and references to it.
// internal::Wrapper<T> // internal::Wrapper<T>
// void CopyTo( void *newSpace) : builds a Wrapper<T> copy of itself in newSpace // void CopyTo( void *newSpace) : builds a Wrapper<T> copy of itself in newSpace
// struct to allow us to copy and test the type of objects // struct to allow us to copy and test the type of objects
struct WrapperBase { struct WrapperBase {
skipping to change at line 301 skipping to change at line 329
template<bool, class T1, class T2> struct pick_one; template<bool, class T1, class T2> struct pick_one;
template<class T1, class T2> struct pick_one<true , T1, T2> { typedef T1 ty pe; }; template<class T1, class T2> struct pick_one<true , T1, T2> { typedef T1 ty pe; };
template<class T1, class T2> struct pick_one<false, T1, T2> { typedef T2 ty pe; }; template<class T1, class T2> struct pick_one<false, T1, T2> { typedef T2 ty pe; };
template< template<class> class Selector, typename T1, typename T2 > template< template<class> class Selector, typename T1, typename T2 >
struct pick_max { struct pick_max {
typedef typename pick_one< (Selector<T1>::value > Selector<T2>::value), T1, T2 >::type type; typedef typename pick_one< (Selector<T1>::value > Selector<T2>::value), T1, T2 >::type type;
}; };
template<typename T> struct size_of { static const int value = sizeof(T); } ; template<typename T> struct size_of { static const int value = sizeof(T); } ;
template<class T> struct alignment_of {
typedef struct { char t; T padded; } test_alignment;
static const size_t value = sizeof(test_alignment) - sizeof(T);
};
template< size_t N, class Tuple, template<class> class Selector > struct pi ck_tuple_max { template< size_t N, class Tuple, template<class> class Selector > struct pi ck_tuple_max {
typedef typename pick_tuple_max<N-1, Tuple, Selector>::type LeftMaxType ; typedef typename pick_tuple_max<N-1, Tuple, Selector>::type LeftMaxType ;
typedef typename tbb::flow::tuple_element<N-1, Tuple>::type ThisType; typedef typename tbb::flow::tuple_element<N-1, Tuple>::type ThisType;
typedef typename pick_max<Selector, LeftMaxType, ThisType>::type type; typedef typename pick_max<Selector, LeftMaxType, ThisType>::type type;
}; };
template< class Tuple, template<class> class Selector > struct pick_tuple_m ax<0, Tuple, Selector> { template< class Tuple, template<class> class Selector > struct pick_tuple_m ax<0, Tuple, Selector> {
typedef typename tbb::flow::tuple_element<0, Tuple>::type type; typedef typename tbb::flow::tuple_element<0, Tuple>::type type;
}; };
skipping to change at line 470 skipping to change at line 494
bool is_default_constructed() const {return my_msg.variant_is_default_c onstructed();} bool is_default_constructed() const {return my_msg.variant_is_default_c onstructed();}
}; //class tagged_msg }; //class tagged_msg
// template to simplify cast and test for tagged_msg in template contexts // template to simplify cast and test for tagged_msg in template contexts
template<typename T, typename V> template<typename T, typename V>
const T& cast_to(V const &v) { return v.template cast_to<T>(); } const T& cast_to(V const &v) { return v.template cast_to<T>(); }
template<typename T, typename V> template<typename T, typename V>
bool is_a(V const &v) { return v.template is_a<T>(); } bool is_a(V const &v) { return v.template is_a<T>(); }
#endif // TBB_PREVIEW_GRAPH_NODES
} // namespace internal } // namespace internal
#endif /* __TBB__flow_graph_types_impl_H */ #endif /* __TBB__flow_graph_types_impl_H */
 End of changes. 5 change blocks. 
34 lines changed or deleted 71 lines changed or added


 _mutex_padding.h   _mutex_padding.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_mutex_padding_H #ifndef __TBB_mutex_padding_H
#define __TBB_mutex_padding_H #define __TBB_mutex_padding_H
// wrapper for padding mutexes to be alone on a cache line, without requiri ng they be allocated // wrapper for padding mutexes to be alone on a cache line, without requiri ng they be allocated
// from a pool. Because we allow them to be defined anywhere they must be two cache lines in size. // from a pool. Because we allow them to be defined anywhere they must be two cache lines in size.
namespace tbb { namespace tbb {
namespace interface7 { namespace interface7 {
namespace internal { namespace internal {
static const size_t cache_line_size = 64; static const size_t cache_line_size = 64;
// Pad a mutex to occupy a number of full cache lines sufficient to avoid f alse sharing // Pad a mutex to occupy a number of full cache lines sufficient to avoid f alse sharing
// with other data; space overhead is up to 2*cache_line_size-1. // with other data; space overhead is up to 2*cache_line_size-1.
template<typename Mutex, bool is_rw> class padded_mutex; template<typename Mutex, bool is_rw> class padded_mutex;
template<typename Mutex> template<typename Mutex>
class padded_mutex<Mutex,false> { class padded_mutex<Mutex,false> : tbb::internal::mutex_copy_deprecated_and_ disabled {
typedef long pad_type; typedef long pad_type;
pad_type my_pad[((sizeof(Mutex)+cache_line_size-1)/cache_line_size+1)*c ache_line_size/sizeof(pad_type)]; pad_type my_pad[((sizeof(Mutex)+cache_line_size-1)/cache_line_size+1)*c ache_line_size/sizeof(pad_type)];
Mutex *impl() { return (Mutex *)((uintptr_t(this)|(cache_line_size-1))+ 1);} Mutex *impl() { return (Mutex *)((uintptr_t(this)|(cache_line_size-1))+ 1);}
public: public:
static const bool is_rw_mutex = Mutex::is_rw_mutex; static const bool is_rw_mutex = Mutex::is_rw_mutex;
static const bool is_recursive_mutex = Mutex::is_recursive_mutex; static const bool is_recursive_mutex = Mutex::is_recursive_mutex;
static const bool is_fair_mutex = Mutex::is_fair_mutex; static const bool is_fair_mutex = Mutex::is_fair_mutex;
skipping to change at line 75 skipping to change at line 67
scoped_lock( padded_mutex& m ) : my_scoped_lock(*m.impl()) { } scoped_lock( padded_mutex& m ) : my_scoped_lock(*m.impl()) { }
~scoped_lock() { } ~scoped_lock() { }
void acquire( padded_mutex& m ) { my_scoped_lock.acquire(*m.impl()) ; } void acquire( padded_mutex& m ) { my_scoped_lock.acquire(*m.impl()) ; }
bool try_acquire( padded_mutex& m ) { return my_scoped_lock.try_acq uire(*m.impl()); } bool try_acquire( padded_mutex& m ) { return my_scoped_lock.try_acq uire(*m.impl()); }
void release() { my_scoped_lock.release(); } void release() { my_scoped_lock.release(); }
}; };
}; };
template<typename Mutex> template<typename Mutex>
class padded_mutex<Mutex,true> { class padded_mutex<Mutex,true> : tbb::internal::mutex_copy_deprecated_and_d isabled {
typedef long pad_type; typedef long pad_type;
pad_type my_pad[((sizeof(Mutex)+cache_line_size-1)/cache_line_size+1)*c ache_line_size/sizeof(pad_type)]; pad_type my_pad[((sizeof(Mutex)+cache_line_size-1)/cache_line_size+1)*c ache_line_size/sizeof(pad_type)];
Mutex *impl() { return (Mutex *)((uintptr_t(this)|(cache_line_size-1))+ 1);} Mutex *impl() { return (Mutex *)((uintptr_t(this)|(cache_line_size-1))+ 1);}
public: public:
static const bool is_rw_mutex = Mutex::is_rw_mutex; static const bool is_rw_mutex = Mutex::is_rw_mutex;
static const bool is_recursive_mutex = Mutex::is_recursive_mutex; static const bool is_recursive_mutex = Mutex::is_recursive_mutex;
static const bool is_fair_mutex = Mutex::is_fair_mutex; static const bool is_fair_mutex = Mutex::is_fair_mutex;
 End of changes. 3 change blocks. 
30 lines changed or deleted 31 lines changed or added


 _tbb_strings.h   _tbb_strings.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
TBB_STRING_RESOURCE(FLOW_BROADCAST_NODE, "broadcast_node") TBB_STRING_RESOURCE(FLOW_BROADCAST_NODE, "broadcast_node")
TBB_STRING_RESOURCE(FLOW_BUFFER_NODE, "buffer_node") TBB_STRING_RESOURCE(FLOW_BUFFER_NODE, "buffer_node")
TBB_STRING_RESOURCE(FLOW_CONTINUE_NODE, "continue_node") TBB_STRING_RESOURCE(FLOW_CONTINUE_NODE, "continue_node")
TBB_STRING_RESOURCE(FLOW_FUNCTION_NODE, "function_node") TBB_STRING_RESOURCE(FLOW_FUNCTION_NODE, "function_node")
TBB_STRING_RESOURCE(FLOW_JOIN_NODE_QUEUEING, "join_node (queueing)") TBB_STRING_RESOURCE(FLOW_JOIN_NODE_QUEUEING, "join_node (queueing)")
TBB_STRING_RESOURCE(FLOW_JOIN_NODE_RESERVING, "join_node (reserving)") TBB_STRING_RESOURCE(FLOW_JOIN_NODE_RESERVING, "join_node (reserving)")
TBB_STRING_RESOURCE(FLOW_JOIN_NODE_TAG_MATCHING, "join_node (tag_matching)" ) TBB_STRING_RESOURCE(FLOW_JOIN_NODE_TAG_MATCHING, "join_node (tag_matching)" )
TBB_STRING_RESOURCE(FLOW_LIMITER_NODE, "limiter_node") TBB_STRING_RESOURCE(FLOW_LIMITER_NODE, "limiter_node")
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 _tbb_windef.h   _tbb_windef.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_tbb_windef_H #ifndef __TBB_tbb_windef_H
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif /* __TBB_tbb_windef_H */ #endif /* __TBB_tbb_windef_H */
// Check that the target Windows version has all API calls requried for TBB . // Check that the target Windows version has all API calls requried for TBB .
// Do not increase the version in condition beyond 0x0500 without prior dis cussion! // Do not increase the version in condition beyond 0x0500 without prior dis cussion!
#if defined(_WIN32_WINNT) && _WIN32_WINNT<0x0501 #if defined(_WIN32_WINNT) && _WIN32_WINNT<0x0501
#error TBB is unable to run on old Windows versions; _WIN32_WINNT must be 0 x0501 or greater. #error TBB is unable to run on old Windows versions; _WIN32_WINNT must be 0 x0501 or greater.
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 _x86_eliding_mutex_impl.h   _x86_eliding_mutex_impl.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB__x86_eliding_mutex_impl_H #ifndef __TBB__x86_eliding_mutex_impl_H
#define __TBB__x86_eliding_mutex_impl_H #define __TBB__x86_eliding_mutex_impl_H
#ifndef __TBB_spin_mutex_H #ifndef __TBB_spin_mutex_H
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#if ( __TBB_x86_32 || __TBB_x86_64 ) #if ( __TBB_x86_32 || __TBB_x86_64 )
skipping to change at line 52 skipping to change at line 44
template<typename Mutex, bool is_rw> template<typename Mutex, bool is_rw>
class padded_mutex; class padded_mutex;
//! An eliding lock that occupies a single byte. //! An eliding lock that occupies a single byte.
/** A x86_eliding_mutex is an HLE-enabled spin mutex. It is recommended to /** A x86_eliding_mutex is an HLE-enabled spin mutex. It is recommended to
put the mutex on a cache line that is not shared by the data it protect s. put the mutex on a cache line that is not shared by the data it protect s.
It should be used for locking short critical sections where the lock is It should be used for locking short critical sections where the lock is
contended but the data it protects are not. If zero-initialized, the contended but the data it protects are not. If zero-initialized, the
mutex is considered unheld. mutex is considered unheld.
@ingroup synchronization */ @ingroup synchronization */
class x86_eliding_mutex { class x86_eliding_mutex : tbb::internal::mutex_copy_deprecated_and_disabled
{
//! 0 if lock is released, 1 if lock is acquired. //! 0 if lock is released, 1 if lock is acquired.
__TBB_atomic_flag flag; __TBB_atomic_flag flag;
friend class padded_mutex<x86_eliding_mutex, false>; friend class padded_mutex<x86_eliding_mutex, false>;
public: public:
//! Construct unacquired lock. //! Construct unacquired lock.
/** Equivalent to zero-initialization of *this. */ /** Equivalent to zero-initialization of *this. */
x86_eliding_mutex() : flag(0) {} x86_eliding_mutex() : flag(0) {}
 End of changes. 2 change blocks. 
30 lines changed or deleted 31 lines changed or added


 _x86_rtm_rw_mutex_impl.h   _x86_rtm_rw_mutex_impl.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB__x86_rtm_rw_mutex_impl_H #ifndef __TBB__x86_rtm_rw_mutex_impl_H
#define __TBB__x86_rtm_rw_mutex_impl_H #define __TBB__x86_rtm_rw_mutex_impl_H
#ifndef __TBB_spin_rw_mutex_H #ifndef __TBB_spin_rw_mutex_H
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#if TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX
#if __TBB_TSX_AVAILABLE #if __TBB_TSX_AVAILABLE
#include "../tbb_stddef.h" #include "../tbb_stddef.h"
#include "../tbb_machine.h" #include "../tbb_machine.h"
#include "../tbb_profiling.h" #include "../tbb_profiling.h"
#include "../spin_rw_mutex.h" #include "../spin_rw_mutex.h"
namespace tbb { namespace tbb {
namespace interface7 { namespace interface8 {
namespace internal { namespace internal {
enum RTM_type { enum RTM_type {
RTM_not_in_mutex, RTM_not_in_mutex,
RTM_transacting_reader, RTM_transacting_reader,
RTM_transacting_writer, RTM_transacting_writer,
RTM_real_reader, RTM_real_reader,
RTM_real_writer RTM_real_writer
}; };
static const unsigned long speculation_granularity = 64; static const unsigned long speculation_granularity = 64;
//! Fast, unfair, spinning speculation-enabled reader-writer lock with back off and //! Fast, unfair, spinning speculation-enabled reader-writer lock with back off and
// writer-preference // writer-preference
/** @ingroup synchronization */ /** @ingroup synchronization */
class x86_rtm_rw_mutex: private spin_rw_mutex { class x86_rtm_rw_mutex: private spin_rw_mutex {
public:
// bug in gcc 3.x.x causes syntax error in spite of the friend declaration
above.
// Make the scoped_lock public in that case.
#if __TBB_USE_X86_RTM_RW_MUTEX || __TBB_GCC_VERSION < 40000 #if __TBB_USE_X86_RTM_RW_MUTEX || __TBB_GCC_VERSION < 40000
// bug in gcc 3.x.x causes syntax error in spite of the friend declaration
below.
// Make the scoped_lock public in that case.
public:
#else #else
private: private:
#endif #endif
friend class padded_mutex<x86_rtm_rw_mutex,true>; friend class interface7::internal::padded_mutex<x86_rtm_rw_mutex,true>;
class scoped_lock; // should be private class scoped_lock; // should be private
friend class scoped_lock;
private: private:
//! @cond INTERNAL //! @cond INTERNAL
//! Internal construct unacquired mutex.
void __TBB_EXPORTED_METHOD internal_construct();
//! Internal acquire write lock. //! Internal acquire write lock.
// only_speculate == true if we're doing a try_lock, else false. // only_speculate == true if we're doing a try_lock, else false.
void __TBB_EXPORTED_METHOD internal_acquire_writer(x86_rtm_rw_mutex::sc oped_lock&, bool only_speculate=false); void __TBB_EXPORTED_METHOD internal_acquire_writer(x86_rtm_rw_mutex::sc oped_lock&, bool only_speculate=false);
//! Internal acquire read lock. //! Internal acquire read lock.
// only_speculate == true if we're doing a try_lock, else false. // only_speculate == true if we're doing a try_lock, else false.
void __TBB_EXPORTED_METHOD internal_acquire_reader(x86_rtm_rw_mutex::sc oped_lock&, bool only_speculate=false); void __TBB_EXPORTED_METHOD internal_acquire_reader(x86_rtm_rw_mutex::sc oped_lock&, bool only_speculate=false);
//! Internal upgrade reader to become a writer. //! Internal upgrade reader to become a writer.
bool __TBB_EXPORTED_METHOD internal_upgrade( x86_rtm_rw_mutex::scoped_l ock& ); bool __TBB_EXPORTED_METHOD internal_upgrade( x86_rtm_rw_mutex::scoped_l ock& );
//! Out of line code for downgrading a writer to a reader. //! Out of line code for downgrading a writer to a reader.
void __TBB_EXPORTED_METHOD internal_downgrade( x86_rtm_rw_mutex::scoped _lock& ); bool __TBB_EXPORTED_METHOD internal_downgrade( x86_rtm_rw_mutex::scoped _lock& );
//! Internal try_acquire write lock. //! Internal try_acquire write lock.
bool __TBB_EXPORTED_METHOD internal_try_acquire_writer( x86_rtm_rw_mute x::scoped_lock& ); bool __TBB_EXPORTED_METHOD internal_try_acquire_writer( x86_rtm_rw_mute x::scoped_lock& );
//! Internal release read lock. //! Internal release lock.
void internal_release_reader( x86_rtm_rw_mutex::scoped_lock& ); void __TBB_EXPORTED_METHOD internal_release( x86_rtm_rw_mutex::scoped_l
ock& );
//! Out of line code for releasing a write lock.
void internal_release_writer(x86_rtm_rw_mutex::scoped_lock& );
static x86_rtm_rw_mutex* internal_get_mutex( const spin_rw_mutex::scope
d_lock& lock )
{
return static_cast<x86_rtm_rw_mutex*>( lock.internal_get_mutex() );
}
static void internal_set_mutex( spin_rw_mutex::scoped_lock& lock, spin_
rw_mutex* mtx )
{
lock.internal_set_mutex( mtx );
}
//! @endcond //! @endcond
public: public:
//! Construct unacquired mutex. //! Construct unacquired mutex.
x86_rtm_rw_mutex() { x86_rtm_rw_mutex() {
w_flag = false; w_flag = false;
#if TBB_USE_THREADING_TOOLS #if TBB_USE_THREADING_TOOLS
internal_construct(); internal_construct();
#endif #endif
} }
skipping to change at line 132 skipping to change at line 132
private: private:
#endif #endif
//! The scoped locking pattern //! The scoped locking pattern
/** It helps to avoid the common problem of forgetting to release lock. /** It helps to avoid the common problem of forgetting to release lock.
It also nicely provides the "node" for queuing locks. */ It also nicely provides the "node" for queuing locks. */
// Speculation-enabled scoped lock for spin_rw_mutex // Speculation-enabled scoped lock for spin_rw_mutex
// The idea is to be able to reuse the acquire/release methods of spin_ rw_mutex // The idea is to be able to reuse the acquire/release methods of spin_ rw_mutex
// and its scoped lock wherever possible. The only way to use a specul ative lock is to use // and its scoped lock wherever possible. The only way to use a specul ative lock is to use
// a scoped_lock. (because transaction_state must be local) // a scoped_lock. (because transaction_state must be local)
class scoped_lock { class scoped_lock : tbb::internal::no_copy {
friend class x86_rtm_rw_mutex; friend class x86_rtm_rw_mutex;
spin_rw_mutex::scoped_lock my_scoped_lock; spin_rw_mutex::scoped_lock my_scoped_lock;
RTM_type transaction_state; RTM_type transaction_state;
public: public:
//! Construct lock that has not acquired a mutex. //! Construct lock that has not acquired a mutex.
/** Equivalent to zero-initialization of *this. */ /** Equivalent to zero-initialization of *this. */
scoped_lock() : my_scoped_lock(), transaction_state(RTM_not_in_mute x) { scoped_lock() : my_scoped_lock(), transaction_state(RTM_not_in_mute x) {
} }
skipping to change at line 161 skipping to change at line 161
~scoped_lock() { ~scoped_lock() {
if(transaction_state != RTM_not_in_mutex) release(); if(transaction_state != RTM_not_in_mutex) release();
} }
//! Acquire lock on given mutex. //! Acquire lock on given mutex.
void acquire( x86_rtm_rw_mutex& m, bool write = true ) { void acquire( x86_rtm_rw_mutex& m, bool write = true ) {
if( write ) m.internal_acquire_writer(*this); if( write ) m.internal_acquire_writer(*this);
else m.internal_acquire_reader(*this); else m.internal_acquire_reader(*this);
} }
void __TBB_EXPORTED_METHOD release(); //! Release lock
void release() {
x86_rtm_rw_mutex* mutex = x86_rtm_rw_mutex::internal_get_mutex(
my_scoped_lock);
__TBB_ASSERT( mutex, "lock is not acquired" );
__TBB_ASSERT( transaction_state!=RTM_not_in_mutex, "lock is not
acquired" );
return mutex->internal_release(*this);
}
//! Upgrade reader to become a writer. //! Upgrade reader to become a writer.
/** Returns whether the upgrade happened without releasing and re-a cquiring the lock */ /** Returns whether the upgrade happened without releasing and re-a cquiring the lock */
bool upgrade_to_writer() { bool upgrade_to_writer() {
x86_rtm_rw_mutex* mutex = static_cast<x86_rtm_rw_mutex*>(my_sco ped_lock.__internal_get_mutex()); x86_rtm_rw_mutex* mutex = x86_rtm_rw_mutex::internal_get_mutex( my_scoped_lock);
__TBB_ASSERT( mutex, "lock is not acquired" ); __TBB_ASSERT( mutex, "lock is not acquired" );
__TBB_ASSERT( transaction_state==RTM_transacting_reader || tran saction_state==RTM_real_reader, "Invalid state for upgrade" );
return mutex->internal_upgrade(*this); return mutex->internal_upgrade(*this);
} }
//! Downgrade writer to become a reader. //! Downgrade writer to become a reader.
/** Returns whether the downgrade happened without releasing and re -acquiring the lock */
bool downgrade_to_reader() { bool downgrade_to_reader() {
x86_rtm_rw_mutex* mutex = static_cast<x86_rtm_rw_mutex*>(my_sco ped_lock.__internal_get_mutex()); x86_rtm_rw_mutex* mutex = x86_rtm_rw_mutex::internal_get_mutex( my_scoped_lock);
__TBB_ASSERT( mutex, "lock is not acquired" ); __TBB_ASSERT( mutex, "lock is not acquired" );
mutex->internal_downgrade(*this); __TBB_ASSERT( transaction_state==RTM_transacting_writer || tran
return true; // real writer -> reader returns true, speculativ saction_state==RTM_real_writer, "Invalid state for downgrade" );
e only changes local state. return mutex->internal_downgrade(*this);
} }
//! Attempt to acquire mutex. //! Attempt to acquire mutex.
/** returns true if successful. */ /** returns true if successful. */
bool try_acquire( x86_rtm_rw_mutex& m, bool write = true ) { bool try_acquire( x86_rtm_rw_mutex& m, bool write = true ) {
#if TBB_USE_DEBUG #if TBB_USE_ASSERT
x86_rtm_rw_mutex* mutex = static_cast<x86_rtm_rw_mutex*>(my_sco x86_rtm_rw_mutex* mutex = x86_rtm_rw_mutex::internal_get_mutex(
ped_lock.__internal_get_mutex()); my_scoped_lock);
__TBB_ASSERT( !mutex, "holding mutex already" ); __TBB_ASSERT( !mutex, "lock is already acquired" );
#endif #endif
// have to assign m to our mutex. // have to assign m to our mutex.
// cannot set the mutex, because try_acquire in spin_rw_mutex d epends on it being NULL. // cannot set the mutex, because try_acquire in spin_rw_mutex d epends on it being NULL.
if(write) return m.internal_try_acquire_writer(*this); if(write) return m.internal_try_acquire_writer(*this);
// speculatively acquire the lock. If this fails, do try_acqui re on the spin_rw_mutex. // speculatively acquire the lock. If this fails, do try_acqui re on the spin_rw_mutex.
m.internal_acquire_reader(*this, /*only_speculate=*/true); m.internal_acquire_reader(*this, /*only_speculate=*/true);
if(transaction_state == RTM_transacting_reader) return true; if(transaction_state == RTM_transacting_reader) return true;
if( my_scoped_lock.try_acquire(m, false)) { if( my_scoped_lock.try_acquire(m, false)) {
transaction_state = RTM_real_reader; transaction_state = RTM_real_reader;
return true; return true;
skipping to change at line 210 skipping to change at line 218
// ISO C++0x compatibility methods not provided because we cannot maint ain // ISO C++0x compatibility methods not provided because we cannot maint ain
// state about whether a thread is in a transaction. // state about whether a thread is in a transaction.
private: private:
char pad[speculation_granularity-sizeof(spin_rw_mutex)]; // padding char pad[speculation_granularity-sizeof(spin_rw_mutex)]; // padding
// If true, writer holds the spin_rw_mutex. // If true, writer holds the spin_rw_mutex.
tbb::atomic<bool> w_flag; // want this on a separate cache line tbb::atomic<bool> w_flag; // want this on a separate cache line
void __TBB_EXPORTED_METHOD internal_construct();
}; // x86_rtm_rw_mutex }; // x86_rtm_rw_mutex
} // namespace internal } // namespace internal
} // namespace interface7 } // namespace interface8
} // namespace tbb } // namespace tbb
#endif /* ( __TBB_x86_32 || __TBB_x86_64 ) */ #endif /* __TBB_TSX_AVAILABLE */
#endif /* TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX */
#endif /* __TBB__x86_rtm_rw_mutex_impl_H */ #endif /* __TBB__x86_rtm_rw_mutex_impl_H */
 End of changes. 22 change blocks. 
56 lines changed or deleted 76 lines changed or added


 aggregator.h   aggregator.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB__aggregator_H #ifndef __TBB__aggregator_H
#define __TBB__aggregator_H #define __TBB__aggregator_H
#if !TBB_PREVIEW_AGGREGATOR #if !TBB_PREVIEW_AGGREGATOR
#error Set TBB_PREVIEW_AGGREGATOR before including aggregator.h #error Set TBB_PREVIEW_AGGREGATOR before including aggregator.h
#endif #endif
#include "atomic.h" #include "atomic.h"
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 aligned_space.h   aligned_space.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_aligned_space_H #ifndef __TBB_aligned_space_H
#define __TBB_aligned_space_H #define __TBB_aligned_space_H
#include "tbb_stddef.h" #include "tbb_stddef.h"
#include "tbb_machine.h" #include "tbb_machine.h"
namespace tbb { namespace tbb {
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 atomic.h   atomic.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_atomic_H #ifndef __TBB_atomic_H
#define __TBB_atomic_H #define __TBB_atomic_H
#include <cstddef> #include <cstddef>
#if _MSC_VER #if _MSC_VER
#define __TBB_LONG_LONG __int64 #define __TBB_LONG_LONG __int64
#else #else
skipping to change at line 529 skipping to change at line 521
} }
}; };
// Helpers to workaround ugly syntax of calling template member function of a // Helpers to workaround ugly syntax of calling template member function of a
// template class with template argument dependent on template parameters. // template class with template argument dependent on template parameters.
template <memory_semantics M, typename T> template <memory_semantics M, typename T>
T load ( const atomic<T>& a ) { return a.template load<M>(); } T load ( const atomic<T>& a ) { return a.template load<M>(); }
template <memory_semantics M, typename T> template <memory_semantics M, typename T>
void store ( atomic<T>& a, T value ) { return a.template store<M>(value); } void store ( atomic<T>& a, T value ) { a.template store<M>(value); }
namespace interface6{ namespace interface6{
//! Make an atomic for use in an initialization (list), as an alternative t o zero-initialization or normal assignment. //! Make an atomic for use in an initialization (list), as an alternative t o zero-initialization or normal assignment.
template<typename T> template<typename T>
atomic<T> make_atomic(T t) { atomic<T> make_atomic(T t) {
atomic<T> a; atomic<T> a;
store<relaxed>(a,t); store<relaxed>(a,t);
return a; return a;
} }
} }
 End of changes. 2 change blocks. 
29 lines changed or deleted 30 lines changed or added


 blocked_range.h   blocked_range.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_blocked_range_H #ifndef __TBB_blocked_range_H
#define __TBB_blocked_range_H #define __TBB_blocked_range_H
#include "tbb_stddef.h" #include "tbb_stddef.h"
namespace tbb { namespace tbb {
/** \page range_req Requirements on range concept /** \page range_req Requirements on range concept
skipping to change at line 108 skipping to change at line 100
Unspecified if end()<begin() or !is_divisible(). */ Unspecified if end()<begin() or !is_divisible(). */
blocked_range( blocked_range& r, split ) : blocked_range( blocked_range& r, split ) :
my_end(r.my_end), my_end(r.my_end),
my_begin(do_split(r, split())), my_begin(do_split(r, split())),
my_grainsize(r.my_grainsize) my_grainsize(r.my_grainsize)
{ {
// only comparison 'less than' is required from values of blocked_r ange objects // only comparison 'less than' is required from values of blocked_r ange objects
__TBB_ASSERT( !(my_begin < r.my_end) && !(r.my_end < my_begin), "bl ocked_range has been split incorrectly" ); __TBB_ASSERT( !(my_begin < r.my_end) && !(r.my_end < my_begin), "bl ocked_range has been split incorrectly" );
} }
#if !TBB_DEPRECATED #if __TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES
//! Static field to support proportional split //! Static field to support proportional split
static const bool is_divisible_in_proportion = true; static const bool is_divisible_in_proportion = true;
//! Split range. //! Split range.
/** The new Range *this has the second part split according to specifie d proportion, the old range r has the first part. /** The new Range *this has the second part split according to specifie d proportion, the old range r has the first part.
Unspecified if end()<begin() or !is_divisible(). */ Unspecified if end()<begin() or !is_divisible(). */
blocked_range( blocked_range& r, proportional_split& proportion ) : blocked_range( blocked_range& r, proportional_split& proportion ) :
my_end(r.my_end), my_end(r.my_end),
my_begin(do_split(r, proportion)), my_begin(do_split(r, proportion)),
my_grainsize(r.my_grainsize) my_grainsize(r.my_grainsize)
{ {
// only comparison 'less than' is required from values of blocked_r ange objects // only comparison 'less than' is required from values of blocked_r ange objects
__TBB_ASSERT( !(my_begin < r.my_end) && !(r.my_end < my_begin), "bl ocked_range has been split incorrectly" ); __TBB_ASSERT( !(my_begin < r.my_end) && !(r.my_end < my_begin), "bl ocked_range has been split incorrectly" );
} }
#endif #endif /* __TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES */
private: private:
/** NOTE: my_end MUST be declared before my_begin, otherwise the forkin g constructor will break. */ /** NOTE: my_end MUST be declared before my_begin, otherwise the forkin g constructor will break. */
Value my_end; Value my_end;
Value my_begin; Value my_begin;
size_type my_grainsize; size_type my_grainsize;
//! Auxiliary function used by forking constructor. //! Auxiliary function used by forking constructor.
/** Using this function lets us not require that Value support assignme nt or default construction. */ /** Using this function lets us not require that Value support assignme nt or default construction. */
static Value do_split( blocked_range& r, split ) static Value do_split( blocked_range& r, split )
{ {
__TBB_ASSERT( r.is_divisible(), "cannot split blocked_range that is not divisible" ); __TBB_ASSERT( r.is_divisible(), "cannot split blocked_range that is not divisible" );
Value middle = r.my_begin + (r.my_end - r.my_begin) / 2u; Value middle = r.my_begin + (r.my_end - r.my_begin) / 2u;
r.my_end = middle; r.my_end = middle;
return middle; return middle;
} }
#if !TBB_DEPRECATED #if __TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES
static Value do_split( blocked_range& r, proportional_split& proportion ) static Value do_split( blocked_range& r, proportional_split& proportion )
{ {
__TBB_ASSERT( r.is_divisible(), "cannot split blocked_range that is not divisible" ); __TBB_ASSERT( r.is_divisible(), "cannot split blocked_range that is not divisible" );
// usage of 32-bit floating point arithmetic is not enough to handl e ranges of // usage of 32-bit floating point arithmetic is not enough to handl e ranges of
// more than 2^24 iterations accurately. However, even on ranges wi th 2^64 // more than 2^24 iterations accurately. However, even on ranges wi th 2^64
// iterations the computational error approximately equals to 0.000 001% which // iterations the computational error approximately equals to 0.000 001% which
// makes small impact on uniform distribution of such range's itera tions (assuming // makes small impact on uniform distribution of such range's itera tions (assuming
// all iterations take equal time to complete). See 'test_partition er_whitebox' // all iterations take equal time to complete). See 'test_partition er_whitebox'
// for implementation of an exact split algorithm // for implementation of an exact split algorithm
size_type right_part = size_type(float(r.size()) * float(proportion .right()) size_type right_part = size_type(float(r.size()) * float(proportion .right())
/ float(proportion.left() + propor tion.right()) + 0.5f); / float(proportion.left() + propor tion.right()) + 0.5f);
return r.my_end = Value(r.my_end - right_part); return r.my_end = Value(r.my_end - right_part);
} }
#endif #endif /* __TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES */
template<typename RowValue, typename ColValue> template<typename RowValue, typename ColValue>
friend class blocked_range2d; friend class blocked_range2d;
template<typename RowValue, typename ColValue, typename PageValue> template<typename RowValue, typename ColValue, typename PageValue>
friend class blocked_range3d; friend class blocked_range3d;
}; };
} // namespace tbb } // namespace tbb
 End of changes. 5 change blocks. 
32 lines changed or deleted 33 lines changed or added


 blocked_range2d.h   blocked_range2d.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_blocked_range2d_H #ifndef __TBB_blocked_range2d_H
#define __TBB_blocked_range2d_H #define __TBB_blocked_range2d_H
#include "tbb_stddef.h" #include "tbb_stddef.h"
#include "blocked_range.h" #include "blocked_range.h"
namespace tbb { namespace tbb {
skipping to change at line 85 skipping to change at line 77
} }
blocked_range2d( blocked_range2d& r, split ) : blocked_range2d( blocked_range2d& r, split ) :
my_rows(r.my_rows), my_rows(r.my_rows),
my_cols(r.my_cols) my_cols(r.my_cols)
{ {
split split_obj; split split_obj;
do_split(r, split_obj); do_split(r, split_obj);
} }
#if !TBB_DEPRECATED #if __TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES
//! Static field to support proportional split //! Static field to support proportional split
static const bool is_divisible_in_proportion = true; static const bool is_divisible_in_proportion = true;
blocked_range2d( blocked_range2d& r, proportional_split& proportion ) : blocked_range2d( blocked_range2d& r, proportional_split& proportion ) :
my_rows(r.my_rows), my_rows(r.my_rows),
my_cols(r.my_cols) my_cols(r.my_cols)
{ {
do_split(r, proportion); do_split(r, proportion);
} }
#endif #endif /* __TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES */
template <typename Split> template <typename Split>
void do_split( blocked_range2d& r, Split& split_obj ) void do_split( blocked_range2d& r, Split& split_obj )
{ {
if( my_rows.size()*double(my_cols.grainsize()) < my_cols.size()*dou ble(my_rows.grainsize()) ) { if( my_rows.size()*double(my_cols.grainsize()) < my_cols.size()*dou ble(my_rows.grainsize()) ) {
my_cols.my_begin = col_range_type::do_split(r.my_cols, split_ob j); my_cols.my_begin = col_range_type::do_split(r.my_cols, split_ob j);
} else { } else {
my_rows.my_begin = row_range_type::do_split(r.my_rows, split_ob j); my_rows.my_begin = row_range_type::do_split(r.my_rows, split_ob j);
} }
} }
 End of changes. 3 change blocks. 
30 lines changed or deleted 31 lines changed or added


 blocked_range3d.h   blocked_range3d.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_blocked_range3d_H #ifndef __TBB_blocked_range3d_H
#define __TBB_blocked_range3d_H #define __TBB_blocked_range3d_H
#include "tbb_stddef.h" #include "tbb_stddef.h"
#include "blocked_range.h" #include "blocked_range.h"
namespace tbb { namespace tbb {
skipping to change at line 92 skipping to change at line 84
blocked_range3d( blocked_range3d& r, split ) : blocked_range3d( blocked_range3d& r, split ) :
my_pages(r.my_pages), my_pages(r.my_pages),
my_rows(r.my_rows), my_rows(r.my_rows),
my_cols(r.my_cols) my_cols(r.my_cols)
{ {
split split_obj; split split_obj;
do_split(r, split_obj); do_split(r, split_obj);
} }
#if !TBB_DEPRECATED #if __TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES
//! Static field to support proportional split //! Static field to support proportional split
static const bool is_divisible_in_proportion = true; static const bool is_divisible_in_proportion = true;
blocked_range3d( blocked_range3d& r, proportional_split& proportion ) : blocked_range3d( blocked_range3d& r, proportional_split& proportion ) :
my_pages(r.my_pages), my_pages(r.my_pages),
my_rows(r.my_rows), my_rows(r.my_rows),
my_cols(r.my_cols) my_cols(r.my_cols)
{ {
do_split(r, proportion); do_split(r, proportion);
} }
#endif #endif /* __TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES */
template <typename Split> template <typename Split>
void do_split( blocked_range3d& r, Split& split_obj) void do_split( blocked_range3d& r, Split& split_obj)
{ {
if ( my_pages.size()*double(my_rows.grainsize()) < my_rows.size()*d ouble(my_pages.grainsize()) ) { if ( my_pages.size()*double(my_rows.grainsize()) < my_rows.size()*d ouble(my_pages.grainsize()) ) {
if ( my_rows.size()*double(my_cols.grainsize()) < my_cols.size( )*double(my_rows.grainsize()) ) { if ( my_rows.size()*double(my_cols.grainsize()) < my_cols.size( )*double(my_rows.grainsize()) ) {
my_cols.my_begin = col_range_type::do_split(r.my_cols, spli t_obj); my_cols.my_begin = col_range_type::do_split(r.my_cols, spli t_obj);
} else { } else {
my_rows.my_begin = row_range_type::do_split(r.my_rows, spli t_obj); my_rows.my_begin = row_range_type::do_split(r.my_rows, spli t_obj);
} }
 End of changes. 3 change blocks. 
30 lines changed or deleted 31 lines changed or added


 cache_aligned_allocator.h   cache_aligned_allocator.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_cache_aligned_allocator_H #ifndef __TBB_cache_aligned_allocator_H
#define __TBB_cache_aligned_allocator_H #define __TBB_cache_aligned_allocator_H
#include <new> #include <new>
#include "tbb_stddef.h" #include "tbb_stddef.h"
#if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN #if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
#include <utility> // std::forward #include <utility> // std::forward
#endif #endif
namespace tbb { namespace tbb {
//! @cond INTERNAL //! @cond INTERNAL
namespace internal { namespace internal {
//! Cache/sector line size. //! Cache/sector line size.
/** @ingroup memory_allocation */ /** @ingroup memory_allocation */
size_t __TBB_EXPORTED_FUNC NFS_GetLineSize(); size_t __TBB_EXPORTED_FUNC NFS_GetLineSize();
skipping to change at line 108 skipping to change at line 100
//! Largest value for which method allocate might succeed. //! Largest value for which method allocate might succeed.
size_type max_size() const throw() { size_type max_size() const throw() {
return (~size_t(0)-internal::NFS_MaxLineSize)/sizeof(value_type); return (~size_t(0)-internal::NFS_MaxLineSize)/sizeof(value_type);
} }
//! Copy-construct value at location pointed to by p. //! Copy-construct value at location pointed to by p.
#if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC #if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
template<typename U, typename... Args> template<typename U, typename... Args>
void construct(U *p, Args&&... args) void construct(U *p, Args&&... args)
#if __TBB_CPP11_STD_FORWARD_BROKEN
{ ::new((void *)p) U((args)...); }
#else
{ ::new((void *)p) U(std::forward<Args>(args)...); } { ::new((void *)p) U(std::forward<Args>(args)...); }
#endif
#else // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC #else // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
#if __TBB_CPP11_RVALUE_REF_PRESENT
void construct( pointer p, value_type&& value ) {::new((void*)(p)) valu
e_type(std::move(value));}
#endif
void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);} void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);}
#endif // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC #endif // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
//! Destroy value at location pointed to by p. //! Destroy value at location pointed to by p.
void destroy( pointer p ) {p->~value_type();} void destroy( pointer p ) {p->~value_type();}
}; };
#if _MSC_VER && !defined(__INTEL_COMPILER) #if _MSC_VER && !defined(__INTEL_COMPILER)
#pragma warning (pop) #pragma warning (pop)
#endif // warning 4100 is back #endif // warning 4100 is back
 End of changes. 5 change blocks. 
33 lines changed or deleted 34 lines changed or added


 combinable.h   combinable.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_combinable_H #ifndef __TBB_combinable_H
#define __TBB_combinable_H #define __TBB_combinable_H
#include "enumerable_thread_specific.h" #include "enumerable_thread_specific.h"
#include "cache_aligned_allocator.h" #include "cache_aligned_allocator.h"
namespace tbb { namespace tbb {
/** \name combinable /** \name combinable
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 concurrent_hash_map.h   concurrent_hash_map.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_concurrent_hash_map_H #ifndef __TBB_concurrent_hash_map_H
#define __TBB_concurrent_hash_map_H #define __TBB_concurrent_hash_map_H
#include "tbb_stddef.h" #include "tbb_stddef.h"
#if !TBB_USE_EXCEPTIONS && _MSC_VER #if !TBB_USE_EXCEPTIONS && _MSC_VER
// Suppress "C++ exception handler used, but unwind semantics are not e nabled" warning in STL headers // Suppress "C++ exception handler used, but unwind semantics are not e nabled" warning in STL headers
#pragma warning (push) #pragma warning (push)
skipping to change at line 480 skipping to change at line 472
r.set_midpoint(); r.set_midpoint();
} }
//! type conversion //! type conversion
template<typename U> template<typename U>
hash_map_range( hash_map_range<U>& r) : hash_map_range( hash_map_range<U>& r) :
my_begin(r.my_begin), my_begin(r.my_begin),
my_end(r.my_end), my_end(r.my_end),
my_midpoint(r.my_midpoint), my_midpoint(r.my_midpoint),
my_grainsize(r.my_grainsize) my_grainsize(r.my_grainsize)
{} {}
#if TBB_DEPRECATED
//! Init range with iterators and grainsize specified
hash_map_range( const Iterator& begin_, const Iterator& end_, size_
type grainsize_ = 1 ) :
my_begin(begin_),
my_end(end_),
my_grainsize(grainsize_)
{
if(!my_end.my_index && !my_end.my_bucket) // end
my_end.my_index = my_end.my_map->my_mask + 1;
set_midpoint();
__TBB_ASSERT( grainsize_>0, "grainsize must be positive" );
}
#endif
//! Init range with container and grainsize specified //! Init range with container and grainsize specified
hash_map_range( const map_type &map, size_type grainsize_ = 1 ) : hash_map_range( const map_type &map, size_type grainsize_ = 1 ) :
my_begin( Iterator( map, 0, map.my_embedded_segment, map.my_emb edded_segment->node_list ) ), my_begin( Iterator( map, 0, map.my_embedded_segment, map.my_emb edded_segment->node_list ) ),
my_end( Iterator( map, map.my_mask + 1, 0, 0 ) ), my_end( Iterator( map, map.my_mask + 1, 0, 0 ) ),
my_grainsize( grainsize_ ) my_grainsize( grainsize_ )
{ {
__TBB_ASSERT( grainsize_>0, "grainsize must be positive" ); __TBB_ASSERT( grainsize_>0, "grainsize must be positive" );
set_midpoint(); set_midpoint();
} }
const Iterator& begin() const {return my_begin;} const Iterator& begin() const {return my_begin;}
skipping to change at line 530 skipping to change at line 509
"my_begin is after my_midpoint" ); "my_begin is after my_midpoint" );
__TBB_ASSERT( my_midpoint.my_index <= my_end.my_index, __TBB_ASSERT( my_midpoint.my_index <= my_end.my_index,
"my_midpoint is after my_end" ); "my_midpoint is after my_end" );
__TBB_ASSERT( my_begin != my_midpoint || my_begin == my_end, __TBB_ASSERT( my_begin != my_midpoint || my_begin == my_end,
"[my_begin, my_midpoint) range should not be empty" ); "[my_begin, my_midpoint) range should not be empty" );
} }
} // internal } // internal
//! @endcond //! @endcond
#if _MSC_VER && !defined(__INTEL_COMPILER)
// Suppress "conditional expression is constant" warning.
#pragma warning( push )
#pragma warning( disable: 4127 )
#endif
//! Unordered map from Key to T. //! Unordered map from Key to T.
/** concurrent_hash_map is associative container with concurrent access. /** concurrent_hash_map is associative container with concurrent access.
@par Compatibility @par Compatibility
The class meets all Container Requirements from C++ Standard (See ISO/I EC 14882:2003(E), clause 23.1). The class meets all Container Requirements from C++ Standard (See ISO/I EC 14882:2003(E), clause 23.1).
@par Exception Safety @par Exception Safety
- Hash function is not permitted to throw an exception. User-defined ty pes Key and T are forbidden from throwing an exception in destructors. - Hash function is not permitted to throw an exception. User-defined ty pes Key and T are forbidden from throwing an exception in destructors.
- If exception happens during insert() operations, it has no effect (un less exception raised by HashCompare::hash() function during grow_segment). - If exception happens during insert() operations, it has no effect (un less exception raised by HashCompare::hash() function during grow_segment).
- If exception happens during operator=() operation, the container can have a part of source items, and methods size() and empty() can return wron g results. - If exception happens during operator=() operation, the container can have a part of source items, and methods size() and empty() can return wron g results.
skipping to change at line 595 skipping to change at line 580
friend class const_accessor; friend class const_accessor;
struct node; struct node;
typedef typename Allocator::template rebind<node>::other node_allocator _type; typedef typename Allocator::template rebind<node>::other node_allocator _type;
node_allocator_type my_allocator; node_allocator_type my_allocator;
HashCompare my_hash_compare; HashCompare my_hash_compare;
struct node : public node_base { struct node : public node_base {
value_type item; value_type item;
node( const Key &key ) : item(key, T()) {} node( const Key &key ) : item(key, T()) {}
node( const Key &key, const T &t ) : item(key, t) {} node( const Key &key, const T &t ) : item(key, t) {}
#if __TBB_CPP11_RVALUE_REF_PRESENT
node( value_type&& i ) : item(std::move(i)){}
#endif //__TBB_CPP11_RVALUE_REF_PRESENT
node( const value_type& i ) : item(i) {}
// exception-safe allocation, see C++ Standard 2003, clause 5.3.4p1 7 // exception-safe allocation, see C++ Standard 2003, clause 5.3.4p1 7
void *operator new( size_t /*size*/, node_allocator_type &a ) { void *operator new( size_t /*size*/, node_allocator_type &a ) {
void *ptr = a.allocate(1); void *ptr = a.allocate(1);
if(!ptr) if(!ptr)
tbb::internal::throw_exception(tbb::internal::eid_bad_alloc ); tbb::internal::throw_exception(tbb::internal::eid_bad_alloc );
return ptr; return ptr;
} }
// match placement-new form above to be called if exception thrown in constructor // match placement-new form above to be called if exception thrown in constructor
void operator delete( void *ptr, node_allocator_type &a ) { a.deall ocate(static_cast<node*>(ptr),1); } void operator delete( void *ptr, node_allocator_type &a ) { a.deall ocate(static_cast<node*>(ptr),1); }
}; };
void delete_node( node_base *n ) { void delete_node( node_base *n ) {
my_allocator.destroy( static_cast<node*>(n) ); my_allocator.destroy( static_cast<node*>(n) );
my_allocator.deallocate( static_cast<node*>(n), 1); my_allocator.deallocate( static_cast<node*>(n), 1);
} }
static node* allocate_node_copy_construct(node_allocator_type& allocato
r, const Key &key, const T * t){
return new( allocator ) node(key, *t);
}
static node* allocate_node_default_construct(node_allocator_type& alloc
ator, const Key &key, const T * ){
return new( allocator ) node(key);
}
static node* do_not_allocate_node(node_allocator_type& , const Key &, c
onst T * ){
__TBB_ASSERT(false,"this dummy function should not be called");
return NULL;
}
node *search_bucket( const key_type &key, bucket *b ) const { node *search_bucket( const key_type &key, bucket *b ) const {
node *n = static_cast<node*>( b->node_list ); node *n = static_cast<node*>( b->node_list );
while( is_valid(n) && !my_hash_compare.equal(key, n->item.first) ) while( is_valid(n) && !my_hash_compare.equal(key, n->item.first) )
n = static_cast<node*>( n->next ); n = static_cast<node*>( n->next );
__TBB_ASSERT(n != internal::rehash_req, "Search can be executed onl y for rehashed bucket"); __TBB_ASSERT(n != internal::rehash_req, "Search can be executed onl y for rehashed bucket");
return n; return n;
} }
//! bucket accessor is to find, rehash, acquire a lock, and access a bu cket //! bucket accessor is to find, rehash, acquire a lock, and access a bu cket
class bucket_accessor : public bucket::scoped_t { class bucket_accessor : public bucket::scoped_t {
skipping to change at line 675 skipping to change at line 678
if( !b_old.is_writer() ) if( !b_old.is_writer() )
if( !b_old.upgrade_to_writer() ) { if( !b_old.upgrade_to_writer() ) {
goto restart; // node ptr can be invalid due to con current erase goto restart; // node ptr can be invalid due to con current erase
} }
*p = n->next; // exclude from b_old *p = n->next; // exclude from b_old
add_to_bucket( b_new, n ); add_to_bucket( b_new, n );
} else p = &n->next; // iterate to next item } else p = &n->next; // iterate to next item
} }
} }
struct call_clear_on_leave {
concurrent_hash_map* my_ch_map;
call_clear_on_leave( concurrent_hash_map* a_ch_map ) : my_ch_map(a_
ch_map) {}
void dismiss() {my_ch_map = 0;}
~call_clear_on_leave(){
if (my_ch_map){
my_ch_map->clear();
}
}
};
public: public:
class accessor; class accessor;
//! Combines data access, locking, and garbage collection. //! Combines data access, locking, and garbage collection.
class const_accessor : private node::scoped_t /*which derived from no_c opy*/ { class const_accessor : private node::scoped_t /*which derived from no_c opy*/ {
friend class concurrent_hash_map<Key,T,HashCompare,Allocator>; friend class concurrent_hash_map<Key,T,HashCompare,Allocator>;
friend class accessor; friend class accessor;
public: public:
//! Type of value //! Type of value
typedef const typename concurrent_hash_map::value_type value_type; typedef const typename concurrent_hash_map::value_type value_type;
//! True if result is empty. //! True if result is empty.
bool empty() const {return !my_node;} bool empty() const { return !my_node; }
//! Set to null //! Set to null
void release() { void release() {
if( my_node ) { if( my_node ) {
node::scoped_t::release(); node::scoped_t::release();
my_node = 0; my_node = 0;
} }
} }
//! Return reference to associated value in hash table. //! Return reference to associated value in hash table.
skipping to change at line 740 skipping to change at line 753
return this->my_node->item; return this->my_node->item;
} }
//! Return pointer to associated value in hash table. //! Return pointer to associated value in hash table.
pointer operator->() const { pointer operator->() const {
return &operator*(); return &operator*();
} }
}; };
//! Construct empty table. //! Construct empty table.
concurrent_hash_map(const allocator_type &a = allocator_type()) concurrent_hash_map( const allocator_type &a = allocator_type() )
: internal::hash_map_base(), my_allocator(a) : internal::hash_map_base(), my_allocator(a)
{} {}
//! Construct empty table with n preallocated buckets. This number serv es also as initial concurrency level. //! Construct empty table with n preallocated buckets. This number serv es also as initial concurrency level.
concurrent_hash_map(size_type n, const allocator_type &a = allocator_ty pe()) concurrent_hash_map( size_type n, const allocator_type &a = allocator_t ype() )
: my_allocator(a) : my_allocator(a)
{ {
reserve( n ); reserve( n );
} }
//! Copy constructor //! Copy constructor
concurrent_hash_map( const concurrent_hash_map& table, const allocator_ type &a = allocator_type()) concurrent_hash_map( const concurrent_hash_map &table, const allocator_ type &a = allocator_type() )
: internal::hash_map_base(), my_allocator(a) : internal::hash_map_base(), my_allocator(a)
{ {
internal_copy(table); internal_copy(table);
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT
//! Move constructor
concurrent_hash_map( concurrent_hash_map &&table )
: internal::hash_map_base(), my_allocator(std::move(table.get_alloc
ator()))
{
swap(table);
}
//! Move constructor
concurrent_hash_map( concurrent_hash_map &&table, const allocator_type
&a )
: internal::hash_map_base(), my_allocator(a)
{
if (a == table.get_allocator()){
this->swap(table);
}else{
call_clear_on_leave scope_guard(this);
internal_copy(std::make_move_iterator(table.begin()), std::make
_move_iterator(table.end()));
scope_guard.dismiss();
}
}
#endif //__TBB_CPP11_RVALUE_REF_PRESENT
//! Construction with copying iteration range and given allocator insta nce //! Construction with copying iteration range and given allocator insta nce
template<typename I> template<typename I>
concurrent_hash_map(I first, I last, const allocator_type &a = allocato r_type()) concurrent_hash_map( I first, I last, const allocator_type &a = allocat or_type() )
: my_allocator(a) : my_allocator(a)
{ {
reserve( std::distance(first, last) ); // TODO: load_factor? reserve( std::distance(first, last) ); // TODO: load_factor?
internal_copy(first, last); internal_copy(first, last);
} }
#if __TBB_INITIALIZER_LISTS_PRESENT #if __TBB_INITIALIZER_LISTS_PRESENT
//! Construct empty table with n preallocated buckets. This number serv es also as initial concurrency level. //! Construct empty table with n preallocated buckets. This number serv es also as initial concurrency level.
concurrent_hash_map(const std::initializer_list<value_type> &il, const allocator_type &a = allocator_type()) concurrent_hash_map( std::initializer_list<value_type> il, const alloca tor_type &a = allocator_type() )
: my_allocator(a) : my_allocator(a)
{ {
reserve(il.size()); reserve(il.size());
internal_copy(il.begin(), il.end()); internal_copy(il.begin(), il.end());
} }
#endif //__TBB_INITIALIZER_LISTS_PRESENT #endif //__TBB_INITIALIZER_LISTS_PRESENT
//! Assignment //! Assignment
concurrent_hash_map& operator=( const concurrent_hash_map& table ) { concurrent_hash_map& operator=( const concurrent_hash_map &table ) {
if( this!=&table ) { if( this!=&table ) {
clear(); clear();
internal_copy(table); internal_copy(table);
} }
return *this; return *this;
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT
//! Move Assignment
concurrent_hash_map& operator=( concurrent_hash_map &&table ) {
if(this != &table){
typedef typename tbb::internal::allocator_traits<allocator_type
>::propagate_on_container_move_assignment pocma_t;
if(pocma_t::value || this->my_allocator == table.my_allocator)
{
concurrent_hash_map trash (std::move(*this));
//TODO: swapping allocators here may be a problem, replace
with single direction moving iff pocma is set
this->swap(table);
} else {
//do per element move
concurrent_hash_map moved_copy(std::move(table), this->my_a
llocator);
this->swap(moved_copy);
}
}
return *this;
}
#endif //__TBB_CPP11_RVALUE_REF_PRESENT
#if __TBB_INITIALIZER_LISTS_PRESENT #if __TBB_INITIALIZER_LISTS_PRESENT
//! Assignment //! Assignment
concurrent_hash_map& operator=( const std::initializer_list<value_type> &il ) { concurrent_hash_map& operator=( std::initializer_list<value_type> il ) {
clear(); clear();
reserve(il.size()); reserve(il.size());
internal_copy(il.begin(), il.end()); internal_copy(il.begin(), il.end());
return *this; return *this;
} }
#endif //__TBB_INITIALIZER_LISTS_PRESENT #endif //__TBB_INITIALIZER_LISTS_PRESENT
//! Rehashes and optionally resizes the whole table. //! Rehashes and optionally resizes the whole table.
/** Useful to optimize performance before or after concurrent operation s. /** Useful to optimize performance before or after concurrent operation s.
Also enables using of find() and count() concurrent methods in seri al context. */ Also enables using of find() and count() concurrent methods in seri al context. */
skipping to change at line 821 skipping to change at line 875
range_type range( size_type grainsize=1 ) { range_type range( size_type grainsize=1 ) {
return range_type( *this, grainsize ); return range_type( *this, grainsize );
} }
const_range_type range( size_type grainsize=1 ) const { const_range_type range( size_type grainsize=1 ) const {
return const_range_type( *this, grainsize ); return const_range_type( *this, grainsize );
} }
//--------------------------------------------------------------------- --- //--------------------------------------------------------------------- ---
// STL support - not thread-safe methods // STL support - not thread-safe methods
//--------------------------------------------------------------------- --- //--------------------------------------------------------------------- ---
iterator begin() {return iterator(*this,0,my_embedded_segment,my_embedd iterator begin() { return iterator( *this, 0, my_embedded_segment, my_e
ed_segment->node_list);} mbedded_segment->node_list ); }
iterator end() {return iterator(*this,0,0,0);} iterator end() { return iterator( *this, 0, 0, 0 ); }
const_iterator begin() const {return const_iterator(*this,0,my_embedded const_iterator begin() const { return const_iterator( *this, 0, my_embe
_segment,my_embedded_segment->node_list);} dded_segment, my_embedded_segment->node_list ); }
const_iterator end() const {return const_iterator(*this,0,0,0);} const_iterator end() const { return const_iterator( *this, 0, 0, 0 ); }
std::pair<iterator, iterator> equal_range( const Key& key ) { return in std::pair<iterator, iterator> equal_range( const Key& key ) { return in
ternal_equal_range(key, end()); } ternal_equal_range( key, end() ); }
std::pair<const_iterator, const_iterator> equal_range( const Key& key ) std::pair<const_iterator, const_iterator> equal_range( const Key& key )
const { return internal_equal_range(key, end()); } const { return internal_equal_range( key, end() ); }
//! Number of items in table. //! Number of items in table.
size_type size() const { return my_size; } size_type size() const { return my_size; }
//! True if size()==0. //! True if size()==0.
bool empty() const { return my_size == 0; } bool empty() const { return my_size == 0; }
//! Upper bound on size. //! Upper bound on size.
size_type max_size() const {return (~size_type(0))/sizeof(node);} size_type max_size() const {return (~size_type(0))/sizeof(node);}
//! Returns the current number of buckets //! Returns the current number of buckets
size_type bucket_count() const { return my_mask+1; } size_type bucket_count() const { return my_mask+1; }
//! return allocator object //! return allocator object
allocator_type get_allocator() const { return this->my_allocator; } allocator_type get_allocator() const { return this->my_allocator; }
//! swap two instances. Iterators are invalidated //! swap two instances. Iterators are invalidated
void swap(concurrent_hash_map &table); void swap( concurrent_hash_map &table );
//--------------------------------------------------------------------- --- //--------------------------------------------------------------------- ---
// concurrent map operations // concurrent map operations
//--------------------------------------------------------------------- --- //--------------------------------------------------------------------- ---
//! Return count of items (0 or 1) //! Return count of items (0 or 1)
size_type count( const Key &key ) const { size_type count( const Key &key ) const {
return const_cast<concurrent_hash_map*>(this)->lookup(/*insert*/fal se, key, NULL, NULL, /*write=*/false ); return const_cast<concurrent_hash_map*>(this)->lookup(/*insert*/fal se, key, NULL, NULL, /*write=*/false, &do_not_allocate_node );
} }
//! Find item and acquire a read lock on the item. //! Find item and acquire a read lock on the item.
/** Return true if item is found, false otherwise. */ /** Return true if item is found, false otherwise. */
bool find( const_accessor &result, const Key &key ) const { bool find( const_accessor &result, const Key &key ) const {
result.release(); result.release();
return const_cast<concurrent_hash_map*>(this)->lookup(/*insert*/fal se, key, NULL, &result, /*write=*/false ); return const_cast<concurrent_hash_map*>(this)->lookup(/*insert*/fal se, key, NULL, &result, /*write=*/false, &do_not_allocate_node );
} }
//! Find item and acquire a write lock on the item. //! Find item and acquire a write lock on the item.
/** Return true if item is found, false otherwise. */ /** Return true if item is found, false otherwise. */
bool find( accessor &result, const Key &key ) { bool find( accessor &result, const Key &key ) {
result.release(); result.release();
return lookup(/*insert*/false, key, NULL, &result, /*write=*/true ) ; return lookup(/*insert*/false, key, NULL, &result, /*write=*/true, &do_not_allocate_node );
} }
//! Insert item (if not already present) and acquire a read lock on the item. //! Insert item (if not already present) and acquire a read lock on the item.
/** Returns true if item is new. */ /** Returns true if item is new. */
bool insert( const_accessor &result, const Key &key ) { bool insert( const_accessor &result, const Key &key ) {
result.release(); result.release();
return lookup(/*insert*/true, key, NULL, &result, /*write=*/false ) ; return lookup(/*insert*/true, key, NULL, &result, /*write=*/false, &allocate_node_default_construct );
} }
//! Insert item (if not already present) and acquire a write lock on th e item. //! Insert item (if not already present) and acquire a write lock on th e item.
/** Returns true if item is new. */ /** Returns true if item is new. */
bool insert( accessor &result, const Key &key ) { bool insert( accessor &result, const Key &key ) {
result.release(); result.release();
return lookup(/*insert*/true, key, NULL, &result, /*write=*/true ); return lookup(/*insert*/true, key, NULL, &result, /*write=*/true, & allocate_node_default_construct );
} }
//! Insert item by copying if there is no such key present already and acquire a read lock on the item. //! Insert item by copying if there is no such key present already and acquire a read lock on the item.
/** Returns true if item is new. */ /** Returns true if item is new. */
bool insert( const_accessor &result, const value_type &value ) { bool insert( const_accessor &result, const value_type &value ) {
result.release(); result.release();
return lookup(/*insert*/true, value.first, &value.second, &result, /*write=*/false ); return lookup(/*insert*/true, value.first, &value.second, &result, /*write=*/false, &allocate_node_copy_construct );
} }
//! Insert item by copying if there is no such key present already and acquire a write lock on the item. //! Insert item by copying if there is no such key present already and acquire a write lock on the item.
/** Returns true if item is new. */ /** Returns true if item is new. */
bool insert( accessor &result, const value_type &value ) { bool insert( accessor &result, const value_type &value ) {
result.release(); result.release();
return lookup(/*insert*/true, value.first, &value.second, &result, /*write=*/true ); return lookup(/*insert*/true, value.first, &value.second, &result, /*write=*/true, &allocate_node_copy_construct );
} }
//! Insert item by copying if there is no such key present already //! Insert item by copying if there is no such key present already
/** Returns true if item is inserted. */ /** Returns true if item is inserted. */
bool insert( const value_type &value ) { bool insert( const value_type &value ) {
return lookup(/*insert*/true, value.first, &value.second, NULL, /*w rite=*/false ); return lookup(/*insert*/true, value.first, &value.second, NULL, /*w rite=*/false, &allocate_node_copy_construct );
} }
//! Insert range [first, last) //! Insert range [first, last)
template<typename I> template<typename I>
void insert(I first, I last) { void insert( I first, I last ) {
for(; first != last; ++first) for ( ; first != last; ++first )
insert( *first ); insert( *first );
} }
#if __TBB_INITIALIZER_LISTS_PRESENT
//! Insert initializer list
void insert( std::initializer_list<value_type> il ) {
insert( il.begin(), il.end() );
}
#endif //__TBB_INITIALIZER_LISTS_PRESENT
//! Erase item. //! Erase item.
/** Return true if item was erased by particularly this call. */ /** Return true if item was erased by particularly this call. */
bool erase( const Key& key ); bool erase( const Key& key );
//! Erase item by const_accessor. //! Erase item by const_accessor.
/** Return true if item was erased by particularly this call. */ /** Return true if item was erased by particularly this call. */
bool erase( const_accessor& item_accessor ) { bool erase( const_accessor& item_accessor ) {
return exclude( item_accessor ); return exclude( item_accessor );
} }
//! Erase item by accessor. //! Erase item by accessor.
/** Return true if item was erased by particularly this call. */ /** Return true if item was erased by particularly this call. */
bool erase( accessor& item_accessor ) { bool erase( accessor& item_accessor ) {
return exclude( item_accessor ); return exclude( item_accessor );
} }
protected: protected:
//! Insert or find item and optionally acquire a lock on the item. //! Insert or find item and optionally acquire a lock on the item.
bool lookup( bool op_insert, const Key &key, const T *t, const_accessor *result, bool write ); bool lookup(bool op_insert, const Key &key, const T *t, const_accessor *result, bool write, node* (*allocate_node)(node_allocator_type& , const Key &, const T * ) ) ;
//! delete item by accessor //! delete item by accessor
bool exclude( const_accessor &item_accessor ); bool exclude( const_accessor &item_accessor );
//! Returns an iterator for an item defined by the key, or for the next item after it (if upper==true) //! Returns an iterator for an item defined by the key, or for the next item after it (if upper==true)
template<typename I> template<typename I>
std::pair<I, I> internal_equal_range( const Key& key, I end ) const; std::pair<I, I> internal_equal_range( const Key& key, I end ) const;
//! Copy "source" to *this, where *this must start out empty. //! Copy "source" to *this, where *this must start out empty.
void internal_copy( const concurrent_hash_map& source ); void internal_copy( const concurrent_hash_map& source );
template<typename I> template<typename I>
void internal_copy(I first, I last); void internal_copy( I first, I last );
//! Fast find when no concurrent erasure is used. For internal use insi de TBB only! //! Fast find when no concurrent erasure is used. For internal use insi de TBB only!
/** Return pointer to item with given key, or NULL if no such item exis ts. /** Return pointer to item with given key, or NULL if no such item exis ts.
Must not be called concurrently with erasure operations. */ Must not be called concurrently with erasure operations. */
const_pointer internal_fast_find( const Key& key ) const { const_pointer internal_fast_find( const Key& key ) const {
hashcode_t h = my_hash_compare.hash( key ); hashcode_t h = my_hash_compare.hash( key );
hashcode_t m = (hashcode_t) itt_load_word_with_acquire( my_mask ); hashcode_t m = (hashcode_t) itt_load_word_with_acquire( my_mask );
node *n; node *n;
restart: restart:
__TBB_ASSERT((m&(m+1))==0, "data structure is invalid"); __TBB_ASSERT((m&(m+1))==0, "data structure is invalid");
skipping to change at line 973 skipping to change at line 1034
} }
n = search_bucket( key, b ); n = search_bucket( key, b );
if( n ) if( n )
return &n->item; return &n->item;
else if( check_mask_race( h, m ) ) else if( check_mask_race( h, m ) )
goto restart; goto restart;
return 0; return 0;
} }
}; };
#if _MSC_VER && !defined(__INTEL_COMPILER)
// Suppress "conditional expression is constant" warning.
#pragma warning( push )
#pragma warning( disable: 4127 )
#endif
template<typename Key, typename T, typename HashCompare, typename A> template<typename Key, typename T, typename HashCompare, typename A>
bool concurrent_hash_map<Key,T,HashCompare,A>::lookup( bool op_insert, cons t Key &key, const T *t, const_accessor *result, bool write ) { bool concurrent_hash_map<Key,T,HashCompare,A>::lookup( bool op_insert, cons t Key &key, const T *t, const_accessor *result, bool write, node* (*allocat e_node)(node_allocator_type& , const Key&, const T*) ) {
__TBB_ASSERT( !result || !result->my_node, NULL ); __TBB_ASSERT( !result || !result->my_node, NULL );
bool return_value; bool return_value;
hashcode_t const h = my_hash_compare.hash( key ); hashcode_t const h = my_hash_compare.hash( key );
hashcode_t m = (hashcode_t) itt_load_word_with_acquire( my_mask ); hashcode_t m = (hashcode_t) itt_load_word_with_acquire( my_mask );
segment_index_t grow_segment = 0; segment_index_t grow_segment = 0;
node *n, *tmp_n = 0; node *n, *tmp_n = 0;
restart: restart:
{//lock scope {//lock scope
__TBB_ASSERT((m&(m+1))==0, "data structure is invalid"); __TBB_ASSERT((m&(m+1))==0, "data structure is invalid");
return_value = false; return_value = false;
// get bucket // get bucket
bucket_accessor b( this, h & m ); bucket_accessor b( this, h & m );
// find a node // find a node
n = search_bucket( key, b() ); n = search_bucket( key, b() );
if( op_insert ) { if( op_insert ) {
// [opt] insert a key // [opt] insert a key
if( !n ) { if( !n ) {
if( !tmp_n ) { if( !tmp_n ) {
if(t) tmp_n = new( my_allocator ) node(key, *t); tmp_n = allocate_node(my_allocator, key, t);
else tmp_n = new( my_allocator ) node(key);
} }
if( !b.is_writer() && !b.upgrade_to_writer() ) { // TODO: i mproved insertion if( !b.is_writer() && !b.upgrade_to_writer() ) { // TODO: i mproved insertion
// Rerun search_list, in case another thread inserted t he item during the upgrade. // Rerun search_list, in case another thread inserted t he item during the upgrade.
n = search_bucket( key, b() ); n = search_bucket( key, b() );
if( is_valid(n) ) { // unfortunately, it did if( is_valid(n) ) { // unfortunately, it did
b.downgrade_to_reader(); b.downgrade_to_reader();
goto exists; goto exists;
} }
} }
if( check_mask_race(h, m) ) if( check_mask_race(h, m) )
skipping to change at line 1147 skipping to change at line 1201
{ {
typename node::scoped_t item_locker( n->mutex, /*write=*/true ); typename node::scoped_t item_locker( n->mutex, /*write=*/true );
} }
// note: there should be no threads pretending to acquire this mutex ag ain, do not try to upgrade const_accessor! // note: there should be no threads pretending to acquire this mutex ag ain, do not try to upgrade const_accessor!
delete_node( n ); // Only one thread can delete it due to write lock on the bucket delete_node( n ); // Only one thread can delete it due to write lock on the bucket
return true; return true;
} }
template<typename Key, typename T, typename HashCompare, typename A> template<typename Key, typename T, typename HashCompare, typename A>
void concurrent_hash_map<Key,T,HashCompare,A>::swap(concurrent_hash_map<Key ,T,HashCompare,A> &table) { void concurrent_hash_map<Key,T,HashCompare,A>::swap(concurrent_hash_map<Key ,T,HashCompare,A> &table) {
//TODO: respect C++11 allocator_traits<A>::propogate_on_constainer_swap
using std::swap; using std::swap;
swap(this->my_allocator, table.my_allocator); swap(this->my_allocator, table.my_allocator);
swap(this->my_hash_compare, table.my_hash_compare); swap(this->my_hash_compare, table.my_hash_compare);
internal_swap(table); internal_swap(table);
} }
template<typename Key, typename T, typename HashCompare, typename A> template<typename Key, typename T, typename HashCompare, typename A>
void concurrent_hash_map<Key,T,HashCompare,A>::rehash(size_type sz) { void concurrent_hash_map<Key,T,HashCompare,A>::rehash(size_type sz) {
reserve( sz ); // TODO: add reduction of number of buckets as well reserve( sz ); // TODO: add reduction of number of buckets as well
hashcode_t mask = my_mask; hashcode_t mask = my_mask;
skipping to change at line 1320 skipping to change at line 1375
} }
if( rehash_required ) rehash(); if( rehash_required ) rehash();
} else internal_copy( source.begin(), source.end() ); } else internal_copy( source.begin(), source.end() );
} }
template<typename Key, typename T, typename HashCompare, typename A> template<typename Key, typename T, typename HashCompare, typename A>
template<typename I> template<typename I>
void concurrent_hash_map<Key,T,HashCompare,A>::internal_copy(I first, I las t) { void concurrent_hash_map<Key,T,HashCompare,A>::internal_copy(I first, I las t) {
hashcode_t m = my_mask; hashcode_t m = my_mask;
for(; first != last; ++first) { for(; first != last; ++first) {
hashcode_t h = my_hash_compare.hash( first->first ); hashcode_t h = my_hash_compare.hash( (*first).first );
bucket *b = get_bucket( h & m ); bucket *b = get_bucket( h & m );
__TBB_ASSERT( b->node_list != internal::rehash_req, "Invalid bucket in destination table"); __TBB_ASSERT( b->node_list != internal::rehash_req, "Invalid bucket in destination table");
node *n = new( my_allocator ) node(first->first, first->second); node *n = new( my_allocator ) node(*first);
add_to_bucket( b, n ); add_to_bucket( b, n );
++my_size; // TODO: replace by non-atomic op ++my_size; // TODO: replace by non-atomic op
} }
} }
} // namespace interface5 } // namespace interface5
using interface5::concurrent_hash_map; using interface5::concurrent_hash_map;
template<typename Key, typename T, typename HashCompare, typename A1, typen ame A2> template<typename Key, typename T, typename HashCompare, typename A1, typen ame A2>
 End of changes. 36 change blocks. 
84 lines changed or deleted 158 lines changed or added


 concurrent_lru_cache.h   concurrent_lru_cache.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_concurrent_lru_cache_H #ifndef __TBB_concurrent_lru_cache_H
#define __TBB_concurrent_lru_cache_H #define __TBB_concurrent_lru_cache_H
#if ! TBB_PREVIEW_CONCURRENT_LRU_CACHE #if ! TBB_PREVIEW_CONCURRENT_LRU_CACHE
#error Set TBB_PREVIEW_CONCURRENT_LRU_CACHE to include concurrent_lru_c ache.h #error Set TBB_PREVIEW_CONCURRENT_LRU_CACHE to include concurrent_lru_c ache.h
#endif #endif
#include <map> #include <map>
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 concurrent_priority_queue.h   concurrent_priority_queue.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_concurrent_priority_queue_H #ifndef __TBB_concurrent_priority_queue_H
#define __TBB_concurrent_priority_queue_H #define __TBB_concurrent_priority_queue_H
#include "atomic.h" #include "atomic.h"
#include "cache_aligned_allocator.h" #include "cache_aligned_allocator.h"
#include "tbb_exception.h" #include "tbb_exception.h"
#include "tbb_stddef.h" #include "tbb_stddef.h"
#include "tbb_profiling.h" #include "tbb_profiling.h"
skipping to change at line 99 skipping to change at line 91
concurrent_priority_queue(InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()) : concurrent_priority_queue(InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()) :
mark(0), data(begin, end, a) mark(0), data(begin, end, a)
{ {
my_aggregator.initialize_handler(my_functor_t(this)); my_aggregator.initialize_handler(my_functor_t(this));
heapify(); heapify();
my_size = data.size(); my_size = data.size();
} }
#if __TBB_INITIALIZER_LISTS_PRESENT #if __TBB_INITIALIZER_LISTS_PRESENT
//! Constructor from std::initializer_list //! Constructor from std::initializer_list
concurrent_priority_queue(std::initializer_list<T> const& init_list, co nst allocator_type &a = allocator_type()) : concurrent_priority_queue(std::initializer_list<T> init_list, const all ocator_type &a = allocator_type()) :
mark(0),data(init_list.begin(), init_list.end(), a) mark(0),data(init_list.begin(), init_list.end(), a)
{ {
my_aggregator.initialize_handler(my_functor_t(this)); my_aggregator.initialize_handler(my_functor_t(this));
heapify(); heapify();
my_size = data.size(); my_size = data.size();
} }
#endif //# __TBB_INITIALIZER_LISTS_PRESENT #endif //# __TBB_INITIALIZER_LISTS_PRESENT
//! Copy constructor //! Copy constructor
/** This operation is unsafe if there are pending concurrent operations on the src queue. */ /** This operation is unsafe if there are pending concurrent operations on the src queue. */
skipping to change at line 130 skipping to change at line 122
my_size(src.my_size), data(src.data.begin(), src.data.end(), a) my_size(src.my_size), data(src.data.begin(), src.data.end(), a)
{ {
my_aggregator.initialize_handler(my_functor_t(this)); my_aggregator.initialize_handler(my_functor_t(this));
heapify(); heapify();
} }
//! Assignment operator //! Assignment operator
/** This operation is unsafe if there are pending concurrent operations on the src queue. */ /** This operation is unsafe if there are pending concurrent operations on the src queue. */
concurrent_priority_queue& operator=(const concurrent_priority_queue& s rc) { concurrent_priority_queue& operator=(const concurrent_priority_queue& s rc) {
if (this != &src) { if (this != &src) {
std::vector<value_type, allocator_type>(src.data.begin(), src.d vector_t(src.data.begin(), src.data.end(), src.data.get_allocat
ata.end(), src.data.get_allocator()).swap(data); or()).swap(data);
mark = src.mark;
my_size = src.my_size;
}
return *this;
}
#if __TBB_CPP11_RVALUE_REF_PRESENT
//! Move constructor
/** This operation is unsafe if there are pending concurrent operations
on the src queue. */
concurrent_priority_queue(concurrent_priority_queue&& src) : mark(src.m
ark),
my_size(src.my_size), data(std::move(src.data))
{
my_aggregator.initialize_handler(my_functor_t(this));
}
//! Move constructor with specific allocator
/** This operation is unsafe if there are pending concurrent operations
on the src queue. */
concurrent_priority_queue(concurrent_priority_queue&& src, const alloca
tor_type& a) : mark(src.mark),
my_size(src.my_size),
#if __TBB_ALLOCATOR_TRAITS_PRESENT
data(std::move(src.data), a)
#else
// Some early version of C++11 STL vector does not have a constructor o
f vector(vector&& , allocator).
// It seems that the reason is absence of support of allocator_traits (
stateful allocators).
data(a)
#endif //__TBB_ALLOCATOR_TRAITS_PRESENT
{
my_aggregator.initialize_handler(my_functor_t(this));
#if !__TBB_ALLOCATOR_TRAITS_PRESENT
if (a != src.data.get_allocator()){
data.reserve(src.data.size());
data.assign(std::make_move_iterator(src.data.begin()), std::mak
e_move_iterator(src.data.end()));
}else{
data = std::move(src.data);
}
#endif //!__TBB_ALLOCATOR_TRAITS_PRESENT
}
//! Move assignment operator
/** This operation is unsafe if there are pending concurrent operations
on the src queue. */
concurrent_priority_queue& operator=( concurrent_priority_queue&& src)
{
if (this != &src) {
mark = src.mark; mark = src.mark;
my_size = src.my_size; my_size = src.my_size;
#if !__TBB_ALLOCATOR_TRAITS_PRESENT
if (data.get_allocator() != src.data.get_allocator()){
vector_t(std::make_move_iterator(src.data.begin()), std::ma
ke_move_iterator(src.data.end()), data.get_allocator()).swap(data);
}else
#endif //!__TBB_ALLOCATOR_TRAITS_PRESENT
{
data = std::move(src.data);
}
} }
return *this; return *this;
} }
#endif //__TBB_CPP11_RVALUE_REF_PRESENT
//! Assign the queue from [begin,end) range, not thread-safe //! Assign the queue from [begin,end) range, not thread-safe
template<typename InputIterator> template<typename InputIterator>
void assign(InputIterator begin, InputIterator end) { void assign(InputIterator begin, InputIterator end) {
std::vector<value_type, allocator_type>(begin, end, data.get_alloca tor()).swap(data); vector_t(begin, end, data.get_allocator()).swap(data);
mark = 0; mark = 0;
my_size = data.size(); my_size = data.size();
heapify(); heapify();
} }
#if __TBB_INITIALIZER_LISTS_PRESENT #if __TBB_INITIALIZER_LISTS_PRESENT
//! Assign the queue from std::initializer_list, not thread-safe //! Assign the queue from std::initializer_list, not thread-safe
void assign(std::initializer_list<T> const& il) { this->assign(il.begin (), il.end()); } void assign(std::initializer_list<T> il) { this->assign(il.begin(), il. end()); }
//! Assign from std::initializer_list, not thread-safe //! Assign from std::initializer_list, not thread-safe
concurrent_priority_queue& operator=(std::initializer_list<T> const& il ) { concurrent_priority_queue& operator=(std::initializer_list<T> il) {
this->assign(il.begin(), il.end()); this->assign(il.begin(), il.end());
return *this; return *this;
} }
#endif //# __TBB_INITIALIZER_LISTS_PRESENT #endif //# __TBB_INITIALIZER_LISTS_PRESENT
//! Returns true if empty, false otherwise //! Returns true if empty, false otherwise
/** Returned value may not reflect results of pending operations. /** Returned value may not reflect results of pending operations.
This operation reads shared data and will trigger a race condition. */ This operation reads shared data and will trigger a race condition. */
bool empty() const { return size()==0; } bool empty() const { return size()==0; }
//! Returns the current number of elements contained in the queue //! Returns the current number of elements contained in the queue
/** Returned value may not reflect results of pending operations. /** Returned value may not reflect results of pending operations.
This operation reads shared data and will trigger a race condition. */ This operation reads shared data and will trigger a race condition. */
size_type size() const { return __TBB_load_with_acquire(my_size); } size_type size() const { return __TBB_load_with_acquire(my_size); }
//! Pushes elem onto the queue, increasing capacity of queue if necessa ry //! Pushes elem onto the queue, increasing capacity of queue if necessa ry
/** This operation can be safely used concurrently with other push, try _pop or reserve operations. */ /** This operation can be safely used concurrently with other push, try _pop or emplace operations. */
void push(const_reference elem) { void push(const_reference elem) {
cpq_operation op_data(elem, PUSH_OP); cpq_operation op_data(elem, PUSH_OP);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
if (op_data.status == FAILED) // exception thrown if (op_data.status == FAILED) // exception thrown
throw_exception(eid_bad_alloc); throw_exception(eid_bad_alloc);
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT
//! Pushes elem onto the queue, increasing capacity of queue if necessa
ry
/** This operation can be safely used concurrently with other push, try
_pop or emplace operations. */
void push(value_type &&elem) {
cpq_operation op_data(elem, PUSH_RVALUE_OP);
my_aggregator.execute(&op_data);
if (op_data.status == FAILED) // exception thrown
throw_exception(eid_bad_alloc);
}
#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
//! Constructs a new element using args as the arguments for its constr
uction and pushes it onto the queue */
/** This operation can be safely used concurrently with other push, try
_pop or emplace operations. */
template<typename... Args>
void emplace(Args&&... args) {
push(value_type(std::forward<Args>(args)...));
}
#endif /* __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT */
#endif /* __TBB_CPP11_RVALUE_REF_PRESENT */
//! Gets a reference to and removes highest priority element //! Gets a reference to and removes highest priority element
/** If a highest priority element was found, sets elem and returns true , /** If a highest priority element was found, sets elem and returns true ,
otherwise returns false. otherwise returns false.
This operation can be safely used concurrently with other push, try _pop or reserve operations. */ This operation can be safely used concurrently with other push, try _pop or emplace operations. */
bool try_pop(reference elem) { bool try_pop(reference elem) {
cpq_operation op_data(POP_OP); cpq_operation op_data(POP_OP);
op_data.elem = &elem; op_data.elem = &elem;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.status==SUCCEEDED; return op_data.status==SUCCEEDED;
} }
//! Clear the queue; not thread-safe //! Clear the queue; not thread-safe
/** This operation is unsafe if there are pending concurrent operations on the queue. /** This operation is unsafe if there are pending concurrent operations on the queue.
Resets size, effectively emptying queue; does not free space. Resets size, effectively emptying queue; does not free space.
skipping to change at line 210 skipping to change at line 273
using std::swap; using std::swap;
data.swap(q.data); data.swap(q.data);
swap(mark, q.mark); swap(mark, q.mark);
swap(my_size, q.my_size); swap(my_size, q.my_size);
} }
//! Return allocator object //! Return allocator object
allocator_type get_allocator() const { return data.get_allocator(); } allocator_type get_allocator() const { return data.get_allocator(); }
private: private:
enum operation_type {INVALID_OP, PUSH_OP, POP_OP}; enum operation_type {INVALID_OP, PUSH_OP, POP_OP, PUSH_RVALUE_OP};
enum operation_status { WAIT=0, SUCCEEDED, FAILED }; enum operation_status { WAIT=0, SUCCEEDED, FAILED };
class cpq_operation : public aggregated_operation<cpq_operation> { class cpq_operation : public aggregated_operation<cpq_operation> {
public: public:
operation_type type; operation_type type;
union { union {
value_type *elem; value_type *elem;
size_type sz; size_type sz;
}; };
cpq_operation(const_reference e, operation_type t) : cpq_operation(const_reference e, operation_type t) :
skipping to change at line 235 skipping to change at line 298
class my_functor_t { class my_functor_t {
concurrent_priority_queue<T, Compare, A> *cpq; concurrent_priority_queue<T, Compare, A> *cpq;
public: public:
my_functor_t() {} my_functor_t() {}
my_functor_t(concurrent_priority_queue<T, Compare, A> *cpq_) : cpq( cpq_) {} my_functor_t(concurrent_priority_queue<T, Compare, A> *cpq_) : cpq( cpq_) {}
void operator()(cpq_operation* op_list) { void operator()(cpq_operation* op_list) {
cpq->handle_operations(op_list); cpq->handle_operations(op_list);
} }
}; };
aggregator< my_functor_t, cpq_operation> my_aggregator; typedef tbb::internal::aggregator< my_functor_t, cpq_operation > aggreg
ator_t;
aggregator_t my_aggregator;
//! Padding added to avoid false sharing //! Padding added to avoid false sharing
char padding1[NFS_MaxLineSize - sizeof(aggregator< my_functor_t, cpq_op eration >)]; char padding1[NFS_MaxLineSize - sizeof(aggregator_t)];
//! The point at which unsorted elements begin //! The point at which unsorted elements begin
size_type mark; size_type mark;
__TBB_atomic size_type my_size; __TBB_atomic size_type my_size;
Compare compare; Compare compare;
//! Padding added to avoid false sharing //! Padding added to avoid false sharing
char padding2[NFS_MaxLineSize - (2*sizeof(size_type)) - sizeof(Compare) ]; char padding2[NFS_MaxLineSize - (2*sizeof(size_type)) - sizeof(Compare) ];
//! Storage for the heap of elements in queue, plus unheapified element s //! Storage for the heap of elements in queue, plus unheapified element s
/** data has the following structure: /** data has the following structure:
binary unheapified binary unheapified
skipping to change at line 262 skipping to change at line 326
[_|...|_|_|...|_| |...| ] [_|...|_|_|...|_| |...| ]
0 ^ ^ ^ 0 ^ ^ ^
| | |__capacity | | |__capacity
| |__my_size | |__my_size
|__mark |__mark
Thus, data stores the binary heap starting at position 0 through Thus, data stores the binary heap starting at position 0 through
mark-1 (it may be empty). Then there are 0 or more elements mark-1 (it may be empty). Then there are 0 or more elements
that have not yet been inserted into the heap, in positions that have not yet been inserted into the heap, in positions
mark through my_size-1. */ mark through my_size-1. */
std::vector<value_type, allocator_type> data; typedef std::vector<value_type, allocator_type> vector_t;
vector_t data;
void handle_operations(cpq_operation *op_list) { void handle_operations(cpq_operation *op_list) {
cpq_operation *tmp, *pop_list=NULL; cpq_operation *tmp, *pop_list=NULL;
__TBB_ASSERT(mark == data.size(), NULL); __TBB_ASSERT(mark == data.size(), NULL);
// First pass processes all constant (amortized; reallocation may h appen) time pushes and pops. // First pass processes all constant (amortized; reallocation may h appen) time pushes and pops.
while (op_list) { while (op_list) {
// ITT note: &(op_list->status) tag is used to cover accesses t o op_list // ITT note: &(op_list->status) tag is used to cover accesses t o op_list
// node. This thread is going to handle the operation, and so w ill acquire it // node. This thread is going to handle the operation, and so w ill acquire it
// and perform the associated operation w/o triggering a race c ondition; the // and perform the associated operation w/o triggering a race c ondition; the
// thread that created the operation is waiting on the status f ield, so when // thread that created the operation is waiting on the status f ield, so when
// this thread is done with the operation, it will perform a // this thread is done with the operation, it will perform a
// store_with_release to give control back to the waiting threa d in // store_with_release to give control back to the waiting threa d in
// aggregator::insert_operation. // aggregator::insert_operation.
call_itt_notify(acquired, &(op_list->status)); call_itt_notify(acquired, &(op_list->status));
__TBB_ASSERT(op_list->type != INVALID_OP, NULL); __TBB_ASSERT(op_list->type != INVALID_OP, NULL);
tmp = op_list; tmp = op_list;
op_list = itt_hide_load_word(op_list->next); op_list = itt_hide_load_word(op_list->next);
if (tmp->type == PUSH_OP) { if (tmp->type == POP_OP) {
__TBB_TRY {
data.push_back(*(tmp->elem));
__TBB_store_with_release(my_size, my_size+1);
itt_store_word_with_release(tmp->status, uintptr_t(SUCC
EEDED));
} __TBB_CATCH(...) {
itt_store_word_with_release(tmp->status, uintptr_t(FAIL
ED));
}
}
else { // tmp->type == POP_OP
__TBB_ASSERT(tmp->type == POP_OP, NULL);
if (mark < data.size() && if (mark < data.size() &&
compare(data[0], data[data.size()-1])) { compare(data[0], data[data.size()-1])) {
// there are newly pushed elems and the last one // there are newly pushed elems and the last one
// is higher than top // is higher than top
*(tmp->elem) = data[data.size()-1]; // copy the data *(tmp->elem) = move(data[data.size()-1]);
__TBB_store_with_release(my_size, my_size-1); __TBB_store_with_release(my_size, my_size-1);
itt_store_word_with_release(tmp->status, uintptr_t(SUCC EEDED)); itt_store_word_with_release(tmp->status, uintptr_t(SUCC EEDED));
data.pop_back(); data.pop_back();
__TBB_ASSERT(mark<=data.size(), NULL); __TBB_ASSERT(mark<=data.size(), NULL);
} }
else { // no convenient item to pop; postpone else { // no convenient item to pop; postpone
itt_hide_store_word(tmp->next, pop_list); itt_hide_store_word(tmp->next, pop_list);
pop_list = tmp; pop_list = tmp;
} }
} else { // PUSH_OP or PUSH_RVALUE_OP
__TBB_ASSERT(tmp->type == PUSH_OP || tmp->type == PUSH_RVAL
UE_OP, "Unknown operation" );
__TBB_TRY{
if (tmp->type == PUSH_OP) {
data.push_back(*(tmp->elem));
} else {
data.push_back(move(*(tmp->elem)));
}
__TBB_store_with_release(my_size, my_size + 1);
itt_store_word_with_release(tmp->status, uintptr_t(SUCC
EEDED));
} __TBB_CATCH(...) {
itt_store_word_with_release(tmp->status, uintptr_t(FAIL
ED));
}
} }
} }
// second pass processes pop operations // second pass processes pop operations
while (pop_list) { while (pop_list) {
tmp = pop_list; tmp = pop_list;
pop_list = itt_hide_load_word(pop_list->next); pop_list = itt_hide_load_word(pop_list->next);
__TBB_ASSERT(tmp->type == POP_OP, NULL); __TBB_ASSERT(tmp->type == POP_OP, NULL);
if (data.empty()) { if (data.empty()) {
itt_store_word_with_release(tmp->status, uintptr_t(FAILED)) ; itt_store_word_with_release(tmp->status, uintptr_t(FAILED)) ;
} }
else { else {
__TBB_ASSERT(mark<=data.size(), NULL); __TBB_ASSERT(mark<=data.size(), NULL);
if (mark < data.size() && if (mark < data.size() &&
compare(data[0], data[data.size()-1])) { compare(data[0], data[data.size()-1])) {
// there are newly pushed elems and the last one is // there are newly pushed elems and the last one is
// higher than top // higher than top
*(tmp->elem) = data[data.size()-1]; // copy the data *(tmp->elem) = move(data[data.size()-1]);
__TBB_store_with_release(my_size, my_size-1); __TBB_store_with_release(my_size, my_size-1);
itt_store_word_with_release(tmp->status, uintptr_t(SUCC EEDED)); itt_store_word_with_release(tmp->status, uintptr_t(SUCC EEDED));
data.pop_back(); data.pop_back();
} }
else { // extract top and push last element down heap else { // extract top and push last element down heap
*(tmp->elem) = data[0]; // copy the data *(tmp->elem) = move(data[0]);
__TBB_store_with_release(my_size, my_size-1); __TBB_store_with_release(my_size, my_size-1);
itt_store_word_with_release(tmp->status, uintptr_t(SUCC EEDED)); itt_store_word_with_release(tmp->status, uintptr_t(SUCC EEDED));
reheap(); reheap();
} }
} }
} }
// heapify any leftover pushed elements before doing the next // heapify any leftover pushed elements before doing the next
// batch of operations // batch of operations
if (mark<data.size()) heapify(); if (mark<data.size()) heapify();
__TBB_ASSERT(mark == data.size(), NULL); __TBB_ASSERT(mark == data.size(), NULL);
} }
//! Merge unsorted elements into heap //! Merge unsorted elements into heap
void heapify() { void heapify() {
if (!mark && data.size()>0) mark = 1; if (!mark && data.size()>0) mark = 1;
for (; mark<data.size(); ++mark) { for (; mark<data.size(); ++mark) {
// for each unheapified element under size // for each unheapified element under size
size_type cur_pos = mark; size_type cur_pos = mark;
value_type to_place = data[mark]; value_type to_place = move(data[mark]);
do { // push to_place up the heap do { // push to_place up the heap
size_type parent = (cur_pos-1)>>1; size_type parent = (cur_pos-1)>>1;
if (!compare(data[parent], to_place)) break; if (!compare(data[parent], to_place)) break;
data[cur_pos] = data[parent]; data[cur_pos] = move(data[parent]);
cur_pos = parent; cur_pos = parent;
} while( cur_pos ); } while( cur_pos );
data[cur_pos] = to_place; data[cur_pos] = move(to_place);
} }
} }
//! Re-heapify after an extraction //! Re-heapify after an extraction
/** Re-heapify by pushing last element down the heap from the root. */ /** Re-heapify by pushing last element down the heap from the root. */
void reheap() { void reheap() {
size_type cur_pos=0, child=1; size_type cur_pos=0, child=1;
while (child < mark) { while (child < mark) {
size_type target = child; size_type target = child;
if (child+1 < mark && compare(data[child], data[child+1])) if (child+1 < mark && compare(data[child], data[child+1]))
++target; ++target;
// target now has the higher priority child // target now has the higher priority child
if (compare(data[target], data[data.size()-1])) break; if (compare(data[target], data[data.size()-1])) break;
data[cur_pos] = data[target]; data[cur_pos] = move(data[target]);
cur_pos = target; cur_pos = target;
child = (cur_pos<<1)+1; child = (cur_pos<<1)+1;
} }
data[cur_pos] = data[data.size()-1]; if (cur_pos != data.size()-1)
data[cur_pos] = move(data[data.size()-1]);
data.pop_back(); data.pop_back();
if (mark > data.size()) mark = data.size(); if (mark > data.size()) mark = data.size();
} }
}; };
} // namespace interface5 } // namespace interface5
using interface5::concurrent_priority_queue; using interface5::concurrent_priority_queue;
} // namespace tbb } // namespace tbb
 End of changes. 25 change blocks. 
61 lines changed or deleted 155 lines changed or added


 concurrent_queue.h   concurrent_queue.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_concurrent_queue_H #ifndef __TBB_concurrent_queue_H
#define __TBB_concurrent_queue_H #define __TBB_concurrent_queue_H
#include "internal/_concurrent_queue_impl.h" #include "internal/_concurrent_queue_impl.h"
namespace tbb { namespace tbb {
namespace strict_ppl { namespace strict_ppl {
skipping to change at line 63 skipping to change at line 55
if( !b ) if( !b )
internal::throw_exception(internal::eid_bad_alloc); internal::throw_exception(internal::eid_bad_alloc);
return b; return b;
} }
//! Deallocates block created by allocate_block. //! Deallocates block created by allocate_block.
/*override*/ virtual void deallocate_block( void *b, size_t n ) { /*override*/ virtual void deallocate_block( void *b, size_t n ) {
my_allocator.deallocate( reinterpret_cast<char*>(b), n ); my_allocator.deallocate( reinterpret_cast<char*>(b), n );
} }
static void copy_construct_item(T* location, const void* src){
new (location) T(*static_cast<const T*>(src));
}
#if __TBB_CPP11_RVALUE_REF_PRESENT
static void move_construct_item(T* location, const void* src) {
new (location) T( std::move(*static_cast<T*>(const_cast<void*>(src)
)) );
}
#endif /* __TBB_CPP11_RVALUE_REF_PRESENT */
public: public:
//! Element type in the queue. //! Element type in the queue.
typedef T value_type; typedef T value_type;
//! Reference type //! Reference type
typedef T& reference; typedef T& reference;
//! Const reference type //! Const reference type
typedef const T& const_reference; typedef const T& const_reference;
skipping to change at line 94 skipping to change at line 95
my_allocator( a ) my_allocator( a )
{ {
} }
//! [begin,end) constructor //! [begin,end) constructor
template<typename InputIterator> template<typename InputIterator>
concurrent_queue( InputIterator begin, InputIterator end, const allocat or_type& a = allocator_type()) : concurrent_queue( InputIterator begin, InputIterator end, const allocat or_type& a = allocator_type()) :
my_allocator( a ) my_allocator( a )
{ {
for( ; begin != end; ++begin ) for( ; begin != end; ++begin )
this->internal_push(&*begin); this->push(*begin);
} }
//! Copy constructor //! Copy constructor
concurrent_queue( const concurrent_queue& src, const allocator_type& a = allocator_type()) : concurrent_queue( const concurrent_queue& src, const allocator_type& a = allocator_type()) :
internal::concurrent_queue_base_v3<T>(), my_allocator( a ) internal::concurrent_queue_base_v3<T>(), my_allocator( a )
{ {
this->assign( src ); this->assign( src, copy_construct_item );
}
#if __TBB_CPP11_RVALUE_REF_PRESENT
//! Move constructors
concurrent_queue( concurrent_queue&& src ) :
internal::concurrent_queue_base_v3<T>(), my_allocator( std::move(sr
c.my_allocator) )
{
this->internal_swap( src );
}
concurrent_queue( concurrent_queue&& src, const allocator_type& a ) :
internal::concurrent_queue_base_v3<T>(), my_allocator( a )
{
// checking that memory allocated by one instance of allocator can
be deallocated
// with another
if( my_allocator == src.my_allocator) {
this->internal_swap( src );
} else {
// allocators are different => performing per-element move
this->assign( src, move_construct_item );
src.clear();
}
} }
#endif /* __TBB_CPP11_RVALUE_REF_PRESENT */
//! Destroy queue //! Destroy queue
~concurrent_queue(); ~concurrent_queue();
//! Enqueue an item at tail of queue. //! Enqueue an item at tail of queue.
void push( const T& source ) { void push( const T& source ) {
this->internal_push( &source ); this->internal_push( &source, copy_construct_item );
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT
void push( T&& source ) {
this->internal_push( &source, move_construct_item );
}
#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
template<typename... Arguments>
void emplace( Arguments&&... args ) {
push( T(std::forward<Arguments>( args )...) );
}
#endif //__TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
#endif /* __TBB_CPP11_RVALUE_REF_PRESENT */
//! Attempt to dequeue an item from head of queue. //! Attempt to dequeue an item from head of queue.
/** Does not wait for item to become available. /** Does not wait for item to become available.
Returns true if successful; false otherwise. */ Returns true if successful; false otherwise. */
bool try_pop( T& result ) { bool try_pop( T& result ) {
return this->internal_try_pop( &result ); return this->internal_try_pop( &result );
} }
//! Return the number of items in the queue; thread unsafe //! Return the number of items in the queue; thread unsafe
size_type unsafe_size() const {return this->internal_size();} size_type unsafe_size() const {return this->internal_size();}
skipping to change at line 166 skipping to change at line 203
} // namespace strict_ppl } // namespace strict_ppl
//! A high-performance thread-safe blocking concurrent bounded queue. //! A high-performance thread-safe blocking concurrent bounded queue.
/** This is the pre-PPL TBB concurrent queue which supports boundedness and blocking semantics. /** This is the pre-PPL TBB concurrent queue which supports boundedness and blocking semantics.
Note that method names agree with the PPL-style concurrent queue. Note that method names agree with the PPL-style concurrent queue.
Multiple threads may each push and pop concurrently. Multiple threads may each push and pop concurrently.
Assignment construction is not allowed. Assignment construction is not allowed.
@ingroup containers */ @ingroup containers */
template<typename T, class A = cache_aligned_allocator<T> > template<typename T, class A = cache_aligned_allocator<T> >
class concurrent_bounded_queue: public internal::concurrent_queue_base_v3 { class concurrent_bounded_queue: public internal::concurrent_queue_base_v8 {
template<typename Container, typename Value> friend class internal::con current_queue_iterator; template<typename Container, typename Value> friend class internal::con current_queue_iterator;
//! Allocator type //! Allocator type
typedef typename A::template rebind<char>::other page_allocator_type; typedef typename A::template rebind<char>::other page_allocator_type;
page_allocator_type my_allocator; page_allocator_type my_allocator;
typedef typename concurrent_queue_base_v3::padded_page<T> padded_page; typedef typename concurrent_queue_base_v3::padded_page<T> padded_page;
typedef typename concurrent_queue_base_v3::copy_specifics copy_specific s;
//! Class used to ensure exception-safety of method "pop" //! Class used to ensure exception-safety of method "pop"
class destroyer: internal::no_copy { class destroyer: internal::no_copy {
T& my_value; T& my_value;
public: public:
destroyer( T& value ) : my_value(value) {} destroyer( T& value ) : my_value(value) {}
~destroyer() {my_value.~T();} ~destroyer() {my_value.~T();}
}; };
T& get_ref( page& p, size_t index ) { T& get_ref( page& p, size_t index ) {
__TBB_ASSERT( index<items_per_page, NULL ); __TBB_ASSERT( index<items_per_page, NULL );
return (&static_cast<padded_page*>(static_cast<void*>(&p))->last)[i ndex]; return (&static_cast<padded_page*>(static_cast<void*>(&p))->last)[i ndex];
} }
/*override*/ virtual void copy_item( page& dst, size_t index, const voi d* src ) { /*override*/ virtual void copy_item( page& dst, size_t index, const voi d* src ) {
new( &get_ref(dst,index) ) T(*static_cast<const T*>(src)); new( &get_ref(dst,index) ) T(*static_cast<const T*>(src));
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT
/*override*/ virtual void move_item( page& dst, size_t index, const voi
d* src ) {
new( &get_ref(dst,index) ) T( std::move(*static_cast<T*>(const_cast
<void*>(src))) );
}
#else
/*override*/ virtual void move_item( page&, size_t, const void* ) {
__TBB_ASSERT( false, "Unreachable code" );
}
#endif
/*override*/ virtual void copy_page_item( page& dst, size_t dindex, con st page& src, size_t sindex ) { /*override*/ virtual void copy_page_item( page& dst, size_t dindex, con st page& src, size_t sindex ) {
new( &get_ref(dst,dindex) ) T( get_ref( const_cast<page&>(src), sin dex ) ); new( &get_ref(dst,dindex) ) T( get_ref( const_cast<page&>(src), sin dex ) );
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT
/*override*/ virtual void move_page_item( page& dst, size_t dindex, con
st page& src, size_t sindex ) {
new( &get_ref(dst,dindex) ) T( std::move(get_ref( const_cast<page&>
(src), sindex )) );
}
#else
/*override*/ virtual void move_page_item( page&, size_t, const page&, s
ize_t ) {
__TBB_ASSERT( false, "Unreachable code" );
}
#endif
/*override*/ virtual void assign_and_destroy_item( void* dst, page& src , size_t index ) { /*override*/ virtual void assign_and_destroy_item( void* dst, page& src , size_t index ) {
T& from = get_ref(src,index); T& from = get_ref(src,index);
destroyer d(from); destroyer d(from);
*static_cast<T*>(dst) = from; *static_cast<T*>(dst) = tbb::internal::move( from );
} }
/*override*/ virtual page *allocate_page() { /*override*/ virtual page *allocate_page() {
size_t n = sizeof(padded_page) + (items_per_page-1)*sizeof(T); size_t n = sizeof(padded_page) + (items_per_page-1)*sizeof(T);
page *p = reinterpret_cast<page*>(my_allocator.allocate( n )); page *p = reinterpret_cast<page*>(my_allocator.allocate( n ));
if( !p ) if( !p )
internal::throw_exception(internal::eid_bad_alloc); internal::throw_exception(internal::eid_bad_alloc);
return p; return p;
} }
skipping to change at line 238 skipping to change at line 296
//! Integral type for representing size of the queue. //! Integral type for representing size of the queue.
/** Note that the size_type is a signed integral type. /** Note that the size_type is a signed integral type.
This is because the size can be negative if there are pending pops without corresponding pushes. */ This is because the size can be negative if there are pending pops without corresponding pushes. */
typedef std::ptrdiff_t size_type; typedef std::ptrdiff_t size_type;
//! Difference type for iterator //! Difference type for iterator
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
//! Construct empty queue //! Construct empty queue
explicit concurrent_bounded_queue(const allocator_type& a = allocator_t ype()) : explicit concurrent_bounded_queue(const allocator_type& a = allocator_t ype()) :
concurrent_queue_base_v3( sizeof(T) ), my_allocator( a ) concurrent_queue_base_v8( sizeof(T) ), my_allocator( a )
{ {
} }
//! Copy constructor //! Copy constructor
concurrent_bounded_queue( const concurrent_bounded_queue& src, const al concurrent_bounded_queue( const concurrent_bounded_queue& src, const al
locator_type& a = allocator_type()) : locator_type& a = allocator_type())
concurrent_queue_base_v3( sizeof(T) ), my_allocator( a ) : concurrent_queue_base_v8( sizeof(T) ), my_allocator( a )
{ {
assign( src ); assign( src );
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT
//! Move constructors
concurrent_bounded_queue( concurrent_bounded_queue&& src )
: concurrent_queue_base_v8( sizeof(T) ), my_allocator( std::move(sr
c.my_allocator) )
{
internal_swap( src );
}
concurrent_bounded_queue( concurrent_bounded_queue&& src, const allocat
or_type& a )
: concurrent_queue_base_v8( sizeof(T) ), my_allocator( a )
{
// checking that memory allocated by one instance of allocator can
be deallocated
// with another
if( my_allocator == src.my_allocator) {
this->internal_swap( src );
} else {
// allocators are different => performing per-element move
this->move_content( src );
src.clear();
}
}
#endif /* __TBB_CPP11_RVALUE_REF_PRESENT */
//! [begin,end) constructor //! [begin,end) constructor
template<typename InputIterator> template<typename InputIterator>
concurrent_bounded_queue( InputIterator begin, InputIterator end, const concurrent_bounded_queue( InputIterator begin, InputIterator end,
allocator_type& a = allocator_type()) : const allocator_type& a = allocator_type())
concurrent_queue_base_v3( sizeof(T) ), my_allocator( a ) : concurrent_queue_base_v8( sizeof(T) ), my_allocator( a )
{ {
for( ; begin != end; ++begin ) for( ; begin != end; ++begin )
internal_push_if_not_full(&*begin); internal_push_if_not_full(&*begin);
} }
//! Destroy queue //! Destroy queue
~concurrent_bounded_queue(); ~concurrent_bounded_queue();
//! Enqueue an item at tail of queue. //! Enqueue an item at tail of queue.
void push( const T& source ) { void push( const T& source ) {
internal_push( &source ); internal_push( &source );
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT
//! Move an item at tail of queue.
void push( T&& source ) {
internal_push_move( &source );
}
#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
template<typename... Arguments>
void emplace( Arguments&&... args ) {
push( T(std::forward<Arguments>( args )...) );
}
#endif /* __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT */
#endif /* __TBB_CPP11_RVALUE_REF_PRESENT */
//! Dequeue item from head of queue. //! Dequeue item from head of queue.
/** Block until an item becomes available, and then dequeue it. */ /** Block until an item becomes available, and then dequeue it. */
void pop( T& destination ) { void pop( T& destination ) {
internal_pop( &destination ); internal_pop( &destination );
} }
#if TBB_USE_EXCEPTIONS #if TBB_USE_EXCEPTIONS
//! Abort all pending queue operations //! Abort all pending queue operations
void abort() { void abort() {
internal_abort(); internal_abort();
} }
#endif #endif
//! Enqueue an item at tail of queue if queue is not already full. //! Enqueue an item at tail of queue if queue is not already full.
/** Does not wait for queue to become not full. /** Does not wait for queue to become not full.
Returns true if item is pushed; false if queue was already full. */ Returns true if item is pushed; false if queue was already full. */
bool try_push( const T& source ) { bool try_push( const T& source ) {
return internal_push_if_not_full( &source ); return internal_push_if_not_full( &source );
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT
//! Move an item at tail of queue if queue is not already full.
/** Does not wait for queue to become not full.
Returns true if item is pushed; false if queue was already full. */
bool try_push( T&& source ) {
return internal_push_move_if_not_full( &source );
}
#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
template<typename... Arguments>
bool try_emplace( Arguments&&... args ) {
return try_push( T(std::forward<Arguments>( args )...) );
}
#endif /* __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT */
#endif /* __TBB_CPP11_RVALUE_REF_PRESENT */
//! Attempt to dequeue an item from head of queue. //! Attempt to dequeue an item from head of queue.
/** Does not wait for item to become available. /** Does not wait for item to become available.
Returns true if successful; false otherwise. */ Returns true if successful; false otherwise. */
bool try_pop( T& destination ) { bool try_pop( T& destination ) {
return internal_pop_if_present( &destination ); return internal_pop_if_present( &destination );
} }
//! Return number of pushes minus number of pops. //! Return number of pushes minus number of pops.
/** Note that the result can be negative if there are pops waiting for the /** Note that the result can be negative if there are pops waiting for the
corresponding pushes. The result can also exceed capacity() if the re corresponding pushes. The result can also exceed capacity() if the re
skipping to change at line 347 skipping to change at line 458
} }
template<typename T, class A> template<typename T, class A>
void concurrent_bounded_queue<T,A>::clear() { void concurrent_bounded_queue<T,A>::clear() {
while( !empty() ) { while( !empty() ) {
T value; T value;
internal_pop_if_present(&value); internal_pop_if_present(&value);
} }
} }
namespace deprecated {
//! A high-performance thread-safe blocking concurrent bounded queue.
/** This is the pre-PPL TBB concurrent queue which support boundedness and
blocking semantics.
Note that method names agree with the PPL-style concurrent queue.
Multiple threads may each push and pop concurrently.
Assignment construction is not allowed.
@ingroup containers */
template<typename T, class A = cache_aligned_allocator<T> >
class concurrent_queue: public concurrent_bounded_queue<T,A> {
#if !__TBB_TEMPLATE_FRIENDS_BROKEN
template<typename Container, typename Value> friend class internal::con
current_queue_iterator;
#endif
public:
//! Construct empty queue
explicit concurrent_queue(const A& a = A()) :
concurrent_bounded_queue<T,A>( a )
{
}
//! Copy constructor
concurrent_queue( const concurrent_queue& src, const A& a = A()) :
concurrent_bounded_queue<T,A>( src, a )
{
}
//! [begin,end) constructor
template<typename InputIterator>
concurrent_queue( InputIterator b /*begin*/, InputIterator e /*end*/, c
onst A& a = A()) :
concurrent_bounded_queue<T,A>( b, e, a )
{
}
//! Enqueue an item at tail of queue if queue is not already full.
/** Does not wait for queue to become not full.
Returns true if item is pushed; false if queue was already full. */
bool push_if_not_full( const T& source ) {
return this->try_push( source );
}
//! Attempt to dequeue an item from head of queue.
/** Does not wait for item to become available.
Returns true if successful; false otherwise.
@deprecated Use try_pop()
*/
bool pop_if_present( T& destination ) {
return this->try_pop( destination );
}
typedef typename concurrent_bounded_queue<T,A>::iterator iterator;
typedef typename concurrent_bounded_queue<T,A>::const_iterator const_it
erator;
//
//---------------------------------------------------------------------
---
// The iterators are intended only for debugging. They are slow and no
t thread safe.
//---------------------------------------------------------------------
---
iterator begin() {return this->unsafe_begin();}
iterator end() {return this->unsafe_end();}
const_iterator begin() const {return this->unsafe_begin();}
const_iterator end() const {return this->unsafe_end();}
};
}
#if TBB_DEPRECATED
using deprecated::concurrent_queue;
#else
using strict_ppl::concurrent_queue; using strict_ppl::concurrent_queue;
#endif
} // namespace tbb } // namespace tbb
#endif /* __TBB_concurrent_queue_H */ #endif /* __TBB_concurrent_queue_H */
 End of changes. 20 change blocks. 
115 lines changed or deleted 170 lines changed or added


 concurrent_unordered_map.h   concurrent_unordered_map.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
/* Container implementations in this header are based on PPL implementation s /* Container implementations in this header are based on PPL implementation s
provided by Microsoft. */ provided by Microsoft. */
#ifndef __TBB_concurrent_unordered_map_H #ifndef __TBB_concurrent_unordered_map_H
#define __TBB_concurrent_unordered_map_H #define __TBB_concurrent_unordered_map_H
#include "internal/_concurrent_unordered_impl.h" #include "internal/_concurrent_unordered_impl.h"
skipping to change at line 90 skipping to change at line 82
template <typename Key, typename T, typename Hasher = tbb::tbb_hash<Key>, t ypename Key_equality = std::equal_to<Key>, template <typename Key, typename T, typename Hasher = tbb::tbb_hash<Key>, t ypename Key_equality = std::equal_to<Key>,
typename Allocator = tbb::tbb_allocator<std::pair<const Key, T> > > typename Allocator = tbb::tbb_allocator<std::pair<const Key, T> > >
class concurrent_unordered_map : class concurrent_unordered_map :
public internal::concurrent_unordered_base< concurrent_unordered_map_tr aits<Key, T, public internal::concurrent_unordered_base< concurrent_unordered_map_tr aits<Key, T,
internal::hash_compare<Key, Hasher, Key_equality>, Allocator, false> > internal::hash_compare<Key, Hasher, Key_equality>, Allocator, false> >
{ {
// Base type definitions // Base type definitions
typedef internal::hash_compare<Key, Hasher, Key_equality> hash_compare; typedef internal::hash_compare<Key, Hasher, Key_equality> hash_compare;
typedef concurrent_unordered_map_traits<Key, T, hash_compare, Allocator , false> traits_type; typedef concurrent_unordered_map_traits<Key, T, hash_compare, Allocator , false> traits_type;
typedef internal::concurrent_unordered_base< traits_type > base_type; typedef internal::concurrent_unordered_base< traits_type > base_type;
using traits_type::my_hash_compare;
#if __TBB_EXTRA_DEBUG #if __TBB_EXTRA_DEBUG
public: public:
#endif #endif
using traits_type::allow_multimapping; using traits_type::allow_multimapping;
public: public:
using base_type::end; using base_type::end;
using base_type::find; using base_type::find;
using base_type::insert; using base_type::insert;
// Type definitions // Type definitions
skipping to change at line 123 skipping to change at line 114
typedef typename base_type::size_type size_type; typedef typename base_type::size_type size_type;
typedef typename base_type::difference_type difference_type; typedef typename base_type::difference_type difference_type;
typedef typename base_type::iterator iterator; typedef typename base_type::iterator iterator;
typedef typename base_type::const_iterator const_iterator; typedef typename base_type::const_iterator const_iterator;
typedef typename base_type::iterator local_iterator; typedef typename base_type::iterator local_iterator;
typedef typename base_type::const_iterator const_local_iterator; typedef typename base_type::const_iterator const_local_iterator;
// Construction/destruction/copying // Construction/destruction/copying
explicit concurrent_unordered_map(size_type n_of_buckets = 8, explicit concurrent_unordered_map(size_type n_of_buckets = base_type::i nitial_bucket_number,
const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(), const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(),
const allocator_type& a = allocator_type()) const allocator_type& a = allocator_type())
: base_type(n_of_buckets, key_compare(_Hasher, _Key_equality), a) : base_type(n_of_buckets, key_compare(_Hasher, _Key_equality), a)
{ {
} }
concurrent_unordered_map(const Allocator& a) : base_type(8, key_compare (), a) concurrent_unordered_map(const Allocator& a) : base_type(base_type::ini tial_bucket_number, key_compare(), a)
{ {
} }
template <typename Iterator> template <typename Iterator>
concurrent_unordered_map(Iterator first, Iterator last, size_type n_of_ buckets = 8, concurrent_unordered_map(Iterator first, Iterator last, size_type n_of_ buckets = base_type::initial_bucket_number,
const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(), const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(),
const allocator_type& a = allocator_type()) const allocator_type& a = allocator_type())
: base_type(n_of_buckets, key_compare(_Hasher, _Key_equality), a) : base_type(n_of_buckets, key_compare(_Hasher, _Key_equality), a)
{ {
for (; first != last; ++first) insert(first, last);
base_type::insert(*first);
} }
#if __TBB_INITIALIZER_LISTS_PRESENT #if __TBB_INITIALIZER_LISTS_PRESENT
//! Constructor from initializer_list //! Constructor from initializer_list
concurrent_unordered_map(std::initializer_list<value_type> const& il, s ize_type n_of_buckets = 8, concurrent_unordered_map(std::initializer_list<value_type> il, size_typ e n_of_buckets = base_type::initial_bucket_number,
const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(), const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(),
const allocator_type& a = allocator_type()) const allocator_type& a = allocator_type())
: base_type(n_of_buckets, key_compare(_Hasher, _Key_equality), a) : base_type(n_of_buckets, key_compare(_Hasher, _Key_equality), a)
{ {
this->insert(il.begin(),il.end()); this->insert(il.begin(),il.end());
} }
#endif //# __TBB_INITIALIZER_LISTS_PRESENT #endif //# __TBB_INITIALIZER_LISTS_PRESENT
concurrent_unordered_map(const concurrent_unordered_map& table) : base_ #if __TBB_CPP11_RVALUE_REF_PRESENT && __TBB_CPP11_IMPLICIT_MOVE_MEMBERS_GEN
type(table) ERATION_FOR_DERIVED_BROKEN
{ concurrent_unordered_map(const concurrent_unordered_map& table)
} : base_type(table)
concurrent_unordered_map(const concurrent_unordered_map& table, const A
llocator& a)
: base_type(table, a)
{ {
} }
concurrent_unordered_map& operator=(const concurrent_unordered_map& tab le) concurrent_unordered_map& operator=(const concurrent_unordered_map& tab le)
{ {
base_type::operator=(table); return static_cast<concurrent_unordered_map&>(base_type::operator=(
return (*this); table));
} }
#if __TBB_INITIALIZER_LISTS_PRESENT concurrent_unordered_map(concurrent_unordered_map&& table)
//! assignment operator from initializer_list : base_type(std::move(table))
concurrent_unordered_map& operator=(std::initializer_list<value_type> c
onst& il)
{
base_type::operator=(il);
return (*this);
}
#endif //# __TBB_INITIALIZER_LISTS_PRESENT
iterator unsafe_erase(const_iterator where)
{ {
return base_type::unsafe_erase(where);
} }
size_type unsafe_erase(const key_type& key) concurrent_unordered_map& operator=(concurrent_unordered_map&& table)
{ {
return base_type::unsafe_erase(key); return static_cast<concurrent_unordered_map&>(base_type::operator=( std::move(table)));
} }
#endif //__TBB_CPP11_IMPLICIT_MOVE_MEMBERS_GENERATION_FOR_DERIVED_BROKEN
iterator unsafe_erase(const_iterator first, const_iterator last) concurrent_unordered_map(const concurrent_unordered_map& table, const A
llocator& a)
: base_type(table, a)
{ {
return base_type::unsafe_erase(first, last);
} }
void swap(concurrent_unordered_map& table) #if __TBB_CPP11_RVALUE_REF_PRESENT
concurrent_unordered_map(concurrent_unordered_map&& table, const Alloca
tor& a) : base_type(std::move(table), a)
{ {
base_type::swap(table);
} }
#endif
// Observers // Observers
hasher hash_function() const
{
return my_hash_compare.my_hash_object;
}
key_equal key_eq() const
{
return my_hash_compare.my_key_compare_object;
}
mapped_type& operator[](const key_type& key) mapped_type& operator[](const key_type& key)
{ {
iterator where = find(key); iterator where = find(key);
if (where == end()) if (where == end())
{ {
where = insert(std::pair<key_type, mapped_type>(key, mapped_typ e())).first; where = insert(std::pair<key_type, mapped_type>(key, mapped_typ e())).first;
} }
return ((*where).second); return ((*where).second);
skipping to change at line 256 skipping to change at line 224
template < typename Key, typename T, typename Hasher = tbb::tbb_hash<Key>, typename Key_equality = std::equal_to<Key>, template < typename Key, typename T, typename Hasher = tbb::tbb_hash<Key>, typename Key_equality = std::equal_to<Key>,
typename Allocator = tbb::tbb_allocator<std::pair<const Key, T> > > typename Allocator = tbb::tbb_allocator<std::pair<const Key, T> > >
class concurrent_unordered_multimap : class concurrent_unordered_multimap :
public internal::concurrent_unordered_base< concurrent_unordered_map_tr aits< Key, T, public internal::concurrent_unordered_base< concurrent_unordered_map_tr aits< Key, T,
internal::hash_compare<Key, Hasher, Key_equality>, Allocator, true> > internal::hash_compare<Key, Hasher, Key_equality>, Allocator, true> >
{ {
// Base type definitions // Base type definitions
typedef internal::hash_compare<Key, Hasher, Key_equality> hash_compare; typedef internal::hash_compare<Key, Hasher, Key_equality> hash_compare;
typedef concurrent_unordered_map_traits<Key, T, hash_compare, Allocator , true> traits_type; typedef concurrent_unordered_map_traits<Key, T, hash_compare, Allocator , true> traits_type;
typedef internal::concurrent_unordered_base< traits_type > base_type; typedef internal::concurrent_unordered_base<traits_type> base_type;
using traits_type::my_hash_compare;
#if __TBB_EXTRA_DEBUG #if __TBB_EXTRA_DEBUG
public: public:
#endif #endif
using traits_type::allow_multimapping; using traits_type::allow_multimapping;
public: public:
using base_type::end;
using base_type::find;
using base_type::insert; using base_type::insert;
// Type definitions // Type definitions
typedef Key key_type; typedef Key key_type;
typedef typename base_type::value_type value_type; typedef typename base_type::value_type value_type;
typedef T mapped_type; typedef T mapped_type;
typedef Hasher hasher; typedef Hasher hasher;
typedef Key_equality key_equal; typedef Key_equality key_equal;
typedef hash_compare key_compare; typedef hash_compare key_compare;
skipping to change at line 290 skipping to change at line 255
typedef typename base_type::size_type size_type; typedef typename base_type::size_type size_type;
typedef typename base_type::difference_type difference_type; typedef typename base_type::difference_type difference_type;
typedef typename base_type::iterator iterator; typedef typename base_type::iterator iterator;
typedef typename base_type::const_iterator const_iterator; typedef typename base_type::const_iterator const_iterator;
typedef typename base_type::iterator local_iterator; typedef typename base_type::iterator local_iterator;
typedef typename base_type::const_iterator const_local_iterator; typedef typename base_type::const_iterator const_local_iterator;
// Construction/destruction/copying // Construction/destruction/copying
explicit concurrent_unordered_multimap(size_type n_of_buckets = 8, explicit concurrent_unordered_multimap(size_type n_of_buckets = base_ty pe::initial_bucket_number,
const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(), const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(),
const allocator_type& a = allocator_type()) const allocator_type& a = allocator_type())
: base_type(n_of_buckets, key_compare(_Hasher, _Key_equality), a) : base_type(n_of_buckets, key_compare(_Hasher, _Key_equality), a)
{ {
} }
concurrent_unordered_multimap(const Allocator& a) : base_type(8, key_co mpare(), a) concurrent_unordered_multimap(const Allocator& a) : base_type(base_type ::initial_bucket_number, key_compare(), a)
{ {
} }
template <typename Iterator> template <typename Iterator>
concurrent_unordered_multimap(Iterator first, Iterator last, size_type n_of_buckets = 8, concurrent_unordered_multimap(Iterator first, Iterator last, size_type n_of_buckets = base_type::initial_bucket_number,
const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(), const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(),
const allocator_type& a = allocator_type()) const allocator_type& a = allocator_type())
: base_type(n_of_buckets,key_compare(_Hasher,_Key_equality), a) : base_type(n_of_buckets,key_compare(_Hasher,_Key_equality), a)
{ {
for (; first != last; ++first) insert(first, last);
base_type::insert(*first);
} }
#if __TBB_INITIALIZER_LISTS_PRESENT #if __TBB_INITIALIZER_LISTS_PRESENT
//! Constructor from initializer_list //! Constructor from initializer_list
concurrent_unordered_multimap(std::initializer_list<value_type> const& il, size_type n_of_buckets = 8, concurrent_unordered_multimap(std::initializer_list<value_type> il, siz e_type n_of_buckets = base_type::initial_bucket_number,
const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(), const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(),
const allocator_type& a = allocator_type()) const allocator_type& a = allocator_type())
: base_type(n_of_buckets, key_compare(_Hasher, _Key_equality), a) : base_type(n_of_buckets, key_compare(_Hasher, _Key_equality), a)
{ {
this->insert(il.begin(),il.end()); this->insert(il.begin(),il.end());
} }
#endif //# __TBB_INITIALIZER_LISTS_PRESENT #endif //# __TBB_INITIALIZER_LISTS_PRESENT
concurrent_unordered_multimap(const concurrent_unordered_multimap& tabl #if __TBB_CPP11_RVALUE_REF_PRESENT && __TBB_CPP11_IMPLICIT_MOVE_MEMBERS_GEN
e) : base_type(table) ERATION_FOR_DERIVED_BROKEN
{ concurrent_unordered_multimap(const concurrent_unordered_multimap& tabl
} e)
: base_type(table)
concurrent_unordered_multimap(const concurrent_unordered_multimap& tabl
e, const Allocator& a)
: base_type(table, a)
{ {
} }
concurrent_unordered_multimap& operator=(const concurrent_unordered_mul timap& table) concurrent_unordered_multimap& operator=(const concurrent_unordered_mul timap& table)
{ {
base_type::operator=(table); return static_cast<concurrent_unordered_multimap&>(base_type::opera
return (*this); tor=(table));
}
#if __TBB_INITIALIZER_LISTS_PRESENT
//! assignment operator from initializer_list
concurrent_unordered_multimap& operator=(std::initializer_list<value_ty
pe> const& il)
{
base_type::operator=(il);
return (*this);
}
#endif //# __TBB_INITIALIZER_LISTS_PRESENT
iterator unsafe_erase(const_iterator where)
{
return base_type::unsafe_erase(where);
} }
size_type unsafe_erase(const key_type& key) concurrent_unordered_multimap(concurrent_unordered_multimap&& table)
: base_type(std::move(table))
{ {
return base_type::unsafe_erase(key);
} }
iterator unsafe_erase(const_iterator first, const_iterator last) concurrent_unordered_multimap& operator=(concurrent_unordered_multimap& & table)
{ {
return base_type::unsafe_erase(first, last); return static_cast<concurrent_unordered_multimap&>(base_type::opera tor=(std::move(table)));
} }
#endif //__TBB_CPP11_IMPLICIT_MOVE_MEMBERS_GENERATION_FOR_DERIVED_BROKEN
void swap(concurrent_unordered_multimap& table) concurrent_unordered_multimap(const concurrent_unordered_multimap& tabl
{ e, const Allocator& a)
base_type::swap(table); : base_type(table, a)
}
// Observers
hasher hash_function() const
{ {
return my_hash_compare.my_hash_object;
} }
key_equal key_eq() const #if __TBB_CPP11_RVALUE_REF_PRESENT
concurrent_unordered_multimap(concurrent_unordered_multimap&& table, co
nst Allocator& a) : base_type(std::move(table), a)
{ {
return my_hash_compare.my_key_compare_object;
} }
#endif
}; };
} // namespace interface5 } // namespace interface5
using interface5::concurrent_unordered_map; using interface5::concurrent_unordered_map;
using interface5::concurrent_unordered_multimap; using interface5::concurrent_unordered_multimap;
} // namespace tbb } // namespace tbb
#endif// __TBB_concurrent_unordered_map_H #endif// __TBB_concurrent_unordered_map_H
 End of changes. 39 change blocks. 
123 lines changed or deleted 77 lines changed or added


 concurrent_unordered_set.h   concurrent_unordered_set.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
/* Container implementations in this header are based on PPL implementation s /* Container implementations in this header are based on PPL implementation s
provided by Microsoft. */ provided by Microsoft. */
#ifndef __TBB_concurrent_unordered_set_H #ifndef __TBB_concurrent_unordered_set_H
#define __TBB_concurrent_unordered_set_H #define __TBB_concurrent_unordered_set_H
#include "internal/_concurrent_unordered_impl.h" #include "internal/_concurrent_unordered_impl.h"
skipping to change at line 72 skipping to change at line 64
hash_compare my_hash_compare; // the comparator predicate for keys hash_compare my_hash_compare; // the comparator predicate for keys
}; };
template <typename Key, typename Hasher = tbb::tbb_hash<Key>, typename Key_ equality = std::equal_to<Key>, typename Allocator = tbb::tbb_allocator<Key> > template <typename Key, typename Hasher = tbb::tbb_hash<Key>, typename Key_ equality = std::equal_to<Key>, typename Allocator = tbb::tbb_allocator<Key> >
class concurrent_unordered_set : public internal::concurrent_unordered_base < concurrent_unordered_set_traits<Key, internal::hash_compare<Key, Hasher, Key_equality>, Allocator, false> > class concurrent_unordered_set : public internal::concurrent_unordered_base < concurrent_unordered_set_traits<Key, internal::hash_compare<Key, Hasher, Key_equality>, Allocator, false> >
{ {
// Base type definitions // Base type definitions
typedef internal::hash_compare<Key, Hasher, Key_equality> hash_compare; typedef internal::hash_compare<Key, Hasher, Key_equality> hash_compare;
typedef internal::concurrent_unordered_base< concurrent_unordered_set_t raits<Key, hash_compare, Allocator, false> > base_type; typedef internal::concurrent_unordered_base< concurrent_unordered_set_t raits<Key, hash_compare, Allocator, false> > base_type;
typedef concurrent_unordered_set_traits<Key, internal::hash_compare<Key , Hasher, Key_equality>, Allocator, false> traits_type; typedef concurrent_unordered_set_traits<Key, internal::hash_compare<Key , Hasher, Key_equality>, Allocator, false> traits_type;
using traits_type::my_hash_compare;
#if __TBB_EXTRA_DEBUG #if __TBB_EXTRA_DEBUG
public: public:
#endif #endif
using traits_type::allow_multimapping; using traits_type::allow_multimapping;
public: public:
using base_type::end;
using base_type::find;
using base_type::insert; using base_type::insert;
// Type definitions // Type definitions
typedef Key key_type; typedef Key key_type;
typedef typename base_type::value_type value_type; typedef typename base_type::value_type value_type;
typedef Key mapped_type; typedef Key mapped_type;
typedef Hasher hasher; typedef Hasher hasher;
typedef Key_equality key_equal; typedef Key_equality key_equal;
typedef hash_compare key_compare; typedef hash_compare key_compare;
skipping to change at line 105 skipping to change at line 94
typedef typename base_type::size_type size_type; typedef typename base_type::size_type size_type;
typedef typename base_type::difference_type difference_type; typedef typename base_type::difference_type difference_type;
typedef typename base_type::iterator iterator; typedef typename base_type::iterator iterator;
typedef typename base_type::const_iterator const_iterator; typedef typename base_type::const_iterator const_iterator;
typedef typename base_type::iterator local_iterator; typedef typename base_type::iterator local_iterator;
typedef typename base_type::const_iterator const_local_iterator; typedef typename base_type::const_iterator const_local_iterator;
// Construction/destruction/copying // Construction/destruction/copying
explicit concurrent_unordered_set(size_type n_of_buckets = 8, const has her& a_hasher = hasher(), explicit concurrent_unordered_set(size_type n_of_buckets = base_type::i nitial_bucket_number, const hasher& a_hasher = hasher(),
const key_equal& a_keyeq = key_equal(), const allocator_type& a = a llocator_type()) const key_equal& a_keyeq = key_equal(), const allocator_type& a = a llocator_type())
: base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a) : base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a)
{ {
} }
concurrent_unordered_set(const Allocator& a) : base_type(8, key_compare (), a) concurrent_unordered_set(const Allocator& a) : base_type(base_type::ini tial_bucket_number, key_compare(), a)
{ {
} }
template <typename Iterator> template <typename Iterator>
concurrent_unordered_set(Iterator first, Iterator last, size_type n_of_ buckets = 8, const hasher& a_hasher = hasher(), concurrent_unordered_set(Iterator first, Iterator last, size_type n_of_ buckets = base_type::initial_bucket_number, const hasher& a_hasher = hasher (),
const key_equal& a_keyeq = key_equal(), const allocator_type& a = a llocator_type()) const key_equal& a_keyeq = key_equal(), const allocator_type& a = a llocator_type())
: base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a) : base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a)
{ {
for (; first != last; ++first) insert(first, last);
base_type::insert(*first);
} }
#if __TBB_INITIALIZER_LISTS_PRESENT #if __TBB_INITIALIZER_LISTS_PRESENT
//! Constructor from initializer_list //! Constructor from initializer_list
concurrent_unordered_set(std::initializer_list<value_type> const& il, si ze_type n_of_buckets = 8, const hasher& a_hasher = hasher(), concurrent_unordered_set(std::initializer_list<value_type> il, size_type n_of_buckets = base_type::initial_bucket_number, const hasher& a_hasher = hasher(),
const key_equal& a_keyeq = key_equal(), const allocator_type& a = a llocator_type()) const key_equal& a_keyeq = key_equal(), const allocator_type& a = a llocator_type())
: base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a) : base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a)
{ {
this->insert(il.begin(),il.end()); this->insert(il.begin(),il.end());
} }
#endif //# __TBB_INITIALIZER_LISTS_PRESENT #endif //# __TBB_INITIALIZER_LISTS_PRESENT
concurrent_unordered_set(const concurrent_unordered_set& table) : base_ #if __TBB_CPP11_RVALUE_REF_PRESENT && __TBB_CPP11_IMPLICIT_MOVE_MEMBERS_GEN
type(table) ERATION_FOR_DERIVED_BROKEN
{ concurrent_unordered_set(const concurrent_unordered_set& table)
} : base_type(table)
concurrent_unordered_set(const concurrent_unordered_set& table, const A
llocator& a)
: base_type(table, a)
{ {
} }
concurrent_unordered_set& operator=(const concurrent_unordered_set& tab le) concurrent_unordered_set& operator=(const concurrent_unordered_set& tab le)
{ {
base_type::operator=(table); return static_cast<concurrent_unordered_set&>(base_type::operator=(
return (*this); table));
}
#if __TBB_INITIALIZER_LISTS_PRESENT
//! assignment operator from initializer_list
concurrent_unordered_set& operator=(std::initializer_list<value_type> c
onst& il)
{
base_type::operator=(il);
return (*this);
}
#endif //# __TBB_INITIALIZER_LISTS_PRESENT
iterator unsafe_erase(const_iterator where)
{
return base_type::unsafe_erase(where);
} }
size_type unsafe_erase(const key_type& key) concurrent_unordered_set(concurrent_unordered_set&& table)
: base_type(std::move(table))
{ {
return base_type::unsafe_erase(key);
} }
iterator unsafe_erase(const_iterator first, const_iterator last) concurrent_unordered_set& operator=(concurrent_unordered_set&& table)
{ {
return base_type::unsafe_erase(first, last); return static_cast<concurrent_unordered_set&>(base_type::operator=( std::move(table)));
} }
#endif //__TBB_CPP11_IMPLICIT_MOVE_MEMBERS_GENERATION_FOR_DERIVED_BROKEN
void swap(concurrent_unordered_set& table) concurrent_unordered_set(const concurrent_unordered_set& table, const A
llocator& a)
: base_type(table, a)
{ {
base_type::swap(table);
} }
// Observers #if __TBB_CPP11_RVALUE_REF_PRESENT
hasher hash_function() const concurrent_unordered_set(concurrent_unordered_set&& table, const Alloca
tor& a)
: base_type(std::move(table), a)
{ {
return my_hash_compare.my_hash_object;
} }
#endif //__TBB_CPP11_RVALUE_REF_PRESENT
key_equal key_eq() const
{
return my_hash_compare.my_key_compare_object;
}
}; };
template <typename Key, typename Hasher = tbb::tbb_hash<Key>, typename Key_ equality = std::equal_to<Key>, template <typename Key, typename Hasher = tbb::tbb_hash<Key>, typename Key_ equality = std::equal_to<Key>,
typename Allocator = tbb::tbb_allocator<Key> > typename Allocator = tbb::tbb_allocator<Key> >
class concurrent_unordered_multiset : class concurrent_unordered_multiset :
public internal::concurrent_unordered_base< concurrent_unordered_set_tr aits<Key, public internal::concurrent_unordered_base< concurrent_unordered_set_tr aits<Key,
internal::hash_compare<Key, Hasher, Key_equality>, Allocator, true> > internal::hash_compare<Key, Hasher, Key_equality>, Allocator, true> >
{ {
public:
// Base type definitions // Base type definitions
typedef internal::hash_compare<Key, Hasher, Key_equality> hash_compare; typedef internal::hash_compare<Key, Hasher, Key_equality> hash_compare;
typedef concurrent_unordered_set_traits<Key, hash_compare, Allocator, t rue> traits_type; typedef concurrent_unordered_set_traits<Key, hash_compare, Allocator, t rue> traits_type;
typedef internal::concurrent_unordered_base< traits_type > base_type; typedef internal::concurrent_unordered_base< traits_type > base_type;
#if __TBB_EXTRA_DEBUG
public:
#endif
using traits_type::allow_multimapping; using traits_type::allow_multimapping;
using traits_type::my_hash_compare; public:
using base_type::insert;
// Type definitions // Type definitions
typedef Key key_type; typedef Key key_type;
typedef typename base_type::value_type value_type; typedef typename base_type::value_type value_type;
typedef Key mapped_type; typedef Key mapped_type;
typedef Hasher hasher; typedef Hasher hasher;
typedef Key_equality key_equal; typedef Key_equality key_equal;
typedef hash_compare key_compare; typedef hash_compare key_compare;
typedef typename base_type::allocator_type allocator_type; typedef typename base_type::allocator_type allocator_type;
skipping to change at line 227 skipping to change at line 198
typedef typename base_type::size_type size_type; typedef typename base_type::size_type size_type;
typedef typename base_type::difference_type difference_type; typedef typename base_type::difference_type difference_type;
typedef typename base_type::iterator iterator; typedef typename base_type::iterator iterator;
typedef typename base_type::const_iterator const_iterator; typedef typename base_type::const_iterator const_iterator;
typedef typename base_type::iterator local_iterator; typedef typename base_type::iterator local_iterator;
typedef typename base_type::const_iterator const_local_iterator; typedef typename base_type::const_iterator const_local_iterator;
// Construction/destruction/copying // Construction/destruction/copying
explicit concurrent_unordered_multiset(size_type n_of_buckets = 8, explicit concurrent_unordered_multiset(size_type n_of_buckets = base_ty pe::initial_bucket_number,
const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(), const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(),
const allocator_type& a = allocator_type()) const allocator_type& a = allocator_type())
: base_type(n_of_buckets, key_compare(_Hasher, _Key_equality), a) : base_type(n_of_buckets, key_compare(_Hasher, _Key_equality), a)
{ {
} }
concurrent_unordered_multiset(const Allocator& a) : base_type(8, key_co mpare(), a) concurrent_unordered_multiset(const Allocator& a) : base_type(base_type ::initial_bucket_number, key_compare(), a)
{ {
} }
template <typename Iterator> template <typename Iterator>
concurrent_unordered_multiset(Iterator first, Iterator last, size_type n_of_buckets = 8, concurrent_unordered_multiset(Iterator first, Iterator last, size_type n_of_buckets = base_type::initial_bucket_number,
const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(), const hasher& _Hasher = hasher(), const key_equal& _Key_equality = key_equal(),
const allocator_type& a = allocator_type()) const allocator_type& a = allocator_type())
: base_type(n_of_buckets, key_compare(_Hasher, _Key_equality), a) : base_type(n_of_buckets, key_compare(_Hasher, _Key_equality), a)
{ {
for (; first != last; ++first) insert(first, last);
{
base_type::insert(*first);
}
} }
#if __TBB_INITIALIZER_LISTS_PRESENT #if __TBB_INITIALIZER_LISTS_PRESENT
//! Constructor from initializer_list //! Constructor from initializer_list
concurrent_unordered_multiset(std::initializer_list<value_type> const& i l, size_type n_of_buckets = 8, const hasher& a_hasher = hasher(), concurrent_unordered_multiset(std::initializer_list<value_type> il, size _type n_of_buckets = base_type::initial_bucket_number, const hasher& a_hash er = hasher(),
const key_equal& a_keyeq = key_equal(), const allocator_type& a = a llocator_type()) const key_equal& a_keyeq = key_equal(), const allocator_type& a = a llocator_type())
: base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a) : base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a)
{ {
this->insert(il.begin(),il.end()); this->insert(il.begin(),il.end());
} }
#endif //# __TBB_INITIALIZER_LISTS_PRESENT #endif //# __TBB_INITIALIZER_LISTS_PRESENT
concurrent_unordered_multiset(const concurrent_unordered_multiset& tabl #if __TBB_CPP11_RVALUE_REF_PRESENT && __TBB_CPP11_IMPLICIT_MOVE_MEMBERS_GEN
e) : base_type(table) ERATION_FOR_DERIVED_BROKEN
concurrent_unordered_multiset(const concurrent_unordered_multiset& table
)
: base_type(table)
{ {
} }
concurrent_unordered_multiset(const concurrent_unordered_multiset& tabl e, const Allocator& a) : base_type(table, a) concurrent_unordered_multiset& operator=(const concurrent_unordered_mult iset& table)
{ {
return static_cast<concurrent_unordered_multiset&>(base_type::opera tor=(table));
} }
concurrent_unordered_multiset& operator=(const concurrent_unordered_mul concurrent_unordered_multiset(concurrent_unordered_multiset&& table)
tiset& table) : base_type(std::move(table))
{ {
base_type::operator=(table);
return (*this);
} }
#if __TBB_INITIALIZER_LISTS_PRESENT concurrent_unordered_multiset& operator=(concurrent_unordered_multiset&&
//! assignment operator from initializer_list table)
concurrent_unordered_multiset& operator=(std::initializer_list<value_ty
pe> const& il)
{
base_type::operator=(il);
return (*this);
}
#endif //# __TBB_INITIALIZER_LISTS_PRESENT
// Modifiers
std::pair<iterator, bool> insert(const value_type& value)
{
return base_type::insert(value);
}
iterator insert(const_iterator where, const value_type& value)
{
return base_type::insert(where, value);
}
template<class Iterator>
void insert(Iterator first, Iterator last)
{
base_type::insert(first, last);
}
iterator unsafe_erase(const_iterator where)
{
return base_type::unsafe_erase(where);
}
size_type unsafe_erase(const key_type& key)
{
return base_type::unsafe_erase(key);
}
iterator unsafe_erase(const_iterator first, const_iterator last)
{
return base_type::unsafe_erase(first, last);
}
void swap(concurrent_unordered_multiset& table)
{ {
base_type::swap(table); return static_cast<concurrent_unordered_multiset&>(base_type::opera tor=(std::move(table)));
} }
#endif //__TBB_CPP11_IMPLICIT_MOVE_MEMBERS_GENERATION_FOR_DERIVED_BROKEN
// Observers concurrent_unordered_multiset(const concurrent_unordered_multiset& tabl
hasher hash_function() const e, const Allocator& a)
: base_type(table, a)
{ {
return my_hash_compare.my_hash_object;
} }
key_equal key_eq() const #if __TBB_CPP11_RVALUE_REF_PRESENT
concurrent_unordered_multiset(concurrent_unordered_multiset&& table, co
nst Allocator& a)
: base_type(std::move(table), a)
{ {
return my_hash_compare.my_key_compare_object;
} }
#endif //__TBB_CPP11_RVALUE_REF_PRESENT
}; };
} // namespace interface5 } // namespace interface5
using interface5::concurrent_unordered_set; using interface5::concurrent_unordered_set;
using interface5::concurrent_unordered_multiset; using interface5::concurrent_unordered_multiset;
} // namespace tbb } // namespace tbb
#endif// __TBB_concurrent_unordered_set_H #endif// __TBB_concurrent_unordered_set_H
 End of changes. 42 change blocks. 
141 lines changed or deleted 84 lines changed or added


 concurrent_vector.h   concurrent_vector.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_concurrent_vector_H #ifndef __TBB_concurrent_vector_H
#define __TBB_concurrent_vector_H #define __TBB_concurrent_vector_H
#include "tbb_stddef.h" #include "tbb_stddef.h"
#include "tbb_exception.h" #include "tbb_exception.h"
#include "atomic.h" #include "atomic.h"
#include "cache_aligned_allocator.h" #include "cache_aligned_allocator.h"
#include "blocked_range.h" #include "blocked_range.h"
skipping to change at line 69 skipping to change at line 61
#endif #endif
#include <limits> /* std::numeric_limits */ #include <limits> /* std::numeric_limits */
#if _MSC_VER==1500 && !__INTEL_COMPILER #if _MSC_VER==1500 && !__INTEL_COMPILER
#pragma warning( pop ) #pragma warning( pop )
#endif #endif
#if __TBB_INITIALIZER_LISTS_PRESENT #if __TBB_INITIALIZER_LISTS_PRESENT
#include <initializer_list> #include <initializer_list>
#endif #endif
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_Wp64) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
// Workaround for overzealous compiler warnings in /Wp64 mode // Workaround for overzealous compiler warnings in /Wp64 mode
#pragma warning (push) #pragma warning (push)
#if defined(_Wp64)
#pragma warning (disable: 4267) #pragma warning (disable: 4267)
#endif #endif
#pragma warning (disable: 4127) //warning C4127: conditional expression
is constant
#endif
namespace tbb { namespace tbb {
template<typename T, class A = cache_aligned_allocator<T> > template<typename T, class A = cache_aligned_allocator<T> >
class concurrent_vector; class concurrent_vector;
template<typename Container, typename Value> template<typename Container, typename Value>
class vector_iterator; class vector_iterator;
//! @cond INTERNAL //! @cond INTERNAL
namespace internal { namespace internal {
//! Bad allocation marker //! Bad allocation marker
static void *const vector_allocation_error_flag = reinterpret_cast<void *>(size_t(63)); static void *const vector_allocation_error_flag = reinterpret_cast<void *>(size_t(63));
//! Exception helper function
template<typename T>
void handle_unconstructed_elements(T* array, size_t n_of_elements){
std::memset(array, 0, n_of_elements * sizeof(T));
}
//! Base class of concurrent vector implementation. //! Base class of concurrent vector implementation.
/** @ingroup containers */ /** @ingroup containers */
class concurrent_vector_base_v3 { class concurrent_vector_base_v3 {
protected: protected:
// Basic types declarations // Basic types declarations
typedef size_t segment_index_t; typedef size_t segment_index_t;
typedef size_t size_type; typedef size_t size_type;
// Using enumerations due to Mac linking problems of static const v ariables // Using enumerations due to Mac linking problems of static const v ariables
enum { enum {
// Size constants // Size constants
default_initial_segments = 1, // 2 initial items default_initial_segments = 1, // 2 initial items
//! Number of slots for segment's pointers inside the class //! Number of slots for segment pointers inside the class
pointers_per_short_table = 3, // to fit into 8 words of entire structure pointers_per_short_table = 3, // to fit into 8 words of entire structure
pointers_per_long_table = sizeof(segment_index_t) * 8 // one se gment per bit pointers_per_long_table = sizeof(segment_index_t) * 8 // one se gment per bit
}; };
struct segment_not_used {}; struct segment_not_used {};
struct segment_allocated {}; struct segment_allocated {};
struct segment_allocation_failed {}; struct segment_allocation_failed {};
class segment_t; class segment_t;
class segment_value_t { class segment_value_t {
void* array; void* array;
private: private:
//TODO: More elegant way to grant access to selected functions _only_? //TODO: More elegant way to grant access to selected functions _only_?
friend class segment_t; friend class segment_t;
segment_value_t(void* an_array):array(an_array) {} explicit segment_value_t(void* an_array):array(an_array) {}
public: public:
friend bool operator==(segment_value_t const& lhs, segment_not_ used ) { return lhs.array == 0;} friend bool operator==(segment_value_t const& lhs, segment_not_ used ) { return lhs.array == 0;}
friend bool operator==(segment_value_t const& lhs, segment_allo cated) { return lhs.array > internal::vector_allocation_error_flag;} friend bool operator==(segment_value_t const& lhs, segment_allo cated) { return lhs.array > internal::vector_allocation_error_flag;}
friend bool operator==(segment_value_t const& lhs, segment_allo cation_failed) { return lhs.array == internal::vector_allocation_error_flag ;} friend bool operator==(segment_value_t const& lhs, segment_allo cation_failed) { return lhs.array == internal::vector_allocation_error_flag ;}
template<typename argument_type> template<typename argument_type>
friend bool operator!=(segment_value_t const& lhs, argument_typ e arg) { return ! (lhs == arg);} friend bool operator!=(segment_value_t const& lhs, argument_typ e arg) { return ! (lhs == arg);}
template<typename T> template<typename T>
T* pointer() const { return static_cast<T*>(const_cast<void*>( array)); } T* pointer() const { return static_cast<T*>(const_cast<void*>( array)); }
}; };
skipping to change at line 209 skipping to change at line 210
//Object that is in middle of construction (i.e. its constructo r is not yet finished) //Object that is in middle of construction (i.e. its constructo r is not yet finished)
//cannot be used concurrently until the construction is finishe d. //cannot be used concurrently until the construction is finishe d.
//Thus to flag other threads that construction is finished, som e synchronization with //Thus to flag other threads that construction is finished, som e synchronization with
//acquire-release semantic should be done by the (external) cod e that uses the vector. //acquire-release semantic should be done by the (external) cod e that uses the vector.
//So, no need to do the synchronization inside the vector. //So, no need to do the synchronization inside the vector.
my_early_size.store<relaxed>(0); my_early_size.store<relaxed>(0);
my_first_block.store<relaxed>(0); // here is not default_initia l_segments my_first_block.store<relaxed>(0); // here is not default_initia l_segments
my_segment.store<relaxed>(my_storage); my_segment.store<relaxed>(my_storage);
} }
__TBB_EXPORTED_METHOD ~concurrent_vector_base_v3(); __TBB_EXPORTED_METHOD ~concurrent_vector_base_v3();
//these helpers methods use the fact that segments are allocated so //these helpers methods use the fact that segments are allocated so
//that every segment size is a (increasing) power of 2. //that every segment size is a (increasing) power of 2.
//with one exception 0 segment has size of 2 as well segment 1; //with one exception 0 segment has size of 2 as well segment 1;
//e.g. size of segment with index of 3 is 2^3=8; //e.g. size of segment with index of 3 is 2^3=8;
static segment_index_t segment_index_of( size_type index ) { static segment_index_t segment_index_of( size_type index ) {
return segment_index_t( __TBB_Log2( index|1 ) ); return segment_index_t( __TBB_Log2( index|1 ) );
} }
skipping to change at line 476 skipping to change at line 478
} }
template<typename T, class A> template<typename T, class A>
class allocator_base { class allocator_base {
public: public:
typedef typename A::template typedef typename A::template
rebind<T>::other allocator_type; rebind<T>::other allocator_type;
allocator_type my_allocator; allocator_type my_allocator;
allocator_base(const allocator_type &a = allocator_type() ) : my_al locator(a) {} allocator_base(const allocator_type &a = allocator_type() ) : my_al locator(a) {}
}; };
} // namespace internal } // namespace internal
//! @endcond //! @endcond
//! Concurrent vector container //! Concurrent vector container
/** concurrent_vector is a container having the following main properties: /** concurrent_vector is a container having the following main properties:
- It provides random indexed access to its elements. The index of the f irst element is 0. - It provides random indexed access to its elements. The index of the f irst element is 0.
- It ensures safe concurrent growing its size (different threads can sa fely append new elements). - It ensures safe concurrent growing its size (different threads can sa fely append new elements).
- Adding new elements does not invalidate existing iterators and does n ot change indices of existing items. - Adding new elements does not invalidate existing iterators and does n ot change indices of existing items.
skipping to change at line 563 skipping to change at line 566
typedef I iterator; typedef I iterator;
typedef ptrdiff_t difference_type; typedef ptrdiff_t difference_type;
generic_range_type( I begin_, I end_, size_t grainsize_ = 1) : bloc ked_range<I>(begin_,end_,grainsize_) {} generic_range_type( I begin_, I end_, size_t grainsize_ = 1) : bloc ked_range<I>(begin_,end_,grainsize_) {}
template<typename U> template<typename U>
generic_range_type( const generic_range_type<U>& r) : blocked_range <I>(r.begin(),r.end(),r.grainsize()) {} generic_range_type( const generic_range_type<U>& r) : blocked_range <I>(r.begin(),r.end(),r.grainsize()) {}
generic_range_type( generic_range_type& r, split ) : blocked_range< I>(r,split()) {} generic_range_type( generic_range_type& r, split ) : blocked_range< I>(r,split()) {}
}; };
template<typename C, typename U> template<typename C, typename U>
friend class internal::vector_iterator; friend class internal::vector_iterator;
public: public:
//--------------------------------------------------------------------- --- //--------------------------------------------------------------------- ---
// STL compatible types // STL compatible types
//--------------------------------------------------------------------- --- //--------------------------------------------------------------------- ---
typedef internal::concurrent_vector_base_v3::size_type size_type; typedef internal::concurrent_vector_base_v3::size_type size_type;
typedef typename internal::allocator_base<T, A>::allocator_type allocat or_type; typedef typename internal::allocator_base<T, A>::allocator_type allocat or_type;
typedef T value_type; typedef T value_type;
typedef ptrdiff_t difference_type; typedef ptrdiff_t difference_type;
typedef T& reference; typedef T& reference;
skipping to change at line 640 skipping to change at line 644
vector_allocator_ptr = &internal_allocator; vector_allocator_ptr = &internal_allocator;
__TBB_TRY { __TBB_TRY {
internal_copy(vector, sizeof(T), &copy_array); internal_copy(vector, sizeof(T), &copy_array);
} __TBB_CATCH(...) { } __TBB_CATCH(...) {
segment_t *table = my_segment.load<relaxed>(); segment_t *table = my_segment.load<relaxed>();
internal_free_segments( table, internal_clear(&destroy_array), my_first_block.load<relaxed>()); internal_free_segments( table, internal_clear(&destroy_array), my_first_block.load<relaxed>());
__TBB_RETHROW(); __TBB_RETHROW();
} }
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT
//! Move constructor
//TODO add __TBB_NOEXCEPT(true) and static_assert(std::has_nothrow_move
_constructor<A>::value)
concurrent_vector( concurrent_vector&& source)
: internal::allocator_base<T, A>(std::move(source)), internal::conc
urrent_vector_base()
{
vector_allocator_ptr = &internal_allocator;
concurrent_vector_base_v3::internal_swap(source);
}
concurrent_vector( concurrent_vector&& source, const allocator_type& a)
: internal::allocator_base<T, A>(a), internal::concurrent_vector_ba
se()
{
vector_allocator_ptr = &internal_allocator;
//C++ standard requires instances of an allocator being compared fo
r equality,
//which means that memory allocated by one instance is possible to
deallocate with the other one.
if (a == source.my_allocator) {
concurrent_vector_base_v3::internal_swap(source);
} else {
__TBB_TRY {
internal_copy(source, sizeof(T), &move_array);
} __TBB_CATCH(...) {
segment_t *table = my_segment.load<relaxed>();
internal_free_segments( table, internal_clear(&destroy_arra
y), my_first_block.load<relaxed>());
__TBB_RETHROW();
}
}
}
#endif
//! Copying constructor for vector with different allocator type //! Copying constructor for vector with different allocator type
template<class M> template<class M>
concurrent_vector( const concurrent_vector<T, M>& vector, const allocat or_type& a = allocator_type() ) concurrent_vector( const concurrent_vector<T, M>& vector, const allocat or_type& a = allocator_type() )
: internal::allocator_base<T, A>(a), internal::concurrent_vector_ba se() : internal::allocator_base<T, A>(a), internal::concurrent_vector_ba se()
{ {
vector_allocator_ptr = &internal_allocator; vector_allocator_ptr = &internal_allocator;
__TBB_TRY { __TBB_TRY {
internal_copy(vector.internal_vector_base(), sizeof(T), &copy_a rray); internal_copy(vector.internal_vector_base(), sizeof(T), &copy_a rray);
} __TBB_CATCH(...) { } __TBB_CATCH(...) {
segment_t *table = my_segment.load<relaxed>(); segment_t *table = my_segment.load<relaxed>();
skipping to change at line 704 skipping to change at line 739
} }
} }
//! Assignment //! Assignment
concurrent_vector& operator=( const concurrent_vector& vector ) { concurrent_vector& operator=( const concurrent_vector& vector ) {
if( this != &vector ) if( this != &vector )
internal_assign(vector, sizeof(T), &destroy_array, &assign_arra y, &copy_array); internal_assign(vector, sizeof(T), &destroy_array, &assign_arra y, &copy_array);
return *this; return *this;
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT
//TODO: add __TBB_NOEXCEPT()
//! Move assignment
concurrent_vector& operator=( concurrent_vector&& other ) {
__TBB_ASSERT(this != &other, "Move assignment to itself is prohibit
ed ");
typedef typename tbb::internal::allocator_traits<A>::propagate_on_c
ontainer_move_assignment pocma_t;
if(pocma_t::value || this->my_allocator == other.my_allocator) {
concurrent_vector trash (std::move(*this));
internal_swap(other);
if (pocma_t::value) {
this->my_allocator = std::move(other.my_allocator);
}
} else {
internal_assign(other, sizeof(T), &destroy_array, &move_assign_
array, &move_array);
}
return *this;
}
#endif
//TODO: add an template assignment operator? (i.e. with different eleme nt type) //TODO: add an template assignment operator? (i.e. with different eleme nt type)
//! Assignment for vector with different allocator type //! Assignment for vector with different allocator type
template<class M> template<class M>
concurrent_vector& operator=( const concurrent_vector<T, M>& vector ) { concurrent_vector& operator=( const concurrent_vector<T, M>& vector ) {
if( static_cast<void*>( this ) != static_cast<const void*>( &vector ) ) if( static_cast<void*>( this ) != static_cast<const void*>( &vector ) )
internal_assign(vector.internal_vector_base(), internal_assign(vector.internal_vector_base(),
sizeof(T), &destroy_array, &assign_array, &copy_array); sizeof(T), &destroy_array, &assign_array, &copy_array);
return *this; return *this;
} }
#if __TBB_INITIALIZER_LISTS_PRESENT #if __TBB_INITIALIZER_LISTS_PRESENT
//! Assignment for initializer_list //! Assignment for initializer_list
concurrent_vector& operator=( const std::initializer_list<T> & init_lis t) { concurrent_vector& operator=( std::initializer_list<T> init_list ) {
internal_clear(&destroy_array); internal_clear(&destroy_array);
internal_assign_iterators(init_list.begin(), init_list.end()); internal_assign_iterators(init_list.begin(), init_list.end());
return *this; return *this;
} }
#endif //#if __TBB_INITIALIZER_LISTS_PRESENT #endif //#if __TBB_INITIALIZER_LISTS_PRESENT
//--------------------------------------------------------------------- --- //--------------------------------------------------------------------- ---
// Concurrent operations // Concurrent operations
//--------------------------------------------------------------------- --- //--------------------------------------------------------------------- ---
//TODO: consider adding overload of grow_by accepting initializer_list: grow_by(std::initializer_list<T>), as a analogy to std::vector::insert(in itializer_list)
//! Grow by "delta" elements. //! Grow by "delta" elements.
#if TBB_DEPRECATED
/** Returns old size. */
size_type grow_by( size_type delta ) {
return delta ? internal_grow_by( delta, sizeof(T), &initialize_arra
y, NULL ) : my_early_size.load();
}
#else
/** Returns iterator pointing to the first new element. */ /** Returns iterator pointing to the first new element. */
iterator grow_by( size_type delta ) { iterator grow_by( size_type delta ) {
return iterator(*this, delta ? internal_grow_by( delta, sizeof(T), &initialize_array, NULL ) : my_early_size.load()); return iterator(*this, delta ? internal_grow_by( delta, sizeof(T), &initialize_array, NULL ) : my_early_size.load());
} }
#endif
//! Grow by "delta" elements using copying constructor. //! Grow by "delta" elements using copying constructor.
#if TBB_DEPRECATED
/** Returns old size. */
size_type grow_by( size_type delta, const_reference t ) {
return delta ? internal_grow_by( delta, sizeof(T), &initialize_arra
y_by, static_cast<const void*>(&t) ) : my_early_size.load();
}
#else
/** Returns iterator pointing to the first new element. */ /** Returns iterator pointing to the first new element. */
iterator grow_by( size_type delta, const_reference t ) { iterator grow_by( size_type delta, const_reference t ) {
return iterator(*this, delta ? internal_grow_by( delta, sizeof(T), &initialize_array_by, static_cast<const void*>(&t) ) : my_early_size.load() ); return iterator(*this, delta ? internal_grow_by( delta, sizeof(T), &initialize_array_by, static_cast<const void*>(&t) ) : my_early_size.load() );
} }
/** Returns iterator pointing to the first new element. */ /** Returns iterator pointing to the first new element. */
template<typename I> template<typename I>
iterator grow_by( I first, I last ) { iterator grow_by( I first, I last ) {
typename std::iterator_traits<I>::difference_type typename std::iterator_traits<I>::difference_type delta = std::dist
delta = std::distance(first, last); ance(first, last);
__TBB_ASSERT( delta > 0, NULL); __TBB_ASSERT( delta >= 0, NULL);
return iterator(*this, internal_grow_by( delta, sizeof(T), &copy_r ange<I>, static_cast<const void*>(&first) )); return iterator(*this, delta ? internal_grow_by(delta, sizeof(T), & copy_range<I>, static_cast<const void*>(&first)) : my_early_size.load());
} }
#endif
#if __TBB_INITIALIZER_LISTS_PRESENT
/** Returns iterator pointing to the first new element. */
iterator grow_by( std::initializer_list<T> init_list ) {
return grow_by( init_list.begin(), init_list.end() );
}
#endif //#if __TBB_INITIALIZER_LISTS_PRESENT
//! Append minimal sequence of elements such that size()>=n. //! Append minimal sequence of elements such that size()>=n.
#if TBB_DEPRECATED
/** The new elements are default constructed. Blocks until all element
s in range [0..n) are allocated.
May return while other elements are being constructed by other thre
ads. */
void grow_to_at_least( size_type n ) {
if( n ) internal_grow_to_at_least_with_result( n, sizeof(T), &initi
alize_array, NULL );
};
#else
/** The new elements are default constructed. Blocks until all element s in range [0..n) are allocated. /** The new elements are default constructed. Blocks until all element s in range [0..n) are allocated.
May return while other elements are being constructed by other thre ads. May return while other elements are being constructed by other thre ads.
Returns iterator that points to beginning of appended sequence. Returns iterator that points to beginning of appended sequence.
If no elements were appended, returns iterator pointing to nth elem ent. */ If no elements were appended, returns iterator pointing to nth elem ent. */
iterator grow_to_at_least( size_type n ) { iterator grow_to_at_least( size_type n ) {
size_type m=0; size_type m=0;
if( n ) { if( n ) {
m = internal_grow_to_at_least_with_result( n, sizeof(T), &initi alize_array, NULL ); m = internal_grow_to_at_least_with_result( n, sizeof(T), &initi alize_array, NULL );
if( m>n ) m=n; if( m>n ) m=n;
} }
skipping to change at line 796 skipping to change at line 833
elements are initialized by copying of t instead of default constru ction. */ elements are initialized by copying of t instead of default constru ction. */
iterator grow_to_at_least( size_type n, const_reference t ) { iterator grow_to_at_least( size_type n, const_reference t ) {
size_type m=0; size_type m=0;
if( n ) { if( n ) {
m = internal_grow_to_at_least_with_result( n, sizeof(T), &initi alize_array_by, &t); m = internal_grow_to_at_least_with_result( n, sizeof(T), &initi alize_array_by, &t);
if( m>n ) m=n; if( m>n ) m=n;
} }
return iterator(*this, m); return iterator(*this, m);
}; };
#endif
//! Push item //! Push item
#if TBB_DEPRECATED
size_type push_back( const_reference item )
#else
/** Returns iterator pointing to the new element. */ /** Returns iterator pointing to the new element. */
iterator push_back( const_reference item ) iterator push_back( const_reference item )
#endif
{ {
size_type k; size_type k;
void *ptr = internal_push_back(sizeof(T),k); T* ptr = static_cast<T*>(internal_push_back(sizeof(T),k));
internal_loop_guide loop(1, ptr); element_construction_guard g(ptr);
loop.init(&item); new(ptr) T(item);
#if TBB_DEPRECATED g.dismiss();
return k;
#else
return iterator(*this, k, ptr); return iterator(*this, k, ptr);
#endif
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT
//! Push item, move-aware
/** Returns iterator pointing to the new element. */
iterator push_back( T&& item )
{
size_type k;
T* ptr = static_cast<T*>(internal_push_back(sizeof(T),k));
element_construction_guard g(ptr);
new(ptr) T(std::move(item));
g.dismiss();
return iterator(*this, k, ptr);
}
#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
//! Push item, create item "in place" with provided arguments
/** Returns iterator pointing to the new element. */
template<typename... Args>
iterator emplace_back( Args&&... args)
{
size_type k;
T* ptr = static_cast<T*>(internal_push_back(sizeof(T),k));
element_construction_guard g(ptr);
new(ptr) T( std::forward<Args>(args)...);
g.dismiss();
return iterator(*this, k, ptr);
}
#endif //__TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
#endif //__TBB_CPP11_RVALUE_REF_PRESENT
//! Get reference to element at given index. //! Get reference to element at given index.
/** This method is thread-safe for concurrent reads, and also while gro wing the vector, /** This method is thread-safe for concurrent reads, and also while gro wing the vector,
as long as the calling thread has checked that index&lt;size(). */ as long as the calling thread has checked that index < size(). */
reference operator[]( size_type index ) { reference operator[]( size_type index ) {
return internal_subscript(index); return internal_subscript(index);
} }
//! Get const reference to element at given index. //! Get const reference to element at given index.
const_reference operator[]( size_type index ) const { const_reference operator[]( size_type index ) const {
return internal_subscript(index); return internal_subscript(index);
} }
//! Get reference to element at given index. Throws exceptions on error s. //! Get reference to element at given index. Throws exceptions on error s.
skipping to change at line 882 skipping to change at line 937
//! Resize the vector. Not thread-safe. //! Resize the vector. Not thread-safe.
void resize( size_type n ) { void resize( size_type n ) {
internal_resize( n, sizeof(T), max_size(), NULL, &destroy_array, &i nitialize_array ); internal_resize( n, sizeof(T), max_size(), NULL, &destroy_array, &i nitialize_array );
} }
//! Resize the vector, copy t for new elements. Not thread-safe. //! Resize the vector, copy t for new elements. Not thread-safe.
void resize( size_type n, const_reference t ) { void resize( size_type n, const_reference t ) {
internal_resize( n, sizeof(T), max_size(), static_cast<const void*> (&t), &destroy_array, &initialize_array_by ); internal_resize( n, sizeof(T), max_size(), static_cast<const void*> (&t), &destroy_array, &initialize_array_by );
} }
#if TBB_DEPRECATED
//! An alias for shrink_to_fit()
void compact() {shrink_to_fit();}
#endif /* TBB_DEPRECATED */
//! Optimize memory usage and fragmentation. //! Optimize memory usage and fragmentation.
void shrink_to_fit(); void shrink_to_fit();
//! Upper bound on argument to reserve. //! Upper bound on argument to reserve.
size_type max_size() const {return (~size_type(0))/sizeof(T);} size_type max_size() const {return (~size_type(0))/sizeof(T);}
//--------------------------------------------------------------------- --- //--------------------------------------------------------------------- ---
// STL support // STL support
//--------------------------------------------------------------------- --- //--------------------------------------------------------------------- ---
skipping to change at line 1027 skipping to change at line 1077
} }
//! assign by iterators //! assign by iterators
template<class I> template<class I>
void internal_assign_iterators(I first, I last); void internal_assign_iterators(I first, I last);
//these functions are marked __TBB_EXPORTED_FUNC as they are called fro m within the library //these functions are marked __TBB_EXPORTED_FUNC as they are called fro m within the library
//! Construct n instances of T, starting at "begin". //! Construct n instances of T, starting at "begin".
static void __TBB_EXPORTED_FUNC initialize_array( void* begin, const vo id*, size_type n ); static void __TBB_EXPORTED_FUNC initialize_array( void* begin, const vo id*, size_type n );
//! Construct n instances of T, starting at "begin". //! Copy-construct n instances of T, starting at "begin".
static void __TBB_EXPORTED_FUNC initialize_array_by( void* begin, const void* src, size_type n ); static void __TBB_EXPORTED_FUNC initialize_array_by( void* begin, const void* src, size_type n );
//! Construct n instances of T, starting at "begin". //! Copy-construct n instances of T by copying single element pointed t o by src, starting at "dst".
static void __TBB_EXPORTED_FUNC copy_array( void* dst, const void* src, size_type n ); static void __TBB_EXPORTED_FUNC copy_array( void* dst, const void* src, size_type n );
//! Construct n instances of T, starting at "begin". #if __TBB_CPP11_RVALUE_REF_PRESENT
//! Move-construct n instances of T, starting at "dst" by copying accor
ding element of src array.
static void __TBB_EXPORTED_FUNC move_array( void* dst, const void* src,
size_type n );
//! Move-assign (using operator=) n instances of T, starting at "dst" b
y assigning according element of src array.
static void __TBB_EXPORTED_FUNC move_assign_array( void* dst, const voi
d* src, size_type n );
#endif
//! Copy-construct n instances of T, starting at "dst" by iterator rang
e of [p_type_erased_iterator, p_type_erased_iterator+n).
template<typename Iterator> template<typename Iterator>
static void __TBB_EXPORTED_FUNC copy_range( void* dst, const void* p_ty pe_erased_iterator, size_type n ); static void __TBB_EXPORTED_FUNC copy_range( void* dst, const void* p_ty pe_erased_iterator, size_type n );
//! Assign n instances of T, starting at "begin". //! Assign (using operator=) n instances of T, starting at "dst" by ass igning according element of src array.
static void __TBB_EXPORTED_FUNC assign_array( void* dst, const void* sr c, size_type n ); static void __TBB_EXPORTED_FUNC assign_array( void* dst, const void* sr c, size_type n );
//! Destroy n instances of T, starting at "begin". //! Destroy n instances of T, starting at "begin".
static void __TBB_EXPORTED_FUNC destroy_array( void* begin, size_type n ); static void __TBB_EXPORTED_FUNC destroy_array( void* begin, size_type n );
//! Exception-aware helper class for filling a segment by exception-dan ger operators of user class //! Exception-aware helper class for filling a segment by exception-dan ger operators of user class
class internal_loop_guide : internal::no_copy { class internal_loop_guide : internal::no_copy {
public: public:
const pointer array; const pointer array;
const size_type n; const size_type n;
size_type i; size_type i;
static const T* as_const_pointer(const void *ptr) { return static_c
ast<const T *>(ptr); }
static T* as_pointer(const void *src) { return static_cast<T*>(cons
t_cast<void *>(src)); }
internal_loop_guide(size_type ntrials, void *ptr) internal_loop_guide(size_type ntrials, void *ptr)
: array(static_cast<pointer>(ptr)), n(ntrials), i(0) {} : array(as_pointer(ptr)), n(ntrials), i(0) {}
void init() { for(; i < n; ++i) new( &array[i] ) T(); } void init() { for(; i < n; ++i) new( &array[i] ) T(); }
void init(const void *src) { for(; i < n; ++i) new( &array[i] ) T(* void init(const void *src) { for(; i < n; ++i) new( &array[i] ) T(*
static_cast<const T*>(src)); } as_const_pointer(src)); }
void copy(const void *src) { for(; i < n; ++i) new( &array[i] ) T(s void copy(const void *src) { for(; i < n; ++i) new( &array[i] ) T(a
tatic_cast<const T*>(src)[i]); } s_const_pointer(src)[i]); }
void assign(const void *src) { for(; i < n; ++i) array[i] = static_ void assign(const void *src) { for(; i < n; ++i) array[i] = as_cons
cast<const T*>(src)[i]; } t_pointer(src)[i]; }
#if __TBB_CPP11_RVALUE_REF_PRESENT
void move_assign(const void *src) { for(; i < n; ++i) array[i
] = std::move(as_pointer(src)[i]); }
void move_construct(const void *src) { for(; i < n; ++i) new( &a
rray[i] ) T( std::move(as_pointer(src)[i]) ); }
#endif
//TODO: rename to construct_range //TODO: rename to construct_range
template<class I> void iterate(I &src) { for(; i < n; ++i, ++src) n ew( &array[i] ) T( *src ); } template<class I> void iterate(I &src) { for(; i < n; ++i, ++src) n ew( &array[i] ) T( *src ); }
~internal_loop_guide() { ~internal_loop_guide() {
if(i < n) // if exception raised, do zeroing on the rest of ite if(i < n) {// if an exception was raised, fill the rest of item
ms s with zeros
std::memset(array+i, 0, (n-i)*sizeof(value_type)); internal::handle_unconstructed_elements(array+i, n-i);
}
}
};
class element_construction_guard : internal::no_copy{
pointer element;
public:
element_construction_guard(pointer an_element) : element (an_elemen
t){}
void dismiss(){ element = NULL; }
~element_construction_guard(){
if (element){
internal::handle_unconstructed_elements(element, 1);
}
} }
}; };
}; };
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#pragma warning (push) #pragma warning (push)
#pragma warning (disable: 4701) // potentially uninitialized local variable "old" #pragma warning (disable: 4701) // potentially uninitialized local variable "old"
#endif #endif
template<typename T, class A> template<typename T, class A>
void concurrent_vector<T, A>::shrink_to_fit() { void concurrent_vector<T, A>::shrink_to_fit() {
skipping to change at line 1146 skipping to change at line 1223
} }
template<typename T, class A> template<class I> template<typename T, class A> template<class I>
void concurrent_vector<T, A>::internal_assign_iterators(I first, I last) { void concurrent_vector<T, A>::internal_assign_iterators(I first, I last) {
__TBB_ASSERT(my_early_size == 0, NULL); __TBB_ASSERT(my_early_size == 0, NULL);
size_type n = std::distance(first, last); size_type n = std::distance(first, last);
if( !n ) return; if( !n ) return;
internal_reserve(n, sizeof(T), max_size()); internal_reserve(n, sizeof(T), max_size());
my_early_size = n; my_early_size = n;
segment_index_t k = 0; segment_index_t k = 0;
//TODO: unify segment iteration code with concurrent_base_v3::helper
size_type sz = segment_size( my_first_block ); size_type sz = segment_size( my_first_block );
while( sz < n ) { while( sz < n ) {
internal_loop_guide loop(sz, my_segment[k].template load<relaxed>() .template pointer<void>()); internal_loop_guide loop(sz, my_segment[k].template load<relaxed>() .template pointer<void>());
loop.iterate(first); loop.iterate(first);
n -= sz; n -= sz;
if( !k ) k = my_first_block; if( !k ) k = my_first_block;
else { ++k; sz <<= 1; } else { ++k; sz <<= 1; }
} }
internal_loop_guide loop(n, my_segment[k].template load<relaxed>().temp late pointer<void>()); internal_loop_guide loop(n, my_segment[k].template load<relaxed>().temp late pointer<void>());
loop.iterate(first); loop.iterate(first);
skipping to change at line 1173 skipping to change at line 1251
template<typename T, class A> template<typename T, class A>
void concurrent_vector<T, A>::initialize_array_by( void* begin, const void *src, size_type n ) { void concurrent_vector<T, A>::initialize_array_by( void* begin, const void *src, size_type n ) {
internal_loop_guide loop(n, begin); loop.init(src); internal_loop_guide loop(n, begin); loop.init(src);
} }
template<typename T, class A> template<typename T, class A>
void concurrent_vector<T, A>::copy_array( void* dst, const void* src, size_ type n ) { void concurrent_vector<T, A>::copy_array( void* dst, const void* src, size_ type n ) {
internal_loop_guide loop(n, dst); loop.copy(src); internal_loop_guide loop(n, dst); loop.copy(src);
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT
template<typename T, class A>
void concurrent_vector<T, A>::move_array( void* dst, const void* src, size_
type n ) {
internal_loop_guide loop(n, dst); loop.move_construct(src);
}
template<typename T, class A>
void concurrent_vector<T, A>::move_assign_array( void* dst, const void* src
, size_type n ) {
internal_loop_guide loop(n, dst); loop.move_assign(src);
}
#endif
template<typename T, class A> template<typename T, class A>
template<typename I> template<typename I>
void concurrent_vector<T, A>::copy_range( void* dst, const void* p_type_era sed_iterator, size_type n ){ void concurrent_vector<T, A>::copy_range( void* dst, const void* p_type_era sed_iterator, size_type n ){
I & iterator ((*const_cast<I*>(static_cast<const I*>(p_type_erased_iter ator)))); I & iterator ((*const_cast<I*>(static_cast<const I*>(p_type_erased_iter ator))));
internal_loop_guide loop(n, dst); loop.iterate(iterator); internal_loop_guide loop(n, dst); loop.iterate(iterator);
} }
template<typename T, class A> template<typename T, class A>
void concurrent_vector<T, A>::assign_array( void* dst, const void* src, siz e_type n ) { void concurrent_vector<T, A>::assign_array( void* dst, const void* src, siz e_type n ) {
internal_loop_guide loop(n, dst); loop.assign(src); internal_loop_guide loop(n, dst); loop.assign(src);
skipping to change at line 1203 skipping to change at line 1293
for( size_type j=n; j>0; --j ) for( size_type j=n; j>0; --j )
array[j-1].~T(); // destructors are supposed to not throw any excep tions array[j-1].~T(); // destructors are supposed to not throw any excep tions
} }
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#pragma warning (pop) #pragma warning (pop)
#endif // warning 4189 is back #endif // warning 4189 is back
// concurrent_vector's template functions // concurrent_vector's template functions
template<typename T, class A1, class A2> template<typename T, class A1, class A2>
inline bool operator==(const concurrent_vector<T, A1> &a, const concurrent_ vector<T, A2> &b) { inline bool operator==(const concurrent_vector<T, A1> &a, const concurrent_ vector<T, A2> &b) {
//TODO: call size() only once per vector (in operator==)
// Simply: return a.size() == b.size() && std::equal(a.begin(), a.en d(), b.begin()); // Simply: return a.size() == b.size() && std::equal(a.begin(), a.en d(), b.begin());
if(a.size() != b.size()) return false; if(a.size() != b.size()) return false;
typename concurrent_vector<T, A1>::const_iterator i(a.begin()); typename concurrent_vector<T, A1>::const_iterator i(a.begin());
typename concurrent_vector<T, A2>::const_iterator j(b.begin()); typename concurrent_vector<T, A2>::const_iterator j(b.begin());
for(; i != a.end(); ++i, ++j) for(; i != a.end(); ++i, ++j)
if( !(*i == *j) ) return false; if( !(*i == *j) ) return false;
return true; return true;
} }
template<typename T, class A1, class A2> template<typename T, class A1, class A2>
skipping to change at line 1238 skipping to change at line 1329
template<typename T, class A1, class A2> template<typename T, class A1, class A2>
inline bool operator>=(const concurrent_vector<T, A1> &a, const concurrent_ vector<T, A2> &b) inline bool operator>=(const concurrent_vector<T, A1> &a, const concurrent_ vector<T, A2> &b)
{ return !(a < b); } { return !(a < b); }
template<typename T, class A> template<typename T, class A>
inline void swap(concurrent_vector<T, A> &a, concurrent_vector<T, A> &b) inline void swap(concurrent_vector<T, A> &a, concurrent_vector<T, A> &b)
{ a.swap( b ); } { a.swap( b ); }
} // namespace tbb } // namespace tbb
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_Wp64) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#pragma warning (pop) #pragma warning (pop)
#endif // warning 4267 is back #endif // warning 4267,4127 are back
#endif /* __TBB_concurrent_vector_H */ #endif /* __TBB_concurrent_vector_H */
 End of changes. 42 change blocks. 
98 lines changed or deleted 216 lines changed or added


 condition_variable   condition_variable 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_condition_variable_H #ifndef __TBB_condition_variable_H
#define __TBB_condition_variable_H #define __TBB_condition_variable_H
#if _WIN32||_WIN64 #if _WIN32||_WIN64
#include "../machine/windows_api.h" #include "../machine/windows_api.h"
namespace tbb { namespace tbb {
namespace interface5 { namespace interface5 {
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 critical_section.h   critical_section.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef _TBB_CRITICAL_SECTION_H_ #ifndef _TBB_CRITICAL_SECTION_H_
#define _TBB_CRITICAL_SECTION_H_ #define _TBB_CRITICAL_SECTION_H_
#if _WIN32||_WIN64 #if _WIN32||_WIN64
#include "machine/windows_api.h" #include "machine/windows_api.h"
#else #else
#include <pthread.h> #include <pthread.h>
#include <errno.h> #include <errno.h>
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 enumerable_thread_specific.h   enumerable_thread_specific.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_enumerable_thread_specific_H #ifndef __TBB_enumerable_thread_specific_H
#define __TBB_enumerable_thread_specific_H #define __TBB_enumerable_thread_specific_H
#include "concurrent_vector.h" #include "concurrent_vector.h"
#include "tbb_thread.h" #include "tbb_thread.h"
#include "tbb_allocator.h" #include "tbb_allocator.h"
#include "tbb_profiling.h" #include "tbb_profiling.h"
#include "cache_aligned_allocator.h" #include "cache_aligned_allocator.h"
skipping to change at line 733 skipping to change at line 725
}; };
typedef typename Allocator::template rebind< padded_element >::othe r padded_allocator_type; typedef typename Allocator::template rebind< padded_element >::othe r padded_allocator_type;
typedef tbb::concurrent_vector< padded_element, padded_allocator_ty pe > internal_collection_type; typedef tbb::concurrent_vector< padded_element, padded_allocator_ty pe > internal_collection_type;
internal::callback_base<T> *my_construct_callback; internal::callback_base<T> *my_construct_callback;
internal_collection_type my_locals; internal_collection_type my_locals;
/*override*/ void* create_local() { /*override*/ void* create_local() {
#if TBB_DEPRECATED
void* lref = &my_locals[my_locals.grow_by(1)];
#else
void* lref = &*my_locals.grow_by(1); void* lref = &*my_locals.grow_by(1);
#endif
my_construct_callback->construct(lref); my_construct_callback->construct(lref);
return lref; return lref;
} }
void unconstruct_locals() { void unconstruct_locals() {
for(typename internal_collection_type::iterator cvi = my_locals .begin(); cvi != my_locals.end(); ++cvi) { for(typename internal_collection_type::iterator cvi = my_locals .begin(); cvi != my_locals.end(); ++cvi) {
cvi->unconstruct(); cvi->unconstruct();
} }
} }
skipping to change at line 933 skipping to change at line 921
typedef internal::ets_base<ets_no_key> base; typedef internal::ets_base<ets_no_key> base;
__TBB_ASSERT(my_locals.size()==0,NULL); __TBB_ASSERT(my_locals.size()==0,NULL);
this->table_reserve_for_copy( other ); this->table_reserve_for_copy( other );
for( base::array* r=other.my_root; r; r=r->next ) { for( base::array* r=other.my_root; r; r=r->next ) {
for( size_t i=0; i<r->size(); ++i ) { for( size_t i=0; i<r->size(); ++i ) {
base::slot& s1 = r->at(i); base::slot& s1 = r->at(i);
if( !s1.empty() ) { if( !s1.empty() ) {
base::slot& s2 = this->table_find(s1.key); base::slot& s2 = this->table_find(s1.key);
if( s2.empty() ) { if( s2.empty() ) {
#if TBB_DEPRECATED
void* lref = &my_locals[my_locals.grow_by(1)];
#else
void* lref = &*my_locals.grow_by(1); void* lref = &*my_locals.grow_by(1);
#endif
s2.ptr = new(lref) T(*(U*)s1.ptr); s2.ptr = new(lref) T(*(U*)s1.ptr);
s2.key = s1.key; s2.key = s1.key;
} else { } else {
// Skip the duplicate // Skip the duplicate
} }
} }
} }
} }
} }
 End of changes. 5 change blocks. 
36 lines changed or deleted 29 lines changed or added


 flow_graph.h   flow_graph.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_flow_graph_H #ifndef __TBB_flow_graph_H
#define __TBB_flow_graph_H #define __TBB_flow_graph_H
#include "tbb_stddef.h" #include "tbb_stddef.h"
#include "atomic.h" #include "atomic.h"
#include "spin_mutex.h" #include "spin_mutex.h"
#include "null_mutex.h" #include "null_mutex.h"
#include "spin_rw_mutex.h" #include "spin_rw_mutex.h"
#include "null_rw_mutex.h" #include "null_rw_mutex.h"
#include "task.h" #include "task.h"
#include "concurrent_vector.h" #include "cache_aligned_allocator.h"
#include "tbb_exception.h"
#include "internal/_aggregator_impl.h" #include "internal/_aggregator_impl.h"
#include "tbb_profiling.h" #include "tbb_profiling.h"
#if TBB_DEPRECATED_FLOW_ENQUEUE #if TBB_DEPRECATED_FLOW_ENQUEUE
#define FLOW_SPAWN(a) tbb::task::enqueue((a)) #define FLOW_SPAWN(a) tbb::task::enqueue((a))
#else #else
#define FLOW_SPAWN(a) tbb::task::spawn((a)) #define FLOW_SPAWN(a) tbb::task::spawn((a))
#endif #endif
// use the VC10 or gcc version of tuple if it is available. // use the VC10 or gcc version of tuple if it is available.
skipping to change at line 127 skipping to change at line 120
virtual bool try_get( T & ) { return false; } virtual bool try_get( T & ) { return false; }
//! Reserves an item in the sender //! Reserves an item in the sender
virtual bool try_reserve( T & ) { return false; } virtual bool try_reserve( T & ) { return false; }
//! Releases the reserved item //! Releases the reserved item
virtual bool try_release( ) { return false; } virtual bool try_release( ) { return false; }
//! Consumes the reserved item //! Consumes the reserved item
virtual bool try_consume( ) { return false; } virtual bool try_consume( ) { return false; }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
//! interface to record edges for traversal & deletion
virtual void internal_add_built_successor( successor_type & ) = 0
;
virtual void internal_delete_built_successor( successor_type & ) = 0
;
virtual void copy_successors( std::vector<successor_type *> &) = 0
;
virtual size_t successor_count() = 0
;
#endif
}; };
template< typename T > class limiter_node; // needed for resetting decreme nter template< typename T > class limiter_node; // needed for resetting decreme nter
template< typename R, typename B > class run_and_put_task; template< typename R, typename B > class run_and_put_task;
static tbb::task * const SUCCESSFULLY_ENQUEUED = (task *)-1; static tbb::task * const SUCCESSFULLY_ENQUEUED = (task *)-1;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
// flags to modify the behavior of the graph reset(). Can be combined.
enum reset_flags {
rf_reset_protocol = 0,
rf_reset_bodies = 1<<0, // delete the current node body, reset to
a copy of the initial node body.
rf_extract = 1<<1 // delete edges (extract() for single node
, reset() for graph.)
};
#define __TBB_PFG_RESET_ARG(exp) exp
#define __TBB_COMMA ,
#else
#define __TBB_PFG_RESET_ARG(exp) /* nothing */
#define __TBB_COMMA /* nothing */
#endif
// enqueue left task if necessary. Returns the non-enqueued task if there is one. // enqueue left task if necessary. Returns the non-enqueued task if there is one.
static inline tbb::task *combine_tasks( tbb::task * left, tbb::task * right ) { static inline tbb::task *combine_tasks( tbb::task * left, tbb::task * right ) {
// if no RHS task, don't change left. // if no RHS task, don't change left.
if(right == NULL) return left; if(right == NULL) return left;
// right != NULL // right != NULL
if(left == NULL) return right; if(left == NULL) return right;
if(left == SUCCESSFULLY_ENQUEUED) return right; if(left == SUCCESSFULLY_ENQUEUED) return right;
// left contains a task // left contains a task
if(right != SUCCESSFULLY_ENQUEUED) { if(right != SUCCESSFULLY_ENQUEUED) {
// both are valid tasks // both are valid tasks
skipping to change at line 165 skipping to change at line 181
typedef T input_type; typedef T input_type;
//! The predecessor type for this node //! The predecessor type for this node
typedef sender<T> predecessor_type; typedef sender<T> predecessor_type;
//! Destructor //! Destructor
virtual ~receiver() {} virtual ~receiver() {}
//! Put an item to the receiver //! Put an item to the receiver
bool try_put( const T& t ) { bool try_put( const T& t ) {
task *res = try_put_task(t); task *res = try_put_task(t);
if(!res) return false; if(!res) return false;
if (res != SUCCESSFULLY_ENQUEUED) FLOW_SPAWN(*res); if (res != SUCCESSFULLY_ENQUEUED) FLOW_SPAWN(*res);
return true; return true;
} }
//! put item to successor; return task to run the successor if possible . //! put item to successor; return task to run the successor if possible .
protected: protected:
template< typename R, typename B > friend class run_and_put_task; template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_cache ; template<typename X, typename Y> friend class internal::broadcast_cache ;
template<typename X, typename Y> friend class internal::round_robin_cac he; template<typename X, typename Y> friend class internal::round_robin_cac he;
virtual task *try_put_task(const T& t) = 0; virtual task *try_put_task(const T& t) = 0;
public: public:
//! Add a predecessor to the node //! Add a predecessor to the node
virtual bool register_predecessor( predecessor_type & ) { return false; } virtual bool register_predecessor( predecessor_type & ) { return false; }
//! Remove a predecessor from the node //! Remove a predecessor from the node
virtual bool remove_predecessor( predecessor_type & ) { return false; } virtual bool remove_predecessor( predecessor_type & ) { return false; }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
virtual void internal_add_built_predecessor( predecessor_type & )
= 0;
virtual void internal_delete_built_predecessor( predecessor_type & )
= 0;
virtual void copy_predecessors( std::vector<predecessor_type *> & )
= 0;
virtual size_t predecessor_count()
= 0;
#endif
protected: protected:
//! put receiver back in initial state //! put receiver back in initial state
template<typename U> friend class limiter_node; template<typename U> friend class limiter_node;
virtual void reset_receiver() = 0; virtual void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags f = rf_rese t_protocol ) ) = 0;
template<typename TT, typename M> template<typename TT, typename M>
friend class internal::successor_cache; friend class internal::successor_cache;
virtual bool is_continue_receiver() { return false; } virtual bool is_continue_receiver() { return false; }
}; };
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
//* holder of edges both for caches and for those nodes which do not have p
redecessor caches.
// C == receiver< ... > or sender< ... >, depending.
template<typename C>
class edge_container {
public:
typedef std::vector<C *> edge_vector;
void add_edge( C &s) {
built_edges.push_back( &s );
}
void delete_edge( C &s) {
for ( typename edge_vector::iterator i = built_edges.begin(); i !=
built_edges.end(); ++i ) {
if ( *i == &s ) {
(void)built_edges.erase(i);
return; // only remove one predecessor per request
}
}
}
void copy_edges( edge_vector &v) {
v = built_edges;
}
size_t edge_count() {
return (size_t)(built_edges.size());
}
void clear() {
built_edges.clear();
}
template< typename S > void sender_extract( S &s );
template< typename R > void receiver_extract( R &r );
private:
edge_vector built_edges;
};
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
//! Base class for receivers of completion messages //! Base class for receivers of completion messages
/** These receivers automatically reset, but cannot be explicitly waited on */ /** These receivers automatically reset, but cannot be explicitly waited on */
class continue_receiver : public receiver< continue_msg > { class continue_receiver : public receiver< continue_msg > {
public: public:
//! The input type //! The input type
typedef continue_msg input_type; typedef continue_msg input_type;
//! The predecessor type for this node //! The predecessor type for this node
typedef sender< continue_msg > predecessor_type; typedef sender< continue_msg > predecessor_type;
skipping to change at line 238 skipping to change at line 303
//! Decrements the trigger threshold //! Decrements the trigger threshold
/** Does not check to see if the removal of the predecessor now makes t he current count /** Does not check to see if the removal of the predecessor now makes t he current count
exceed the new threshold. So removing a predecessor while the grap h is active can cause exceed the new threshold. So removing a predecessor while the grap h is active can cause
unexpected results. */ unexpected results. */
/* override */ bool remove_predecessor( predecessor_type & ) { /* override */ bool remove_predecessor( predecessor_type & ) {
spin_mutex::scoped_lock l(my_mutex); spin_mutex::scoped_lock l(my_mutex);
--my_predecessor_count; --my_predecessor_count;
return true; return true;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<predecessor_type *> predecessor_vector_type;
/*override*/ void internal_add_built_predecessor( predecessor_type &s)
{
spin_mutex::scoped_lock l(my_mutex);
my_built_predecessors.add_edge( s );
}
/*override*/ void internal_delete_built_predecessor( predecessor_type &
s) {
spin_mutex::scoped_lock l(my_mutex);
my_built_predecessors.delete_edge(s);
}
/*override*/ void copy_predecessors( predecessor_vector_type &v) {
spin_mutex::scoped_lock l(my_mutex);
my_built_predecessors.copy_edges(v);
}
/*override*/ size_t predecessor_count() {
spin_mutex::scoped_lock l(my_mutex);
return my_built_predecessors.edge_count();
}
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
protected: protected:
template< typename R, typename B > friend class run_and_put_task; template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_cache ; template<typename X, typename Y> friend class internal::broadcast_cache ;
template<typename X, typename Y> friend class internal::round_robin_cac he; template<typename X, typename Y> friend class internal::round_robin_cac he;
// execute body is supposed to be too small to create a task for. // execute body is supposed to be too small to create a task for.
/* override */ task *try_put_task( const input_type & ) { /* override */ task *try_put_task( const input_type & ) {
{ {
spin_mutex::scoped_lock l(my_mutex); spin_mutex::scoped_lock l(my_mutex);
if ( ++my_current_count < my_predecessor_count ) if ( ++my_current_count < my_predecessor_count )
return SUCCESSFULLY_ENQUEUED; return SUCCESSFULLY_ENQUEUED;
else else
my_current_count = 0; my_current_count = 0;
} }
task * res = execute(); task * res = execute();
if(!res) return SUCCESSFULLY_ENQUEUED; if(!res) return SUCCESSFULLY_ENQUEUED;
return res; return res;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
edge_container<predecessor_type> my_built_predecessors;
#endif
spin_mutex my_mutex; spin_mutex my_mutex;
int my_predecessor_count; int my_predecessor_count;
int my_current_count; int my_current_count;
int my_initial_predecessor_count; int my_initial_predecessor_count;
// the friend declaration in the base class did not eliminate the "prot ected class" // the friend declaration in the base class did not eliminate the "prot ected class"
// error in gcc 4.1.2 // error in gcc 4.1.2
template<typename U> friend class limiter_node; template<typename U> friend class limiter_node;
/*override*/void reset_receiver() { /*override*/void reset_receiver( __TBB_PFG_RESET_ARG(reset_flags f) )
{
my_current_count = 0; my_current_count = 0;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
if(f & rf_extract) {
my_built_predecessors.receiver_extract(*this);
my_predecessor_count = my_initial_predecessor_count;
}
#endif
} }
//! Does whatever should happen when the threshold is reached //! Does whatever should happen when the threshold is reached
/** This should be very fast or else spawn a task. This is /** This should be very fast or else spawn a task. This is
called while the sender is blocked in the try_put(). */ called while the sender is blocked in the try_put(). */
virtual task * execute() = 0; virtual task * execute() = 0;
template<typename TT, typename M> template<typename TT, typename M>
friend class internal::successor_cache; friend class internal::successor_cache;
/*override*/ bool is_continue_receiver() { return true; } /*override*/ bool is_continue_receiver() { return true; }
}; };
} // interface7 } // interface7
} // flow } // flow
} // tbb } // tbb
#include "internal/_flow_graph_trace_impl.h" #include "internal/_flow_graph_trace_impl.h"
namespace tbb { namespace tbb {
namespace flow { namespace flow {
namespace interface7 { namespace interface7 {
#include "internal/_flow_graph_types_impl.h"
#include "internal/_flow_graph_impl.h" #include "internal/_flow_graph_impl.h"
using namespace internal::graph_policy_namespace; using namespace internal::graph_policy_namespace;
class graph; class graph;
class graph_node; class graph_node;
template <typename GraphContainerType, typename GraphNodeType> template <typename GraphContainerType, typename GraphNodeType>
class graph_iterator { class graph_iterator {
friend class graph; friend class graph;
friend class graph_node; friend class graph_node;
skipping to change at line 400 skipping to change at line 500
//! Constructs a graph with isolated task_group_context //! Constructs a graph with isolated task_group_context
explicit graph() : my_nodes(NULL), my_nodes_last(NULL) explicit graph() : my_nodes(NULL), my_nodes_last(NULL)
{ {
own_context = true; own_context = true;
cancelled = false; cancelled = false;
caught_exception = false; caught_exception = false;
my_context = new task_group_context(); my_context = new task_group_context();
my_root_task = ( new ( task::allocate_root(*my_context) ) empty_tas k ); my_root_task = ( new ( task::allocate_root(*my_context) ) empty_tas k );
my_root_task->set_ref_count(1); my_root_task->set_ref_count(1);
tbb::internal::fgt_graph( this ); tbb::internal::fgt_graph( this );
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
my_is_active = true;
#endif
} }
//! Constructs a graph with use_this_context as context //! Constructs a graph with use_this_context as context
explicit graph(task_group_context& use_this_context) : explicit graph(task_group_context& use_this_context) :
my_context(&use_this_context), my_nodes(NULL), my_nodes_last(NULL) my_context(&use_this_context), my_nodes(NULL), my_nodes_last(NULL)
{ {
own_context = false; own_context = false;
my_root_task = ( new ( task::allocate_root(*my_context) ) empty_tas k ); my_root_task = ( new ( task::allocate_root(*my_context) ) empty_tas k );
my_root_task->set_ref_count(1); my_root_task->set_ref_count(1);
tbb::internal::fgt_graph( this ); tbb::internal::fgt_graph( this );
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
my_is_active = true;
#endif
} }
//! Destroys the graph. //! Destroys the graph.
/** Calls wait_for_all, then destroys the root task and context. */ /** Calls wait_for_all, then destroys the root task and context. */
~graph() { ~graph() {
wait_for_all(); wait_for_all();
my_root_task->set_ref_count(0); my_root_task->set_ref_count(0);
task::destroy( *my_root_task ); task::destroy( *my_root_task );
if (own_context) delete my_context; if (own_context) delete my_context;
} }
skipping to change at line 488 skipping to change at line 594
throw; throw;
} }
#endif #endif
my_context->reset(); // consistent with behavior in catch() my_context->reset(); // consistent with behavior in catch()
my_root_task->set_ref_count(1); my_root_task->set_ref_count(1);
} }
} }
//! Returns the root task of the graph //! Returns the root task of the graph
task * root_task() { task * root_task() {
return my_root_task; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
if (!my_is_active)
return NULL;
else
#endif
return my_root_task;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
void set_active(bool a = true) {
my_is_active = a;
}
bool is_active() {
return my_is_active;
}
#endif
// ITERATORS // ITERATORS
template<typename C, typename N> template<typename C, typename N>
friend class graph_iterator; friend class graph_iterator;
// Graph iterator typedefs // Graph iterator typedefs
typedef graph_iterator<graph,graph_node> iterator; typedef graph_iterator<graph,graph_node> iterator;
typedef graph_iterator<const graph,const graph_node> const_iterator; typedef graph_iterator<const graph,const graph_node> const_iterator;
// Graph iterator constructors // Graph iterator constructors
//! start iterator //! start iterator
skipping to change at line 517 skipping to change at line 638
const_iterator end() const { return const_iterator(this, false); } const_iterator end() const { return const_iterator(this, false); }
//! start const iterator //! start const iterator
const_iterator cbegin() const { return const_iterator(this, true); } const_iterator cbegin() const { return const_iterator(this, true); }
//! end const iterator //! end const iterator
const_iterator cend() const { return const_iterator(this, false); } const_iterator cend() const { return const_iterator(this, false); }
//! return status of graph execution //! return status of graph execution
bool is_cancelled() { return cancelled; } bool is_cancelled() { return cancelled; }
bool exception_thrown() { return caught_exception; } bool exception_thrown() { return caught_exception; }
// un-thread-safe state reset. // thread-unsafe state reset.
void reset(); void reset(__TBB_PFG_RESET_ARG(reset_flags f = rf_reset_protocol));
private: private:
task *my_root_task; task *my_root_task;
task_group_context *my_context; task_group_context *my_context;
bool own_context; bool own_context;
bool cancelled; bool cancelled;
bool caught_exception; bool caught_exception;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
bool my_is_active;
#endif
graph_node *my_nodes, *my_nodes_last; graph_node *my_nodes, *my_nodes_last;
spin_mutex nodelist_mutex; spin_mutex nodelist_mutex;
void register_node(graph_node *n); void register_node(graph_node *n);
void remove_node(graph_node *n); void remove_node(graph_node *n);
}; // class graph }; // class graph
template <typename C, typename N> template <typename C, typename N>
skipping to change at line 578 skipping to change at line 702
my_graph.register_node(this); my_graph.register_node(this);
} }
virtual ~graph_node() { virtual ~graph_node() {
my_graph.remove_node(this); my_graph.remove_node(this);
} }
#if TBB_PREVIEW_FLOW_GRAPH_TRACE #if TBB_PREVIEW_FLOW_GRAPH_TRACE
virtual void set_name( const char *name ) = 0; virtual void set_name( const char *name ) = 0;
#endif #endif
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
virtual void extract( reset_flags f=rf_extract ) {
bool a = my_graph.is_active();
my_graph.set_active(false);
reset((reset_flags)(f|rf_extract));
my_graph.set_active(a);
}
#endif
protected: protected:
virtual void reset() = 0; virtual void reset(__TBB_PFG_RESET_ARG(reset_flags f=rf_reset_protocol) ) = 0;
}; };
inline void graph::register_node(graph_node *n) { inline void graph::register_node(graph_node *n) {
n->next = NULL; n->next = NULL;
{ {
spin_mutex::scoped_lock lock(nodelist_mutex); spin_mutex::scoped_lock lock(nodelist_mutex);
n->prev = my_nodes_last; n->prev = my_nodes_last;
if (my_nodes_last) my_nodes_last->next = n; if (my_nodes_last) my_nodes_last->next = n;
my_nodes_last = n; my_nodes_last = n;
if (!my_nodes) my_nodes = n; if (!my_nodes) my_nodes = n;
skipping to change at line 605 skipping to change at line 738
spin_mutex::scoped_lock lock(nodelist_mutex); spin_mutex::scoped_lock lock(nodelist_mutex);
__TBB_ASSERT(my_nodes && my_nodes_last, "graph::remove_node: Error: no registered nodes"); __TBB_ASSERT(my_nodes && my_nodes_last, "graph::remove_node: Error: no registered nodes");
if (n->prev) n->prev->next = n->next; if (n->prev) n->prev->next = n->next;
if (n->next) n->next->prev = n->prev; if (n->next) n->next->prev = n->prev;
if (my_nodes_last == n) my_nodes_last = n->prev; if (my_nodes_last == n) my_nodes_last = n->prev;
if (my_nodes == n) my_nodes = n->next; if (my_nodes == n) my_nodes = n->next;
} }
n->prev = n->next = NULL; n->prev = n->next = NULL;
} }
inline void graph::reset() { inline void graph::reset( __TBB_PFG_RESET_ARG( reset_flags f )) {
// reset context // reset context
task *saved_my_root_task = my_root_task; task *saved_my_root_task = my_root_task;
my_root_task = NULL; my_root_task = NULL;
if(my_context) my_context->reset(); if(my_context) my_context->reset();
cancelled = false; cancelled = false;
caught_exception = false; caught_exception = false;
// reset all the nodes comprising the graph // reset all the nodes comprising the graph
for(iterator ii = begin(); ii != end(); ++ii) { for(iterator ii = begin(); ii != end(); ++ii) {
graph_node *my_p = &(*ii); graph_node *my_p = &(*ii);
my_p->reset(); my_p->reset(__TBB_PFG_RESET_ARG(f));
} }
my_root_task = saved_my_root_task; my_root_task = saved_my_root_task;
} }
#include "internal/_flow_graph_node_impl.h" #include "internal/_flow_graph_node_impl.h"
//! An executable node that acts as a source, i.e. it has no predecessors //! An executable node that acts as a source, i.e. it has no predecessors
template < typename Output > template < typename Output >
class source_node : public graph_node, public sender< Output > { class source_node : public graph_node, public sender< Output > {
protected: protected:
using graph_node::my_graph; using graph_node::my_graph;
public: public:
//! The type of the output message, which is complete //! The type of the output message, which is complete
typedef Output output_type; typedef Output output_type;
//! The type of successors of this node //! The type of successors of this node
typedef receiver< Output > successor_type; typedef receiver< Output > successor_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<successor_type *> successor_vector_type;
#endif
//! Constructor for a node with a successor //! Constructor for a node with a successor
template< typename Body > template< typename Body >
source_node( graph &g, Body body, bool is_active = true ) source_node( graph &g, Body body, bool is_active = true )
: graph_node(g), my_active(is_active), init_my_active(is_active), : graph_node(g), my_active(is_active), init_my_active(is_active),
my_body( new internal::source_body_leaf< output_type, Body>(body) ) , my_body( new internal::source_body_leaf< output_type, Body>(body) ) ,
my_reserved(false), my_has_cached_item(false) my_reserved(false), my_has_cached_item(false)
{ {
my_successors.set_owner(this); my_successors.set_owner(this);
tbb::internal::fgt_node_with_body( tbb::internal::FLOW_SOURCE_NODE, &this->my_graph, tbb::internal::fgt_node_with_body( tbb::internal::FLOW_SOURCE_NODE, &this->my_graph,
static_cast<sender<output_type> *>(this), this->my_body ); static_cast<sender<output_type> *>(this), this->my_body );
skipping to change at line 668 skipping to change at line 805
//! The destructor //! The destructor
~source_node() { delete my_body; } ~source_node() { delete my_body; }
#if TBB_PREVIEW_FLOW_GRAPH_TRACE #if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) { /* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name ); tbb::internal::fgt_node_desc( this, name );
} }
#endif #endif
//! Add a new successor to this node //! Add a new successor to this node
/* override */ bool register_successor( receiver<output_type> &r ) { /* override */ bool register_successor( successor_type &r ) {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
my_successors.register_successor(r); my_successors.register_successor(r);
if ( my_active ) if ( my_active )
spawn_put(); spawn_put();
return true; return true;
} }
//! Removes a successor from this node //! Removes a successor from this node
/* override */ bool remove_successor( receiver<output_type> &r ) { /* override */ bool remove_successor( successor_type &r ) {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
my_successors.remove_successor(r); my_successors.remove_successor(r);
return true; return true;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
/*override*/void internal_add_built_successor( successor_type &r) {
spin_mutex::scoped_lock lock(my_mutex);
my_successors.internal_add_built_successor(r);
}
/*override*/void internal_delete_built_successor( successor_type &r) {
spin_mutex::scoped_lock lock(my_mutex);
my_successors.internal_delete_built_successor(r);
}
/*override*/size_t successor_count() {
spin_mutex::scoped_lock lock(my_mutex);
return my_successors.successor_count();
}
/*override*/void copy_successors(successor_vector_type &v) {
spin_mutex::scoped_lock l(my_mutex);
my_successors.copy_successors(v);
}
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
//! Request an item from the node //! Request an item from the node
/*override */ bool try_get( output_type &v ) { /*override */ bool try_get( output_type &v ) {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
if ( my_reserved ) if ( my_reserved )
return false; return false;
if ( my_has_cached_item ) { if ( my_has_cached_item ) {
v = my_cached_item; v = my_cached_item;
my_has_cached_item = false; my_has_cached_item = false;
return true; return true;
skipping to change at line 755 skipping to change at line 914
} }
template<typename Body> template<typename Body>
Body copy_function_object() { Body copy_function_object() {
internal::source_body<output_type> &body_ref = *this->my_body; internal::source_body<output_type> &body_ref = *this->my_body;
return dynamic_cast< internal::source_body_leaf<output_type, Body> & >(body_ref).get_body(); return dynamic_cast< internal::source_body_leaf<output_type, Body> & >(body_ref).get_body();
} }
protected: protected:
//! resets the node to its initial state //! resets the source_node to its initial state
void reset() { void reset( __TBB_PFG_RESET_ARG(reset_flags f)) {
my_active = init_my_active; my_active = init_my_active;
my_reserved =false; my_reserved =false;
if(my_has_cached_item) { if(my_has_cached_item) {
my_has_cached_item = false; my_has_cached_item = false;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
my_successors.reset(f);
if(f & rf_reset_bodies) my_body->reset_body();
#endif
} }
private: private:
spin_mutex my_mutex; spin_mutex my_mutex;
bool my_active; bool my_active;
bool init_my_active; bool init_my_active;
internal::source_body<output_type> *my_body; internal::source_body<output_type> *my_body;
internal::broadcast_cache< output_type > my_successors; internal::broadcast_cache< output_type > my_successors;
bool my_reserved; bool my_reserved;
bool my_has_cached_item; bool my_has_cached_item;
skipping to change at line 834 skipping to change at line 997
class function_node : public graph_node, public internal::function_input<In put,Output,Allocator>, public internal::function_output<Output> { class function_node : public graph_node, public internal::function_input<In put,Output,Allocator>, public internal::function_output<Output> {
protected: protected:
using graph_node::my_graph; using graph_node::my_graph;
public: public:
typedef Input input_type; typedef Input input_type;
typedef Output output_type; typedef Output output_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
typedef internal::function_input<input_type,output_type,Allocator> fInp ut_type; typedef internal::function_input<input_type,output_type,Allocator> fInp ut_type;
typedef internal::function_output<output_type> fOutput_type; typedef internal::function_output<output_type> fOutput_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEAURES
typedef std::vector<predecessor_type *> predecessor_vector_type;
typedef std::vector<successor_type *> successor_vector_type;
#endif
//! Constructor //! Constructor
template< typename Body > template< typename Body >
function_node( graph &g, size_t concurrency, Body body ) : function_node( graph &g, size_t concurrency, Body body ) :
graph_node(g), internal::function_input<input_type,output_type,Allo cator>(g, concurrency, body) { graph_node(g), internal::function_input<input_type,output_type,Allo cator>(g, concurrency, body) {
tbb::internal::fgt_node_with_body( tbb::internal::FLOW_FUNCTION_NOD E, &this->graph_node::my_graph, static_cast<receiver<input_type> *>(this), tbb::internal::fgt_node_with_body( tbb::internal::FLOW_FUNCTION_NOD E, &this->graph_node::my_graph, static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this), this->my_body ); static_cast<sender<output_type> *>(this), this->my_body );
} }
//! Copy constructor //! Copy constructor
skipping to change at line 864 skipping to change at line 1031
} }
#endif #endif
protected: protected:
template< typename R, typename B > friend class run_and_put_task; template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_cache ; template<typename X, typename Y> friend class internal::broadcast_cache ;
template<typename X, typename Y> friend class internal::round_robin_cac he; template<typename X, typename Y> friend class internal::round_robin_cac he;
using fInput_type::try_put_task; using fInput_type::try_put_task;
// override of graph_node's reset. // override of graph_node's reset.
/*override*/void reset() {fInput_type::reset_function_input(); } /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) {
fInput_type::reset_function_input(__TBB_PFG_RESET_ARG(f));
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
successors().reset(f);
__TBB_ASSERT(!(f & rf_extract) || successors().empty(), "function_n
ode successors not empty");
__TBB_ASSERT(this->my_predecessors.empty(), "function_node predeces
sors not empty");
#endif
}
/* override */ internal::broadcast_cache<output_type> &successors () { return fOutput_type::my_successors; } /* override */ internal::broadcast_cache<output_type> &successors () { return fOutput_type::my_successors; }
}; };
//! Implements a function node that supports Input -> Output //! Implements a function node that supports Input -> Output
template < typename Input, typename Output, typename Allocator > template < typename Input, typename Output, typename Allocator >
class function_node<Input,Output,queueing,Allocator> : public graph_node, p ublic internal::function_input<Input,Output,Allocator>, public internal::fu nction_output<Output> { class function_node<Input,Output,queueing,Allocator> : public graph_node, p ublic internal::function_input<Input,Output,Allocator>, public internal::fu nction_output<Output> {
protected: protected:
using graph_node::my_graph; using graph_node::my_graph;
public: public:
typedef Input input_type; typedef Input input_type;
typedef Output output_type; typedef Output output_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
typedef internal::function_input<input_type,output_type,Allocator> fInp ut_type; typedef internal::function_input<input_type,output_type,Allocator> fInp ut_type;
typedef internal::function_input_queue<input_type, Allocator> queue_typ e; typedef internal::function_input_queue<input_type, Allocator> queue_typ e;
typedef internal::function_output<output_type> fOutput_type; typedef internal::function_output<output_type> fOutput_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<predecessor_type *> predecessor_vector_type;
typedef std::vector<successor_type *> successor_vector_type;
#endif
//! Constructor //! Constructor
template< typename Body > template< typename Body >
function_node( graph &g, size_t concurrency, Body body ) : function_node( graph &g, size_t concurrency, Body body ) :
graph_node(g), fInput_type( g, concurrency, body, new queue_type() ) { graph_node(g), fInput_type( g, concurrency, body, new queue_type() ) {
tbb::internal::fgt_node_with_body( tbb::internal::FLOW_FUNCTION_NOD E, &this->graph_node::my_graph, static_cast<receiver<input_type> *>(this), tbb::internal::fgt_node_with_body( tbb::internal::FLOW_FUNCTION_NOD E, &this->graph_node::my_graph, static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this), this->my_body ); static_cast<sender<output_type> *>(this), this->my_body );
} }
//! Copy constructor //! Copy constructor
skipping to change at line 910 skipping to change at line 1088
tbb::internal::fgt_node_desc( this, name ); tbb::internal::fgt_node_desc( this, name );
} }
#endif #endif
protected: protected:
template< typename R, typename B > friend class run_and_put_task; template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_cache ; template<typename X, typename Y> friend class internal::broadcast_cache ;
template<typename X, typename Y> friend class internal::round_robin_cac he; template<typename X, typename Y> friend class internal::round_robin_cac he;
using fInput_type::try_put_task; using fInput_type::try_put_task;
/*override*/void reset() { fInput_type::reset_function_input(); } /*override*/void reset( __TBB_PFG_RESET_ARG(reset_flags f)) {
fInput_type::reset_function_input(__TBB_PFG_RESET_ARG(f));
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
successors().reset(f);
__TBB_ASSERT(!(f & rf_extract) || successors().empty(), "function_n
ode successors not empty");
__TBB_ASSERT(!(f & rf_extract) || this->my_predecessors.empty(), "f
unction_node predecessors not empty");
#endif
}
/* override */ internal::broadcast_cache<output_type> &successors () { return fOutput_type::my_successors; } /* override */ internal::broadcast_cache<output_type> &successors () { return fOutput_type::my_successors; }
}; };
#include "internal/_flow_graph_types_impl.h"
//! implements a function node that supports Input -> (set of outputs) //! implements a function node that supports Input -> (set of outputs)
// Output is a tuple of output types. // Output is a tuple of output types.
template < typename Input, typename Output, graph_buffer_policy = queueing, typename Allocator=cache_aligned_allocator<Input> > template < typename Input, typename Output, graph_buffer_policy = queueing, typename Allocator=cache_aligned_allocator<Input> >
class multifunction_node : class multifunction_node :
public graph_node, public graph_node,
public internal::multifunction_input public internal::multifunction_input
< <
Input, Input,
typename internal::wrap_tuple_elements< typename internal::wrap_tuple_elements<
tbb::flow::tuple_size<Output>::value, // #elements in tuple tbb::flow::tuple_size<Output>::value, // #elements in tuple
skipping to change at line 966 skipping to change at line 1150
} }
#if TBB_PREVIEW_FLOW_GRAPH_TRACE #if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) { /* override */ void set_name( const char *name ) {
tbb::internal::fgt_multioutput_node_desc( this, name ); tbb::internal::fgt_multioutput_node_desc( this, name );
} }
#endif #endif
// all the guts are in multifunction_input... // all the guts are in multifunction_input...
protected: protected:
/*override*/void reset() { base_type::reset(); } /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) { base_type: :reset(__TBB_PFG_RESET_ARG(f)); }
}; // multifunction_node }; // multifunction_node
template < typename Input, typename Output, typename Allocator > template < typename Input, typename Output, typename Allocator >
class multifunction_node<Input,Output,queueing,Allocator> : public graph_no de, public internal::multifunction_input<Input, class multifunction_node<Input,Output,queueing,Allocator> : public graph_no de, public internal::multifunction_input<Input,
typename internal::wrap_tuple_elements<tbb::flow::tuple_size<Output>::v alue, internal::multifunction_output, Output>::type, Allocator> { typename internal::wrap_tuple_elements<tbb::flow::tuple_size<Output>::v alue, internal::multifunction_output, Output>::type, Allocator> {
protected: protected:
using graph_node::my_graph; using graph_node::my_graph;
static const int N = tbb::flow::tuple_size<Output>::value; static const int N = tbb::flow::tuple_size<Output>::value;
public: public:
typedef Input input_type; typedef Input input_type;
skipping to change at line 1005 skipping to change at line 1189
} }
#if TBB_PREVIEW_FLOW_GRAPH_TRACE #if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) { /* override */ void set_name( const char *name ) {
tbb::internal::fgt_multioutput_node_desc( this, name ); tbb::internal::fgt_multioutput_node_desc( this, name );
} }
#endif #endif
// all the guts are in multifunction_input... // all the guts are in multifunction_input...
protected: protected:
/*override*/void reset() { base_type::reset(); } /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) { base_type: :reset(__TBB_PFG_RESET_ARG(f)); }
}; // multifunction_node }; // multifunction_node
//! split_node: accepts a tuple as input, forwards each element of the tupl e to its //! split_node: accepts a tuple as input, forwards each element of the tupl e to its
// successors. The node has unlimited concurrency, so though it is marked as // successors. The node has unlimited concurrency, so though it is marked as
// "rejecting" it does not reject inputs. // "rejecting" it does not reject inputs.
template<typename TupleType, typename Allocator=cache_aligned_allocator<Tup leType> > template<typename TupleType, typename Allocator=cache_aligned_allocator<Tup leType> >
class split_node : public multifunction_node<TupleType, TupleType, rejectin g, Allocator> { class split_node : public multifunction_node<TupleType, TupleType, rejectin g, Allocator> {
static const int N = tbb::flow::tuple_size<TupleType>::value; static const int N = tbb::flow::tuple_size<TupleType>::value;
typedef multifunction_node<TupleType,TupleType,rejecting,Allocator> bas e_type; typedef multifunction_node<TupleType,TupleType,rejecting,Allocator> bas e_type;
public: public:
skipping to change at line 1096 skipping to change at line 1280
tbb::internal::fgt_node_desc( this, name ); tbb::internal::fgt_node_desc( this, name );
} }
#endif #endif
protected: protected:
template< typename R, typename B > friend class run_and_put_task; template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_cache ; template<typename X, typename Y> friend class internal::broadcast_cache ;
template<typename X, typename Y> friend class internal::round_robin_cac he; template<typename X, typename Y> friend class internal::round_robin_cac he;
using fInput_type::try_put_task; using fInput_type::try_put_task;
/*override*/void reset() { internal::continue_input<Output>::reset_rece /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) {
iver(); } fInput_type::reset_receiver(__TBB_PFG_RESET_ARG(f));
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
successors().reset(f);
__TBB_ASSERT(!(f & rf_extract) || successors().empty(), "continue_n
ode not reset");
#endif
}
/* override */ internal::broadcast_cache<output_type> &successors () { return fOutput_type::my_successors; } /* override */ internal::broadcast_cache<output_type> &successors () { return fOutput_type::my_successors; }
}; // continue_node }; // continue_node
template< typename T > template< typename T >
class overwrite_node : public graph_node, public receiver<T>, public sender <T> { class overwrite_node : public graph_node, public receiver<T>, public sender <T> {
protected: protected:
using graph_node::my_graph; using graph_node::my_graph;
public: public:
typedef T input_type; typedef T input_type;
typedef T output_type; typedef T output_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<predecessor_type *> predecessor_vector_type;
typedef std::vector<successor_type *> successor_vector_type;
#endif
overwrite_node(graph &g) : graph_node(g), my_buffer_is_valid(false) { overwrite_node(graph &g) : graph_node(g), my_buffer_is_valid(false) {
my_successors.set_owner( this ); my_successors.set_owner( this );
tbb::internal::fgt_node( tbb::internal::FLOW_OVERWRITE_NODE, &this- >my_graph, tbb::internal::fgt_node( tbb::internal::FLOW_OVERWRITE_NODE, &this- >my_graph,
static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) ); static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) );
} }
// Copy constructor; doesn't take anything from src; default won't work // Copy constructor; doesn't take anything from src; default won't work
overwrite_node( const overwrite_node& src ) : overwrite_node( const overwrite_node& src ) :
graph_node(src.my_graph), receiver<T>(), sender<T>(), my_buffer_is_ valid(false) graph_node(src.my_graph), receiver<T>(), sender<T>(), my_buffer_is_ valid(false)
skipping to change at line 1159 skipping to change at line 1353
} }
return true; return true;
} }
/* override */ bool remove_successor( successor_type &s ) { /* override */ bool remove_successor( successor_type &s ) {
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
my_successors.remove_successor(s); my_successors.remove_successor(s);
return true; return true;
} }
/* override */ bool try_get( T &v ) { #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
/*override*/void internal_add_built_successor( successor_type &s) {
spin_mutex::scoped_lock l( my_mutex );
my_successors.internal_add_built_successor(s);
}
/*override*/void internal_delete_built_successor( successor_type &s) {
spin_mutex::scoped_lock l( my_mutex );
my_successors.internal_delete_built_successor(s);
}
/*override*/size_t successor_count() {
spin_mutex::scoped_lock l( my_mutex );
return my_successors.successor_count();
}
/*override*/ void copy_successors(successor_vector_type &v) {
spin_mutex::scoped_lock l( my_mutex );
my_successors.copy_successors(v);
}
/*override*/ void internal_add_built_predecessor( predecessor_type &p)
{
spin_mutex::scoped_lock l( my_mutex );
my_built_predecessors.add_edge(p);
}
/*override*/ void internal_delete_built_predecessor( predecessor_type &
p) {
spin_mutex::scoped_lock l( my_mutex );
my_built_predecessors.delete_edge(p);
}
/*override*/size_t predecessor_count() {
spin_mutex::scoped_lock l( my_mutex );
return my_built_predecessors.edge_count();
}
/*override*/void copy_predecessors(predecessor_vector_type &v) {
spin_mutex::scoped_lock l( my_mutex );
my_built_predecessors.copy_edges(v);
}
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
/* override */ bool try_get( input_type &v ) {
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
if ( my_buffer_is_valid ) { if ( my_buffer_is_valid ) {
v = my_buffer; v = my_buffer;
return true; return true;
} }
return false; return false;
} }
bool is_valid() { bool is_valid() {
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
skipping to change at line 1182 skipping to change at line 1418
void clear() { void clear() {
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
my_buffer_is_valid = false; my_buffer_is_valid = false;
} }
protected: protected:
template< typename R, typename B > friend class run_and_put_task; template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_cache ; template<typename X, typename Y> friend class internal::broadcast_cache ;
template<typename X, typename Y> friend class internal::round_robin_cac he; template<typename X, typename Y> friend class internal::round_robin_cac he;
/* override */ task * try_put_task( const T &v ) { /* override */ task * try_put_task( const input_type &v ) {
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
my_buffer = v; my_buffer = v;
my_buffer_is_valid = true; my_buffer_is_valid = true;
task * rtask = my_successors.try_put_task(v); task * rtask = my_successors.try_put_task(v);
if(!rtask) rtask = SUCCESSFULLY_ENQUEUED; if(!rtask) rtask = SUCCESSFULLY_ENQUEUED;
return rtask; return rtask;
} }
/*override*/void reset() { my_buffer_is_valid = false; } /*override*/void reset( __TBB_PFG_RESET_ARG(reset_flags f)) {
my_buffer_is_valid = false;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
my_successors.reset(f);
if (f&rf_extract) {
my_built_predecessors.receiver_extract(*this);
}
#endif
}
spin_mutex my_mutex; spin_mutex my_mutex;
internal::broadcast_cache< T, null_rw_mutex > my_successors; internal::broadcast_cache< input_type, null_rw_mutex > my_successors;
T my_buffer; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
edge_container<sender<input_type> > my_built_predecessors;
#endif
input_type my_buffer;
bool my_buffer_is_valid; bool my_buffer_is_valid;
/*override*/void reset_receiver() {} /*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags /*f*/))
}; {}
}; // overwrite_node
template< typename T > template< typename T >
class write_once_node : public overwrite_node<T> { class write_once_node : public overwrite_node<T> {
public: public:
typedef T input_type; typedef T input_type;
typedef T output_type; typedef T output_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
//! Constructor //! Constructor
skipping to change at line 1251 skipping to change at line 1498
return res; return res;
} }
} }
}; };
//! Forwards messages of type T to all successors //! Forwards messages of type T to all successors
template <typename T> template <typename T>
class broadcast_node : public graph_node, public receiver<T>, public sender <T> { class broadcast_node : public graph_node, public receiver<T>, public sender <T> {
protected: protected:
using graph_node::my_graph; using graph_node::my_graph;
private:
internal::broadcast_cache<T> my_successors;
public: public:
typedef T input_type; typedef T input_type;
typedef T output_type; typedef T output_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<predecessor_type *> predecessor_vector_type;
typedef std::vector<successor_type *> successor_vector_type;
#endif
private:
internal::broadcast_cache<input_type> my_successors;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
edge_container<predecessor_type> my_built_predecessors;
spin_mutex pred_mutex;
#endif
public:
broadcast_node(graph& g) : graph_node(g) { broadcast_node(graph& g) : graph_node(g) {
my_successors.set_owner( this ); my_successors.set_owner( this );
tbb::internal::fgt_node( tbb::internal::FLOW_BROADCAST_NODE, &this- >my_graph, tbb::internal::fgt_node( tbb::internal::FLOW_BROADCAST_NODE, &this- >my_graph,
static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) ); static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) );
} }
// Copy constructor // Copy constructor
broadcast_node( const broadcast_node& src ) : broadcast_node( const broadcast_node& src ) :
graph_node(src.my_graph), receiver<T>(), sender<T>() graph_node(src.my_graph), receiver<T>(), sender<T>()
skipping to change at line 1292 skipping to change at line 1548
my_successors.register_successor( r ); my_successors.register_successor( r );
return true; return true;
} }
//! Removes s as a successor //! Removes s as a successor
virtual bool remove_successor( receiver<T> &r ) { virtual bool remove_successor( receiver<T> &r ) {
my_successors.remove_successor( r ); my_successors.remove_successor( r );
return true; return true;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
/*override*/ void internal_add_built_successor(successor_type &r) {
my_successors.internal_add_built_successor(r);
}
/*override*/ void internal_delete_built_successor(successor_type &r) {
my_successors.internal_delete_built_successor(r);
}
/*override*/ size_t successor_count() {
return my_successors.successor_count();
}
/*override*/ void copy_successors(successor_vector_type &v) {
my_successors.copy_successors(v);
}
/*override*/ void internal_add_built_predecessor( predecessor_type &p)
{
my_built_predecessors.add_edge(p);
}
/*override*/ void internal_delete_built_predecessor( predecessor_type &
p) {
my_built_predecessors.delete_edge(p);
}
/*override*/ size_t predecessor_count() {
return my_built_predecessors.edge_count();
}
/*override*/ void copy_predecessors(predecessor_vector_type &v) {
my_built_predecessors.copy_edges(v);
}
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
protected: protected:
template< typename R, typename B > friend class run_and_put_task; template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_cache ; template<typename X, typename Y> friend class internal::broadcast_cache ;
template<typename X, typename Y> friend class internal::round_robin_cac he; template<typename X, typename Y> friend class internal::round_robin_cac he;
//! build a task to run the successor if possible. Default is old beha vior. //! build a task to run the successor if possible. Default is old beha vior.
/*override*/ task *try_put_task(const T& t) { /*override*/ task *try_put_task(const T& t) {
task *new_task = my_successors.try_put_task(t); task *new_task = my_successors.try_put_task(t);
if(!new_task) new_task = SUCCESSFULLY_ENQUEUED; if(!new_task) new_task = SUCCESSFULLY_ENQUEUED;
return new_task; return new_task;
} }
/*override*/void reset() {} /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) {
/*override*/void reset_receiver() {} #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
my_successors.reset(f);
if (f&rf_extract) {
my_built_predecessors.receiver_extract(*this);
}
__TBB_ASSERT(!(f & rf_extract) || my_successors.empty(), "Error res
etting broadcast_node");
#endif
}
/*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags /*f*/))
{}
}; // broadcast_node }; // broadcast_node
#include "internal/_flow_graph_item_buffer_impl.h"
//! Forwards messages in arbitrary order //! Forwards messages in arbitrary order
template <typename T, typename A=cache_aligned_allocator<T> > template <typename T, typename A=cache_aligned_allocator<T> >
class buffer_node : public graph_node, public reservable_item_buffer<T, A>, public receiver<T>, public sender<T> { class buffer_node : public graph_node, public internal::reservable_item_buf fer<T, A>, public receiver<T>, public sender<T> {
protected: protected:
using graph_node::my_graph; using graph_node::my_graph;
public: public:
typedef T input_type; typedef T input_type;
typedef T output_type; typedef T output_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
typedef buffer_node<T, A> my_class; typedef buffer_node<T, A> my_class;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<predecessor_type *> predecessor_vector_type;
typedef std::vector<successor_type *> successor_vector_type;
#endif
protected: protected:
typedef size_t size_type; typedef size_t size_type;
internal::round_robin_cache< T, null_rw_mutex > my_successors; internal::round_robin_cache< T, null_rw_mutex > my_successors;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
edge_container<predecessor_type> my_built_predecessors;
#endif
friend class internal::forward_task_bypass< buffer_node< T, A > >; friend class internal::forward_task_bypass< buffer_node< T, A > >;
enum op_type {reg_succ, rem_succ, req_item, res_item, rel_res, con_res, enum op_type {reg_succ, rem_succ, req_item, res_item, rel_res, con_res,
put_item, try_fwd_task }; put_item, try_fwd_task
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
, add_blt_succ, del_blt_succ,
add_blt_pred, del_blt_pred,
blt_succ_cnt, blt_pred_cnt,
blt_succ_cpy, blt_pred_cpy // create vector copies of preds and s
uccs
#endif
};
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
// implements the aggregator_operation concept // implements the aggregator_operation concept
class buffer_operation : public internal::aggregated_operation< buffer_ operation > { class buffer_operation : public internal::aggregated_operation< buffer_ operation > {
public: public:
char type; char type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
task * ltask;
union {
input_type *elem;
successor_type *r;
predecessor_type *p;
size_t cnt_val;
successor_vector_type *svec;
predecessor_vector_type *pvec;
};
#else
T *elem; T *elem;
task * ltask; task * ltask;
successor_type *r; successor_type *r;
buffer_operation(const T& e, op_type t) : type(char(t)), elem(const #endif
_cast<T*>(&e)) , ltask(NULL) , r(NULL) {} buffer_operation(const T& e, op_type t) : type(char(t))
buffer_operation(op_type t) : type(char(t)) , ltask(NULL) , r(NULL)
{} #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
, ltask(NULL), elem(const
_cast<T*>(&e))
#else
, elem(const_cast<T*>(&e)
) , ltask(NULL)
#endif
{}
buffer_operation(op_type t) : type(char(t)), ltask(NULL) {}
}; };
bool forwarder_busy; bool forwarder_busy;
typedef internal::aggregating_functor<my_class, buffer_operation> my_ha ndler; typedef internal::aggregating_functor<my_class, buffer_operation> my_ha ndler;
friend class internal::aggregating_functor<my_class, buffer_operation>; friend class internal::aggregating_functor<my_class, buffer_operation>;
internal::aggregator< my_handler, buffer_operation> my_aggregator; internal::aggregator< my_handler, buffer_operation> my_aggregator;
virtual void handle_operations(buffer_operation *op_list) { virtual void handle_operations(buffer_operation *op_list) {
buffer_operation *tmp = NULL; buffer_operation *tmp = NULL;
bool try_forwarding=false; bool try_forwarding=false;
while (op_list) { while (op_list) {
tmp = op_list; tmp = op_list;
op_list = op_list->next; op_list = op_list->next;
switch (tmp->type) { switch (tmp->type) {
case reg_succ: internal_reg_succ(tmp); try_forwarding = true; break; case reg_succ: internal_reg_succ(tmp); try_forwarding = true; break;
case rem_succ: internal_rem_succ(tmp); break; case rem_succ: internal_rem_succ(tmp); break;
case req_item: internal_pop(tmp); break; case req_item: internal_pop(tmp); break;
case res_item: internal_reserve(tmp); break; case res_item: internal_reserve(tmp); break;
case rel_res: internal_release(tmp); try_forwarding = true; b reak; case rel_res: internal_release(tmp); try_forwarding = true; b reak;
case con_res: internal_consume(tmp); try_forwarding = true; b reak; case con_res: internal_consume(tmp); try_forwarding = true; b reak;
case put_item: internal_push(tmp); try_forwarding = true; brea k; case put_item: internal_push(tmp); try_forwarding = (tmp->stat us == SUCCEEDED); break;
case try_fwd_task: internal_forward_task(tmp); break; case try_fwd_task: internal_forward_task(tmp); break;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
// edge recording
case add_blt_succ: internal_add_built_succ(tmp); break;
case del_blt_succ: internal_del_built_succ(tmp); break;
case add_blt_pred: internal_add_built_pred(tmp); break;
case del_blt_pred: internal_del_built_pred(tmp); break;
case blt_succ_cnt: internal_succ_cnt(tmp); break;
case blt_pred_cnt: internal_pred_cnt(tmp); break;
case blt_succ_cpy: internal_copy_succs(tmp); break;
case blt_pred_cpy: internal_copy_preds(tmp); break;
#endif
} }
} }
if (try_forwarding && !forwarder_busy) { if (try_forwarding && !forwarder_busy) {
task* tp = this->my_graph.root_task(); task* tp = this->my_graph.root_task();
if(tp) { if(tp) {
forwarder_busy = true; forwarder_busy = true;
task *new_task = new(task::allocate_additional_child_of(*tp )) internal:: task *new_task = new(task::allocate_additional_child_of(*tp )) internal::
forward_task_bypass forward_task_bypass
< buffer_node<input_type, A> >(*this); < buffer_node<input_type, A> >(*this);
// tmp should point to the last item handled by the aggrega tor. This is the operation // tmp should point to the last item handled by the aggrega tor. This is the operation
skipping to change at line 1416 skipping to change at line 1757
my_successors.register_successor(*(op->r)); my_successors.register_successor(*(op->r));
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} }
//! Remove successor //! Remove successor
virtual void internal_rem_succ(buffer_operation *op) { virtual void internal_rem_succ(buffer_operation *op) {
my_successors.remove_successor(*(op->r)); my_successors.remove_successor(*(op->r));
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
virtual void internal_add_built_succ(buffer_operation *op) {
my_successors.internal_add_built_successor(*(op->r));
__TBB_store_with_release(op->status, SUCCEEDED);
}
virtual void internal_del_built_succ(buffer_operation *op) {
my_successors.internal_delete_built_successor(*(op->r));
__TBB_store_with_release(op->status, SUCCEEDED);
}
virtual void internal_add_built_pred(buffer_operation *op) {
my_built_predecessors.add_edge(*(op->p));
__TBB_store_with_release(op->status, SUCCEEDED);
}
virtual void internal_del_built_pred(buffer_operation *op) {
my_built_predecessors.delete_edge(*(op->p));
__TBB_store_with_release(op->status, SUCCEEDED);
}
virtual void internal_succ_cnt(buffer_operation *op) {
op->cnt_val = my_successors.successor_count();
__TBB_store_with_release(op->status, SUCCEEDED);
}
virtual void internal_pred_cnt(buffer_operation *op) {
op->cnt_val = my_built_predecessors.edge_count();
__TBB_store_with_release(op->status, SUCCEEDED);
}
virtual void internal_copy_succs(buffer_operation *op) {
my_successors.copy_successors(*(op->svec));
__TBB_store_with_release(op->status, SUCCEEDED);
}
virtual void internal_copy_preds(buffer_operation *op) {
my_built_predecessors.copy_edges(*(op->pvec));
__TBB_store_with_release(op->status, SUCCEEDED);
}
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
//! Tries to forward valid items to successors //! Tries to forward valid items to successors
virtual void internal_forward_task(buffer_operation *op) { virtual void internal_forward_task(buffer_operation *op) {
if (this->my_reserved || !this->item_valid(this->my_tail-1)) { if (this->my_reserved || !this->my_item_valid(this->my_tail-1)) {
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
this->forwarder_busy = false; this->forwarder_busy = false;
return; return;
} }
T i_copy; T i_copy;
task * last_task = NULL; task * last_task = NULL;
size_type counter = my_successors.size(); size_type counter = my_successors.size();
// Try forwarding, giving each successor a chance // Try forwarding, giving each successor a chance
while (counter>0 && !this->buffer_empty() && this->item_valid(this- while (counter>0 && !this->buffer_empty() && this->my_item_valid(th
>my_tail-1)) { is->my_tail-1)) {
this->fetch_back(i_copy); this->copy_back(i_copy);
task *new_task = my_successors.try_put_task(i_copy); task *new_task = my_successors.try_put_task(i_copy);
last_task = combine_tasks(last_task, new_task);
if(new_task) { if(new_task) {
this->invalidate_back(); last_task = combine_tasks(last_task, new_task);
--(this->my_tail); this->destroy_back();
} }
--counter; --counter;
} }
op->ltask = last_task; // return task op->ltask = last_task; // return task
if (last_task && !counter) { if (last_task && !counter) {
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} }
else { else {
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
forwarder_busy = false; forwarder_busy = false;
skipping to change at line 1482 skipping to change at line 1864
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} }
virtual void internal_release(buffer_operation *op) { virtual void internal_release(buffer_operation *op) {
this->release_front(); this->release_front();
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} }
public: public:
//! Constructor //! Constructor
buffer_node( graph &g ) : graph_node(g), reservable_item_buffer<T>(), buffer_node( graph &g ) : graph_node(g), internal::reservable_item_buff er<T>(),
forwarder_busy(false) { forwarder_busy(false) {
my_successors.set_owner(this); my_successors.set_owner(this);
my_aggregator.initialize_handler(my_handler(this)); my_aggregator.initialize_handler(my_handler(this));
tbb::internal::fgt_node( tbb::internal::FLOW_BUFFER_NODE, &this->my _graph, tbb::internal::fgt_node( tbb::internal::FLOW_BUFFER_NODE, &this->my _graph,
static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) ); static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) );
} }
//! Copy constructor //! Copy constructor
buffer_node( const buffer_node& src ) : graph_node(src.my_graph), buffer_node( const buffer_node& src ) : graph_node(src.my_graph),
reservable_item_buffer<T>(), receiver<T>(), sender<T>() { internal::reservable_item_buffer<T>(), receiver<T>(), sender<T>() {
forwarder_busy = false; forwarder_busy = false;
my_successors.set_owner(this); my_successors.set_owner(this);
my_aggregator.initialize_handler(my_handler(this)); my_aggregator.initialize_handler(my_handler(this));
tbb::internal::fgt_node( tbb::internal::FLOW_BUFFER_NODE, &this->my _graph, tbb::internal::fgt_node( tbb::internal::FLOW_BUFFER_NODE, &this->my _graph,
static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) ); static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) );
} }
virtual ~buffer_node() {} virtual ~buffer_node() {}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE #if TBB_PREVIEW_FLOW_GRAPH_TRACE
skipping to change at line 1514 skipping to change at line 1896
tbb::internal::fgt_node_desc( this, name ); tbb::internal::fgt_node_desc( this, name );
} }
#endif #endif
// //
// message sender implementation // message sender implementation
// //
//! Adds a new successor. //! Adds a new successor.
/** Adds successor r to the list of successors; may forward tasks. */ /** Adds successor r to the list of successors; may forward tasks. */
/* override */ bool register_successor( receiver<output_type> &r ) { /* override */ bool register_successor( successor_type &r ) {
buffer_operation op_data(reg_succ); buffer_operation op_data(reg_succ);
op_data.r = &r; op_data.r = &r;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
(void)enqueue_forwarding_task(op_data); (void)enqueue_forwarding_task(op_data);
return true; return true;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
/*override*/ void internal_add_built_successor( successor_type &r) {
buffer_operation op_data(add_blt_succ);
op_data.r = &r;
my_aggregator.execute(&op_data);
}
/*override*/ void internal_delete_built_successor( successor_type &r) {
buffer_operation op_data(del_blt_succ);
op_data.r = &r;
my_aggregator.execute(&op_data);
}
/*override*/ void internal_add_built_predecessor( predecessor_type &p)
{
buffer_operation op_data(add_blt_pred);
op_data.p = &p;
my_aggregator.execute(&op_data);
}
/*override*/ void internal_delete_built_predecessor( predecessor_type &
p) {
buffer_operation op_data(del_blt_pred);
op_data.p = &p;
my_aggregator.execute(&op_data);
}
/*override*/ size_t predecessor_count() {
buffer_operation op_data(blt_pred_cnt);
my_aggregator.execute(&op_data);
return op_data.cnt_val;
}
/*override*/ size_t successor_count() {
buffer_operation op_data(blt_succ_cnt);
my_aggregator.execute(&op_data);
return op_data.cnt_val;
}
/*override*/ void copy_predecessors( predecessor_vector_type &v ) {
buffer_operation op_data(blt_pred_cpy);
op_data.pvec = &v;
my_aggregator.execute(&op_data);
}
/*override*/ void copy_successors( successor_vector_type &v ) {
buffer_operation op_data(blt_succ_cpy);
op_data.svec = &v;
my_aggregator.execute(&op_data);
}
#endif
//! Removes a successor. //! Removes a successor.
/** Removes successor r from the list of successors. /** Removes successor r from the list of successors.
It also calls r.remove_predecessor(*this) to remove this node as a predecessor. */ It also calls r.remove_predecessor(*this) to remove this node as a predecessor. */
/* override */ bool remove_successor( receiver<output_type> &r ) { /* override */ bool remove_successor( successor_type &r ) {
r.remove_predecessor(*this); r.remove_predecessor(*this);
buffer_operation op_data(rem_succ); buffer_operation op_data(rem_succ);
op_data.r = &r; op_data.r = &r;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
// even though this operation does not cause a forward, if we are t he handler, and // even though this operation does not cause a forward, if we are t he handler, and
// a forward is scheduled, we may be the first to reach this point after the aggregator, // a forward is scheduled, we may be the first to reach this point after the aggregator,
// and so should check for the task. // and so should check for the task.
(void)enqueue_forwarding_task(op_data); (void)enqueue_forwarding_task(op_data);
return true; return true;
} }
skipping to change at line 1587 skipping to change at line 2019
protected: protected:
template< typename R, typename B > friend class run_and_put_task; template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_cache ; template<typename X, typename Y> friend class internal::broadcast_cache ;
template<typename X, typename Y> friend class internal::round_robin_cac he; template<typename X, typename Y> friend class internal::round_robin_cac he;
//! receive an item, return a task *if possible //! receive an item, return a task *if possible
/* override */ task *try_put_task(const T &t) { /* override */ task *try_put_task(const T &t) {
buffer_operation op_data(t, put_item); buffer_operation op_data(t, put_item);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
task *ft = grab_forwarding_task(op_data); task *ft = grab_forwarding_task(op_data);
if(!ft) { // sequencer_nodes can return failure (if an item has been previous
ly inserted)
// We have to spawn the returned task if our own operation fails.
if(ft && op_data.status == FAILED) {
// we haven't succeeded queueing the item, but for some reason
the
// call returned a task (if another request resulted in a succe
ssful
// forward this could happen.) Queue the task and reset the po
inter.
FLOW_SPAWN(*ft); ft = NULL;
}
else if(!ft && op_data.status == SUCCEEDED) {
ft = SUCCESSFULLY_ENQUEUED; ft = SUCCESSFULLY_ENQUEUED;
} }
return ft; return ft;
} }
/*override*/void reset() { /*override*/void reset( __TBB_PFG_RESET_ARG(reset_flags f)) {
reservable_item_buffer<T, A>::reset(); internal::reservable_item_buffer<T, A>::reset();
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
my_successors.reset(f);
if (f&rf_extract) {
my_built_predecessors.receiver_extract(*this);
}
#endif
forwarder_busy = false; forwarder_busy = false;
} }
/*override*/void reset_receiver() { /*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags /*f*/))
// nothing to do; no predecesor_cache { }
}
}; // buffer_node }; // buffer_node
//! Forwards messages in FIFO order //! Forwards messages in FIFO order
template <typename T, typename A=cache_aligned_allocator<T> > template <typename T, typename A=cache_aligned_allocator<T> >
class queue_node : public buffer_node<T, A> { class queue_node : public buffer_node<T, A> {
protected: protected:
typedef typename buffer_node<T, A>::size_type size_type; typedef buffer_node<T, A> base_type;
typedef typename buffer_node<T, A>::buffer_operation queue_operation; typedef typename base_type::size_type size_type;
typedef typename base_type::buffer_operation queue_operation;
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
/* override */ void internal_forward_task(queue_operation *op) { /* override */ void internal_forward_task(queue_operation *op) {
if (this->my_reserved || !this->item_valid(this->my_head)) { if (this->my_reserved || !this->my_item_valid(this->my_head)) {
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
this->forwarder_busy = false; this->forwarder_busy = false;
return; return;
} }
T i_copy; T i_copy;
task *last_task = NULL; task *last_task = NULL;
size_type counter = this->my_successors.size(); size_type counter = this->my_successors.size();
// Keep trying to send items while there is at least one accepting successor // Keep trying to send items while there is at least one accepting successor
while (counter>0 && this->item_valid(this->my_head)) { while (counter>0 && this->my_item_valid(this->my_head)) {
this->fetch_front(i_copy); this->copy_front(i_copy);
task *new_task = this->my_successors.try_put_task(i_copy); task *new_task = this->my_successors.try_put_task(i_copy);
if(new_task) { if(new_task) {
this->invalidate_front(); this->destroy_front();
++(this->my_head);
last_task = combine_tasks(last_task, new_task); last_task = combine_tasks(last_task, new_task);
} }
--counter; --counter;
} }
op->ltask = last_task; op->ltask = last_task;
if (last_task && !counter) if (last_task && !counter)
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
else { else {
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
this->forwarder_busy = false; this->forwarder_busy = false;
} }
} }
/* override */ void internal_pop(queue_operation *op) { /* override */ void internal_pop(queue_operation *op) {
if ( this->my_reserved || !this->item_valid(this->my_head)){ if ( this->my_reserved || !this->my_item_valid(this->my_head)){
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
} }
else { else {
this->pop_front(*(op->elem)); this->pop_front(*(op->elem));
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} }
} }
/* override */ void internal_reserve(queue_operation *op) { /* override */ void internal_reserve(queue_operation *op) {
if (this->my_reserved || !this->item_valid(this->my_head)) { if (this->my_reserved || !this->my_item_valid(this->my_head)) {
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
} }
else { else {
this->my_reserved = true; this->reserve_front(*(op->elem));
this->fetch_front(*(op->elem));
this->invalidate_front();
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} }
} }
/* override */ void internal_consume(queue_operation *op) { /* override */ void internal_consume(queue_operation *op) {
this->consume_front(); this->consume_front();
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} }
public: public:
typedef T input_type; typedef T input_type;
typedef T output_type; typedef T output_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
//! Constructor //! Constructor
queue_node( graph &g ) : buffer_node<T, A>(g) { queue_node( graph &g ) : base_type(g) {
tbb::internal::fgt_node( tbb::internal::FLOW_QUEUE_NODE, &(this->my _graph), tbb::internal::fgt_node( tbb::internal::FLOW_QUEUE_NODE, &(this->my _graph),
static_cast<receiver<input_type> *>(this), static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this) ) ; static_cast<sender<output_type> *>(this) ) ;
} }
//! Copy constructor //! Copy constructor
queue_node( const queue_node& src) : buffer_node<T, A>(src) { queue_node( const queue_node& src) : base_type(src) {
tbb::internal::fgt_node( tbb::internal::FLOW_QUEUE_NODE, &(this->my _graph), tbb::internal::fgt_node( tbb::internal::FLOW_QUEUE_NODE, &(this->my _graph),
static_cast<receiver<input_type> *>(this), static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this) ) ; static_cast<sender<output_type> *>(this) ) ;
} }
#if TBB_PREVIEW_FLOW_GRAPH_TRACE #if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) { /* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name ); tbb::internal::fgt_node_desc( this, name );
} }
#endif #endif
}; /*override*/void reset( __TBB_PFG_RESET_ARG(reset_flags f)) {
base_type::reset(__TBB_PFG_RESET_ARG(f));
}
}; // queue_node
//! Forwards messages in sequence order //! Forwards messages in sequence order
template< typename T, typename A=cache_aligned_allocator<T> > template< typename T, typename A=cache_aligned_allocator<T> >
class sequencer_node : public queue_node<T, A> { class sequencer_node : public queue_node<T, A> {
internal::function_body< T, size_t > *my_sequencer; internal::function_body< T, size_t > *my_sequencer;
// my_sequencer should be a benign function and must be callable
// from a parallel context. Does this mean it needn't be reset?
public: public:
typedef T input_type; typedef T input_type;
typedef T output_type; typedef T output_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
//! Constructor //! Constructor
template< typename Sequencer > template< typename Sequencer >
sequencer_node( graph &g, const Sequencer& s ) : queue_node<T, A>(g), sequencer_node( graph &g, const Sequencer& s ) : queue_node<T, A>(g),
my_sequencer(new internal::function_body_leaf< T, size_t, Sequencer >(s) ) { my_sequencer(new internal::function_body_leaf< T, size_t, Sequencer >(s) ) {
skipping to change at line 1740 skipping to change at line 2188
protected: protected:
typedef typename buffer_node<T, A>::size_type size_type; typedef typename buffer_node<T, A>::size_type size_type;
typedef typename buffer_node<T, A>::buffer_operation sequencer_operatio n; typedef typename buffer_node<T, A>::buffer_operation sequencer_operatio n;
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
private: private:
/* override */ void internal_push(sequencer_operation *op) { /* override */ void internal_push(sequencer_operation *op) {
size_type tag = (*my_sequencer)(*(op->elem)); size_type tag = (*my_sequencer)(*(op->elem));
#if !TBB_DEPRECATED_SEQUENCER_DUPLICATES
if(tag < this->my_head) {
// have already emitted a message with this tag
__TBB_store_with_release(op->status, FAILED);
return;
}
#endif
// cannot modify this->my_tail now; the buffer would be inconsisten
t.
size_t new_tail = (tag+1 > this->my_tail) ? tag+1 : this->my_tail;
this->my_tail = (tag+1 > this->my_tail) ? tag+1 : this->my_tail; if(this->size(new_tail) > this->capacity()) {
this->grow_my_array(this->size(new_tail));
if(this->size() > this->capacity()) }
this->grow_my_array(this->size()); // tail already has 1 added this->my_tail = new_tail;
to it if(this->place_item(tag,*(op->elem))) {
this->item(tag) = std::make_pair( *(op->elem), true ); __TBB_store_with_release(op->status, SUCCEEDED);
__TBB_store_with_release(op->status, SUCCEEDED); }
else {
// already have a message with this tag
__TBB_store_with_release(op->status, FAILED);
}
} }
}; }; // sequencer_node
//! Forwards messages in priority order //! Forwards messages in priority order
template< typename T, typename Compare = std::less<T>, typename A=cache_ali gned_allocator<T> > template< typename T, typename Compare = std::less<T>, typename A=cache_ali gned_allocator<T> >
class priority_queue_node : public buffer_node<T, A> { class priority_queue_node : public buffer_node<T, A> {
public: public:
typedef T input_type; typedef T input_type;
typedef T output_type; typedef T output_type;
typedef buffer_node<T,A> base_type; typedef buffer_node<T,A> base_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
skipping to change at line 1782 skipping to change at line 2244
} }
#if TBB_PREVIEW_FLOW_GRAPH_TRACE #if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) { /* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name ); tbb::internal::fgt_node_desc( this, name );
} }
#endif #endif
protected: protected:
/*override*/void reset() { /*override*/void reset( __TBB_PFG_RESET_ARG(reset_flags f)) {
mark = 0; mark = 0;
base_type::reset(); base_type::reset(__TBB_PFG_RESET_ARG(f));
} }
typedef typename buffer_node<T, A>::size_type size_type; typedef typename buffer_node<T, A>::size_type size_type;
typedef typename buffer_node<T, A>::item_type item_type; typedef typename buffer_node<T, A>::item_type item_type;
typedef typename buffer_node<T, A>::buffer_operation prio_operation; typedef typename buffer_node<T, A>::buffer_operation prio_operation;
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
/* override */ void handle_operations(prio_operation *op_list) { /* override */ void handle_operations(prio_operation *op_list) {
prio_operation *tmp = op_list /*, *pop_list*/ ; prio_operation *tmp = op_list /*, *pop_list*/ ;
skipping to change at line 1808 skipping to change at line 2270
op_list = op_list->next; op_list = op_list->next;
switch (tmp->type) { switch (tmp->type) {
case buffer_node<T, A>::reg_succ: this->internal_reg_succ(tmp); try_forwarding = true; break; case buffer_node<T, A>::reg_succ: this->internal_reg_succ(tmp); try_forwarding = true; break;
case buffer_node<T, A>::rem_succ: this->internal_rem_succ(tmp); break; case buffer_node<T, A>::rem_succ: this->internal_rem_succ(tmp); break;
case buffer_node<T, A>::put_item: internal_push(tmp); try_forwa rding = true; break; case buffer_node<T, A>::put_item: internal_push(tmp); try_forwa rding = true; break;
case buffer_node<T, A>::try_fwd_task: internal_forward_task(tmp ); break; case buffer_node<T, A>::try_fwd_task: internal_forward_task(tmp ); break;
case buffer_node<T, A>::rel_res: internal_release(tmp); try_for warding = true; break; case buffer_node<T, A>::rel_res: internal_release(tmp); try_for warding = true; break;
case buffer_node<T, A>::con_res: internal_consume(tmp); try_for warding = true; break; case buffer_node<T, A>::con_res: internal_consume(tmp); try_for warding = true; break;
case buffer_node<T, A>::req_item: internal_pop(tmp); break; case buffer_node<T, A>::req_item: internal_pop(tmp); break;
case buffer_node<T, A>::res_item: internal_reserve(tmp); break; case buffer_node<T, A>::res_item: internal_reserve(tmp); break;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
case buffer_node<T, A>::add_blt_succ: this->internal_add_built_
succ(tmp); break;
case buffer_node<T, A>::del_blt_succ: this->internal_del_built_
succ(tmp); break;
case buffer_node<T, A>::add_blt_pred: this->internal_add_built_
pred(tmp); break;
case buffer_node<T, A>::del_blt_pred: this->internal_del_built_
pred(tmp); break;
case buffer_node<T, A>::blt_succ_cnt: this->internal_succ_cnt(t
mp); break;
case buffer_node<T, A>::blt_pred_cnt: this->internal_pred_cnt(t
mp); break;
case buffer_node<T, A>::blt_succ_cpy: this->internal_copy_succs
(tmp); break;
case buffer_node<T, A>::blt_pred_cpy: this->internal_copy_preds
(tmp); break;
#endif
} }
} }
// process pops! for now, no special pop processing // process pops! for now, no special pop processing
if (mark<this->my_tail) heapify(); if (mark<this->my_tail) heapify();
if (try_forwarding && !this->forwarder_busy) { if (try_forwarding && !this->forwarder_busy) {
task* tp = this->my_graph.root_task(); task* tp = this->my_graph.root_task();
if(tp) { if(tp) {
this->forwarder_busy = true; this->forwarder_busy = true;
task *new_task = new(task::allocate_additional_child_of(*tp )) internal:: task *new_task = new(task::allocate_additional_child_of(*tp )) internal::
forward_task_bypass forward_task_bypass
skipping to change at line 1840 skipping to change at line 2312
task * last_task = NULL; // flagged when a successor accepts task * last_task = NULL; // flagged when a successor accepts
size_type counter = this->my_successors.size(); size_type counter = this->my_successors.size();
if (this->my_reserved || this->my_tail == 0) { if (this->my_reserved || this->my_tail == 0) {
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
this->forwarder_busy = false; this->forwarder_busy = false;
return; return;
} }
// Keep trying to send while there exists an accepting successor // Keep trying to send while there exists an accepting successor
while (counter>0 && this->my_tail > 0) { while (counter>0 && this->my_tail > 0) {
i_copy = this->my_array[0].first; i_copy = this->get_my_item(0);
task * new_task = this->my_successors.try_put_task(i_copy); task * new_task = this->my_successors.try_put_task(i_copy);
last_task = combine_tasks(last_task, new_task);
if ( new_task ) { if ( new_task ) {
if (mark == this->my_tail) --mark; last_task = combine_tasks(last_task, new_task);
--(this->my_tail); this->destroy_item(0); // we've forwarded this item
this->my_array[0].first=this->my_array[this->my_tail].first if (mark == this->my_tail) --mark;
; if(--(this->my_tail)) { // didn't consume last item on heap
this->move_item(0,this->my_tail);
}
if (this->my_tail > 1) // don't reheap for heap of size 1 if (this->my_tail > 1) // don't reheap for heap of size 1
reheap(); reheap();
} }
--counter; --counter;
} }
op->ltask = last_task; op->ltask = last_task;
if (last_task && !counter) if (last_task && !counter)
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
else { else {
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
this->forwarder_busy = false; this->forwarder_busy = false;
} }
} }
/* override */ void internal_push(prio_operation *op) { /* override */ void internal_push(prio_operation *op) {
if ( this->my_tail >= this->my_array_size ) if ( this->my_tail >= this->my_array_size )
this->grow_my_array( this->my_tail + 1 ); this->grow_my_array( this->my_tail + 1 );
this->my_array[this->my_tail] = std::make_pair( *(op->elem), true ) ; (void) this->place_item(this->my_tail, *(op->elem));
++(this->my_tail); ++(this->my_tail);
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} }
/* override */ void internal_pop(prio_operation *op) { /* override */ void internal_pop(prio_operation *op) {
// if empty or already reserved, don't pop
if ( this->my_reserved == true || this->my_tail == 0 ) { if ( this->my_reserved == true || this->my_tail == 0 ) {
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
return;
} }
else { if (mark<this->my_tail && // item pushed, no re-heap
if (mark<this->my_tail && compare(this->get_my_item(0),
compare(this->my_array[0].first, this->get_my_item(this->my_tail-1))) {
this->my_array[this->my_tail-1].first)) { // there are newly pushed elems; last one higher than top
// there are newly pushed elems; last one higher than top // copy the data
// copy the data this->fetch_item(this->my_tail-1, *(op->elem));
*(op->elem) = this->my_array[this->my_tail-1].first; __TBB_store_with_release(op->status, SUCCEEDED);
--(this->my_tail); --(this->my_tail);
__TBB_store_with_release(op->status, SUCCEEDED); return;
}
else { // extract and push the last element down heap
*(op->elem) = this->my_array[0].first; // copy the data
if (mark == this->my_tail) --mark;
--(this->my_tail);
__TBB_store_with_release(op->status, SUCCEEDED);
this->my_array[0].first=this->my_array[this->my_tail].first
;
if (this->my_tail > 1) // don't reheap for heap of size 1
reheap();
}
} }
// extract and push the last element down heap
*(op->elem) = this->get_my_item(0); // copy the data, item 0 still
valid
__TBB_store_with_release(op->status, SUCCEEDED);
if (mark == this->my_tail) --mark;
__TBB_ASSERT(this->my_item_valid(this->my_tail - 1), NULL);
if(--(this->my_tail)) {
// there were two or more items in heap. Move the
// last item to the top of the heap
this->set_my_item(0,this->get_my_item(this->my_tail));
}
this->destroy_item(this->my_tail);
if (this->my_tail > 1) // don't reheap for heap of size 1
reheap();
} }
/* override */ void internal_reserve(prio_operation *op) { /* override */ void internal_reserve(prio_operation *op) {
if (this->my_reserved == true || this->my_tail == 0) { if (this->my_reserved == true || this->my_tail == 0) {
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
return;
} }
else { this->my_reserved = true;
this->my_reserved = true; *(op->elem) = reserved_item = this->get_my_item(0);
*(op->elem) = reserved_item = this->my_array[0].first; if (mark == this->my_tail) --mark;
if (mark == this->my_tail) --mark; --(this->my_tail);
--(this->my_tail); __TBB_store_with_release(op->status, SUCCEEDED);
__TBB_store_with_release(op->status, SUCCEEDED); this->set_my_item(0, this->get_my_item(this->my_tail));
this->my_array[0].first = this->my_array[this->my_tail].first; this->destroy_item(this->my_tail);
if (this->my_tail > 1) // don't reheap for heap of size 1 if (this->my_tail > 1)
reheap(); reheap();
}
} }
/* override */ void internal_consume(prio_operation *op) { /* override */ void internal_consume(prio_operation *op) {
this->my_reserved = false; this->my_reserved = false;
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} }
/* override */ void internal_release(prio_operation *op) { /* override */ void internal_release(prio_operation *op) {
if (this->my_tail >= this->my_array_size) if (this->my_tail >= this->my_array_size)
this->grow_my_array( this->my_tail + 1 ); this->grow_my_array( this->my_tail + 1 );
this->my_array[this->my_tail] = std::make_pair(reserved_item, true) ; this->set_my_item(this->my_tail, reserved_item);
++(this->my_tail); ++(this->my_tail);
this->my_reserved = false; this->my_reserved = false;
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
heapify(); heapify();
} }
private: private:
Compare compare; Compare compare;
size_type mark; size_type mark;
input_type reserved_item; input_type reserved_item;
// turn array into heap
void heapify() { void heapify() {
if (!mark) mark = 1; if (!mark) mark = 1;
for (; mark<this->my_tail; ++mark) { // for each unheaped element for (; mark<this->my_tail; ++mark) { // for each unheaped element
size_type cur_pos = mark; size_type cur_pos = mark;
input_type to_place = this->my_array[mark].first; input_type to_place;
this->fetch_item(mark,to_place);
do { // push to_place up the heap do { // push to_place up the heap
size_type parent = (cur_pos-1)>>1; size_type parent = (cur_pos-1)>>1;
if (!compare(this->my_array[parent].first, to_place)) if (!compare(this->get_my_item(parent), to_place))
break; break;
this->my_array[cur_pos].first = this->my_array[parent].firs t; this->move_item(cur_pos, parent);
cur_pos = parent; cur_pos = parent;
} while( cur_pos ); } while( cur_pos );
this->my_array[cur_pos].first = to_place; (void) this->place_item(cur_pos, to_place);
} }
} }
// otherwise heapified array with new root element; rearrange to heap
void reheap() { void reheap() {
size_type cur_pos=0, child=1; size_type cur_pos=0, child=1;
while (child < mark) { while (child < mark) {
size_type target = child; size_type target = child;
if (child+1<mark && if (child+1<mark &&
compare(this->my_array[child].first, compare(this->get_my_item(child),
this->my_array[child+1].first)) this->get_my_item(child+1)))
++target; ++target;
// target now has the higher priority child // target now has the higher priority child
if (compare(this->my_array[target].first, if (compare(this->get_my_item(target),
this->my_array[this->my_tail].first)) this->get_my_item(cur_pos)))
break; break;
this->my_array[cur_pos].first = this->my_array[target].first; // swap
this->swap_items(cur_pos, target);
cur_pos = target; cur_pos = target;
child = (cur_pos<<1)+1; child = (cur_pos<<1)+1;
} }
this->my_array[cur_pos].first = this->my_array[this->my_tail].first ;
} }
}; }; // priority_queue_node
//! Forwards messages only if the threshold has not been reached //! Forwards messages only if the threshold has not been reached
/** This node forwards items until its threshold is reached. /** This node forwards items until its threshold is reached.
It contains no buffering. If the downstream node rejects, the It contains no buffering. If the downstream node rejects, the
message is dropped. */ message is dropped. */
template< typename T > template< typename T >
class limiter_node : public graph_node, public receiver< T >, public sender < T > { class limiter_node : public graph_node, public receiver< T >, public sender < T > {
protected: protected:
using graph_node::my_graph; using graph_node::my_graph;
public: public:
typedef T input_type; typedef T input_type;
typedef T output_type; typedef T output_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<successor_type *> successor_vector_type;
typedef std::vector<predecessor_type *> predecessor_vector_type;
#endif
private: private:
size_t my_threshold; size_t my_threshold;
size_t my_count; //number of successful puts size_t my_count; //number of successful puts
size_t my_tries; //number of active put attempts size_t my_tries; //number of active put attempts
internal::reservable_predecessor_cache< T > my_predecessors; internal::reservable_predecessor_cache< T, spin_mutex > my_predecessors ;
spin_mutex my_mutex; spin_mutex my_mutex;
internal::broadcast_cache< T > my_successors; internal::broadcast_cache< T > my_successors;
int init_decrement_predecessors; int init_decrement_predecessors;
friend class internal::forward_task_bypass< limiter_node<T> >; friend class internal::forward_task_bypass< limiter_node<T> >;
// Let decrementer call decrement_counter() // Let decrementer call decrement_counter()
friend class internal::decrementer< limiter_node<T> >; friend class internal::decrementer< limiter_node<T> >;
bool check_conditions() { bool check_conditions() { // always called under lock
return ( my_count + my_tries < my_threshold && !my_predecessors.emp ty() && !my_successors.empty() ); return ( my_count + my_tries < my_threshold && !my_predecessors.emp ty() && !my_successors.empty() );
} }
// only returns a valid task pointer or NULL, never SUCCESSFULLY_ENQUEU ED // only returns a valid task pointer or NULL, never SUCCESSFULLY_ENQUEU ED
task *forward_task() { task *forward_task() {
input_type v; input_type v;
task *rval = NULL; task *rval = NULL;
bool reserved = false; bool reserved = false;
{ {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
skipping to change at line 2127 skipping to change at line 2615
} }
//! Removes a successor from this node //! Removes a successor from this node
/** r.remove_predecessor(*this) is also called. */ /** r.remove_predecessor(*this) is also called. */
/* override */ bool remove_successor( receiver<output_type> &r ) { /* override */ bool remove_successor( receiver<output_type> &r ) {
r.remove_predecessor(*this); r.remove_predecessor(*this);
my_successors.remove_successor(r); my_successors.remove_successor(r);
return true; return true;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
/*override*/void internal_add_built_successor(receiver<output_type> &sr
c) {
my_successors.internal_add_built_successor(src);
}
/*override*/void internal_delete_built_successor(receiver<output_type>
&src) {
my_successors.internal_delete_built_successor(src);
}
/*override*/size_t successor_count() { return my_successors.successor_c
ount(); }
/*override*/ void copy_successors(successor_vector_type &v) {
my_successors.copy_successors(v);
}
/*override*/void internal_add_built_predecessor(sender<output_type> &sr
c) {
my_predecessors.internal_add_built_predecessor(src);
}
/*override*/void internal_delete_built_predecessor(sender<output_type>
&src) {
my_predecessors.internal_delete_built_predecessor(src);
}
/*override*/size_t predecessor_count() { return my_predecessors.predece
ssor_count(); }
/*override*/ void copy_predecessors(predecessor_vector_type &v) {
my_predecessors.copy_predecessors(v);
}
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
//! Adds src to the list of cached predecessors. //! Adds src to the list of cached predecessors.
/* override */ bool register_predecessor( predecessor_type &src ) { /* override */ bool register_predecessor( predecessor_type &src ) {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
my_predecessors.add( src ); my_predecessors.add( src );
task* tp = this->my_graph.root_task(); task* tp = this->my_graph.root_task();
if ( my_count + my_tries < my_threshold && !my_successors.empty() & & tp ) { if ( my_count + my_tries < my_threshold && !my_successors.empty() & & tp ) {
FLOW_SPAWN( (* new ( task::allocate_additional_child_of( *tp ) ) FLOW_SPAWN( (* new ( task::allocate_additional_child_of( *tp ) )
internal::forward_task_bypass < limiter_node<T> >( *this ) ) ); internal::forward_task_bypass < limiter_node<T> >( *this ) ) );
} }
return true; return true;
skipping to change at line 2179 skipping to change at line 2697
} }
} }
else { else {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
++my_count; ++my_count;
--my_tries; --my_tries;
} }
return rtask; return rtask;
} }
/*override*/void reset() { /*override*/void reset( __TBB_PFG_RESET_ARG(reset_flags f)) {
my_count = 0; my_count = 0;
my_predecessors.reset(); my_predecessors.reset(__TBB_PFG_RESET_ARG(f));
decrement.reset_receiver(); decrement.reset_receiver(__TBB_PFG_RESET_ARG(f));
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
my_successors.reset(f);
#endif
} }
/*override*/void reset_receiver() { my_predecessors.reset(); } /*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags f)) { m y_predecessors.reset(__TBB_PFG_RESET_ARG(f)); }
}; // limiter_node }; // limiter_node
#include "internal/_flow_graph_join_impl.h" #include "internal/_flow_graph_join_impl.h"
using internal::reserving_port; using internal::reserving_port;
using internal::queueing_port; using internal::queueing_port;
using internal::tag_matching_port; using internal::tag_matching_port;
using internal::input_port; using internal::input_port;
using internal::tag_value; using internal::tag_value;
using internal::NO_TAG; using internal::NO_TAG;
skipping to change at line 2339 skipping to change at line 2860
} }
#if TBB_PREVIEW_FLOW_GRAPH_TRACE #if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) { /* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name ); tbb::internal::fgt_node_desc( this, name );
} }
#endif #endif
}; };
#if TBB_PREVIEW_GRAPH_NODES
// indexer node // indexer node
#include "internal/_flow_graph_indexer_impl.h" #include "internal/_flow_graph_indexer_impl.h"
struct indexer_null_type {}; struct indexer_null_type {};
template<typename T0, typename T1=indexer_null_type, typename T2=indexer_nu ll_type, typename T3=indexer_null_type, template<typename T0, typename T1=indexer_null_type, typename T2=indexer_nu ll_type, typename T3=indexer_null_type,
typename T4=indexer_null_type, typename T5=indexer_nu ll_type, typename T6=indexer_null_type, typename T4=indexer_null_type, typename T5=indexer_nu ll_type, typename T6=indexer_null_type,
typename T7=indexer_null_type, typename T8=indexer_nu ll_type, typename T9=indexer_null_type> class indexer_node; typename T7=indexer_null_type, typename T8=indexer_nu ll_type, typename T9=indexer_null_type> class indexer_node;
//indexer node specializations //indexer node specializations
skipping to change at line 2614 skipping to change at line 3134
} }
#if TBB_PREVIEW_FLOW_GRAPH_TRACE #if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) { /* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name ); tbb::internal::fgt_node_desc( this, name );
} }
#endif #endif
}; };
#endif //variadic max 10 #endif //variadic max 10
#endif // TBB_PREVIEW_GRAPH_NODES
//! Makes an edge between a single predecessor and a single successor //! Makes an edge between a single predecessor and a single successor
template< typename T > template< typename T >
inline void make_edge( sender<T> &p, receiver<T> &s ) { inline void make_edge( sender<T> &p, receiver<T> &s ) {
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
s.internal_add_built_predecessor(p);
p.internal_add_built_successor(s);
#endif
p.register_successor( s ); p.register_successor( s );
tbb::internal::fgt_make_edge( &p, &s ); tbb::internal::fgt_make_edge( &p, &s );
} }
//! Makes an edge between a single predecessor and a single successor //! Makes an edge between a single predecessor and a single successor
template< typename T > template< typename T >
inline void remove_edge( sender<T> &p, receiver<T> &s ) { inline void remove_edge( sender<T> &p, receiver<T> &s ) {
p.remove_successor( s ); p.remove_successor( s );
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
// TODO: should we try to remove p from the predecessor list of s, in c
ase the edge is reversed?
p.internal_delete_built_successor(s);
s.internal_delete_built_predecessor(p);
#endif
tbb::internal::fgt_remove_edge( &p, &s ); tbb::internal::fgt_remove_edge( &p, &s );
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
template<typename C >
template< typename S >
void edge_container<C>::sender_extract( S &s ) {
edge_vector e = built_edges;
for ( typename edge_vector::iterator i = e.begin(); i != e.end(); ++i )
{
remove_edge(s, **i);
}
}
template<typename C >
template< typename R >
void edge_container<C>::receiver_extract( R &r ) {
edge_vector e = built_edges;
for ( typename edge_vector::iterator i = e.begin(); i != e.end(); ++i )
{
remove_edge(**i, r);
}
}
#endif
//! Returns a copy of the body from a function or continue node //! Returns a copy of the body from a function or continue node
template< typename Body, typename Node > template< typename Body, typename Node >
Body copy_body( Node &n ) { Body copy_body( Node &n ) {
return n.template copy_function_object<Body>(); return n.template copy_function_object<Body>();
} }
} // interface7 } // interface7
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
using interface7::reset_flags;
using interface7::rf_reset_protocol;
using interface7::rf_reset_bodies;
using interface7::rf_extract;
#endif
using interface7::graph; using interface7::graph;
using interface7::graph_node; using interface7::graph_node;
using interface7::continue_msg; using interface7::continue_msg;
using interface7::sender; using interface7::sender;
using interface7::receiver; using interface7::receiver;
using interface7::continue_receiver; using interface7::continue_receiver;
using interface7::source_node; using interface7::source_node;
using interface7::function_node; using interface7::function_node;
using interface7::multifunction_node; using interface7::multifunction_node;
using interface7::split_node; using interface7::split_node;
using interface7::internal::output_port; using interface7::internal::output_port;
#if TBB_PREVIEW_GRAPH_NODES
using interface7::indexer_node; using interface7::indexer_node;
using interface7::internal::tagged_msg; using interface7::internal::tagged_msg;
using interface7::internal::cast_to; using interface7::internal::cast_to;
using interface7::internal::is_a; using interface7::internal::is_a;
#endif
using interface7::continue_node; using interface7::continue_node;
using interface7::overwrite_node; using interface7::overwrite_node;
using interface7::write_once_node; using interface7::write_once_node;
using interface7::broadcast_node; using interface7::broadcast_node;
using interface7::buffer_node; using interface7::buffer_node;
using interface7::queue_node; using interface7::queue_node;
using interface7::sequencer_node; using interface7::sequencer_node;
using interface7::priority_queue_node; using interface7::priority_queue_node;
using interface7::limiter_node; using interface7::limiter_node;
using namespace interface7::internal::graph_policy_namespace; using namespace interface7::internal::graph_policy_namespace;
skipping to change at line 2677 skipping to change at line 3229
using interface7::input_port; using interface7::input_port;
using interface7::copy_body; using interface7::copy_body;
using interface7::make_edge; using interface7::make_edge;
using interface7::remove_edge; using interface7::remove_edge;
using interface7::internal::NO_TAG; using interface7::internal::NO_TAG;
using interface7::internal::tag_value; using interface7::internal::tag_value;
} // flow } // flow
} // tbb } // tbb
#undef __TBB_PFG_RESET_ARG
#undef __TBB_COMMA
#endif // __TBB_flow_graph_H #endif // __TBB_flow_graph_H
 End of changes. 126 change blocks. 
177 lines changed or deleted 790 lines changed or added


 gcc_armv7.h   gcc_armv7.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
/* /*
Platform isolation layer for the ARMv7-a architecture. Platform isolation layer for the ARMv7-a architecture.
*/ */
#ifndef __TBB_machine_H #ifndef __TBB_machine_H
#error Do not include this file directly; include tbb_machine.h instead #error Do not include this file directly; include tbb_machine.h instead
#endif #endif
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 gcc_generic.h   gcc_generic.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#if !defined(__TBB_machine_H) || defined(__TBB_machine_gcc_generic_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_gcc_generic_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_gcc_generic_H #define __TBB_machine_gcc_generic_H
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 gcc_ia32_common.h   gcc_ia32_common.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_machine_gcc_ia32_common_H #ifndef __TBB_machine_gcc_ia32_common_H
#define __TBB_machine_gcc_ia32_common_H #define __TBB_machine_gcc_ia32_common_H
//TODO: Add a higher-level function, e.g. tbb::interal::log2(), into tbb_st ddef.h, which //TODO: Add a higher-level function, e.g. tbb::interal::log2(), into tbb_st ddef.h, which
//uses __TBB_Log2 and contains the assert and remove the assert from here a nd all other //uses __TBB_Log2 and contains the assert and remove the assert from here a nd all other
//platform-specific headers. //platform-specific headers.
//TODO: Check if use of gcc intrinsic gives a better chance for cross call optimizations //TODO: Check if use of gcc intrinsic gives a better chance for cross call optimizations
static inline intptr_t __TBB_machine_lg( uintptr_t x ) { template <typename T>
__TBB_ASSERT(x, "__TBB_Log2(0) undefined"); static inline intptr_t __TBB_machine_lg( T x ) {
__TBB_ASSERT(x>0, "The logarithm of a non-positive value is undefined."
);
uintptr_t j; uintptr_t j;
__asm__ ("bsr %1,%0" : "=r"(j) : "r"(x)); __asm__("bsr %1,%0" : "=r"(j) : "r"((uintptr_t)x));
return j; return j;
} }
#define __TBB_Log2(V) __TBB_machine_lg(V) #define __TBB_Log2(V) __TBB_machine_lg(V)
#ifndef __TBB_Pause #ifndef __TBB_Pause
//TODO: check if raising a ratio of pause instructions to loop control inst ructions //TODO: check if raising a ratio of pause instructions to loop control inst ructions
//(via e.g. loop unrolling) gives any benefit for HT. E.g, the current imp lementation //(via e.g. loop unrolling) gives any benefit for HT. E.g, the current imp lementation
//does about 2 CPU-consuming instructions for every pause instruction. Per haps for //does about 2 CPU-consuming instructions for every pause instruction. Per haps for
//high pause counts it should use an unrolled loop to raise the ratio, and thus free //high pause counts it should use an unrolled loop to raise the ratio, and thus free
//up more integer cycles for the other hyperthread. On the other hand, if the loop is //up more integer cycles for the other hyperthread. On the other hand, if the loop is
 End of changes. 3 change blocks. 
31 lines changed or deleted 34 lines changed or added


 gcc_itsx.h   gcc_itsx.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#if !defined(__TBB_machine_H) || defined(__TBB_machine_gcc_itsx_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_gcc_itsx_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_gcc_itsx_H #define __TBB_machine_gcc_itsx_H
#define __TBB_OP_XACQUIRE 0xF2 #define __TBB_OP_XACQUIRE 0xF2
#define __TBB_OP_XRELEASE 0xF3 #define __TBB_OP_XRELEASE 0xF3
skipping to change at line 72 skipping to change at line 64
inline static void __TBB_machine_unlock_elided( volatile uint8_t* lk ) inline static void __TBB_machine_unlock_elided( volatile uint8_t* lk )
{ {
__asm__ volatile (".byte " __TBB_STRINGIZE(__TBB_OP_XRELEASE)"; movb $0 , %0" __asm__ volatile (".byte " __TBB_STRINGIZE(__TBB_OP_XRELEASE)"; movb $0 , %0"
: "=m"(*lk) : "m"(*lk) : "memory" ); : "=m"(*lk) : "m"(*lk) : "memory" );
} }
#if __TBB_TSX_INTRINSICS_PRESENT #if __TBB_TSX_INTRINSICS_PRESENT
#include <immintrin.h> #include <immintrin.h>
#define __TBB_machine_is_in_transaction _xtest #define __TBB_machine_is_in_transaction _xtest
#define __TBB_machine_begin_transaction _xbegin
#define __TBB_machine_end_transaction _xend
#define __TBB_machine_transaction_conflict_abort() _xabort(0xff)
#else #else
/*! /*!
* Check if the instruction is executed in a transaction or not * Check if the instruction is executed in a transaction or not
*/ */
inline static bool __TBB_machine_is_in_transaction() inline static bool __TBB_machine_is_in_transaction()
{ {
int8_t res = 0; int8_t res = 0;
#if __TBB_x86_32 #if __TBB_x86_32
__asm__ volatile (".byte 0x0F; .byte 0x01; .byte 0xD6;\n" __asm__ volatile (".byte 0x0F; .byte 0x01; .byte 0xD6;\n"
"setz %0" : "=q"(res) : : "memory" ); "setz %0" : "=q"(res) : : "memory" );
#else #else
__asm__ volatile (".byte 0x0F; .byte 0x01; .byte 0xD6;\n" __asm__ volatile (".byte 0x0F; .byte 0x01; .byte 0xD6;\n"
"setz %0" : "=r"(res) : : "memory" ); "setz %0" : "=r"(res) : : "memory" );
#endif #endif
return res==0; return res==0;
} }
#endif /* __TBB_TSX_INTRINSICS_PRESENT */
#if TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX
#if __TBB_TSX_INTRINSICS_PRESENT
#define __TBB_machine_begin_transaction _xbegin
#define __TBB_machine_end_transaction _xend
#define __TBB_machine_transaction_conflict_abort() _xabort(0xff)
#else
/*! /*!
* Enter speculative execution mode. * Enter speculative execution mode.
* @return -1 on success * @return -1 on success
* abort cause ( or 0 ) on abort * abort cause ( or 0 ) on abort
*/ */
inline static uint32_t __TBB_machine_begin_transaction() inline static uint32_t __TBB_machine_begin_transaction()
{ {
uint32_t res = ~uint32_t(0); // success value uint32_t res = ~uint32_t(0); // success value
__asm__ volatile ("1: .byte 0xC7; .byte 0xF8;\n" // XBEGIN <abort-offset> __asm__ volatile ("1: .byte 0xC7; .byte 0xF8;\n" // XBEGIN <abort-offset>
skipping to change at line 140 skipping to change at line 124
/* /*
* aborts with code 0xFF (lock already held) * aborts with code 0xFF (lock already held)
*/ */
inline static void __TBB_machine_transaction_conflict_abort() inline static void __TBB_machine_transaction_conflict_abort()
{ {
__asm__ volatile (".byte 0xC6; .byte 0xF8; .byte 0xFF" :::"memory"); __asm__ volatile (".byte 0xC6; .byte 0xF8; .byte 0xFF" :::"memory");
} }
#endif /* __TBB_TSX_INTRINSICS_PRESENT */ #endif /* __TBB_TSX_INTRINSICS_PRESENT */
#endif // TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX
 End of changes. 4 change blocks. 
39 lines changed or deleted 32 lines changed or added


 ibm_aix51.h   ibm_aix51.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
// TODO: revise by comparing with mac_ppc.h // TODO: revise by comparing with mac_ppc.h
#if !defined(__TBB_machine_H) || defined(__TBB_machine_ibm_aix51_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_ibm_aix51_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_ibm_aix51_H #define __TBB_machine_ibm_aix51_H
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 icc_generic.h   icc_generic.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#if !defined(__TBB_machine_H) || defined(__TBB_machine_icc_generic_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_icc_generic_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#if ! __TBB_ICC_BUILTIN_ATOMICS_PRESENT #if ! __TBB_ICC_BUILTIN_ATOMICS_PRESENT
#error "Intel C++ Compiler of at least 12.0 version is needed to use IC C intrinsics port" #error "Intel C++ Compiler of at least 12.0 version is needed to use IC C intrinsics port"
#endif #endif
skipping to change at line 60 skipping to change at line 52
#define __TBB_WORDSIZE 4 #define __TBB_WORDSIZE 4
#else #else
#define __TBB_WORDSIZE 8 #define __TBB_WORDSIZE 8
#endif #endif
#define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE #define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE
//__TBB_compiler_fence() defined just in case, as it seems not to be used o n its own anywhere else //__TBB_compiler_fence() defined just in case, as it seems not to be used o n its own anywhere else
#if _MSC_VER #if _MSC_VER
//TODO: any way to use same intrinsics on windows and linux? //TODO: any way to use same intrinsics on windows and linux?
#pragma intrinsic(_ReadWriteBarrier) #pragma intrinsic(_ReadWriteBarrier)
#pragma intrinsic(_mm_mfence)
#define __TBB_compiler_fence() _ReadWriteBarrier() #define __TBB_compiler_fence() _ReadWriteBarrier()
#define __TBB_full_memory_fence() _mm_mfence()
#else #else
#define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") #define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory")
#endif
#ifndef __TBB_full_memory_fence
#if _MSC_VER
//TODO: any way to use same intrinsics on windows and linux?
#pragma intrinsic(_mm_mfence)
#define __TBB_full_memory_fence() _mm_mfence()
#else
#define __TBB_full_memory_fence() __asm__ __volatile__("mfence": : :"me mory") #define __TBB_full_memory_fence() __asm__ __volatile__("mfence": : :"me mory")
#endif #endif
#endif
#define __TBB_control_consistency_helper() __TBB_compiler_fence() #define __TBB_control_consistency_helper() __TBB_compiler_fence()
namespace tbb { namespace internal { namespace tbb { namespace internal {
//TODO: is there any way to reuse definition of memory_order enum from ICC instead of copy paste. //TODO: is there any way to reuse definition of memory_order enum from ICC instead of copy paste.
//however it seems unlikely that ICC will silently change exact enum values , as they are defined //however it seems unlikely that ICC will silently change exact enum values , as they are defined
//in the ISO exactly like this. //in the ISO exactly like this.
//TODO: add test that exact values of the enum are same as in the ISO C++11 //TODO: add test that exact values of the enum are same as in the ISO C++11
typedef enum memory_order { typedef enum memory_order {
memory_order_relaxed, memory_order_consume, memory_order_acquire, memory_order_relaxed, memory_order_consume, memory_order_acquire,
 End of changes. 5 change blocks. 
30 lines changed or deleted 38 lines changed or added


 linux_common.h   linux_common.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_machine_H #ifndef __TBB_machine_H
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#include <sched.h> #include <sched.h>
#define __TBB_Yield() sched_yield() #define __TBB_Yield() sched_yield()
#include <unistd.h> #include <unistd.h>
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 linux_ia32.h   linux_ia32.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_ia32_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_ia32_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_linux_ia32_H #define __TBB_machine_linux_ia32_H
#include <stdint.h> #include <stdint.h>
#include "gcc_ia32_common.h" #include "gcc_ia32_common.h"
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 linux_ia64.h   linux_ia64.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_ia64_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_ia64_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_linux_ia64_H #define __TBB_machine_linux_ia64_H
#include <stdint.h> #include <stdint.h>
#include <ia64intrin.h> #include <ia64intrin.h>
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 linux_intel64.h   linux_intel64.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_intel64_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_intel64_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_linux_intel64_H #define __TBB_machine_linux_intel64_H
#include <stdint.h> #include <stdint.h>
#include "gcc_ia32_common.h" #include "gcc_ia32_common.h"
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 mac_ppc.h   mac_ppc.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#if !defined(__TBB_machine_H) || defined(__TBB_machine_gcc_power_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_gcc_power_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_gcc_power_H #define __TBB_machine_gcc_power_H
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 macos_common.h   macos_common.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#if !defined(__TBB_machine_H) || defined(__TBB_machine_macos_common_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_macos_common_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_macos_common_H #define __TBB_machine_macos_common_H
#include <sched.h> #include <sched.h>
#define __TBB_Yield() sched_yield() #define __TBB_Yield() sched_yield()
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 memory_pool.h   memory_pool.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_memory_pool_H #ifndef __TBB_memory_pool_H
#define __TBB_memory_pool_H #define __TBB_memory_pool_H
#if !TBB_PREVIEW_MEMORY_POOL #if !TBB_PREVIEW_MEMORY_POOL
#error Set TBB_PREVIEW_MEMORY_POOL to include memory_pool.h #error Set TBB_PREVIEW_MEMORY_POOL to include memory_pool.h
#endif #endif
/** @file */ /** @file */
#include "scalable_allocator.h" #include "scalable_allocator.h"
#include <new> // std::bad_alloc #include <new> // std::bad_alloc
#if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN #if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
#include <utility> // std::forward #include <utility> // std::forward
#endif #endif
#if __TBB_EXTRA_DEBUG #if __TBB_EXTRA_DEBUG
#define __TBBMALLOC_ASSERT ASSERT #define __TBBMALLOC_ASSERT ASSERT
#else #else
#define __TBBMALLOC_ASSERT(a,b) ((void)0) #define __TBBMALLOC_ASSERT(a,b) ((void)0)
#endif #endif
namespace tbb { namespace tbb {
skipping to change at line 140 skipping to change at line 132
} }
//! Largest value for which method allocate might succeed. //! Largest value for which method allocate might succeed.
size_type max_size() const throw() { size_type max_size() const throw() {
size_type max = static_cast<size_type>(-1) / sizeof (value_type); size_type max = static_cast<size_type>(-1) / sizeof (value_type);
return (max > 0 ? max : 1); return (max > 0 ? max : 1);
} }
//! Copy-construct value at location pointed to by p. //! Copy-construct value at location pointed to by p.
#if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC #if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
template<typename U, typename... Args> template<typename U, typename... Args>
void construct(U *p, Args&&... args) void construct(U *p, Args&&... args)
#if __TBB_CPP11_STD_FORWARD_BROKEN
{ ::new((void *)p) U((args)...); }
#else
{ ::new((void *)p) U(std::forward<Args>(args)...); } { ::new((void *)p) U(std::forward<Args>(args)...); }
#endif
#else // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC #else // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
#if __TBB_CPP11_RVALUE_REF_PRESENT
void construct( pointer p, value_type&& value ) {::new((void*)(p)) valu
e_type(std::move(value));}
#endif
void construct( pointer p, const value_type& value ) { ::new((void*)(p) ) value_type(value); } void construct( pointer p, const value_type& value ) { ::new((void*)(p) ) value_type(value); }
#endif // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC #endif // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
//! Destroy value at location pointed to by p. //! Destroy value at location pointed to by p.
void destroy( pointer p ) { p->~value_type(); } void destroy( pointer p ) { p->~value_type(); }
}; };
#if _MSC_VER && !defined(__INTEL_COMPILER) #if _MSC_VER && !defined(__INTEL_COMPILER)
#pragma warning (pop) #pragma warning (pop)
 End of changes. 5 change blocks. 
33 lines changed or deleted 34 lines changed or added


 mic_common.h   mic_common.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_mic_common_H #ifndef __TBB_mic_common_H
#define __TBB_mic_common_H #define __TBB_mic_common_H
#ifndef __TBB_machine_H #ifndef __TBB_machine_H
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#if ! __TBB_DEFINE_MIC #if ! __TBB_DEFINE_MIC
skipping to change at line 50 skipping to change at line 42
#ifndef __TBB_PREFETCHING #ifndef __TBB_PREFETCHING
#define __TBB_PREFETCHING 1 #define __TBB_PREFETCHING 1
#endif #endif
#if __TBB_PREFETCHING #if __TBB_PREFETCHING
#include <immintrin.h> #include <immintrin.h>
#define __TBB_cl_prefetch(p) _mm_prefetch((const char*)p, _MM_HINT_T1) #define __TBB_cl_prefetch(p) _mm_prefetch((const char*)p, _MM_HINT_T1)
#define __TBB_cl_evict(p) _mm_clevict(p, _MM_HINT_T1) #define __TBB_cl_evict(p) _mm_clevict(p, _MM_HINT_T1)
#endif #endif
/** Intel(R) Many Integrated Core Architecture does not support mfence and pause instructions **/ /** Intel(R) Many Integrated Core Architecture does not support mfence and pause instructions **/
#if !TBB_USE_ICC_BUILTINS #define __TBB_full_memory_fence() __asm__ __volatile__("lock; addl $0,(%%rs
#define __TBB_full_memory_fence() __asm__ __volatile__("lock; addl $0,( p)":::"memory")
%%rsp)":::"memory")
#endif
#define __TBB_Pause(x) _mm_delay_32(16*(x)) #define __TBB_Pause(x) _mm_delay_32(16*(x))
#define __TBB_STEALING_PAUSE 1500/16 #define __TBB_STEALING_PAUSE 1500/16
#include <sched.h> #include <sched.h>
#define __TBB_Yield() sched_yield() #define __TBB_Yield() sched_yield()
// low-level timing intrinsic and its type // low-level timing intrinsic and its type
#define __TBB_machine_time_stamp() _rdtsc() #define __TBB_machine_time_stamp() _rdtsc()
typedef uint64_t machine_tsc_t; typedef uint64_t machine_tsc_t;
/** Specifics **/ /** Specifics **/
 End of changes. 2 change blocks. 
32 lines changed or deleted 31 lines changed or added


 msvc_armv7.h   msvc_armv7.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#if !defined(__TBB_machine_H) || defined(__TBB_msvc_armv7_H) #if !defined(__TBB_machine_H) || defined(__TBB_msvc_armv7_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_msvc_armv7_H #define __TBB_msvc_armv7_H
#include <intrin.h> #include <intrin.h>
#include <float.h> #include <float.h>
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 msvc_ia32_common.h   msvc_ia32_common.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_machine_msvc_ia32_common_H #ifndef __TBB_machine_msvc_ia32_common_H
#define __TBB_machine_msvc_ia32_common_H #define __TBB_machine_msvc_ia32_common_H
#include <intrin.h> #include <intrin.h>
//TODO: consider moving this macro to tbb_config.h and used there MSVC asm is used //TODO: consider moving this macro to tbb_config.h and used there MSVC asm is used
#if !_M_X64 || __INTEL_COMPILER #if !_M_X64 || __INTEL_COMPILER
#define __TBB_X86_MSVC_INLINE_ASM_AVAILABLE 1 #define __TBB_X86_MSVC_INLINE_ASM_AVAILABLE 1
skipping to change at line 208 skipping to change at line 200
extern "C" { extern "C" {
__int8 __TBB_EXPORTED_FUNC __TBB_machine_try_lock_elided (volatile void * ptr); __int8 __TBB_EXPORTED_FUNC __TBB_machine_try_lock_elided (volatile void * ptr);
void __TBB_EXPORTED_FUNC __TBB_machine_unlock_elided (volatile void* ptr); void __TBB_EXPORTED_FUNC __TBB_machine_unlock_elided (volatile void* ptr);
// 'pause' instruction aborts HLE/RTM transactions // 'pause' instruction aborts HLE/RTM transactions
#if __TBB_PAUSE_USE_INTRINSIC #if __TBB_PAUSE_USE_INTRINSIC
inline static void __TBB_machine_try_lock_elided_cancel() { _mm_pause() ; } inline static void __TBB_machine_try_lock_elided_cancel() { _mm_pause() ; }
#else #else
inline static void __TBB_machine_try_lock_elided_cancel() { _asm pause; } inline static void __TBB_machine_try_lock_elided_cancel() { _asm pause; }
#endif #endif
#if __TBB_TSX_INTRINSICS_PRESENT
#define __TBB_machine_is_in_transaction _xtest
#else
__int8 __TBB_EXPORTED_FUNC __TBB_machine_is_in_transaction();
#endif /* __TBB_TSX_INTRINSICS_PRESENT */
#if TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX
#if __TBB_TSX_INTRINSICS_PRESENT #if __TBB_TSX_INTRINSICS_PRESENT
#define __TBB_machine_is_in_transaction _xtest
#define __TBB_machine_begin_transaction _xbegin #define __TBB_machine_begin_transaction _xbegin
#define __TBB_machine_end_transaction _xend #define __TBB_machine_end_transaction _xend
// The value (0xFF) below comes from the // The value (0xFF) below comes from the
// Intel(R) 64 and IA-32 Architectures Optimization Reference Manual 12 .4.5 lock not free // Intel(R) 64 and IA-32 Architectures Optimization Reference Manual 12 .4.5 lock not free
#define __TBB_machine_transaction_conflict_abort() _xabort(0xFF) #define __TBB_machine_transaction_conflict_abort() _xabort(0xFF)
#else #else
__int8 __TBB_EXPORTED_FUNC __TBB_machine_is_in_transaction();
unsigned __int32 __TBB_EXPORTED_FUNC __TBB_machine_begin_transaction(); unsigned __int32 __TBB_EXPORTED_FUNC __TBB_machine_begin_transaction();
void __TBB_EXPORTED_FUNC __TBB_machine_end_transaction(); void __TBB_EXPORTED_FUNC __TBB_machine_end_transaction();
void __TBB_EXPORTED_FUNC __TBB_machine_transaction_conflict _abort(); void __TBB_EXPORTED_FUNC __TBB_machine_transaction_conflict _abort();
#endif /* __TBB_TSX_INTRINSICS_PRESENT */ #endif /* __TBB_TSX_INTRINSICS_PRESENT */
#endif /* TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX */
} }
#endif /* __TBB_machine_msvc_ia32_common_H */ #endif /* __TBB_machine_msvc_ia32_common_H */
 End of changes. 8 change blocks. 
42 lines changed or deleted 34 lines changed or added


 mutex.h   mutex.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_mutex_H #ifndef __TBB_mutex_H
#define __TBB_mutex_H #define __TBB_mutex_H
#if _WIN32||_WIN64 #if _WIN32||_WIN64
#include "machine/windows_api.h" #include "machine/windows_api.h"
#else #else
#include <pthread.h> #include <pthread.h>
#endif /* _WIN32||_WIN64 */ #endif /* _WIN32||_WIN64 */
skipping to change at line 48 skipping to change at line 40
#include <new> #include <new>
#include "aligned_space.h" #include "aligned_space.h"
#include "tbb_stddef.h" #include "tbb_stddef.h"
#include "tbb_profiling.h" #include "tbb_profiling.h"
namespace tbb { namespace tbb {
//! Wrapper around the platform's native reader-writer lock. //! Wrapper around the platform's native reader-writer lock.
/** For testing purposes only. /** For testing purposes only.
@ingroup synchronization */ @ingroup synchronization */
class mutex { class mutex : internal::mutex_copy_deprecated_and_disabled {
public: public:
//! Construct unacquired mutex. //! Construct unacquired mutex.
mutex() { mutex() {
#if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
internal_construct(); internal_construct();
#else #else
#if _WIN32||_WIN64 #if _WIN32||_WIN64
InitializeCriticalSectionEx(&impl, 4000, 0); InitializeCriticalSectionEx(&impl, 4000, 0);
#else #else
int error_code = pthread_mutex_init(&impl,NULL); int error_code = pthread_mutex_init(&impl,NULL);
skipping to change at line 164 skipping to change at line 156
//! Acquire lock //! Acquire lock
void lock() { void lock() {
#if TBB_USE_ASSERT #if TBB_USE_ASSERT
aligned_space<scoped_lock> tmp; aligned_space<scoped_lock> tmp;
new(tmp.begin()) scoped_lock(*this); new(tmp.begin()) scoped_lock(*this);
#else #else
#if _WIN32||_WIN64 #if _WIN32||_WIN64
EnterCriticalSection(&impl); EnterCriticalSection(&impl);
#else #else
pthread_mutex_lock(&impl); int error_code = pthread_mutex_lock(&impl);
if( error_code )
tbb::internal::handle_perror(error_code,"mutex: pthread_mutex_l
ock failed");
#endif /* _WIN32||_WIN64 */ #endif /* _WIN32||_WIN64 */
#endif /* TBB_USE_ASSERT */ #endif /* TBB_USE_ASSERT */
} }
//! Try acquiring lock (non-blocking) //! Try acquiring lock (non-blocking)
/** Return true if lock acquired; false otherwise. */ /** Return true if lock acquired; false otherwise. */
bool try_lock() { bool try_lock() {
#if TBB_USE_ASSERT #if TBB_USE_ASSERT
aligned_space<scoped_lock> tmp; aligned_space<scoped_lock> tmp;
scoped_lock& s = *tmp.begin(); scoped_lock& s = *tmp.begin();
 End of changes. 3 change blocks. 
30 lines changed or deleted 34 lines changed or added


 null_mutex.h   null_mutex.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_null_mutex_H #ifndef __TBB_null_mutex_H
#define __TBB_null_mutex_H #define __TBB_null_mutex_H
#include "tbb_stddef.h"
namespace tbb { namespace tbb {
//! A mutex which does nothing //! A mutex which does nothing
/** A null_mutex does no operation and simulates success. /** A null_mutex does no operation and simulates success.
@ingroup synchronization */ @ingroup synchronization */
class null_mutex { class null_mutex : internal::mutex_copy_deprecated_and_disabled {
//! Deny assignment and copy construction
null_mutex( const null_mutex& );
void operator=( const null_mutex& );
public: public:
//! Represents acquisition of a mutex. //! Represents acquisition of a mutex.
class scoped_lock { class scoped_lock : internal::no_copy {
public: public:
scoped_lock() {} scoped_lock() {}
scoped_lock( null_mutex& ) {} scoped_lock( null_mutex& ) {}
~scoped_lock() {} ~scoped_lock() {}
void acquire( null_mutex& ) {} void acquire( null_mutex& ) {}
bool try_acquire( null_mutex& ) { return true; } bool try_acquire( null_mutex& ) { return true; }
void release() {} void release() {}
}; };
null_mutex() {} null_mutex() {}
 End of changes. 4 change blocks. 
33 lines changed or deleted 33 lines changed or added


 null_rw_mutex.h   null_rw_mutex.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_null_rw_mutex_H #ifndef __TBB_null_rw_mutex_H
#define __TBB_null_rw_mutex_H #define __TBB_null_rw_mutex_H
#include "tbb_stddef.h"
namespace tbb { namespace tbb {
//! A rw mutex which does nothing //! A rw mutex which does nothing
/** A null_rw_mutex is a rw mutex that does nothing and simulates successfu l operation. /** A null_rw_mutex is a rw mutex that does nothing and simulates successfu l operation.
@ingroup synchronization */ @ingroup synchronization */
class null_rw_mutex { class null_rw_mutex : internal::mutex_copy_deprecated_and_disabled {
//! Deny assignment and copy construction
null_rw_mutex( const null_rw_mutex& );
void operator=( const null_rw_mutex& );
public: public:
//! Represents acquisition of a mutex. //! Represents acquisition of a mutex.
class scoped_lock { class scoped_lock : internal::no_copy {
public: public:
scoped_lock() {} scoped_lock() {}
scoped_lock( null_rw_mutex& , bool = true ) {} scoped_lock( null_rw_mutex& , bool = true ) {}
~scoped_lock() {} ~scoped_lock() {}
void acquire( null_rw_mutex& , bool = true ) {} void acquire( null_rw_mutex& , bool = true ) {}
bool upgrade_to_writer() { return true; } bool upgrade_to_writer() { return true; }
bool downgrade_to_reader() { return true; } bool downgrade_to_reader() { return true; }
bool try_acquire( null_rw_mutex& , bool = true ) { return true; } bool try_acquire( null_rw_mutex& , bool = true ) { return true; }
void release() {} void release() {}
}; };
 End of changes. 4 change blocks. 
33 lines changed or deleted 33 lines changed or added


 parallel_do.h   parallel_do.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_parallel_do_H #ifndef __TBB_parallel_do_H
#define __TBB_parallel_do_H #define __TBB_parallel_do_H
#include "internal/_range_iterator.h"
#include "task.h" #include "task.h"
#include "aligned_space.h" #include "aligned_space.h"
#include <iterator> #include <iterator>
namespace tbb { namespace tbb {
//! @cond INTERNAL //! @cond INTERNAL
namespace internal { namespace internal {
template<typename Body, typename Item> class parallel_do_feeder_impl; template<typename Body, typename Item> class parallel_do_feeder_impl;
template<typename Body> class do_group_task; template<typename Body> class do_group_task;
skipping to change at line 490 skipping to change at line 483
#if __TBB_TASK_GROUP_CONTEXT #if __TBB_TASK_GROUP_CONTEXT
task_group_context context; task_group_context context;
#endif // __TBB_TASK_GROUP_CONTEXT #endif // __TBB_TASK_GROUP_CONTEXT
internal::select_parallel_do( first, last, body, &Body::operator() internal::select_parallel_do( first, last, body, &Body::operator()
#if __TBB_TASK_GROUP_CONTEXT #if __TBB_TASK_GROUP_CONTEXT
, context , context
#endif // __TBB_TASK_GROUP_CONTEXT #endif // __TBB_TASK_GROUP_CONTEXT
); );
} }
template<typename Range, typename Body>
void parallel_do(Range& rng, const Body& body) {
parallel_do(tbb::internal::first(rng), tbb::internal::last(rng), body);
}
template<typename Range, typename Body>
void parallel_do(const Range& rng, const Body& body) {
parallel_do(tbb::internal::first(rng), tbb::internal::last(rng), body);
}
#if __TBB_TASK_GROUP_CONTEXT #if __TBB_TASK_GROUP_CONTEXT
//! Parallel iteration over a range, with optional addition of more work an d user-supplied context //! Parallel iteration over a range, with optional addition of more work an d user-supplied context
/** @ingroup algorithms */ /** @ingroup algorithms */
template<typename Iterator, typename Body> template<typename Iterator, typename Body>
void parallel_do( Iterator first, Iterator last, const Body& body, task_gro up_context& context ) void parallel_do( Iterator first, Iterator last, const Body& body, task_gro up_context& context )
{ {
if ( first == last ) if ( first == last )
return; return;
internal::select_parallel_do( first, last, body, &Body::operator(), con text ); internal::select_parallel_do( first, last, body, &Body::operator(), con text );
} }
template<typename Range, typename Body>
void parallel_do(Range& rng, const Body& body, task_group_context& context)
{
parallel_do(tbb::internal::first(rng), tbb::internal::last(rng), body,
context);
}
template<typename Range, typename Body>
void parallel_do(const Range& rng, const Body& body, task_group_context& co
ntext) {
parallel_do(tbb::internal::first(rng), tbb::internal::last(rng), body,
context);
}
#endif // __TBB_TASK_GROUP_CONTEXT #endif // __TBB_TASK_GROUP_CONTEXT
//@} //@}
} // namespace } // namespace
#endif /* __TBB_parallel_do_H */ #endif /* __TBB_parallel_do_H */
 End of changes. 4 change blocks. 
28 lines changed or deleted 55 lines changed or added


 parallel_for.h   parallel_for.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_parallel_for_H #ifndef __TBB_parallel_for_H
#define __TBB_parallel_for_H #define __TBB_parallel_for_H
#include <new> #include <new>
#include "task.h" #include "task.h"
#include "partitioner.h" #include "partitioner.h"
#include "blocked_range.h" #include "blocked_range.h"
#include "tbb_exception.h" #include "tbb_exception.h"
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 parallel_for_each.h   parallel_for_each.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_parallel_for_each_H #ifndef __TBB_parallel_for_each_H
#define __TBB_parallel_for_each_H #define __TBB_parallel_for_each_H
#include "parallel_do.h" #include "parallel_do.h"
namespace tbb { namespace tbb {
//! @cond INTERNAL //! @cond INTERNAL
skipping to change at line 64 skipping to change at line 56
**/ **/
//@{ //@{
//! Calls function f for all items from [first, last) interval using user-s upplied context //! Calls function f for all items from [first, last) interval using user-s upplied context
/** @ingroup algorithms */ /** @ingroup algorithms */
#if __TBB_TASK_GROUP_CONTEXT #if __TBB_TASK_GROUP_CONTEXT
template<typename InputIterator, typename Function> template<typename InputIterator, typename Function>
void parallel_for_each(InputIterator first, InputIterator last, const Funct ion& f, task_group_context &context) { void parallel_for_each(InputIterator first, InputIterator last, const Funct ion& f, task_group_context &context) {
internal::parallel_for_each_body<Function, InputIterator> body(f); internal::parallel_for_each_body<Function, InputIterator> body(f);
tbb::parallel_do (first, last, body, context); tbb::parallel_do (first, last, body, context);
} }
//! Calls function f for all items from rng using user-supplied context
/** @ingroup algorithms */
template<typename Range, typename Function>
void parallel_for_each(Range& rng, const Function& f, task_group_context& c
ontext) {
parallel_for_each(tbb::internal::first(rng), tbb::internal::last(rng),
f, context);
}
//! Calls function f for all items from const rng user-supplied context
/** @ingroup algorithms */
template<typename Range, typename Function>
void parallel_for_each(const Range& rng, const Function& f, task_group_cont
ext& context) {
parallel_for_each(tbb::internal::first(rng), tbb::internal::last(rng),
f, context);
}
#endif /* __TBB_TASK_GROUP_CONTEXT */ #endif /* __TBB_TASK_GROUP_CONTEXT */
//! Uses default context //! Uses default context
template<typename InputIterator, typename Function> template<typename InputIterator, typename Function>
void parallel_for_each(InputIterator first, InputIterator last, const Funct ion& f) { void parallel_for_each(InputIterator first, InputIterator last, const Funct ion& f) {
internal::parallel_for_each_body<Function, InputIterator> body(f); internal::parallel_for_each_body<Function, InputIterator> body(f);
tbb::parallel_do (first, last, body); tbb::parallel_do (first, last, body);
} }
//! Uses default context
template<typename Range, typename Function>
void parallel_for_each(Range& rng, const Function& f) {
parallel_for_each(tbb::internal::first(rng), tbb::internal::last(rng),
f);
}
//! Uses default context
template<typename Range, typename Function>
void parallel_for_each(const Range& rng, const Function& f) {
parallel_for_each(tbb::internal::first(rng), tbb::internal::last(rng),
f);
}
//@} //@}
} // namespace } // namespace
#endif /* __TBB_parallel_for_each_H */ #endif /* __TBB_parallel_for_each_H */
 End of changes. 3 change blocks. 
28 lines changed or deleted 61 lines changed or added


 parallel_invoke.h   parallel_invoke.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_parallel_invoke_H #ifndef __TBB_parallel_invoke_H
#define __TBB_parallel_invoke_H #define __TBB_parallel_invoke_H
#include "task.h" #include "task.h"
#if __TBB_VARIADIC_PARALLEL_INVOKE
#include <utility>
#endif
namespace tbb { namespace tbb {
#if !__TBB_TASK_GROUP_CONTEXT #if !__TBB_TASK_GROUP_CONTEXT
/** Dummy to avoid cluttering the bulk of the header with enormous amou nt of ifdefs. **/ /** Dummy to avoid cluttering the bulk of the header with enormous amou nt of ifdefs. **/
struct task_group_context {}; struct task_group_context {};
#endif /* __TBB_TASK_GROUP_CONTEXT */ #endif /* __TBB_TASK_GROUP_CONTEXT */
//! @cond INTERNAL //! @cond INTERNAL
namespace internal { namespace internal {
// Simple task object, executing user method // Simple task object, executing user method
skipping to change at line 106 skipping to change at line 102
// Dummy functor class // Dummy functor class
class parallel_invoke_noop { class parallel_invoke_noop {
public: public:
void operator() () const {} void operator() () const {}
}; };
// Creates a helper object with user-defined number of children exp ected // Creates a helper object with user-defined number of children exp ected
parallel_invoke_helper(int number_of_children) parallel_invoke_helper(int number_of_children)
{ {
set_ref_count(number_of_children + 1); set_ref_count(number_of_children + 1);
} }
#if __TBB_VARIADIC_PARALLEL_INVOKE
void add_children() {}
void add_children(tbb::task_group_context&) {}
template <typename function>
void add_children(function&& _func)
{
internal::function_invoker<function>* invoker = new (allocate_c
hild()) internal::function_invoker<function>(std::forward<function>(_func))
;
__TBB_ASSERT(invoker, "Child task allocation failed");
spawn(*invoker);
}
template<typename function>
void add_children(function&& _func, tbb::task_group_context&)
{
add_children(std::forward<function>(_func));
}
// Adds child(ren) task(s) and spawns them
template <typename function1, typename function2, typename... funct
ion>
void add_children(function1&& _func1, function2&& _func2, function&
&... _func)
{
// The third argument is dummy, it is ignored actually.
parallel_invoke_noop noop;
typedef internal::spawner<2, function1, function2, parallel_inv
oke_noop> spawner_type;
spawner_type & sub_root = *new(allocate_child()) spawner_type(s
td::forward<function1>(_func1), std::forward<function2>(_func2), noop);
spawn(sub_root);
add_children(std::forward<function>(_func)...);
}
#else
// Adds child task and spawns it // Adds child task and spawns it
template <typename function> template <typename function>
void add_child (const function &_func) void add_children (const function &_func)
{ {
internal::function_invoker<function>* invoker = new (allocate_c hild()) internal::function_invoker<function>(_func); internal::function_invoker<function>* invoker = new (allocate_c hild()) internal::function_invoker<function>(_func);
__TBB_ASSERT(invoker, "Child task allocation failed"); __TBB_ASSERT(invoker, "Child task allocation failed");
spawn(*invoker); spawn(*invoker);
} }
// Adds a task with multiple child tasks and spawns it // Adds a task with multiple child tasks and spawns it
// two arguments // two arguments
template <typename function1, typename function2> template <typename function1, typename function2>
void add_children (const function1& _func1, const function2& _func2 ) void add_children (const function1& _func1, const function2& _func2 )
skipping to change at line 132 skipping to change at line 159
internal::spawner<2, function1, function2, parallel_invoke_noop >& sub_root = *new(allocate_child())internal::spawner<2, function1, functio n2, parallel_invoke_noop>(_func1, _func2, noop); internal::spawner<2, function1, function2, parallel_invoke_noop >& sub_root = *new(allocate_child())internal::spawner<2, function1, functio n2, parallel_invoke_noop>(_func1, _func2, noop);
spawn(sub_root); spawn(sub_root);
} }
// three arguments // three arguments
template <typename function1, typename function2, typename function 3> template <typename function1, typename function2, typename function 3>
void add_children (const function1& _func1, const function2& _func2 , const function3& _func3) void add_children (const function1& _func1, const function2& _func2 , const function3& _func3)
{ {
internal::spawner<3, function1, function2, function3>& sub_root = *new(allocate_child())internal::spawner<3, function1, function2, functio n3>(_func1, _func2, _func3); internal::spawner<3, function1, function2, function3>& sub_root = *new(allocate_child())internal::spawner<3, function1, function2, functio n3>(_func1, _func2, _func3);
spawn(sub_root); spawn(sub_root);
} }
#endif // __TBB_VARIADIC_PARALLEL_INVOKE
// Waits for all child tasks // Waits for all child tasks
template <typename F0> template <typename F0>
void run_and_finish(const F0& f0) void run_and_finish(const F0& f0)
{ {
internal::function_invoker<F0>* invoker = new (allocate_child() ) internal::function_invoker<F0>(f0); internal::function_invoker<F0>* invoker = new (allocate_child() ) internal::function_invoker<F0>(f0);
__TBB_ASSERT(invoker, "Child task allocation failed"); __TBB_ASSERT(invoker, "Child task allocation failed");
spawn_and_wait_for_all(*invoker); spawn_and_wait_for_all(*invoker);
} }
}; };
skipping to change at line 159 skipping to change at line 187
parallel_invoke_cleaner(int number_of_children, tbb::task_group_con text&) parallel_invoke_cleaner(int number_of_children, tbb::task_group_con text&)
: root(*new(task::allocate_root()) internal::parallel_invoke_he lper(number_of_children)) : root(*new(task::allocate_root()) internal::parallel_invoke_he lper(number_of_children))
#endif /* !__TBB_TASK_GROUP_CONTEXT */ #endif /* !__TBB_TASK_GROUP_CONTEXT */
{} {}
~parallel_invoke_cleaner(){ ~parallel_invoke_cleaner(){
root.destroy(root); root.destroy(root);
} }
internal::parallel_invoke_helper& root; internal::parallel_invoke_helper& root;
}; };
#if __TBB_VARIADIC_PARALLEL_INVOKE
// Determine whether the last parameter in a pack is task_group_context
template<typename... T> struct impl_selector; // to workaround a GCC bu
g
template<typename T1, typename... T> struct impl_selector<T1, T...> {
typedef typename impl_selector<T...>::type type;
};
template<typename T> struct impl_selector<T> {
typedef false_type type;
};
template<> struct impl_selector<task_group_context&> {
typedef true_type type;
};
// Select task_group_context parameter from the back of a pack
task_group_context& get_context( task_group_context& tgc ) { return tgc
; }
template<typename T1, typename... T>
task_group_context& get_context( T1&& /*ignored*/, T&&... t )
{ return get_context( std::forward<T>(t)... ); }
// task_group_context is known to be at the back of the parameter pack
template<typename F0, typename F1, typename... F>
void parallel_invoke_impl(true_type, F0&& f0, F1&& f1, F&&... f) {
__TBB_STATIC_ASSERT(sizeof...(F)>0, "Variadic parallel_invoke imple
mentation broken?");
// # of child tasks: f0, f1, and a task for each two elements of th
e pack except the last
const size_t number_of_children = 2 + sizeof...(F)/2;
parallel_invoke_cleaner cleaner(number_of_children, get_context(std
::forward<F>(f)...));
parallel_invoke_helper& root = cleaner.root;
root.add_children(std::forward<F>(f)...);
root.add_children(std::forward<F1>(f1));
root.run_and_finish(std::forward<F0>(f0));
}
// task_group_context is not in the pack, needs to be added
template<typename F0, typename F1, typename... F>
void parallel_invoke_impl(false_type, F0&& f0, F1&& f1, F&&... f) {
tbb::task_group_context context;
// Add context to the arguments, and redirect to the other overload
parallel_invoke_impl(true_type(), std::forward<F0>(f0), std::forwar
d<F1>(f1), std::forward<F>(f)..., context);
}
#endif
} // namespace internal } // namespace internal
//! @endcond //! @endcond
/** \name parallel_invoke /** \name parallel_invoke
**/ **/
//@{ //@{
//! Executes a list of tasks in parallel and waits for all tasks to complet e. //! Executes a list of tasks in parallel and waits for all tasks to complet e.
/** @ingroup algorithms */ /** @ingroup algorithms */
#if __TBB_VARIADIC_PARALLEL_INVOKE
// parallel_invoke for two or more arguments via variadic templates
// presence of task_group_context is defined automatically
template<typename F0, typename F1, typename... F>
void parallel_invoke(F0&& f0, F1&& f1, F&&... f) {
typedef typename internal::impl_selector<internal::false_type, F...>::t
ype selector_type;
internal::parallel_invoke_impl(selector_type(), std::forward<F0>(f0), s
td::forward<F1>(f1), std::forward<F>(f)...);
}
#else
// parallel_invoke with user-defined context // parallel_invoke with user-defined context
// two arguments // two arguments
template<typename F0, typename F1 > template<typename F0, typename F1 >
void parallel_invoke(const F0& f0, const F1& f1, tbb::task_group_context& c ontext) { void parallel_invoke(const F0& f0, const F1& f1, tbb::task_group_context& c ontext) {
internal::parallel_invoke_cleaner cleaner(2, context); internal::parallel_invoke_cleaner cleaner(2, context);
internal::parallel_invoke_helper& root = cleaner.root; internal::parallel_invoke_helper& root = cleaner.root;
root.add_child(f1); root.add_children(f1);
root.run_and_finish(f0); root.run_and_finish(f0);
} }
// three arguments // three arguments
template<typename F0, typename F1, typename F2 > template<typename F0, typename F1, typename F2 >
void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, tbb::task_gr oup_context& context) { void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, tbb::task_gr oup_context& context) {
internal::parallel_invoke_cleaner cleaner(3, context); internal::parallel_invoke_cleaner cleaner(3, context);
internal::parallel_invoke_helper& root = cleaner.root; internal::parallel_invoke_helper& root = cleaner.root;
root.add_child(f2); root.add_children(f2);
root.add_child(f1); root.add_children(f1);
root.run_and_finish(f0); root.run_and_finish(f0);
} }
// four arguments // four arguments
template<typename F0, typename F1, typename F2, typename F3> template<typename F0, typename F1, typename F2, typename F3>
void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3 , void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3 ,
tbb::task_group_context& context) tbb::task_group_context& context)
{ {
internal::parallel_invoke_cleaner cleaner(4, context); internal::parallel_invoke_cleaner cleaner(4, context);
internal::parallel_invoke_helper& root = cleaner.root; internal::parallel_invoke_helper& root = cleaner.root;
root.add_child(f3); root.add_children(f3);
root.add_child(f2); root.add_children(f2);
root.add_child(f1); root.add_children(f1);
root.run_and_finish(f0); root.run_and_finish(f0);
} }
// five arguments // five arguments
template<typename F0, typename F1, typename F2, typename F3, typename F4 > template<typename F0, typename F1, typename F2, typename F3, typename F4 >
void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3 , const F4& f4, void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3 , const F4& f4,
tbb::task_group_context& context) tbb::task_group_context& context)
{ {
internal::parallel_invoke_cleaner cleaner(3, context); internal::parallel_invoke_cleaner cleaner(3, context);
skipping to change at line 366 skipping to change at line 451
} }
// ten arguments // ten arguments
template<typename F0, typename F1, typename F2, typename F3, typename F4, template<typename F0, typename F1, typename F2, typename F3, typename F4,
typename F5, typename F6, typename F7, typename F8, typename F9> typename F5, typename F6, typename F7, typename F8, typename F9>
void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3 , const F4& f4, void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3 , const F4& f4,
const F5& f5, const F6& f6, const F7& f7, const F8& f8 , const F9& f9) const F5& f5, const F6& f6, const F7& f7, const F8& f8 , const F9& f9)
{ {
task_group_context context; task_group_context context;
parallel_invoke<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9>(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, context); parallel_invoke<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9>(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, context);
} }
#endif // __TBB_VARIADIC_PARALLEL_INVOKE
//@} //@}
} // namespace } // namespace
#endif /* __TBB_parallel_invoke_H */ #endif /* __TBB_parallel_invoke_H */
 End of changes. 11 change blocks. 
36 lines changed or deleted 144 lines changed or added


 parallel_reduce.h   parallel_reduce.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_parallel_reduce_H #ifndef __TBB_parallel_reduce_H
#define __TBB_parallel_reduce_H #define __TBB_parallel_reduce_H
#include <new> #include <new>
#include "task.h" #include "task.h"
#include "aligned_space.h" #include "aligned_space.h"
#include "partitioner.h" #include "partitioner.h"
#include "tbb_profiling.h" #include "tbb_profiling.h"
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 parallel_scan.h   parallel_scan.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_parallel_scan_H #ifndef __TBB_parallel_scan_H
#define __TBB_parallel_scan_H #define __TBB_parallel_scan_H
#include "task.h" #include "task.h"
#include "aligned_space.h" #include "aligned_space.h"
#include <new> #include <new>
#include "partitioner.h" #include "partitioner.h"
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 parallel_sort.h   parallel_sort.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_parallel_sort_H #ifndef __TBB_parallel_sort_H
#define __TBB_parallel_sort_H #define __TBB_parallel_sort_H
#include "parallel_for.h" #include "parallel_for.h"
#include "blocked_range.h" #include "blocked_range.h"
#include "internal/_range_iterator.h"
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
#include <functional> #include <functional>
namespace tbb { namespace tbb {
//! @cond INTERNAL //! @cond INTERNAL
namespace internal { namespace internal {
//! Range used in quicksort to split elements into subranges based on a val ue. //! Range used in quicksort to split elements into subranges based on a val ue.
skipping to change at line 220 skipping to change at line 213
} }
} }
//! Sorts the data in [begin,end) with a default comparator \c std::less<Ra ndomAccessIterator> //! Sorts the data in [begin,end) with a default comparator \c std::less<Ra ndomAccessIterator>
/** @ingroup algorithms **/ /** @ingroup algorithms **/
template<typename RandomAccessIterator> template<typename RandomAccessIterator>
inline void parallel_sort( RandomAccessIterator begin, RandomAccessIterator end ) { inline void parallel_sort( RandomAccessIterator begin, RandomAccessIterator end ) {
parallel_sort( begin, end, std::less< typename std::iterator_traits<Ran domAccessIterator>::value_type >() ); parallel_sort( begin, end, std::less< typename std::iterator_traits<Ran domAccessIterator>::value_type >() );
} }
//! Sorts the data in rng using the given comparator
/** @ingroup algorithms **/
template<typename Range, typename Compare>
void parallel_sort(Range& rng, const Compare& comp) {
parallel_sort(tbb::internal::first(rng), tbb::internal::last(rng), comp
);
}
//! Sorts the data in const rng using the given comparator
/** @ingroup algorithms **/
template<typename Range, typename Compare>
void parallel_sort(const Range& rng, const Compare& comp) {
parallel_sort(tbb::internal::first(rng), tbb::internal::last(rng), comp
);
}
//! Sorts the data in rng with a default comparator \c std::less<RandomAcce
ssIterator>
/** @ingroup algorithms **/
template<typename Range>
void parallel_sort(Range& rng) {
parallel_sort(tbb::internal::first(rng), tbb::internal::last(rng));
}
//! Sorts the data in const rng with a default comparator \c std::less<Rand
omAccessIterator>
/** @ingroup algorithms **/
template<typename Range>
void parallel_sort(const Range& rng) {
parallel_sort(tbb::internal::first(rng), tbb::internal::last(rng));
}
//! Sorts the data in the range \c [begin,end) with a default comparator \c std::less<T> //! Sorts the data in the range \c [begin,end) with a default comparator \c std::less<T>
/** @ingroup algorithms **/ /** @ingroup algorithms **/
template<typename T> template<typename T>
inline void parallel_sort( T * begin, T * end ) { inline void parallel_sort( T * begin, T * end ) {
parallel_sort( begin, end, std::less< T >() ); parallel_sort( begin, end, std::less< T >() );
} }
//@} //@}
} // namespace tbb } // namespace tbb
 End of changes. 3 change blocks. 
28 lines changed or deleted 62 lines changed or added


 parallel_while.h   parallel_while.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_parallel_while #ifndef __TBB_parallel_while
#define __TBB_parallel_while #define __TBB_parallel_while
#include "task.h" #include "task.h"
#include <new> #include <new>
namespace tbb { namespace tbb {
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 partitioner.h   partitioner.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_partitioner_H #ifndef __TBB_partitioner_H
#define __TBB_partitioner_H #define __TBB_partitioner_H
#ifndef __TBB_INITIAL_CHUNKS #ifndef __TBB_INITIAL_CHUNKS
// initial task divisions per thread // initial task divisions per thread
#define __TBB_INITIAL_CHUNKS 2 #define __TBB_INITIAL_CHUNKS 2
#endif #endif
#ifndef __TBB_RANGE_POOL_CAPACITY #ifndef __TBB_RANGE_POOL_CAPACITY
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 pipeline.h   pipeline.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_pipeline_H #ifndef __TBB_pipeline_H
#define __TBB_pipeline_H #define __TBB_pipeline_H
#include "atomic.h" #include "atomic.h"
#include "task.h" #include "task.h"
#include "tbb_allocator.h" #include "tbb_allocator.h"
#include <cstddef> #include <cstddef>
//TODO: consider more accurate method to check if need to implement <type_t #if __TBB_CPP11_TYPE_PROPERTIES_PRESENT || __TBB_TR1_TYPE_PROPERTIES_IN_STD
rais> ourself _PRESENT
#if !TBB_IMPLEMENT_CPP0X
#include <type_traits> #include <type_traits>
#endif #endif
namespace tbb { namespace tbb {
class pipeline; class pipeline;
class filter; class filter;
//! @cond INTERNAL //! @cond INTERNAL
namespace internal { namespace internal {
skipping to change at line 333 skipping to change at line 324
template<typename T, typename U, typename Body> friend class internal:: concrete_filter; template<typename T, typename U, typename Body> friend class internal:: concrete_filter;
public: public:
void stop() { is_pipeline_stopped = true; } void stop() { is_pipeline_stopped = true; }
}; };
//! @cond INTERNAL //! @cond INTERNAL
namespace internal { namespace internal {
template<typename T> struct tbb_large_object {enum { value = sizeof(T) > si zeof(void *) }; }; template<typename T> struct tbb_large_object {enum { value = sizeof(T) > si zeof(void *) }; };
#if TBB_IMPLEMENT_CPP0X // Obtain type properties in one or another way
// cannot use SFINAE in current compilers. Explicitly list the types we wi #if __TBB_CPP11_TYPE_PROPERTIES_PRESENT
sh to be template<typename T> struct tbb_trivially_copyable { enum { value = std::is
// placed as-is in the pipeline input_buffers. _trivially_copyable<T>::value }; };
#elif __TBB_TR1_TYPE_PROPERTIES_IN_STD_PRESENT
template<typename T> struct tbb_trivially_copyable { enum { value = std::ha
s_trivial_copy_constructor<T>::value }; };
#else
// Explicitly list the types we wish to be placed as-is in the pipeline inp
ut_buffers.
template<typename T> struct tbb_trivially_copyable { enum { value = false } ; }; template<typename T> struct tbb_trivially_copyable { enum { value = false } ; };
template<typename T> struct tbb_trivially_copyable <T*> { enum { value = tr ue }; }; template<typename T> struct tbb_trivially_copyable <T*> { enum { value = tr ue }; };
template<> struct tbb_trivially_copyable <short> { enum { value = true }; } ; template<> struct tbb_trivially_copyable <short> { enum { value = true }; } ;
template<> struct tbb_trivially_copyable <unsigned short> { enum { value = true }; }; template<> struct tbb_trivially_copyable <unsigned short> { enum { value = true }; };
template<> struct tbb_trivially_copyable <int> { enum { value = !tbb_large_ object<int>::value }; }; template<> struct tbb_trivially_copyable <int> { enum { value = !tbb_large_ object<int>::value }; };
template<> struct tbb_trivially_copyable <unsigned int> { enum { value = !t bb_large_object<int>::value }; }; template<> struct tbb_trivially_copyable <unsigned int> { enum { value = !t bb_large_object<int>::value }; };
template<> struct tbb_trivially_copyable <long> { enum { value = !tbb_large _object<long>::value }; }; template<> struct tbb_trivially_copyable <long> { enum { value = !tbb_large _object<long>::value }; };
template<> struct tbb_trivially_copyable <unsigned long> { enum { value = ! tbb_large_object<long>::value }; }; template<> struct tbb_trivially_copyable <unsigned long> { enum { value = ! tbb_large_object<long>::value }; };
template<> struct tbb_trivially_copyable <float> { enum { value = !tbb_larg e_object<float>::value }; }; template<> struct tbb_trivially_copyable <float> { enum { value = !tbb_larg e_object<float>::value }; };
template<> struct tbb_trivially_copyable <double> { enum { value = !tbb_lar ge_object<double>::value }; }; template<> struct tbb_trivially_copyable <double> { enum { value = !tbb_lar ge_object<double>::value }; };
#else #endif // Obtaining type properties
#if __GNUC__==4 && __GNUC_MINOR__>=4 && __GXX_EXPERIMENTAL_CXX0X__
template<typename T> struct tbb_trivially_copyable { enum { value = std::ha
s_trivial_copy_constructor<T>::value }; };
#else
template<typename T> struct tbb_trivially_copyable { enum { value = std::is
_trivially_copyable<T>::value }; };
#endif //
#endif // TBB_IMPLEMENT_CPP0X
template<typename T> struct is_large_object {enum { value = tbb_large_objec t<T>::value || !tbb_trivially_copyable<T>::value }; }; template<typename T> struct is_large_object {enum { value = tbb_large_objec t<T>::value || !tbb_trivially_copyable<T>::value }; };
template<typename T, bool> class token_helper; template<typename T, bool> class token_helper;
// large object helper (uses tbb_allocator) // large object helper (uses tbb_allocator)
template<typename T> template<typename T>
class token_helper<T, true> { class token_helper<T, true> {
public: public:
typedef typename tbb::tbb_allocator<T> allocator; typedef typename tbb::tbb_allocator<T> allocator;
 End of changes. 4 change blocks. 
44 lines changed or deleted 42 lines changed or added


 ppl.h   ppl.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_compat_ppl_H #ifndef __TBB_compat_ppl_H
#define __TBB_compat_ppl_H #define __TBB_compat_ppl_H
#include "../task_group.h" #include "../task_group.h"
#include "../parallel_invoke.h" #include "../parallel_invoke.h"
#include "../parallel_for_each.h" #include "../parallel_for_each.h"
#include "../parallel_for.h" #include "../parallel_for.h"
#include "../tbb_exception.h" #include "../tbb_exception.h"
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 queuing_mutex.h   queuing_mutex.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_queuing_mutex_H #ifndef __TBB_queuing_mutex_H
#define __TBB_queuing_mutex_H #define __TBB_queuing_mutex_H
#include "tbb_config.h" #include "tbb_config.h"
#if !TBB_USE_EXCEPTIONS && _MSC_VER #if !TBB_USE_EXCEPTIONS && _MSC_VER
// Suppress "C++ exception handler used, but unwind semantics are not e nabled" warning in STL headers // Suppress "C++ exception handler used, but unwind semantics are not e nabled" warning in STL headers
#pragma warning (push) #pragma warning (push)
skipping to change at line 53 skipping to change at line 45
#pragma warning (pop) #pragma warning (pop)
#endif #endif
#include "atomic.h" #include "atomic.h"
#include "tbb_profiling.h" #include "tbb_profiling.h"
namespace tbb { namespace tbb {
//! Queuing mutex with local-only spinning. //! Queuing mutex with local-only spinning.
/** @ingroup synchronization */ /** @ingroup synchronization */
class queuing_mutex { class queuing_mutex : internal::mutex_copy_deprecated_and_disabled {
public: public:
//! Construct unacquired mutex. //! Construct unacquired mutex.
queuing_mutex() { queuing_mutex() {
q_tail = NULL; q_tail = NULL;
#if TBB_USE_THREADING_TOOLS #if TBB_USE_THREADING_TOOLS
internal_construct(); internal_construct();
#endif #endif
} }
//! The scoped locking pattern //! The scoped locking pattern
 End of changes. 2 change blocks. 
29 lines changed or deleted 30 lines changed or added


 queuing_rw_mutex.h   queuing_rw_mutex.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_queuing_rw_mutex_H #ifndef __TBB_queuing_rw_mutex_H
#define __TBB_queuing_rw_mutex_H #define __TBB_queuing_rw_mutex_H
#include "tbb_config.h" #include "tbb_config.h"
#if !TBB_USE_EXCEPTIONS && _MSC_VER #if !TBB_USE_EXCEPTIONS && _MSC_VER
// Suppress "C++ exception handler used, but unwind semantics are not e nabled" warning in STL headers // Suppress "C++ exception handler used, but unwind semantics are not e nabled" warning in STL headers
#pragma warning (push) #pragma warning (push)
skipping to change at line 55 skipping to change at line 47
#include "atomic.h" #include "atomic.h"
#include "tbb_profiling.h" #include "tbb_profiling.h"
namespace tbb { namespace tbb {
//! Queuing reader-writer mutex with local-only spinning. //! Queuing reader-writer mutex with local-only spinning.
/** Adapted from Krieger, Stumm, et al. pseudocode at /** Adapted from Krieger, Stumm, et al. pseudocode at
http://www.eecg.toronto.edu/parallel/pubs_abs.html#Krieger_etal_ICPP93 http://www.eecg.toronto.edu/parallel/pubs_abs.html#Krieger_etal_ICPP93
@ingroup synchronization */ @ingroup synchronization */
class queuing_rw_mutex { class queuing_rw_mutex : internal::mutex_copy_deprecated_and_disabled {
public: public:
//! Construct unacquired mutex. //! Construct unacquired mutex.
queuing_rw_mutex() { queuing_rw_mutex() {
q_tail = NULL; q_tail = NULL;
#if TBB_USE_THREADING_TOOLS #if TBB_USE_THREADING_TOOLS
internal_construct(); internal_construct();
#endif #endif
} }
//! Destructor asserts if the mutex is acquired, i.e. q_tail is non-NUL L //! Destructor asserts if the mutex is acquired, i.e. q_tail is non-NUL L
 End of changes. 2 change blocks. 
29 lines changed or deleted 30 lines changed or added


 reader_writer_lock.h   reader_writer_lock.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_reader_writer_lock_H #ifndef __TBB_reader_writer_lock_H
#define __TBB_reader_writer_lock_H #define __TBB_reader_writer_lock_H
#include "tbb_thread.h" #include "tbb_thread.h"
#include "tbb_allocator.h" #include "tbb_allocator.h"
#include "atomic.h" #include "atomic.h"
namespace tbb { namespace tbb {
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 recursive_mutex.h   recursive_mutex.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_recursive_mutex_H #ifndef __TBB_recursive_mutex_H
#define __TBB_recursive_mutex_H #define __TBB_recursive_mutex_H
#if _WIN32||_WIN64 #if _WIN32||_WIN64
#include "machine/windows_api.h" #include "machine/windows_api.h"
#else #else
#include <pthread.h> #include <pthread.h>
#endif /* _WIN32||_WIN64 */ #endif /* _WIN32||_WIN64 */
#include <new> #include <new>
#include "aligned_space.h" #include "aligned_space.h"
#include "tbb_stddef.h" #include "tbb_stddef.h"
#include "tbb_profiling.h" #include "tbb_profiling.h"
namespace tbb { namespace tbb {
//! Mutex that allows recursive mutex acquisition. //! Mutex that allows recursive mutex acquisition.
/** Mutex that allows recursive mutex acquisition. /** Mutex that allows recursive mutex acquisition.
@ingroup synchronization */ @ingroup synchronization */
class recursive_mutex { class recursive_mutex : internal::mutex_copy_deprecated_and_disabled {
public: public:
//! Construct unacquired recursive_mutex. //! Construct unacquired recursive_mutex.
recursive_mutex() { recursive_mutex() {
#if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
internal_construct(); internal_construct();
#else #else
#if _WIN32||_WIN64 #if _WIN32||_WIN64
InitializeCriticalSectionEx(&impl, 4000, 0); InitializeCriticalSectionEx(&impl, 4000, 0);
#else #else
pthread_mutexattr_t mtx_attr; pthread_mutexattr_t mtx_attr;
skipping to change at line 174 skipping to change at line 166
//! Acquire lock //! Acquire lock
void lock() { void lock() {
#if TBB_USE_ASSERT #if TBB_USE_ASSERT
aligned_space<scoped_lock> tmp; aligned_space<scoped_lock> tmp;
new(tmp.begin()) scoped_lock(*this); new(tmp.begin()) scoped_lock(*this);
#else #else
#if _WIN32||_WIN64 #if _WIN32||_WIN64
EnterCriticalSection(&impl); EnterCriticalSection(&impl);
#else #else
pthread_mutex_lock(&impl); int error_code = pthread_mutex_lock(&impl);
if( error_code )
tbb::internal::handle_perror(error_code,"recursive_mutex: pthre
ad_mutex_lock failed");
#endif /* _WIN32||_WIN64 */ #endif /* _WIN32||_WIN64 */
#endif /* TBB_USE_ASSERT */ #endif /* TBB_USE_ASSERT */
} }
//! Try acquiring lock (non-blocking) //! Try acquiring lock (non-blocking)
/** Return true if lock acquired; false otherwise. */ /** Return true if lock acquired; false otherwise. */
bool try_lock() { bool try_lock() {
#if TBB_USE_ASSERT #if TBB_USE_ASSERT
aligned_space<scoped_lock> tmp; aligned_space<scoped_lock> tmp;
return (new(tmp.begin()) scoped_lock)->internal_try_acquire(*this); return (new(tmp.begin()) scoped_lock)->internal_try_acquire(*this);
 End of changes. 3 change blocks. 
30 lines changed or deleted 34 lines changed or added


 runtime_loader.h   runtime_loader.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_runtime_loader_H #ifndef __TBB_runtime_loader_H
#define __TBB_runtime_loader_H #define __TBB_runtime_loader_H
#if ! TBB_PREVIEW_RUNTIME_LOADER #if ! TBB_PREVIEW_RUNTIME_LOADER
#error Set TBB_PREVIEW_RUNTIME_LOADER to include runtime_loader.h #error Set TBB_PREVIEW_RUNTIME_LOADER to include runtime_loader.h
#endif #endif
#include "tbb_stddef.h" #include "tbb_stddef.h"
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 scalable_allocator.h   scalable_allocator.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_scalable_allocator_H #ifndef __TBB_scalable_allocator_H
#define __TBB_scalable_allocator_H #define __TBB_scalable_allocator_H
/** @file */ /** @file */
#include <stddef.h> /* Need ptrdiff_t and size_t from here. */ #include <stddef.h> /* Need ptrdiff_t and size_t from here. */
#if !_MSC_VER #if !_MSC_VER
#include <stdint.h> /* Need intptr_t from here. */ #include <stdint.h> /* Need intptr_t from here. */
#endif #endif
skipping to change at line 215 skipping to change at line 207
/* Ensure that including this header does not cause implicit linkage with T BB */ /* Ensure that including this header does not cause implicit linkage with T BB */
#ifndef __TBB_NO_IMPLICIT_LINKAGE #ifndef __TBB_NO_IMPLICIT_LINKAGE
#define __TBB_NO_IMPLICIT_LINKAGE 1 #define __TBB_NO_IMPLICIT_LINKAGE 1
#include "tbb_stddef.h" #include "tbb_stddef.h"
#undef __TBB_NO_IMPLICIT_LINKAGE #undef __TBB_NO_IMPLICIT_LINKAGE
#else #else
#include "tbb_stddef.h" #include "tbb_stddef.h"
#endif #endif
#if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN #if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
#include <utility> // std::forward #include <utility> // std::forward
#endif #endif
namespace tbb { namespace tbb {
#if _MSC_VER && !defined(__INTEL_COMPILER) #if _MSC_VER && !defined(__INTEL_COMPILER)
// Workaround for erroneous "unreferenced parameter" warning in method destroy. // Workaround for erroneous "unreferenced parameter" warning in method destroy.
#pragma warning (push) #pragma warning (push)
#pragma warning (disable: 4100) #pragma warning (disable: 4100)
#endif #endif
skipping to change at line 270 skipping to change at line 262
} }
//! Largest value for which method allocate might succeed. //! Largest value for which method allocate might succeed.
size_type max_size() const throw() { size_type max_size() const throw() {
size_type absolutemax = static_cast<size_type>(-1) / sizeof (value_ type); size_type absolutemax = static_cast<size_type>(-1) / sizeof (value_ type);
return (absolutemax > 0 ? absolutemax : 1); return (absolutemax > 0 ? absolutemax : 1);
} }
#if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC #if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
template<typename U, typename... Args> template<typename U, typename... Args>
void construct(U *p, Args&&... args) void construct(U *p, Args&&... args)
#if __TBB_CPP11_STD_FORWARD_BROKEN
{ ::new((void *)p) U((args)...); }
#else
{ ::new((void *)p) U(std::forward<Args>(args)...); } { ::new((void *)p) U(std::forward<Args>(args)...); }
#endif
#else // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC #else // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
#if __TBB_CPP11_RVALUE_REF_PRESENT
void construct( pointer p, value_type&& value ) { ::new((void*)(p)) val
ue_type( std::move( value ) ); }
#endif
void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);} void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);}
#endif // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC #endif // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
void destroy( pointer p ) {p->~value_type();} void destroy( pointer p ) {p->~value_type();}
}; };
#if _MSC_VER && !defined(__INTEL_COMPILER) #if _MSC_VER && !defined(__INTEL_COMPILER)
#pragma warning (pop) #pragma warning (pop)
#endif // warning 4100 is back #endif // warning 4100 is back
//! Analogous to std::allocator<void>, as defined in ISO C++ Standard, Sect ion 20.4.1 //! Analogous to std::allocator<void>, as defined in ISO C++ Standard, Sect ion 20.4.1
 End of changes. 5 change blocks. 
33 lines changed or deleted 34 lines changed or added


 spin_mutex.h   spin_mutex.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_spin_mutex_H #ifndef __TBB_spin_mutex_H
#define __TBB_spin_mutex_H #define __TBB_spin_mutex_H
#include <cstddef> #include <cstddef>
#include <new> #include <new>
#include "aligned_space.h" #include "aligned_space.h"
#include "tbb_stddef.h" #include "tbb_stddef.h"
#include "tbb_machine.h" #include "tbb_machine.h"
skipping to change at line 48 skipping to change at line 40
#include "internal/_mutex_padding.h" #include "internal/_mutex_padding.h"
namespace tbb { namespace tbb {
//! A lock that occupies a single byte. //! A lock that occupies a single byte.
/** A spin_mutex is a spin mutex that fits in a single byte. /** A spin_mutex is a spin mutex that fits in a single byte.
It should be used only for locking short critical sections It should be used only for locking short critical sections
(typically less than 20 instructions) when fairness is not an issue. (typically less than 20 instructions) when fairness is not an issue.
If zero-initialized, the mutex is considered unheld. If zero-initialized, the mutex is considered unheld.
@ingroup synchronization */ @ingroup synchronization */
class spin_mutex { class spin_mutex : internal::mutex_copy_deprecated_and_disabled {
//! 0 if lock is released, 1 if lock is acquired. //! 0 if lock is released, 1 if lock is acquired.
__TBB_atomic_flag flag; __TBB_atomic_flag flag;
public: public:
//! Construct unacquired lock. //! Construct unacquired lock.
/** Equivalent to zero-initialization of *this. */ /** Equivalent to zero-initialization of *this. */
spin_mutex() : flag(0) { spin_mutex() : flag(0) {
#if TBB_USE_THREADING_TOOLS #if TBB_USE_THREADING_TOOLS
internal_construct(); internal_construct();
#endif #endif
 End of changes. 2 change blocks. 
29 lines changed or deleted 30 lines changed or added


 spin_rw_mutex.h   spin_rw_mutex.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_spin_rw_mutex_H #ifndef __TBB_spin_rw_mutex_H
#define __TBB_spin_rw_mutex_H #define __TBB_spin_rw_mutex_H
#include "tbb_stddef.h" #include "tbb_stddef.h"
#include "tbb_machine.h" #include "tbb_machine.h"
#include "tbb_profiling.h" #include "tbb_profiling.h"
#include "internal/_mutex_padding.h" #include "internal/_mutex_padding.h"
namespace tbb { namespace tbb {
#if __TBB_TSX_AVAILABLE
namespace interface8 { namespace internal {
class x86_rtm_rw_mutex;
}}
#endif
class spin_rw_mutex_v3; class spin_rw_mutex_v3;
typedef spin_rw_mutex_v3 spin_rw_mutex; typedef spin_rw_mutex_v3 spin_rw_mutex;
//! Fast, unfair, spinning reader-writer lock with backoff and writer-prefe rence //! Fast, unfair, spinning reader-writer lock with backoff and writer-prefe rence
/** @ingroup synchronization */ /** @ingroup synchronization */
class spin_rw_mutex_v3 { class spin_rw_mutex_v3 : internal::mutex_copy_deprecated_and_disabled {
//! @cond INTERNAL //! @cond INTERNAL
//! Internal acquire write lock. //! Internal acquire write lock.
bool __TBB_EXPORTED_METHOD internal_acquire_writer(); bool __TBB_EXPORTED_METHOD internal_acquire_writer();
//! Out of line code for releasing a write lock. //! Out of line code for releasing a write lock.
/** This code has debug checking and instrumentation for Intel(R) Threa d Checker and Intel(R) Thread Profiler. */ /** This code has debug checking and instrumentation for Intel(R) Threa d Checker and Intel(R) Thread Profiler. */
void __TBB_EXPORTED_METHOD internal_release_writer(); void __TBB_EXPORTED_METHOD internal_release_writer();
//! Internal acquire read lock. //! Internal acquire read lock.
skipping to change at line 92 skipping to change at line 91
//! Destructor asserts if the mutex is acquired, i.e. state is zero. //! Destructor asserts if the mutex is acquired, i.e. state is zero.
~spin_rw_mutex_v3() { ~spin_rw_mutex_v3() {
__TBB_ASSERT( !state, "destruction of an acquired mutex"); __TBB_ASSERT( !state, "destruction of an acquired mutex");
}; };
#endif /* TBB_USE_ASSERT */ #endif /* TBB_USE_ASSERT */
//! The scoped locking pattern //! The scoped locking pattern
/** It helps to avoid the common problem of forgetting to release lock. /** It helps to avoid the common problem of forgetting to release lock.
It also nicely provides the "node" for queuing locks. */ It also nicely provides the "node" for queuing locks. */
class scoped_lock : internal::no_copy { class scoped_lock : internal::no_copy {
#if __TBB_TSX_AVAILABLE
friend class tbb::interface8::internal::x86_rtm_rw_mutex;
// helper methods for x86_rtm_rw_mutex
spin_rw_mutex *internal_get_mutex() const { return mutex; }
void internal_set_mutex(spin_rw_mutex* m) { mutex = m; }
#endif
public: public:
//! Construct lock that has not acquired a mutex. //! Construct lock that has not acquired a mutex.
/** Equivalent to zero-initialization of *this. */ /** Equivalent to zero-initialization of *this. */
scoped_lock() : mutex(NULL), is_writer(false) {} scoped_lock() : mutex(NULL), is_writer(false) {}
//! Acquire lock on given mutex. //! Acquire lock on given mutex.
scoped_lock( spin_rw_mutex& m, bool write = true ) : mutex(NULL) { scoped_lock( spin_rw_mutex& m, bool write = true ) : mutex(NULL) {
acquire(m, write); acquire(m, write);
} }
skipping to change at line 164 skipping to change at line 169
__TBB_ASSERT( !mutex, "holding mutex already" ); __TBB_ASSERT( !mutex, "holding mutex already" );
bool result; bool result;
is_writer = write; is_writer = write;
result = write? m.internal_try_acquire_writer() result = write? m.internal_try_acquire_writer()
: m.internal_try_acquire_reader(); : m.internal_try_acquire_reader();
if( result ) if( result )
mutex = &m; mutex = &m;
return result; return result;
} }
#if TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX
// helper methods for speculation-based spin_rw_mutex
spin_rw_mutex *__internal_get_mutex() {
return mutex;
}
// have to be able to "NULL"-ify the mutex
void __internal_set_mutex(spin_rw_mutex* m) {
mutex = m;
}
void __internal_set_writer(bool flag=true) {
is_writer = flag;
}
#endif /* TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX */
protected: protected:
//! The pointer to the current mutex that is held, or NULL if no mu tex is held. //! The pointer to the current mutex that is held, or NULL if no mu tex is held.
spin_rw_mutex* mutex; spin_rw_mutex* mutex;
//! If mutex!=NULL, then is_writer is true if holding a writer lock , false if holding a reader lock. //! If mutex!=NULL, then is_writer is true if holding a writer lock , false if holding a reader lock.
/** Not defined if not holding a lock. */ /** Not defined if not holding a lock. */
bool is_writer; bool is_writer;
}; };
skipping to change at line 243 skipping to change at line 233
Bit 2..N = number of readers holding lock */ Bit 2..N = number of readers holding lock */
state_t state; state_t state;
private: private:
void __TBB_EXPORTED_METHOD internal_construct(); void __TBB_EXPORTED_METHOD internal_construct();
}; };
__TBB_DEFINE_PROFILING_SET_NAME(spin_rw_mutex) __TBB_DEFINE_PROFILING_SET_NAME(spin_rw_mutex)
} // namespace tbb } // namespace tbb
#if TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX
#if __TBB_TSX_AVAILABLE #if __TBB_TSX_AVAILABLE
#include "internal/_x86_rtm_rw_mutex_impl.h" #include "internal/_x86_rtm_rw_mutex_impl.h"
#endif #endif
namespace tbb { namespace tbb {
namespace interface7 { namespace interface8 {
//! A cross-platform spin reader/writer mutex with speculative lock acquisi tion. //! A cross-platform spin reader/writer mutex with speculative lock acquisi tion.
/** On platforms with proper HW support, this lock may speculatively execut e /** On platforms with proper HW support, this lock may speculatively execut e
its critical sections, using HW mechanisms to detect real data races an d its critical sections, using HW mechanisms to detect real data races an d
ensure atomicity of the critical sections. In particular, it uses ensure atomicity of the critical sections. In particular, it uses
Intel(R) Transactional Synchronization Extensions (Intel(R) TSX). Intel(R) Transactional Synchronization Extensions (Intel(R) TSX).
Without such HW support, it behaves like a spin_rw_mutex. Without such HW support, it behaves like a spin_rw_mutex.
It should be used for locking short critical sections where the lock is It should be used for locking short critical sections where the lock is
contended but the data it protects are not. contended but the data it protects are not.
@ingroup synchronization */ @ingroup synchronization */
#if __TBB_TSX_AVAILABLE #if __TBB_TSX_AVAILABLE
typedef interface7::internal::padded_mutex<tbb::interface7::internal::x86_r tm_rw_mutex,true> speculative_spin_rw_mutex; typedef interface7::internal::padded_mutex<tbb::interface8::internal::x86_r tm_rw_mutex,true> speculative_spin_rw_mutex;
#else #else
typedef interface7::internal::padded_mutex<tbb::spin_rw_mutex,true> specula tive_spin_rw_mutex; typedef interface7::internal::padded_mutex<tbb::spin_rw_mutex,true> specula tive_spin_rw_mutex;
#endif #endif
} // namespace interface7 } // namespace interface8
using interface7::speculative_spin_rw_mutex; using interface8::speculative_spin_rw_mutex;
__TBB_DEFINE_PROFILING_SET_NAME(speculative_spin_rw_mutex) __TBB_DEFINE_PROFILING_SET_NAME(speculative_spin_rw_mutex)
} // namespace tbb } // namespace tbb
#endif /* TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX */
#endif /* __TBB_spin_rw_mutex_H */ #endif /* __TBB_spin_rw_mutex_H */
 End of changes. 12 change blocks. 
50 lines changed or deleted 48 lines changed or added


 sunos_sparc.h   sunos_sparc.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#if !defined(__TBB_machine_H) || defined(__TBB_machine_sunos_sparc_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_sunos_sparc_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_sunos_sparc_H #define __TBB_machine_sunos_sparc_H
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 task.h   task.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_task_H #ifndef __TBB_task_H
#define __TBB_task_H #define __TBB_task_H
#include "tbb_stddef.h" #include "tbb_stddef.h"
#include "tbb_machine.h" #include "tbb_machine.h"
#include <climits> #include <climits>
typedef struct ___itt_caller *__itt_caller; typedef struct ___itt_caller *__itt_caller;
namespace tbb { namespace tbb {
class task; class task;
class task_list; class task_list;
#if __TBB_TASK_GROUP_CONTEXT
class task_group_context; class task_group_context;
#endif /* __TBB_TASK_GROUP_CONTEXT */
// MSVC does not allow taking the address of a member that was defined // MSVC does not allow taking the address of a member that was defined
// privately in task_base and made public in class task via a using declara tion. // privately in task_base and made public in class task via a using declara tion.
#if _MSC_VER || (__GNUC__==3 && __GNUC_MINOR__<3) #if _MSC_VER || (__GNUC__==3 && __GNUC_MINOR__<3)
#define __TBB_TASK_BASE_ACCESS public #define __TBB_TASK_BASE_ACCESS public
#else #else
#define __TBB_TASK_BASE_ACCESS private #define __TBB_TASK_BASE_ACCESS private
#endif #endif
namespace internal { //< @cond INTERNAL namespace internal { //< @cond INTERNAL
skipping to change at line 352 skipping to change at line 341
concurrent_wait = 0x0004ul << traits_offset, concurrent_wait = 0x0004ul << traits_offset,
#if TBB_USE_CAPTURED_EXCEPTION #if TBB_USE_CAPTURED_EXCEPTION
default_traits = 0 default_traits = 0
#else #else
default_traits = exact_exception default_traits = exact_exception
#endif /* !TBB_USE_CAPTURED_EXCEPTION */ #endif /* !TBB_USE_CAPTURED_EXCEPTION */
}; };
private: private:
enum state { enum state {
may_have_children = 1 may_have_children = 1,
// the following enumerations must be the last, new 2^x values must
go above
next_state_value, low_unused_state_bit = (next_state_value-1)*2
}; };
union { union {
//! Flavor of this context: bound or isolated. //! Flavor of this context: bound or isolated.
// TODO: describe asynchronous use, and whether any memory semantic s are needed // TODO: describe asynchronous use, and whether any memory semantic s are needed
__TBB_atomic kind_type my_kind; __TBB_atomic kind_type my_kind;
uintptr_t _my_kind_aligner; uintptr_t _my_kind_aligner;
}; };
//! Pointer to the context of the parent cancellation group. NULL for i solated contexts. //! Pointer to the context of the parent cancellation group. NULL for i solated contexts.
skipping to change at line 534 skipping to change at line 525
static const kind_type binding_required = bound; static const kind_type binding_required = bound;
static const kind_type binding_completed = kind_type(bound+1); static const kind_type binding_completed = kind_type(bound+1);
static const kind_type detached = kind_type(binding_completed+1); static const kind_type detached = kind_type(binding_completed+1);
static const kind_type dying = kind_type(detached+1); static const kind_type dying = kind_type(detached+1);
//! Propagates any state change detected to *this, and as an optimisati on possibly also upward along the heritage line. //! Propagates any state change detected to *this, and as an optimisati on possibly also upward along the heritage line.
template <typename T> template <typename T>
void propagate_task_group_state ( T task_group_context::*mptr_state, ta sk_group_context& src, T new_state ); void propagate_task_group_state ( T task_group_context::*mptr_state, ta sk_group_context& src, T new_state );
//! Makes sure that the context is registered with a scheduler instance
.
inline void finish_initialization ( internal::generic_scheduler *local_
sched );
//! Registers this context with the local scheduler and binds it to its parent context //! Registers this context with the local scheduler and binds it to its parent context
void bind_to ( internal::generic_scheduler *local_sched ); void bind_to ( internal::generic_scheduler *local_sched );
//! Registers this context with the local scheduler //! Registers this context with the local scheduler
void register_with ( internal::generic_scheduler *local_sched ); void register_with ( internal::generic_scheduler *local_sched );
#if __TBB_FP_CONTEXT
//! Copies FPU control setting from another context
// TODO: Consider adding #else stub in order to omit #if sections in ot
her code
void copy_fp_settings( const task_group_context &src );
#endif /* __TBB_FP_CONTEXT */
}; // class task_group_context }; // class task_group_context
#endif /* __TBB_TASK_GROUP_CONTEXT */ #endif /* __TBB_TASK_GROUP_CONTEXT */
//! Base class for user-defined tasks. //! Base class for user-defined tasks.
/** @ingroup task_scheduling */ /** @ingroup task_scheduling */
class task: __TBB_TASK_BASE_ACCESS interface5::internal::task_base { class task: __TBB_TASK_BASE_ACCESS interface5::internal::task_base {
//! Set reference count //! Set reference count
void __TBB_EXPORTED_METHOD internal_set_ref_count( int count ); void __TBB_EXPORTED_METHOD internal_set_ref_count( int count );
skipping to change at line 686 skipping to change at line 679
#if __TBB_RECYCLE_TO_ENQUEUE #if __TBB_RECYCLE_TO_ENQUEUE
//! Schedule this to enqueue after descendant tasks complete. //! Schedule this to enqueue after descendant tasks complete.
/** Save enqueue/spawn difference, it has the semantics of recycle_as_s afe_continuation. */ /** Save enqueue/spawn difference, it has the semantics of recycle_as_s afe_continuation. */
void recycle_to_enqueue() { void recycle_to_enqueue() {
__TBB_ASSERT( prefix().state==executing, "execute not running, or a lready recycled" ); __TBB_ASSERT( prefix().state==executing, "execute not running, or a lready recycled" );
prefix().state = to_enqueue; prefix().state = to_enqueue;
} }
#endif /* __TBB_RECYCLE_TO_ENQUEUE */ #endif /* __TBB_RECYCLE_TO_ENQUEUE */
// All depth-related methods are obsolete, and are retained for the sak
e
// of backward source compatibility only
intptr_t depth() const {return 0;}
void set_depth( intptr_t ) {}
void add_to_depth( int ) {}
//--------------------------------------------------------------------- --- //--------------------------------------------------------------------- ---
// Spawning and blocking // Spawning and blocking
//--------------------------------------------------------------------- --- //--------------------------------------------------------------------- ---
//! Set reference count //! Set reference count
void set_ref_count( int count ) { void set_ref_count( int count ) {
#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
internal_set_ref_count(count); internal_set_ref_count(count);
#else #else
prefix().ref_count = count; prefix().ref_count = count;
 End of changes. 7 change blocks. 
44 lines changed or deleted 39 lines changed or added


 task_arena.h   task_arena.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_task_arena_H #ifndef __TBB_task_arena_H
#define __TBB_task_arena_H #define __TBB_task_arena_H
#include "task.h" #include "task.h"
#include "tbb_exception.h" #include "tbb_exception.h"
#if TBB_USE_THREADING_TOOLS #if TBB_USE_THREADING_TOOLS
#include "atomic.h" // for as_atomic #include "atomic.h" // for as_atomic
#endif #endif
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 task_group.h   task_group.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_task_group_H #ifndef __TBB_task_group_H
#define __TBB_task_group_H #define __TBB_task_group_H
#include "task.h" #include "task.h"
#include "tbb_exception.h" #include "tbb_exception.h"
#if __TBB_TASK_GROUP_CONTEXT #if __TBB_TASK_GROUP_CONTEXT
skipping to change at line 175 skipping to change at line 167
my_context.cancel_group_execution(); my_context.cancel_group_execution();
} }
}; // class task_group_base }; // class task_group_base
} // namespace internal } // namespace internal
class task_group : public internal::task_group_base { class task_group : public internal::task_group_base {
public: public:
task_group () : task_group_base( task_group_context::concurrent_wait ) {} task_group () : task_group_base( task_group_context::concurrent_wait ) {}
#if TBB_DEPRECATED
~task_group() __TBB_TRY {
__TBB_ASSERT( my_root->ref_count() != 0, NULL );
if( my_root->ref_count() > 1 )
my_root->wait_for_all();
}
#if TBB_USE_EXCEPTIONS
catch (...) {
// Have to destroy my_root here as the base class destructor won't
be called
task::destroy(*my_root);
throw;
}
#endif /* TBB_USE_EXCEPTIONS */
#endif /* TBB_DEPRECATED */
#if __SUNPRO_CC #if __SUNPRO_CC
template<typename F> template<typename F>
void run( task_handle<F>& h ) { void run( task_handle<F>& h ) {
internal_run< task_handle<F>, internal::task_handle_task<F> >( h ); internal_run< task_handle<F>, internal::task_handle_task<F> >( h );
} }
#else #else
using task_group_base::run; using task_group_base::run;
#endif #endif
template<typename F> template<typename F>
 End of changes. 2 change blocks. 
44 lines changed or deleted 29 lines changed or added


 task_scheduler_init.h   task_scheduler_init.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_task_scheduler_init_H #ifndef __TBB_task_scheduler_init_H
#define __TBB_task_scheduler_init_H #define __TBB_task_scheduler_init_H
#include "tbb_stddef.h" #include "tbb_stddef.h"
#include "limits.h" #include "limits.h"
namespace tbb { namespace tbb {
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 task_scheduler_observer.h   task_scheduler_observer.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_task_scheduler_observer_H #ifndef __TBB_task_scheduler_observer_H
#define __TBB_task_scheduler_observer_H #define __TBB_task_scheduler_observer_H
#include "atomic.h" #include "atomic.h"
#if __TBB_TASK_ARENA #if __TBB_TASK_ARENA
#include "task_arena.h" #include "task_arena.h"
#endif //__TBB_TASK_ARENA #endif //__TBB_TASK_ARENA
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 tbb.h   tbb.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_tbb_H #ifndef __TBB_tbb_H
#define __TBB_tbb_H #define __TBB_tbb_H
/** /**
This header bulk-includes declarations or definitions of all the functi onality This header bulk-includes declarations or definitions of all the functi onality
provided by TBB (save for malloc dependent headers). provided by TBB (save for malloc dependent headers).
If you use only a few TBB constructs, consider including specific heade rs only. If you use only a few TBB constructs, consider including specific heade rs only.
skipping to change at line 50 skipping to change at line 42
#if TBB_PREVIEW_AGGREGATOR #if TBB_PREVIEW_AGGREGATOR
#include "aggregator.h" #include "aggregator.h"
#endif #endif
#include "aligned_space.h" #include "aligned_space.h"
#include "atomic.h" #include "atomic.h"
#include "blocked_range.h" #include "blocked_range.h"
#include "blocked_range2d.h" #include "blocked_range2d.h"
#include "blocked_range3d.h" #include "blocked_range3d.h"
#include "cache_aligned_allocator.h" #include "cache_aligned_allocator.h"
#include "combinable.h" #include "combinable.h"
#include "concurrent_unordered_map.h"
#include "concurrent_hash_map.h" #include "concurrent_hash_map.h"
#if TBB_PREVIEW_CONCURRENT_LRU_CACHE
#include "concurrent_lru_cache.h"
#endif
#include "concurrent_priority_queue.h"
#include "concurrent_queue.h" #include "concurrent_queue.h"
#include "concurrent_unordered_map.h"
#include "concurrent_unordered_set.h"
#include "concurrent_vector.h" #include "concurrent_vector.h"
#include "critical_section.h" #include "critical_section.h"
#include "enumerable_thread_specific.h" #include "enumerable_thread_specific.h"
#include "flow_graph.h"
#include "mutex.h" #include "mutex.h"
#include "null_mutex.h" #include "null_mutex.h"
#include "null_rw_mutex.h" #include "null_rw_mutex.h"
#include "parallel_do.h" #include "parallel_do.h"
#include "parallel_for.h" #include "parallel_for.h"
#include "parallel_for_each.h" #include "parallel_for_each.h"
#include "parallel_invoke.h" #include "parallel_invoke.h"
#include "parallel_reduce.h" #include "parallel_reduce.h"
#include "parallel_scan.h" #include "parallel_scan.h"
#include "parallel_sort.h" #include "parallel_sort.h"
#include "partitioner.h" #include "partitioner.h"
#include "pipeline.h" #include "pipeline.h"
#include "queuing_mutex.h" #include "queuing_mutex.h"
#include "queuing_rw_mutex.h" #include "queuing_rw_mutex.h"
#include "reader_writer_lock.h" #include "reader_writer_lock.h"
#include "concurrent_priority_queue.h"
#include "recursive_mutex.h" #include "recursive_mutex.h"
#include "spin_mutex.h" #include "spin_mutex.h"
#include "spin_rw_mutex.h" #include "spin_rw_mutex.h"
#include "task.h" #include "task.h"
#include "task_arena.h"
#include "task_group.h" #include "task_group.h"
#include "task_scheduler_init.h" #include "task_scheduler_init.h"
#include "task_scheduler_observer.h" #include "task_scheduler_observer.h"
#include "tbb_allocator.h" #include "tbb_allocator.h"
#include "tbb_exception.h" #include "tbb_exception.h"
#include "tbb_thread.h" #include "tbb_thread.h"
#include "tick_count.h" #include "tick_count.h"
#endif /* __TBB_tbb_H */ #endif /* __TBB_tbb_H */
 End of changes. 7 change blocks. 
30 lines changed or deleted 37 lines changed or added


 tbb_allocator.h   tbb_allocator.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_tbb_allocator_H #ifndef __TBB_tbb_allocator_H
#define __TBB_tbb_allocator_H #define __TBB_tbb_allocator_H
#include "tbb_stddef.h" #include "tbb_stddef.h"
#include <new> #include <new>
#if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN #if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
#include <utility> // std::forward #include <utility> // std::forward
#endif #endif
#if !TBB_USE_EXCEPTIONS && _MSC_VER #if !TBB_USE_EXCEPTIONS && _MSC_VER
// Suppress "C++ exception handler used, but unwind semantics are not e nabled" warning in STL headers // Suppress "C++ exception handler used, but unwind semantics are not e nabled" warning in STL headers
#pragma warning (push) #pragma warning (push)
#pragma warning (disable: 4530) #pragma warning (disable: 4530)
#endif #endif
#include <cstring> #include <cstring>
skipping to change at line 127 skipping to change at line 119
//! Largest value for which method allocate might succeed. //! Largest value for which method allocate might succeed.
size_type max_size() const throw() { size_type max_size() const throw() {
size_type max = static_cast<size_type>(-1) / sizeof (value_type); size_type max = static_cast<size_type>(-1) / sizeof (value_type);
return (max > 0 ? max : 1); return (max > 0 ? max : 1);
} }
//! Copy-construct value at location pointed to by p. //! Copy-construct value at location pointed to by p.
#if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC #if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
template<typename U, typename... Args> template<typename U, typename... Args>
void construct(U *p, Args&&... args) void construct(U *p, Args&&... args)
#if __TBB_CPP11_STD_FORWARD_BROKEN
{ ::new((void *)p) U((args)...); }
#else
{ ::new((void *)p) U(std::forward<Args>(args)...); } { ::new((void *)p) U(std::forward<Args>(args)...); }
#endif
#else // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC #else // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
#if __TBB_CPP11_RVALUE_REF_PRESENT
void construct( pointer p, value_type&& value ) {::new((void*)(p)) valu
e_type(std::move(value));}
#endif
void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);} void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);}
#endif // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC #endif // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
//! Destroy value at location pointed to by p. //! Destroy value at location pointed to by p.
void destroy( pointer p ) {p->~value_type();} void destroy( pointer p ) {p->~value_type();}
//! Returns current allocator //! Returns current allocator
static malloc_type allocator_type() { static malloc_type allocator_type() {
return internal::is_malloc_used_v3() ? standard : scalable; return internal::is_malloc_used_v3() ? standard : scalable;
} }
 End of changes. 5 change blocks. 
33 lines changed or deleted 34 lines changed or added


 tbb_annotate.h   tbb_annotate.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_annotate_H #ifndef __TBB_annotate_H
#define __TBB_annotate_H #define __TBB_annotate_H
// Macros used by the Intel(R) Parallel Advisor. // Macros used by the Intel(R) Parallel Advisor.
#ifdef __TBB_NORMAL_EXECUTION #ifdef __TBB_NORMAL_EXECUTION
#define ANNOTATE_SITE_BEGIN( site ) #define ANNOTATE_SITE_BEGIN( site )
#define ANNOTATE_SITE_END( site ) #define ANNOTATE_SITE_END( site )
#define ANNOTATE_TASK_BEGIN( task ) #define ANNOTATE_TASK_BEGIN( task )
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 tbb_config.h   tbb_config.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_tbb_config_H #ifndef __TBB_tbb_config_H
#define __TBB_tbb_config_H #define __TBB_tbb_config_H
/** This header is supposed to contain macro definitions and C style commen ts only. /** This header is supposed to contain macro definitions and C style commen ts only.
The macros defined here are intended to control such aspects of TBB bui ld as The macros defined here are intended to control such aspects of TBB bui ld as
- presence of compiler features - presence of compiler features
- compilation modes - compilation modes
- feature sets - feature sets
skipping to change at line 54 skipping to change at line 46
#endif #endif
// note that when ICC is in use __TBB_GCC_VERSION might not closely match G CC version on the machine // note that when ICC is in use __TBB_GCC_VERSION might not closely match G CC version on the machine
#define __TBB_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC _PATCHLEVEL__) #define __TBB_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC _PATCHLEVEL__)
#if __clang__ #if __clang__
/**according to clang documentation version can be vendor specific **/ /**according to clang documentation version can be vendor specific **/
#define __TBB_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) #define __TBB_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
#endif #endif
/** Preprocessor symbols to determine HW architecture **/
#if _WIN32||_WIN64
# if defined(_M_X64)||defined(__x86_64__) // the latter for MinGW suppor
t
# define __TBB_x86_64 1
# elif defined(_M_IA64)
# define __TBB_ipf 1
# elif defined(_M_IX86)||defined(__i386__) // the latter for MinGW suppor
t
# define __TBB_x86_32 1
# else
# define __TBB_generic_arch 1
# endif
#else /* Assume generic Unix */
# if !__linux__ && !__APPLE__
# define __TBB_generic_os 1
# endif
# if __x86_64__
# define __TBB_x86_64 1
# elif __ia64__
# define __TBB_ipf 1
# elif __i386__||__i386 // __i386 is for Sun OS
# define __TBB_x86_32 1
# else
# define __TBB_generic_arch 1
# endif
#endif
#if __MIC__ || __MIC2__
#define __TBB_DEFINE_MIC 1
#endif
#define __TBB_TSX_AVAILABLE (__TBB_x86_32 || __TBB_x86_64) && !__TBB_DEFIN
E_MIC
/** Presence of compiler features **/ /** Presence of compiler features **/
#if __INTEL_COMPILER == 9999 && __INTEL_COMPILER_BUILD_DATE == 20110811 #if __INTEL_COMPILER == 9999 && __INTEL_COMPILER_BUILD_DATE == 20110811
/* Intel(R) Composer XE 2011 Update 6 incorrectly sets __INTEL_COMPILER. Fi x it. */ /* Intel(R) Composer XE 2011 Update 6 incorrectly sets __INTEL_COMPILER. Fi x it. */
#undef __INTEL_COMPILER #undef __INTEL_COMPILER
#define __INTEL_COMPILER 1210 #define __INTEL_COMPILER 1210
#endif #endif
#if __TBB_GCC_VERSION >= 40400 && !defined(__INTEL_COMPILER) #if __TBB_GCC_VERSION >= 40400 && !defined(__INTEL_COMPILER)
/** warning suppression pragmas available in GCC since 4.4 **/ /** warning suppression pragmas available in GCC since 4.4 **/
skipping to change at line 89 skipping to change at line 114
/** C++11 mode detection macros for Intel C++ compiler (enabled by -std =c++0x option): /** C++11 mode detection macros for Intel C++ compiler (enabled by -std =c++0x option):
__INTEL_CXX11_MODE__ for version >=13.0 __INTEL_CXX11_MODE__ for version >=13.0
__STDC_HOSTED__ for version >=12.0 on Windows, __STDC_HOSTED__ for version >=12.0 on Windows,
__GXX_EXPERIMENTAL_CXX0X__ for version >=12.0 on Linux and OS X. **/ __GXX_EXPERIMENTAL_CXX0X__ for version >=12.0 on Linux and OS X. **/
// On Windows, C++11 features supported by Visual Studio 2010 and high er are enabled by default // On Windows, C++11 features supported by Visual Studio 2010 and high er are enabled by default
#ifndef __INTEL_CXX11_MODE__ #ifndef __INTEL_CXX11_MODE__
#define __INTEL_CXX11_MODE__ ((_MSC_VER && __STDC_HOSTED__) || __GX X_EXPERIMENTAL_CXX0X__) #define __INTEL_CXX11_MODE__ ((_MSC_VER && __STDC_HOSTED__) || __GX X_EXPERIMENTAL_CXX0X__)
// TODO: check if more conditions can be simplified with the above macro // TODO: check if more conditions can be simplified with the above macro
#endif #endif
#define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (__INTEL_CXX11_MODE__ && __VARIADIC_TEMPLATES) #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (__INTEL_CXX11_MODE__ && __VARIADIC_TEMPLATES)
#define __TBB_CPP11_RVALUE_REF_PRESENT ((__GXX_EXPERIMENTAL_ // Both r-value reference support in compiler and std::move/std::forwar
CXX0X__ || _MSC_VER >= 1600) && __INTEL_COMPILER >= 1200) d
// presence in C++ standard library is checked.
#define __TBB_CPP11_RVALUE_REF_PRESENT ((__GXX_EXPERIMENTAL_
CXX0X__ && (__TBB_GCC_VERSION >= 40300 || _LIBCPP_VERSION) || _MSC_VER >= 1
600) && __INTEL_COMPILER >= 1200)
#if _MSC_VER >= 1600 #if _MSC_VER >= 1600
#define __TBB_EXCEPTION_PTR_PRESENT ( __INTEL_COMPILER > 1300 \ #define __TBB_EXCEPTION_PTR_PRESENT ( __INTEL_COMPILER > 1300 \
/*ICC 12.1 Upd 10 and 13 beta Upd 2 fixed exception_ptr linking issue*/ \ /*ICC 12.1 Upd 10 and 13 beta Upd 2 fixed exception_ptr linking issue*/ \
|| (__INTEL_COMPILER == 1300 && __INTEL_COMPILER_BUILD_DATE >= 20120530) \ || (__INTEL_COMPILER == 1300 && __INTEL_COMPILER_BUILD_DATE >= 20120530) \
|| (__INTEL_COMPILER == 1210 && __INTEL_COMPILER_BUILD_DATE >= 20120410) ) || (__INTEL_COMPILER == 1210 && __INTEL_COMPILER_BUILD_DATE >= 20120410) )
/** libstdc++ that comes with GCC 4.6 use C++11 features not supported by ICC 12.1. /** libstdc++ that comes with GCC 4.6 use C++11 features not supported by ICC 12.1.
* Because of that ICC 12.1 does not support C++11 mode with with gcc 4.6 (or higher), * Because of that ICC 12.1 does not support C++11 mode with with gcc 4.6 (or higher),
* and therefore does not define __GXX_EXPERIMENTAL_CXX0X__ macro **/ * and therefore does not define __GXX_EXPERIMENTAL_CXX0X__ macro **/
#elif __TBB_GCC_VERSION >= 40404 && __TBB_GCC_VERSION < 40600 #elif __TBB_GCC_VERSION >= 40404 && __TBB_GCC_VERSION < 40600
#define __TBB_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __INTEL_COMPILER >= 1200) #define __TBB_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __INTEL_COMPILER >= 1200)
skipping to change at line 122 skipping to change at line 149
#endif #endif
#else #else
/** TODO: when MSVC2013 is supported by Intel C++ compiler, it will be enabled silently by compiler, so rule will need to be updated.**/ /** TODO: when MSVC2013 is supported by Intel C++ compiler, it will be enabled silently by compiler, so rule will need to be updated.**/
#define __TBB_INITIALIZER_LISTS_PRESENT __INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1400 && (_MSC_VER >= 1800 || __TBB_GCC_VERSION >= 40 400 || _LIBCPP_VERSION) #define __TBB_INITIALIZER_LISTS_PRESENT __INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1400 && (_MSC_VER >= 1800 || __TBB_GCC_VERSION >= 40 400 || _LIBCPP_VERSION)
#endif #endif
#define __TBB_CONSTEXPR_PRESENT __INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1400 #define __TBB_CONSTEXPR_PRESENT __INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1400
#define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT __INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1200 #define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT __INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1200
/** ICC seems to disable support of noexcept event in c++11 when compil ing in compatibility mode for gcc <4.6 **/ /** ICC seems to disable support of noexcept event in c++11 when compil ing in compatibility mode for gcc <4.6 **/
#define __TBB_NOEXCEPT_PRESENT __INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1300 && (__TBB_GCC_VERSION >= 40600 || _LIBCPP_VERSI ON || _MSC_VER) #define __TBB_NOEXCEPT_PRESENT __INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1300 && (__TBB_GCC_VERSION >= 40600 || _LIBCPP_VERSI ON || _MSC_VER)
#define __TBB_CPP11_STD_BEGIN_END_PRESENT (_MSC_VER >= 1700 ||
__GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1310 && (__TBB_GCC_VERSIO
N >= 40600 || _LIBCPP_VERSION))
#define __TBB_CPP11_AUTO_PRESENT (_MSC_VER >= 1600 ||
__GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1210)
#define __TBB_CPP11_DECLTYPE_PRESENT (_MSC_VER >= 1600 ||
__GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1210)
#elif __clang__ #elif __clang__
//TODO: these options need to be rechecked //TODO: these options need to be rechecked
/** on OS X* the only way to get C++11 is to use clang. For library feature s (e.g. exception_ptr) libc++ is also /** on OS X* the only way to get C++11 is to use clang. For library feature s (e.g. exception_ptr) libc++ is also
* required. So there is no need to check GCC version for clang**/ * required. So there is no need to check GCC version for clang**/
#define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT __has_feature(__cxx_ #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (__has_feature(__cxx
variadic_templates__) _variadic_templates__))
#define __TBB_CPP11_RVALUE_REF_PRESENT __has_feature(__cxx_ #define __TBB_CPP11_RVALUE_REF_PRESENT (__has_feature(__cxx
rvalue_references__) _rvalue_references__) && (__TBB_GCC_VERSION >= 40300 || _LIBCPP_VERSION))
/** TODO: extend exception_ptr related conditions to cover libstdc++ **/ /** TODO: extend exception_ptr related conditions to cover libstdc++ **/
#define __TBB_EXCEPTION_PTR_PRESENT (__cplusplus >= 20110 3L && _LIBCPP_VERSION) #define __TBB_EXCEPTION_PTR_PRESENT (__cplusplus >= 20110 3L && _LIBCPP_VERSION)
#define __TBB_MAKE_EXCEPTION_PTR_PRESENT (__cplusplus >= 20110 3L && _LIBCPP_VERSION) #define __TBB_MAKE_EXCEPTION_PTR_PRESENT (__cplusplus >= 20110 3L && _LIBCPP_VERSION)
#define __TBB_STATIC_ASSERT_PRESENT __has_feature(__cxx_s tatic_assert__) #define __TBB_STATIC_ASSERT_PRESENT __has_feature(__cxx_s tatic_assert__)
/**Clang (preprocessor) has problems with dealing with expression havin /**Clang (preprocessor) has problems with dealing with expression havin
g __has_include in #if's g __has_include in #ifs
* used inside C++ code. (At least version that comes with OS X 10.8) * * used inside C++ code. (At least version that comes with OS X 10.8 :
*/ Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)) **/
#if (__GXX_EXPERIMENTAL_CXX0X__ && __has_include(<tuple>)) #if (__GXX_EXPERIMENTAL_CXX0X__ && __has_include(<tuple>))
#define __TBB_CPP11_TUPLE_PRESENT 1 #define __TBB_CPP11_TUPLE_PRESENT 1
#endif #endif
#if (__has_feature(__cxx_generalized_initializers__) && __has_include(< initializer_list>)) #if (__has_feature(__cxx_generalized_initializers__) && __has_include(< initializer_list>))
#define __TBB_INITIALIZER_LISTS_PRESENT 1 #define __TBB_INITIALIZER_LISTS_PRESENT 1
#endif #endif
#define __TBB_CONSTEXPR_PRESENT __has_feature(__cxx_c onstexpr__) #define __TBB_CONSTEXPR_PRESENT __has_feature(__cxx_c onstexpr__)
#define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT (__has_feature(__cxx_ defaulted_functions__) && __has_feature(__cxx_deleted_functions__)) #define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT (__has_feature(__cxx_ defaulted_functions__) && __has_feature(__cxx_deleted_functions__))
/**For some unknown reason __has_feature(__cxx_noexcept) does not yiel d true for all cases. Compiler bug ? **/ /**For some unknown reason __has_feature(__cxx_noexcept) does not yiel d true for all cases. Compiler bug ? **/
#define __TBB_NOEXCEPT_PRESENT (__cplusplus >= 20110 3L) #define __TBB_NOEXCEPT_PRESENT (__cplusplus >= 20110 3L)
#define __TBB_CPP11_STD_BEGIN_END_PRESENT (__has_feature(__cxx_
range_for__) && _LIBCPP_VERSION)
#define __TBB_CPP11_AUTO_PRESENT __has_feature(__cxx_a
uto_type__)
#define __TBB_CPP11_DECLTYPE_PRESENT __has_feature(__cxx_d
ecltype__)
#elif __GNUC__ #elif __GNUC__
#define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT __GXX_EXPERIMENTAL_CX X0X__ #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT __GXX_EXPERIMENTAL_CX X0X__
#define __TBB_CPP11_RVALUE_REF_PRESENT __GXX_EXPERIMENTAL_CX X0X__ #define __TBB_CPP11_RVALUE_REF_PRESENT __GXX_EXPERIMENTAL_CX X0X__
/** __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 here is a substitution for _GLIB CXX_ATOMIC_BUILTINS_4, which is a prerequisite /** __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 here is a substitution for _GLIB CXX_ATOMIC_BUILTINS_4, which is a prerequisite
for exception_ptr but cannot be used in this file because it is def ined in a header, not by the compiler. for exception_ptr but cannot be used in this file because it is def ined in a header, not by the compiler.
If the compiler has no atomic intrinsics, the C++ library should no t expect those as well. **/ If the compiler has no atomic intrinsics, the C++ library should no t expect those as well. **/
#define __TBB_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40404 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) #define __TBB_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40404 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
#define __TBB_MAKE_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40600) #define __TBB_MAKE_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40600)
#define __TBB_STATIC_ASSERT_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40300) #define __TBB_STATIC_ASSERT_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40300)
#define __TBB_CPP11_TUPLE_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40300) #define __TBB_CPP11_TUPLE_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40300)
#define __TBB_INITIALIZER_LISTS_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40400) #define __TBB_INITIALIZER_LISTS_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40400)
/** gcc seems have to support constexpr from 4.4 but tests in (test_ato mic) seeming reasonable fail to compile prior 4.6**/ /** gcc seems have to support constexpr from 4.4 but tests in (test_ato mic) seeming reasonable fail to compile prior 4.6**/
#define __TBB_CONSTEXPR_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40400) #define __TBB_CONSTEXPR_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40400)
#define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40400) #define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40400)
#define __TBB_NOEXCEPT_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40600) #define __TBB_NOEXCEPT_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40600)
#define __TBB_CPP11_STD_BEGIN_END_PRESENT (__GXX_EXPERIMENTAL_C
XX0X__ && __TBB_GCC_VERSION >= 40600)
#define __TBB_CPP11_AUTO_PRESENT (__GXX_EXPERIMENTAL_C
XX0X__ && __TBB_GCC_VERSION >= 40400)
#define __TBB_CPP11_DECLTYPE_PRESENT (__GXX_EXPERIMENTAL_C
XX0X__ && __TBB_GCC_VERSION >= 40400)
#elif _MSC_VER #elif _MSC_VER
#define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (_MSC_VER >= 1800) #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (_MSC_VER >= 1800)
#define __TBB_CPP11_RVALUE_REF_PRESENT (_MSC_VER >= 1600) #define __TBB_CPP11_RVALUE_REF_PRESENT (_MSC_VER >= 1600)
#define __TBB_EXCEPTION_PTR_PRESENT (_MSC_VER >= 1600) #define __TBB_EXCEPTION_PTR_PRESENT (_MSC_VER >= 1600)
#define __TBB_STATIC_ASSERT_PRESENT (_MSC_VER >= 1600) #define __TBB_STATIC_ASSERT_PRESENT (_MSC_VER >= 1600)
#define __TBB_MAKE_EXCEPTION_PTR_PRESENT (_MSC_VER >= 1700) #define __TBB_MAKE_EXCEPTION_PTR_PRESENT (_MSC_VER >= 1700)
#define __TBB_CPP11_TUPLE_PRESENT (_MSC_VER >= 1600) #define __TBB_CPP11_TUPLE_PRESENT (_MSC_VER >= 1600)
#define __TBB_INITIALIZER_LISTS_PRESENT (_MSC_VER >= 1800) #define __TBB_INITIALIZER_LISTS_PRESENT (_MSC_VER >= 1800)
#define __TBB_CONSTEXPR_PRESENT 0 #define __TBB_CONSTEXPR_PRESENT 0
#define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT (_MSC_VER >= 1800) #define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT (_MSC_VER >= 1800)
#define __TBB_NOEXCEPT_PRESENT 0 /*for _MSC_VER == 1 800*/ #define __TBB_NOEXCEPT_PRESENT 0 /*for _MSC_VER == 1 800*/
#define __TBB_CPP11_STD_BEGIN_END_PRESENT (_MSC_VER >= 1700)
#define __TBB_CPP11_AUTO_PRESENT (_MSC_VER >= 1600)
#define __TBB_CPP11_DECLTYPE_PRESENT (_MSC_VER >= 1600)
#else #else
#define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 0 #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 0
#define __TBB_CPP11_RVALUE_REF_PRESENT 0 #define __TBB_CPP11_RVALUE_REF_PRESENT 0
#define __TBB_EXCEPTION_PTR_PRESENT 0 #define __TBB_EXCEPTION_PTR_PRESENT 0
#define __TBB_STATIC_ASSERT_PRESENT 0 #define __TBB_STATIC_ASSERT_PRESENT 0
#define __TBB_MAKE_EXCEPTION_PTR_PRESENT 0 #define __TBB_MAKE_EXCEPTION_PTR_PRESENT 0
#define __TBB_CPP11_TUPLE_PRESENT 0 #define __TBB_CPP11_TUPLE_PRESENT 0
#define __TBB_INITIALIZER_LISTS_PRESENT 0 #define __TBB_INITIALIZER_LISTS_PRESENT 0
#define __TBB_CONSTEXPR_PRESENT 0 #define __TBB_CONSTEXPR_PRESENT 0
#define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT 0 #define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT 0
#define __TBB_NOEXCEPT_PRESENT 0 #define __TBB_NOEXCEPT_PRESENT 0
#define __TBB_CPP11_STD_BEGIN_END_PRESENT 0
#define __TBB_CPP11_AUTO_PRESENT 0
#define __TBB_CPP11_DECLTYPE_PRESENT 0
#endif #endif
// C++11 standard library features
#define __TBB_CPP11_TYPE_PROPERTIES_PRESENT (_LIBCPP_VERSION || _MSC_V
ER >= 1700)
#define __TBB_TR1_TYPE_PROPERTIES_IN_STD_PRESENT (__GXX_EXPERIMENTAL_CXX0X_
_ && __TBB_GCC_VERSION >= 40300 || _MSC_VER >= 1600)
//TODO: Probably more accurate way is to analyze version of stdlibc++ via__
GLIBCXX__ instead of __TBB_GCC_VERSION
#define __TBB_ALLOCATOR_TRAITS_PRESENT (__cplusplus >= 201103L &&
_LIBCPP_VERSION || _MSC_VER >= 1700 ||
\
__GXX_EXPERIMENTAL_CXX0X_
_ && __TBB_GCC_VERSION >= 40700 && !(__TBB_GCC_VERSION == 40700 && __TBB_DE
FINE_MIC) \
)
//TODO: not clear how exactly this macro affects exception_ptr - investigat e //TODO: not clear how exactly this macro affects exception_ptr - investigat e
// On linux ICC fails to find existing std::exception_ptr in libstdc++ with out this define // On linux ICC fails to find existing std::exception_ptr in libstdc++ with out this define
#if __INTEL_COMPILER && __GNUC__ && __TBB_EXCEPTION_PTR_PRESENT && !defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) #if __INTEL_COMPILER && __GNUC__ && __TBB_EXCEPTION_PTR_PRESENT && !defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1 #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
#endif #endif
// Work around a bug in MinGW32 // Work around a bug in MinGW32
#if __MINGW32__ && __TBB_EXCEPTION_PTR_PRESENT && !defined(_GLIBCXX_ATOMIC_ BUILTINS_4) #if __MINGW32__ && __TBB_EXCEPTION_PTR_PRESENT && !defined(_GLIBCXX_ATOMIC_ BUILTINS_4)
#define _GLIBCXX_ATOMIC_BUILTINS_4 #define _GLIBCXX_ATOMIC_BUILTINS_4
#endif #endif
skipping to change at line 214 skipping to change at line 265
#if __TBB_GCC_VERSION >= 40306 || __INTEL_COMPILER >= 1200 #if __TBB_GCC_VERSION >= 40306 || __INTEL_COMPILER >= 1200
/** built-in atomics available in GCC since 4.1.2 **/ /** built-in atomics available in GCC since 4.1.2 **/
#define __TBB_GCC_BUILTIN_ATOMICS_PRESENT 1 #define __TBB_GCC_BUILTIN_ATOMICS_PRESENT 1
#endif #endif
#if __INTEL_COMPILER >= 1200 #if __INTEL_COMPILER >= 1200
/** built-in C++11 style atomics available in ICC since 12.0 **/ /** built-in C++11 style atomics available in ICC since 12.0 **/
#define __TBB_ICC_BUILTIN_ATOMICS_PRESENT 1 #define __TBB_ICC_BUILTIN_ATOMICS_PRESENT 1
#endif #endif
#if __MIC__ || __MIC2__ #define __TBB_TSX_INTRINSICS_PRESENT ((__RTM__ || _MSC_VER>=1700 || __INTEL
#define __TBB_DEFINE_MIC 1 _COMPILER>=1300) && !__TBB_DEFINE_MIC && !__ANDROID__)
#endif
#define __TBB_TSX_INTRINSICS_PRESENT ( (__TBB_GCC_VERSION>=40800) || (_MSC_
VER>=1700) || (__INTEL_COMPILER>=1300) ) && !__TBB_DEFINE_MIC && !__ANDROID
__
/** User controlled TBB features & modes **/ /** User controlled TBB features & modes **/
#ifndef TBB_USE_DEBUG #ifndef TBB_USE_DEBUG
#ifdef TBB_DO_ASSERT
#define TBB_USE_DEBUG TBB_DO_ASSERT
#else
#ifdef _DEBUG #ifdef _DEBUG
#define TBB_USE_DEBUG _DEBUG #define TBB_USE_DEBUG _DEBUG
#else #else
#define TBB_USE_DEBUG 0 #define TBB_USE_DEBUG 0
#endif #endif
#endif /* TBB_DO_ASSERT */
#endif /* TBB_USE_DEBUG */ #endif /* TBB_USE_DEBUG */
#ifndef TBB_USE_ASSERT #ifndef TBB_USE_ASSERT
#ifdef TBB_DO_ASSERT
#define TBB_USE_ASSERT TBB_DO_ASSERT
#else
#define TBB_USE_ASSERT TBB_USE_DEBUG #define TBB_USE_ASSERT TBB_USE_DEBUG
#endif /* TBB_DO_ASSERT */
#endif /* TBB_USE_ASSERT */ #endif /* TBB_USE_ASSERT */
#ifndef TBB_USE_THREADING_TOOLS #ifndef TBB_USE_THREADING_TOOLS
#ifdef TBB_DO_THREADING_TOOLS
#define TBB_USE_THREADING_TOOLS TBB_DO_THREADING_TOOLS
#else
#define TBB_USE_THREADING_TOOLS TBB_USE_DEBUG #define TBB_USE_THREADING_TOOLS TBB_USE_DEBUG
#endif /* TBB_DO_THREADING_TOOLS */
#endif /* TBB_USE_THREADING_TOOLS */ #endif /* TBB_USE_THREADING_TOOLS */
#ifndef TBB_USE_PERFORMANCE_WARNINGS #ifndef TBB_USE_PERFORMANCE_WARNINGS
#ifdef TBB_PERFORMANCE_WARNINGS #ifdef TBB_PERFORMANCE_WARNINGS
#define TBB_USE_PERFORMANCE_WARNINGS TBB_PERFORMANCE_WARNINGS #define TBB_USE_PERFORMANCE_WARNINGS TBB_PERFORMANCE_WARNINGS
#else #else
#define TBB_USE_PERFORMANCE_WARNINGS TBB_USE_DEBUG #define TBB_USE_PERFORMANCE_WARNINGS TBB_USE_DEBUG
#endif /* TBB_PEFORMANCE_WARNINGS */ #endif /* TBB_PEFORMANCE_WARNINGS */
#endif /* TBB_USE_PERFORMANCE_WARNINGS */ #endif /* TBB_USE_PERFORMANCE_WARNINGS */
skipping to change at line 355 skipping to change at line 390
#ifndef __TBB_FP_CONTEXT #ifndef __TBB_FP_CONTEXT
#define __TBB_FP_CONTEXT __TBB_TASK_GROUP_CONTEXT #define __TBB_FP_CONTEXT __TBB_TASK_GROUP_CONTEXT
#endif /* __TBB_FP_CONTEXT */ #endif /* __TBB_FP_CONTEXT */
#if __TBB_FP_CONTEXT && !__TBB_TASK_GROUP_CONTEXT #if __TBB_FP_CONTEXT && !__TBB_TASK_GROUP_CONTEXT
#error __TBB_FP_CONTEXT requires __TBB_TASK_GROUP_CONTEXT to be enabled #error __TBB_FP_CONTEXT requires __TBB_TASK_GROUP_CONTEXT to be enabled
#endif #endif
#ifndef __TBB_TASK_ARENA #ifndef __TBB_TASK_ARENA
#define __TBB_TASK_ARENA (__TBB_BUILD||TBB_PREVIEW_TASK_ARENA) #define __TBB_TASK_ARENA 1
#endif /* __TBB_TASK_ARENA */ #endif /* __TBB_TASK_ARENA */
#if __TBB_TASK_ARENA #if __TBB_TASK_ARENA
#define __TBB_RECYCLE_TO_ENQUEUE __TBB_BUILD // keep non-official #define __TBB_RECYCLE_TO_ENQUEUE __TBB_BUILD // keep non-official
#if !__TBB_SCHEDULER_OBSERVER #if !__TBB_SCHEDULER_OBSERVER
#error TBB_PREVIEW_TASK_ARENA requires __TBB_SCHEDULER_OBSERVER to be enabled #error __TBB_TASK_ARENA requires __TBB_SCHEDULER_OBSERVER to be ena bled
#endif #endif
#endif /* __TBB_TASK_ARENA */ #endif /* __TBB_TASK_ARENA */
#ifndef __TBB_ARENA_OBSERVER #ifndef __TBB_ARENA_OBSERVER
#define __TBB_ARENA_OBSERVER ((__TBB_BUILD||TBB_PREVIEW_LOCAL_OBSERVER) && __TBB_SCHEDULER_OBSERVER) #define __TBB_ARENA_OBSERVER ((__TBB_BUILD||TBB_PREVIEW_LOCAL_OBSERVER) && __TBB_SCHEDULER_OBSERVER)
#endif /* __TBB_ARENA_OBSERVER */ #endif /* __TBB_ARENA_OBSERVER */
#ifndef __TBB_SLEEP_PERMISSION #ifndef __TBB_SLEEP_PERMISSION
#define __TBB_SLEEP_PERMISSION ((__TBB_CPF_BUILD||TBB_PREVIEW_LOCAL_OBS ERVER)&& __TBB_SCHEDULER_OBSERVER) #define __TBB_SLEEP_PERMISSION ((__TBB_CPF_BUILD||TBB_PREVIEW_LOCAL_OBS ERVER)&& __TBB_SCHEDULER_OBSERVER)
#endif /* __TBB_SLEEP_PERMISSION */ #endif /* __TBB_SLEEP_PERMISSION */
skipping to change at line 411 skipping to change at line 446
#ifndef __TBB_DEFAULT_PARTITIONER #ifndef __TBB_DEFAULT_PARTITIONER
#if TBB_DEPRECATED #if TBB_DEPRECATED
/** Default partitioner for parallel loop templates in TBB 1.0-2.1 */ /** Default partitioner for parallel loop templates in TBB 1.0-2.1 */
#define __TBB_DEFAULT_PARTITIONER tbb::simple_partitioner #define __TBB_DEFAULT_PARTITIONER tbb::simple_partitioner
#else #else
/** Default partitioner for parallel loop templates since TBB 2.2 */ /** Default partitioner for parallel loop templates since TBB 2.2 */
#define __TBB_DEFAULT_PARTITIONER tbb::auto_partitioner #define __TBB_DEFAULT_PARTITIONER tbb::auto_partitioner
#endif /* TBB_DEPRECATED */ #endif /* TBB_DEPRECATED */
#endif /* !defined(__TBB_DEFAULT_PARTITIONER */ #endif /* !defined(__TBB_DEFAULT_PARTITIONER */
#ifndef __TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES
#define __TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES 1
#endif
#ifdef _VARIADIC_MAX #ifdef _VARIADIC_MAX
#define __TBB_VARIADIC_MAX _VARIADIC_MAX #define __TBB_VARIADIC_MAX _VARIADIC_MAX
#else #else
#if _MSC_VER >= 1700 #if _MSC_VER >= 1700
#define __TBB_VARIADIC_MAX 5 /* current VS11 setting, may change. */ #define __TBB_VARIADIC_MAX 5 /* current VS11 setting, may change. */
#else #else
#define __TBB_VARIADIC_MAX 10 #define __TBB_VARIADIC_MAX 10
#endif #endif
#endif #endif
#if !defined(TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX)
#define TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX __TBB_CPF_BUILD
#endif /* TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX */
#if TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX && !__TBB_CPF_BUILD
#define __TBB_NO_IMPLICIT_LINKAGE 1
#endif /* TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX && !__TBB_CPF_BUILD */
/** __TBB_WIN8UI_SUPPORT enables support of New Windows*8 Store Apps and li mit a possibility to load /** __TBB_WIN8UI_SUPPORT enables support of New Windows*8 Store Apps and li mit a possibility to load
shared libraries at run time only from application container **/ shared libraries at run time only from application container **/
#if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP #if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP
#define __TBB_WIN8UI_SUPPORT 1 #define __TBB_WIN8UI_SUPPORT 1
#else #else
#define __TBB_WIN8UI_SUPPORT 0 #define __TBB_WIN8UI_SUPPORT 0
#endif #endif
// Define preprocessor symbols used to determine architecture
#if _WIN32||_WIN64
# if defined(_M_X64)||defined(__x86_64__) // the latter for MinGW suppor
t
# define __TBB_x86_64 1
# elif defined(_M_IA64)
# define __TBB_ipf 1
# elif defined(_M_IX86)||defined(__i386__) // the latter for MinGW suppor
t
# define __TBB_x86_32 1
# endif
#else /* Assume generic Unix */
# if !__linux__ && !__APPLE__
# define __TBB_generic_os 1
# endif
# if __x86_64__
# define __TBB_x86_64 1
# elif __ia64__
# define __TBB_ipf 1
# elif __i386__||__i386 // __i386 is for Sun OS
# define __TBB_x86_32 1
# else
# define __TBB_generic_arch 1
# endif
#endif
#define __TBB_TSX_AVAILABLE (__TBB_x86_32 || __TBB_x86_64) && !__TBB_DEFIN
E_MIC
/** Macros of the form __TBB_XXX_BROKEN denote known issues that are caused by /** Macros of the form __TBB_XXX_BROKEN denote known issues that are caused by
the bugs in compilers, standard or OS specific libraries. They should b e the bugs in compilers, standard or OS specific libraries. They should b e
removed as soon as the corresponding bugs are fixed or the buggy OS/com piler removed as soon as the corresponding bugs are fixed or the buggy OS/com piler
versions go out of the support list. versions go out of the support list.
**/ **/
#if __ANDROID__ && __TBB_GCC_VERSION <= 40403 && !__GCC_HAVE_SYNC_COMPARE_A ND_SWAP_8 #if __ANDROID__ && __TBB_GCC_VERSION <= 40403 && !__GCC_HAVE_SYNC_COMPARE_A ND_SWAP_8
/** Necessary because on Android 8-byte CAS and F&A are not available f or some processor architectures, /** Necessary because on Android 8-byte CAS and F&A are not available f or some processor architectures,
but no mandatory warning message appears from GCC 4.4.3. Instead, o nly a linkage error occurs when but no mandatory warning message appears from GCC 4.4.3. Instead, o nly a linkage error occurs when
these atomic operations are used (such as in unit test test_atomic. exe). **/ these atomic operations are used (such as in unit test test_atomic. exe). **/
skipping to change at line 552 skipping to change at line 557
incorrect code when __asm__ arguments have a cast to volatile. **/ incorrect code when __asm__ arguments have a cast to volatile. **/
#define __TBB_ICC_ASM_VOLATILE_BROKEN 1 #define __TBB_ICC_ASM_VOLATILE_BROKEN 1
#endif #endif
#if !__INTEL_COMPILER && (_MSC_VER || __GNUC__==3 && __GNUC_MINOR__<=2) #if !__INTEL_COMPILER && (_MSC_VER || __GNUC__==3 && __GNUC_MINOR__<=2)
/** Bug in GCC 3.2 and MSVC compilers that sometimes return 0 for __ali gnof(T) /** Bug in GCC 3.2 and MSVC compilers that sometimes return 0 for __ali gnof(T)
when T has not yet been instantiated. **/ when T has not yet been instantiated. **/
#define __TBB_ALIGNOF_NOT_INSTANTIATED_TYPES_BROKEN 1 #define __TBB_ALIGNOF_NOT_INSTANTIATED_TYPES_BROKEN 1
#endif #endif
/* Actually for Clang it should be name __TBB_CPP11_STD_FORWARD_PRESENT.
* But in order to check for presence of std:: library feature we need to r
ecognize
* is standard library actually used stdlibc++ (GNU one) or libc++ (clang o
ne).
* Unfortunately it is not possible at the moment. So postponing it to late
r moment.*/
/*TODO: for clang rename it to __TBB_CPP11_STD_FORWARD_PRESENT and re-imple
ment it.*/
#if (__INTEL_COMPILER) || (__clang__ && __TBB_GCC_VERSION <= 40300)
#define __TBB_CPP11_STD_FORWARD_BROKEN 1
#else
#define __TBB_CPP11_STD_FORWARD_BROKEN 0
#endif
#if __TBB_DEFINE_MIC #if __TBB_DEFINE_MIC
/** Main thread and user's thread have different default thread affinit y masks. **/ /** Main thread and user's thread have different default thread affinit y masks. **/
#define __TBB_MAIN_THREAD_AFFINITY_BROKEN 1 #define __TBB_MAIN_THREAD_AFFINITY_BROKEN 1
#endif #endif
#if __GXX_EXPERIMENTAL_CXX0X__ && !defined(__EXCEPTIONS) && \ #if __GXX_EXPERIMENTAL_CXX0X__ && !defined(__EXCEPTIONS) && \
((!__INTEL_COMPILER && !__clang__ && (__TBB_GCC_VERSION>=40400 && __TBB _GCC_VERSION<40600)) || \ ((!__INTEL_COMPILER && !__clang__ && (__TBB_GCC_VERSION>=40400 && __TBB _GCC_VERSION<40600)) || \
(__INTEL_COMPILER<=1400 && (__TBB_GCC_VERSION>=40400 && __TBB_GCC_VERS ION<=40800))) (__INTEL_COMPILER<=1400 && (__TBB_GCC_VERSION>=40400 && __TBB_GCC_VERS ION<=40801)))
/* There is an issue for specific GCC toolchain when C++11 is enabled /* There is an issue for specific GCC toolchain when C++11 is enabled
and exceptions are disabled: and exceptions are disabled:
exceprion_ptr.h/nested_exception.h use throw unconditionally. exceprion_ptr.h/nested_exception.h use throw unconditionally.
GCC can ignore 'throw' since 4.6; but with ICC the issue still exists. GCC can ignore 'throw' since 4.6; but with ICC the issue still exists.
*/ */
#define __TBB_LIBSTDCPP_EXCEPTION_HEADERS_BROKEN 1 #define __TBB_LIBSTDCPP_EXCEPTION_HEADERS_BROKEN 1
#else #else
#define __TBB_LIBSTDCPP_EXCEPTION_HEADERS_BROKEN 0 #define __TBB_LIBSTDCPP_EXCEPTION_HEADERS_BROKEN 0
#endif #endif
#if __INTEL_COMPILER==1300 && __TBB_GCC_VERSION>=40700 && defined(__GXX_EXP
ERIMENTAL_CXX0X__)
/* Some C++11 features used inside libstdc++ are not supported by Intel com
piler.
* Checking version of gcc instead of libstdc++ because
* - they are directly connected,
* - for now it is not possible to check version of any standard library i
n this file
*/
#define __TBB_ICC_13_0_CPP11_STDLIB_SUPPORT_BROKEN 1
#else
#define __TBB_ICC_13_0_CPP11_STDLIB_SUPPORT_BROKEN 0
#endif
#if (__GNUC__==4 && __GNUC_MINOR__==4 ) && !defined(__INTEL_COMPILER) && !d efined(__clang__) #if (__GNUC__==4 && __GNUC_MINOR__==4 ) && !defined(__INTEL_COMPILER) && !d efined(__clang__)
/** excessive warnings related to strict aliasing rules in GCC 4.4 **/ /** excessive warnings related to strict aliasing rules in GCC 4.4 **/
#define __TBB_GCC_STRICT_ALIASING_BROKEN 1 #define __TBB_GCC_STRICT_ALIASING_BROKEN 1
/* topical remedy: #pragma GCC diagnostic ignored "-Wstrict-aliasing" * / /* topical remedy: #pragma GCC diagnostic ignored "-Wstrict-aliasing" * /
#if !__TBB_GCC_WARNING_SUPPRESSION_PRESENT #if !__TBB_GCC_WARNING_SUPPRESSION_PRESENT
#error Warning suppression is not supported, while should. #error Warning suppression is not supported, while should.
#endif #endif
#endif #endif
/*In a PIC mode some versions of GCC 4.1.2 generate incorrect inlined code for 8 byte __sync_val_compare_and_swap intrinisc */ /*In a PIC mode some versions of GCC 4.1.2 generate incorrect inlined code for 8 byte __sync_val_compare_and_swap intrinsic */
#if __TBB_GCC_VERSION == 40102 && __PIC__ && !defined(__INTEL_COMPILER) && !defined(__clang__) #if __TBB_GCC_VERSION == 40102 && __PIC__ && !defined(__INTEL_COMPILER) && !defined(__clang__)
#define __TBB_GCC_CAS8_BUILTIN_INLINING_BROKEN 1 #define __TBB_GCC_CAS8_BUILTIN_INLINING_BROKEN 1
#endif #endif
#if __TBB_x86_32 && (__linux__ || __APPLE__ || _WIN32 || __sun) && ((defin ed(__INTEL_COMPILER) && __INTEL_COMPILER <= 1400) || (__GNUC__==3 && __GNUC _MINOR__==3 ) || defined(__SUNPRO_CC)) #if __TBB_x86_32 && (__linux__ || __APPLE__ || _WIN32 || __sun || __ANDROID __) && (__INTEL_COMPILER || (__GNUC__==3 && __GNUC_MINOR__==3 ) || __SUNPR O_CC)
// Some compilers for IA-32 fail to provide 8-byte alignment of objects on the stack, // Some compilers for IA-32 fail to provide 8-byte alignment of objects on the stack,
// even if the object specifies 8-byte alignment. On such platforms, t he IA-32 implementation // even if the object specifies 8-byte alignment. On such platforms, t he IA-32 implementation
// of 64 bit atomics (e.g. atomic<long long>) use different tactics dep ending upon // of 64 bit atomics (e.g. atomic<long long>) use different tactics dep ending upon
// whether the object is properly aligned or not. // whether the object is properly aligned or not.
#define __TBB_FORCE_64BIT_ALIGNMENT_BROKEN 1 #define __TBB_FORCE_64BIT_ALIGNMENT_BROKEN 1
#else #else
#define __TBB_FORCE_64BIT_ALIGNMENT_BROKEN 0 #define __TBB_FORCE_64BIT_ALIGNMENT_BROKEN 0
#endif #endif
#if __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT && __TBB_GCC_VERSION < 40700 & & !defined(__INTEL_COMPILER) && !defined (__clang__) #if __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT && __TBB_GCC_VERSION < 40700 & & !defined(__INTEL_COMPILER) && !defined (__clang__)
#define __TBB_ZERO_INIT_WITH_DEFAULTED_CTOR_BROKEN 1 #define __TBB_ZERO_INIT_WITH_DEFAULTED_CTOR_BROKEN 1
#endif #endif
#if _MSC_VER && _MSC_VER <= 1800 && !__INTEL_COMPILER #if _MSC_VER && _MSC_VER <= 1800 && !__INTEL_COMPILER
// With MSVC, when an array is passed by const reference to a template function, // With MSVC, when an array is passed by const reference to a template function,
// constness from the function parameter may get propagated to the temp late parameter. // constness from the function parameter may get propagated to the temp late parameter.
#define __TBB_CONST_REF_TO_ARRAY_TEMPLATE_PARAM_BROKEN 1 #define __TBB_CONST_REF_TO_ARRAY_TEMPLATE_PARAM_BROKEN 1
#endif #endif
// A compiler bug: a disabled copy constructor prevents use of the moving c
onstructor
#define __TBB_IF_NO_COPY_CTOR_MOVE_SEMANTICS_BROKEN (_MSC_VER && (__INTEL_C
OMPILER >= 1300 && __INTEL_COMPILER <= 1310) && !__INTEL_CXX11_MODE__)
// MSVC 2013 and ICC 15 seems do not generate implicit move constructor for
empty derived class while should
#define __TBB_CPP11_IMPLICIT_MOVE_MEMBERS_GENERATION_FOR_DERIVED_BROKEN (_
_TBB_CPP11_RVALUE_REF_PRESENT && \
( !__INTEL_COMPILER && _MSC_VER && _MSC_VER <=1800 || __INTEL_COMPILE
R && __INTEL_COMPILER <= 1500 ))
/** End of __TBB_XXX_BROKEN macro section **/ /** End of __TBB_XXX_BROKEN macro section **/
#if defined(_MSC_VER) && _MSC_VER>=1500 && !defined(__INTEL_COMPILER) #if defined(_MSC_VER) && _MSC_VER>=1500 && !defined(__INTEL_COMPILER)
// A macro to suppress erroneous or benign "unreachable code" MSVC warn ing (4702) // A macro to suppress erroneous or benign "unreachable code" MSVC warn ing (4702)
#define __TBB_MSVC_UNREACHABLE_CODE_IGNORED 1 #define __TBB_MSVC_UNREACHABLE_CODE_IGNORED 1
#endif #endif
#define __TBB_ATOMIC_CTORS (__TBB_CONSTEXPR_PRESENT && __TBB_DEFAULTED_ AND_DELETED_FUNC_PRESENT && (!__TBB_ZERO_INIT_WITH_DEFAULTED_CTOR_BROKEN)) #define __TBB_ATOMIC_CTORS (__TBB_CONSTEXPR_PRESENT && __TBB_DEFAULTED_ AND_DELETED_FUNC_PRESENT && (!__TBB_ZERO_INIT_WITH_DEFAULTED_CTOR_BROKEN))
#define __TBB_ALLOCATOR_CONSTRUCT_VARIADIC (__TBB_CPP11_VARIADIC_TEMPL ATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT) #define __TBB_ALLOCATOR_CONSTRUCT_VARIADIC (__TBB_CPP11_VARIADIC_TEMPL ATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT)
#define __TBB_VARIADIC_PARALLEL_INVOKE (TBB_PREVIEW_VARIADIC_PARAL
LEL_INVOKE && __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_
REF_PRESENT)
#endif /* __TBB_tbb_config_H */ #endif /* __TBB_tbb_config_H */
 End of changes. 30 change blocks. 
114 lines changed or deleted 162 lines changed or added


 tbb_exception.h   tbb_exception.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_exception_H #ifndef __TBB_exception_H
#define __TBB_exception_H #define __TBB_exception_H
#include "tbb_stddef.h" #include "tbb_stddef.h"
#if !TBB_USE_EXCEPTIONS && _MSC_VER #if !TBB_USE_EXCEPTIONS && _MSC_VER
// Suppress "C++ exception handler used, but unwind semantics are not e nabled" warning in STL headers // Suppress "C++ exception handler used, but unwind semantics are not e nabled" warning in STL headers
#pragma warning (push) #pragma warning (push)
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 tbb_machine.h   tbb_machine.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_machine_H #ifndef __TBB_machine_H
#define __TBB_machine_H #define __TBB_machine_H
/** This header provides basic platform abstraction layer by hooking up app ropriate /** This header provides basic platform abstraction layer by hooking up app ropriate
architecture/OS/compiler specific headers from the /include/tbb/machine directory. architecture/OS/compiler specific headers from the /include/tbb/machine directory.
If a plug-in header does not implement all the required APIs, it must s pecify If a plug-in header does not implement all the required APIs, it must s pecify
the missing ones by setting one or more of the following macros: the missing ones by setting one or more of the following macros:
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 tbb_profiling.h   tbb_profiling.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_profiling_H #ifndef __TBB_profiling_H
#define __TBB_profiling_H #define __TBB_profiling_H
namespace tbb { namespace tbb {
namespace internal { namespace internal {
// //
// This is not under __TBB_ITT_STRUCTURE_API because these values a re used directly in flow_graph.h. // This is not under __TBB_ITT_STRUCTURE_API because these values a re used directly in flow_graph.h.
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 tbb_stddef.h   tbb_stddef.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_tbb_stddef_H #ifndef __TBB_tbb_stddef_H
#define __TBB_tbb_stddef_H #define __TBB_tbb_stddef_H
// Marketing-driven product version // Marketing-driven product version
#define TBB_VERSION_MAJOR 4 #define TBB_VERSION_MAJOR 4
#define TBB_VERSION_MINOR 2 #define TBB_VERSION_MINOR 3
// Engineering-focused interface version // Engineering-focused interface version
#define TBB_INTERFACE_VERSION 7005 #define TBB_INTERFACE_VERSION 8000
#define TBB_INTERFACE_VERSION_MAJOR TBB_INTERFACE_VERSION/1000 #define TBB_INTERFACE_VERSION_MAJOR TBB_INTERFACE_VERSION/1000
// The oldest major interface version still supported // The oldest major interface version still supported
// To be used in SONAME, manifests, etc. // To be used in SONAME, manifests, etc.
#define TBB_COMPATIBLE_INTERFACE_VERSION 2 #define TBB_COMPATIBLE_INTERFACE_VERSION 2
#define __TBB_STRING_AUX(x) #x #define __TBB_STRING_AUX(x) #x
#define __TBB_STRING(x) __TBB_STRING_AUX(x) #define __TBB_STRING(x) __TBB_STRING_AUX(x)
// We do not need defines below for resource processing on windows // We do not need defines below for resource processing on windows
skipping to change at line 371 skipping to change at line 363
//! Base class for types that should not be copied or assigned. //! Base class for types that should not be copied or assigned.
class no_copy: no_assign { class no_copy: no_assign {
//! Deny copy construction //! Deny copy construction
no_copy( const no_copy& ); no_copy( const no_copy& );
public: public:
//! Allow default construction //! Allow default construction
no_copy() {} no_copy() {}
}; };
//! Class for determining type of std::allocator<T>::value_type. #if TBB_DEPRECATED_MUTEX_COPYING
template<typename T> class mutex_copy_deprecated_and_disabled {};
struct allocator_type { #else
typedef T value_type; // By default various implementations of mutexes are not copy constructible
}; // and not copy assignable.
class mutex_copy_deprecated_and_disabled : no_copy {};
#if _MSC_VER
//! Microsoft std::allocator has non-standard extension that strips const f
rom a type.
template<typename T>
struct allocator_type<const T> {
typedef T value_type;
};
#endif #endif
//! A template to select either 32-bit or 64-bit constant as compile time,
depending on machine word size.
template <unsigned u, unsigned long long ull >
struct select_size_t_constant {
//Explicit cast is needed to avoid compiler warnings about possible tru
ncation.
//The value of the right size, which is selected by ?:, is anyway not
truncated or promoted.
static const size_t value = (size_t)((sizeof(size_t)==sizeof(u)) ? u :
ull);
};
//! A function to check if passed in pointer is aligned on a specific borde r //! A function to check if passed in pointer is aligned on a specific borde r
template<typename T> template<typename T>
inline bool is_aligned(T* pointer, uintptr_t alignment) { inline bool is_aligned(T* pointer, uintptr_t alignment) {
return 0==((uintptr_t)pointer & (alignment-1)); return 0==((uintptr_t)pointer & (alignment-1));
} }
//! A function to check if passed integer is a power of 2 //! A function to check if passed integer is a power of 2
template<typename integer_type> template<typename integer_type>
inline bool is_power_of_two(integer_type arg) { inline bool is_power_of_two(integer_type arg) {
return arg && (0 == (arg & (arg - 1))); return arg && (0 == (arg & (arg - 1)));
skipping to change at line 435 skipping to change at line 413
void suppress_unused_warning( const T& ) {} void suppress_unused_warning( const T& ) {}
// Struct to be used as a version tag for inline functions. // Struct to be used as a version tag for inline functions.
/** Version tag can be necessary to prevent loader on Linux from using the wrong /** Version tag can be necessary to prevent loader on Linux from using the wrong
symbol in debug builds (when inline functions are compiled as out-of-li ne). **/ symbol in debug builds (when inline functions are compiled as out-of-li ne). **/
struct version_tag_v3 {}; struct version_tag_v3 {};
typedef version_tag_v3 version_tag; typedef version_tag_v3 version_tag;
} // internal } // internal
//! @endcond
} // tbb } // tbb
namespace tbb { namespace internal { // Following is a set of classes and functions typically used in compile-ti
me "metaprogramming".
// TODO: move all that to a separate header
#if __TBB_ALLOCATOR_TRAITS_PRESENT
#include <memory> //for allocator_traits
#endif
#if __TBB_CPP11_RVALUE_REF_PRESENT || _LIBCPP_VERSION
#include <utility> // for std::move
#endif
namespace tbb {
namespace internal {
//! Class for determining type of std::allocator<T>::value_type.
template<typename T>
struct allocator_type {
typedef T value_type;
};
#if _MSC_VER
//! Microsoft std::allocator has non-standard extension that strips const f
rom a type.
template<typename T>
struct allocator_type<const T> {
typedef T value_type;
};
#endif
// Ad-hoc implementation of true_type & false_type
// Intended strictly for internal use! For public APIs (traits etc), use C+
+11 analogues.
template <bool v>
struct bool_constant {
static /*constexpr*/ const bool value = v;
};
typedef bool_constant<true> true_type;
typedef bool_constant<false> false_type;
#if __TBB_ALLOCATOR_TRAITS_PRESENT
using std::allocator_traits;
#else
template<typename allocator>
struct allocator_traits{
typedef tbb::internal::false_type propagate_on_container_move_assignmen
t;
};
#endif
//! A template to select either 32-bit or 64-bit constant as compile time,
depending on machine word size.
template <unsigned u, unsigned long long ull >
struct select_size_t_constant {
//Explicit cast is needed to avoid compiler warnings about possible tru
ncation.
//The value of the right size, which is selected by ?:, is anyway not
truncated or promoted.
static const size_t value = (size_t)((sizeof(size_t)==sizeof(u)) ? u :
ull);
};
#if __TBB_CPP11_RVALUE_REF_PRESENT
using std::move;
#elif defined(_LIBCPP_NAMESPACE)
// libc++ defines "pre-C++11 move" similarly to our; use it to avoid name c
onflicts in some cases.
using std::_LIBCPP_NAMESPACE::move;
#else
template <typename T>
T& move( T& x ) { return x; }
#endif
template <bool condition> template <bool condition>
struct STATIC_ASSERTION_FAILED; struct STATIC_ASSERTION_FAILED;
template <> template <>
struct STATIC_ASSERTION_FAILED<false> { enum {value=1};}; struct STATIC_ASSERTION_FAILED<false> { enum {value=1};};
template<> template<>
struct STATIC_ASSERTION_FAILED<true>; //intentionally left undefined to cau se compile time error struct STATIC_ASSERTION_FAILED<true>; //intentionally left undefined to cau se compile time error
}} // namespace tbb { namespace internal {
//! @endcond
}} // namespace tbb::internal
#if __TBB_STATIC_ASSERT_PRESENT #if __TBB_STATIC_ASSERT_PRESENT
#define __TBB_STATIC_ASSERT(condition,msg) static_assert(condition,msg) #define __TBB_STATIC_ASSERT(condition,msg) static_assert(condition,msg)
#else #else
//please note condition is intentionally inverted to get a bit more underst andable error msg //please note condition is intentionally inverted to get a bit more underst andable error msg
#define __TBB_STATIC_ASSERT_IMPL1(condition,msg,line) \ #define __TBB_STATIC_ASSERT_IMPL1(condition,msg,line) \
enum {static_assert_on_line_##line = tbb::internal::STATIC_ASSERTION_FA ILED<!(condition)>::value} enum {static_assert_on_line_##line = tbb::internal::STATIC_ASSERTION_FA ILED<!(condition)>::value}
#define __TBB_STATIC_ASSERT_IMPL(condition,msg,line) __TBB_STATIC_ASSERT_IM PL1(condition,msg,line) #define __TBB_STATIC_ASSERT_IMPL(condition,msg,line) __TBB_STATIC_ASSERT_IM PL1(condition,msg,line)
//! Verify at compile time that passed in condition is hold //! Verify at compile time that passed in condition is hold
 End of changes. 8 change blocks. 
59 lines changed or deleted 113 lines changed or added


 tbb_thread.h   tbb_thread.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_tbb_thread_H #ifndef __TBB_tbb_thread_H
#define __TBB_tbb_thread_H #define __TBB_tbb_thread_H
#include "tbb_stddef.h" #include "tbb_stddef.h"
#if _WIN32||_WIN64 #if _WIN32||_WIN64
#include "machine/windows_api.h" #include "machine/windows_api.h"
#define __TBB_NATIVE_THREAD_ROUTINE unsigned WINAPI #define __TBB_NATIVE_THREAD_ROUTINE unsigned WINAPI
#define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) unsigned (WINAPI* r)( void* ) #define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) unsigned (WINAPI* r)( void* )
skipping to change at line 68 skipping to change at line 60
#if !TBB_USE_EXCEPTIONS && _MSC_VER #if !TBB_USE_EXCEPTIONS && _MSC_VER
#pragma warning (pop) #pragma warning (pop)
#endif #endif
namespace tbb { namespace tbb {
namespace internal { namespace internal {
class tbb_thread_v3; class tbb_thread_v3;
} }
inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ); inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ) __TBB_NOEXCEPT(true);
namespace internal { namespace internal {
//! Allocate a closure //! Allocate a closure
void* __TBB_EXPORTED_FUNC allocate_closure_v3( size_t size ); void* __TBB_EXPORTED_FUNC allocate_closure_v3( size_t size );
//! Free a closure allocated by allocate_closure_v3 //! Free a closure allocated by allocate_closure_v3
void __TBB_EXPORTED_FUNC free_closure_v3( void* ); void __TBB_EXPORTED_FUNC free_closure_v3( void* );
struct thread_closure_base { struct thread_closure_base {
void* operator new( size_t size ) {return allocate_closure_v3(size) ;} void* operator new( size_t size ) {return allocate_closure_v3(size) ;}
skipping to change at line 122 skipping to change at line 114
thread_closure_2 *self = static_cast<thread_closure_2*>(c); thread_closure_2 *self = static_cast<thread_closure_2*>(c);
self->function(self->arg1, self->arg2); self->function(self->arg1, self->arg2);
delete self; delete self;
return 0; return 0;
} }
thread_closure_2( const F& f, const X& x, const Y& y ) : function(f ), arg1(x), arg2(y) {} thread_closure_2( const F& f, const X& x, const Y& y ) : function(f ), arg1(x), arg2(y) {}
}; };
//! Versioned thread class. //! Versioned thread class.
class tbb_thread_v3 { class tbb_thread_v3 {
#if __TBB_IF_NO_COPY_CTOR_MOVE_SEMANTICS_BROKEN
// Workaround for a compiler bug: declaring the copy constructor as
public
// enables use of the moving constructor.
// The definition is not provided in order to prohibit copying.
public:
#endif
tbb_thread_v3(const tbb_thread_v3&); // = delete; // Deny access tbb_thread_v3(const tbb_thread_v3&); // = delete; // Deny access
public: public:
#if _WIN32||_WIN64 #if _WIN32||_WIN64
typedef HANDLE native_handle_type; typedef HANDLE native_handle_type;
#else #else
typedef pthread_t native_handle_type; typedef pthread_t native_handle_type;
#endif // _WIN32||_WIN64 #endif // _WIN32||_WIN64
class id; class id;
//! Constructs a thread object that does not represent a thread of execution. //! Constructs a thread object that does not represent a thread of execution.
tbb_thread_v3() : my_handle(0) tbb_thread_v3() __TBB_NOEXCEPT(true) : my_handle(0)
#if _WIN32||_WIN64 #if _WIN32||_WIN64
, my_thread_id(0) , my_thread_id(0)
#endif // _WIN32||_WIN64 #endif // _WIN32||_WIN64
{} {}
//! Constructs an object and executes f() in a new thread //! Constructs an object and executes f() in a new thread
template <class F> explicit tbb_thread_v3(F f) { template <class F> explicit tbb_thread_v3(F f) {
typedef internal::thread_closure_0<F> closure_type; typedef internal::thread_closure_0<F> closure_type;
internal_start(closure_type::start_routine, new closure_type(f) ); internal_start(closure_type::start_routine, new closure_type(f) );
} }
skipping to change at line 154 skipping to change at line 152
template <class F, class X> tbb_thread_v3(F f, X x) { template <class F, class X> tbb_thread_v3(F f, X x) {
typedef internal::thread_closure_1<F,X> closure_type; typedef internal::thread_closure_1<F,X> closure_type;
internal_start(closure_type::start_routine, new closure_type(f, x)); internal_start(closure_type::start_routine, new closure_type(f, x));
} }
//! Constructs an object and executes f(x,y) in a new thread //! Constructs an object and executes f(x,y) in a new thread
template <class F, class X, class Y> tbb_thread_v3(F f, X x, Y y) { template <class F, class X, class Y> tbb_thread_v3(F f, X x, Y y) {
typedef internal::thread_closure_2<F,X,Y> closure_type; typedef internal::thread_closure_2<F,X,Y> closure_type;
internal_start(closure_type::start_routine, new closure_type(f, x,y)); internal_start(closure_type::start_routine, new closure_type(f, x,y));
} }
tbb_thread_v3& operator=(tbb_thread_v3& x) { #if __TBB_CPP11_RVALUE_REF_PRESENT
if (joinable()) detach(); tbb_thread_v3(tbb_thread_v3&& x) __TBB_NOEXCEPT(true)
my_handle = x.my_handle; : my_handle(x.my_handle)
x.my_handle = 0;
#if _WIN32||_WIN64 #if _WIN32||_WIN64
my_thread_id = x.my_thread_id; , my_thread_id(x.my_thread_id)
x.my_thread_id = 0; #endif
#endif // _WIN32||_WIN64 {
x.internal_wipe();
}
tbb_thread_v3& operator=(tbb_thread_v3&& x) __TBB_NOEXCEPT(true) {
internal_move(x);
return *this; return *this;
} }
void swap( tbb_thread_v3& t ) {tbb::swap( *this, t );} private:
bool joinable() const {return my_handle!=0; } tbb_thread_v3& operator=(const tbb_thread_v3& x); // = delete;
public:
#else // __TBB_CPP11_RVALUE_REF_PRESENT
tbb_thread_v3& operator=(tbb_thread_v3& x) {
internal_move(x);
return *this;
}
#endif // __TBB_CPP11_RVALUE_REF_PRESENT
void swap( tbb_thread_v3& t ) __TBB_NOEXCEPT(true) {tbb::swap( *thi
s, t );}
bool joinable() const __TBB_NOEXCEPT(true) {return my_handle!=0; }
//! The completion of the thread represented by *this happens befor e join() returns. //! The completion of the thread represented by *this happens befor e join() returns.
void __TBB_EXPORTED_METHOD join(); void __TBB_EXPORTED_METHOD join();
//! When detach() returns, *this no longer represents the possibly continuing thread of execution. //! When detach() returns, *this no longer represents the possibly continuing thread of execution.
void __TBB_EXPORTED_METHOD detach(); void __TBB_EXPORTED_METHOD detach();
~tbb_thread_v3() {if( joinable() ) detach();} ~tbb_thread_v3() {if( joinable() ) detach();}
inline id get_id() const; inline id get_id() const __TBB_NOEXCEPT(true);
native_handle_type native_handle() { return my_handle; } native_handle_type native_handle() { return my_handle; }
//! The number of hardware thread contexts. //! The number of hardware thread contexts.
/** Before TBB 3.0 U4 this methods returned the number of logical C PU in /** Before TBB 3.0 U4 this methods returned the number of logical C PU in
the system. Currently on Windows, Linux and FreeBSD it returns the the system. Currently on Windows, Linux and FreeBSD it returns the
number of logical CPUs available to the current process in acco rdance number of logical CPUs available to the current process in acco rdance
with its affinity mask. with its affinity mask.
NOTE: The return value of this method never changes after its f irst NOTE: The return value of this method never changes after its f irst
invocation. This means that changes in the process affinity mas k that invocation. This means that changes in the process affinity mas k that
took place after this method was first invoked will not affect the took place after this method was first invoked will not affect the
number of worker threads in the TBB worker threads pool. **/ number of worker threads in the TBB worker threads pool. **/
static unsigned __TBB_EXPORTED_FUNC hardware_concurrency(); static unsigned __TBB_EXPORTED_FUNC hardware_concurrency() __TBB_NO EXCEPT(true);
private: private:
native_handle_type my_handle; native_handle_type my_handle;
#if _WIN32||_WIN64 #if _WIN32||_WIN64
thread_id_type my_thread_id; thread_id_type my_thread_id;
#endif // _WIN32||_WIN64 #endif // _WIN32||_WIN64
void internal_wipe() __TBB_NOEXCEPT(true) {
my_handle = 0;
#if _WIN32||_WIN64
my_thread_id = 0;
#endif
}
void internal_move(tbb_thread_v3& x) __TBB_NOEXCEPT(true) {
if (joinable()) detach();
my_handle = x.my_handle;
#if _WIN32||_WIN64
my_thread_id = x.my_thread_id;
#endif // _WIN32||_WIN64
x.internal_wipe();
}
/** Runs start_routine(closure) on another thread and sets my_handl e to the handle of the created thread. */ /** Runs start_routine(closure) on another thread and sets my_handl e to the handle of the created thread. */
void __TBB_EXPORTED_METHOD internal_start( __TBB_NATIVE_THREAD_ROUT INE_PTR(start_routine), void __TBB_EXPORTED_METHOD internal_start( __TBB_NATIVE_THREAD_ROUT INE_PTR(start_routine),
void* closure ); void* closure );
friend void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thr ead_v3& t2 ); friend void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thr ead_v3& t2 );
friend void tbb::swap( tbb_thread_v3& t1, tbb_thread_v3& t2 ); friend void tbb::swap( tbb_thread_v3& t1, tbb_thread_v3& t2 ) __TBB _NOEXCEPT(true);
}; };
class tbb_thread_v3::id { class tbb_thread_v3::id {
#if _WIN32||_WIN64 #if _WIN32||_WIN64
thread_id_type my_id; thread_id_type my_id;
id( thread_id_type id_ ) : my_id(id_) {} id( thread_id_type id_ ) : my_id(id_) {}
#else #else
pthread_t my_id; pthread_t my_id;
id( pthread_t id_ ) : my_id(id_) {} id( pthread_t id_ ) : my_id(id_) {}
#endif // _WIN32||_WIN64 #endif // _WIN32||_WIN64
friend class tbb_thread_v3; friend class tbb_thread_v3;
public: public:
id() : my_id(0) {} id() __TBB_NOEXCEPT(true) : my_id(0) {}
friend bool operator==( tbb_thread_v3::id x, tbb_thread_v3::id y ); friend bool operator==( tbb_thread_v3::id x, tbb_thread_v3::id y )
friend bool operator!=( tbb_thread_v3::id x, tbb_thread_v3::id y ); __TBB_NOEXCEPT(true);
friend bool operator<( tbb_thread_v3::id x, tbb_thread_v3::id y ); friend bool operator!=( tbb_thread_v3::id x, tbb_thread_v3::id y )
friend bool operator<=( tbb_thread_v3::id x, tbb_thread_v3::id y ); __TBB_NOEXCEPT(true);
friend bool operator>( tbb_thread_v3::id x, tbb_thread_v3::id y ); friend bool operator<( tbb_thread_v3::id x, tbb_thread_v3::id y ) _
friend bool operator>=( tbb_thread_v3::id x, tbb_thread_v3::id y ); _TBB_NOEXCEPT(true);
friend bool operator<=( tbb_thread_v3::id x, tbb_thread_v3::id y )
__TBB_NOEXCEPT(true);
friend bool operator>( tbb_thread_v3::id x, tbb_thread_v3::id y ) _
_TBB_NOEXCEPT(true);
friend bool operator>=( tbb_thread_v3::id x, tbb_thread_v3::id y )
__TBB_NOEXCEPT(true);
template<class charT, class traits> template<class charT, class traits>
friend std::basic_ostream<charT, traits>& friend std::basic_ostream<charT, traits>&
operator<< (std::basic_ostream<charT, traits> &out, operator<< (std::basic_ostream<charT, traits> &out,
tbb_thread_v3::id id) tbb_thread_v3::id id)
{ {
out << id.my_id; out << id.my_id;
return out; return out;
} }
friend tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3(); friend tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
}; // tbb_thread_v3::id }; // tbb_thread_v3::id
tbb_thread_v3::id tbb_thread_v3::get_id() const { tbb_thread_v3::id tbb_thread_v3::get_id() const __TBB_NOEXCEPT(true) {
#if _WIN32||_WIN64 #if _WIN32||_WIN64
return id(my_thread_id); return id(my_thread_id);
#else #else
return id(my_handle); return id(my_handle);
#endif // _WIN32||_WIN64 #endif // _WIN32||_WIN64
} }
void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 ); void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 );
tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3(); tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
void __TBB_EXPORTED_FUNC thread_yield_v3(); void __TBB_EXPORTED_FUNC thread_yield_v3();
void __TBB_EXPORTED_FUNC thread_sleep_v3(const tick_count::interval_t & i); void __TBB_EXPORTED_FUNC thread_sleep_v3(const tick_count::interval_t & i);
inline bool operator==(tbb_thread_v3::id x, tbb_thread_v3::id y) inline bool operator==(tbb_thread_v3::id x, tbb_thread_v3::id y) __TBB_ NOEXCEPT(true)
{ {
return x.my_id == y.my_id; return x.my_id == y.my_id;
} }
inline bool operator!=(tbb_thread_v3::id x, tbb_thread_v3::id y) inline bool operator!=(tbb_thread_v3::id x, tbb_thread_v3::id y) __TBB_ NOEXCEPT(true)
{ {
return x.my_id != y.my_id; return x.my_id != y.my_id;
} }
inline bool operator<(tbb_thread_v3::id x, tbb_thread_v3::id y) inline bool operator<(tbb_thread_v3::id x, tbb_thread_v3::id y) __TBB_N OEXCEPT(true)
{ {
return x.my_id < y.my_id; return x.my_id < y.my_id;
} }
inline bool operator<=(tbb_thread_v3::id x, tbb_thread_v3::id y) inline bool operator<=(tbb_thread_v3::id x, tbb_thread_v3::id y) __TBB_ NOEXCEPT(true)
{ {
return x.my_id <= y.my_id; return x.my_id <= y.my_id;
} }
inline bool operator>(tbb_thread_v3::id x, tbb_thread_v3::id y) inline bool operator>(tbb_thread_v3::id x, tbb_thread_v3::id y) __TBB_N OEXCEPT(true)
{ {
return x.my_id > y.my_id; return x.my_id > y.my_id;
} }
inline bool operator>=(tbb_thread_v3::id x, tbb_thread_v3::id y) inline bool operator>=(tbb_thread_v3::id x, tbb_thread_v3::id y) __TBB_ NOEXCEPT(true)
{ {
return x.my_id >= y.my_id; return x.my_id >= y.my_id;
} }
} // namespace internal; } // namespace internal;
//! Users reference thread class by name tbb_thread //! Users reference thread class by name tbb_thread
typedef internal::tbb_thread_v3 tbb_thread; typedef internal::tbb_thread_v3 tbb_thread;
using internal::operator==; using internal::operator==;
using internal::operator!=; using internal::operator!=;
using internal::operator<; using internal::operator<;
using internal::operator>; using internal::operator>;
using internal::operator<=; using internal::operator<=;
using internal::operator>=; using internal::operator>=;
inline void move( tbb_thread& t1, tbb_thread& t2 ) { inline void move( tbb_thread& t1, tbb_thread& t2 ) {
internal::move_v3(t1, t2); internal::move_v3(t1, t2);
} }
inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ) { inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ) __TBB_NOEXCEPT(true) {
tbb::tbb_thread::native_handle_type h = t1.my_handle; tbb::tbb_thread::native_handle_type h = t1.my_handle;
t1.my_handle = t2.my_handle; t1.my_handle = t2.my_handle;
t2.my_handle = h; t2.my_handle = h;
#if _WIN32||_WIN64 #if _WIN32||_WIN64
thread_id_type i = t1.my_thread_id; thread_id_type i = t1.my_thread_id;
t1.my_thread_id = t2.my_thread_id; t1.my_thread_id = t2.my_thread_id;
t2.my_thread_id = i; t2.my_thread_id = i;
#endif /* _WIN32||_WIN64 */ #endif /* _WIN32||_WIN64 */
} }
 End of changes. 21 change blocks. 
57 lines changed or deleted 100 lines changed or added


 tbbmalloc_proxy.h   tbbmalloc_proxy.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
/* /*
Replacing the standard memory allocation routines in Microsoft* C/C++ RTL Replacing the standard memory allocation routines in Microsoft* C/C++ RTL
(malloc/free, global new/delete, etc.) with the TBB memory allocator. (malloc/free, global new/delete, etc.) with the TBB memory allocator.
Include the following header to a source of any binary which is loaded duri ng Include the following header to a source of any binary which is loaded duri ng
application startup application startup
#include "tbb/tbbmalloc_proxy.h" #include "tbb/tbbmalloc_proxy.h"
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 thread   thread 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_thread_H #ifndef __TBB_thread_H
#define __TBB_thread_H #define __TBB_thread_H
#include "../tbb_thread.h" #include "../tbb_thread.h"
#if TBB_IMPLEMENT_CPP0X #if TBB_IMPLEMENT_CPP0X
namespace std { namespace std {
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 tick_count.h   tick_count.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_tick_count_H #ifndef __TBB_tick_count_H
#define __TBB_tick_count_H #define __TBB_tick_count_H
#include "tbb_stddef.h" #include "tbb_stddef.h"
#if _WIN32||_WIN64 #if _WIN32||_WIN64
#include "machine/windows_api.h" #include "machine/windows_api.h"
#elif __linux__ #elif __linux__
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 tuple   tuple 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_tuple_H #ifndef __TBB_tuple_H
#define __TBB_tuple_H #define __TBB_tuple_H
#include <utility> #include <utility>
#include "../tbb_stddef.h" #include "../tbb_stddef.h"
// build preprocessor variables for varying number of arguments // build preprocessor variables for varying number of arguments
// Need the leading comma so the empty __TBB_T_PACK will not cause a syntax error. // Need the leading comma so the empty __TBB_T_PACK will not cause a syntax error.
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 windows_api.h   windows_api.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#ifndef __TBB_machine_windows_api_H #ifndef __TBB_machine_windows_api_H
#define __TBB_machine_windows_api_H #define __TBB_machine_windows_api_H
#if _WIN32 || _WIN64 #if _WIN32 || _WIN64
#if _XBOX #if _XBOX
#define NONET #define NONET
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 windows_ia32.h   windows_ia32.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#if !defined(__TBB_machine_H) || defined(__TBB_machine_windows_ia32_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_windows_ia32_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_windows_ia32_H #define __TBB_machine_windows_ia32_H
#include "msvc_ia32_common.h" #include "msvc_ia32_common.h"
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 windows_intel64.h   windows_intel64.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
#if !defined(__TBB_machine_H) || defined(__TBB_machine_windows_intel64_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_windows_intel64_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_windows_intel64_H #define __TBB_machine_windows_intel64_H
#define __TBB_WORDSIZE 8 #define __TBB_WORDSIZE 8
#define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE #define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added


 xbox360_ppc.h   xbox360_ppc.h 
/* /*
Copyright 2005-2014 Intel Corporation. All Rights Reserved. Copyright 2005-2014 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks. This file is part of Threading Building Blocks. Threading Building Bloc
ks is free software;
Threading Building Blocks is free software; you can redistribute it you can redistribute it and/or modify it under the terms of the GNU Gen
and/or modify it under the terms of the GNU General Public License eral Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation. Threading
Building Blocks is
Threading Building Blocks is distributed in the hope that it will be distributed in the hope that it will be useful, but WITHOUT ANY WARRANT
useful, but WITHOUT ANY WARRANTY; without even the implied warranty Y; without even the
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
GNU General Public License for more details. .
See the GNU General Public License for more details. You should have
You should have received a copy of the GNU General Public License received a copy of
along with Threading Building Blocks; if not, write to the Free Softwar the GNU General Public License along with Threading Building Blocks; i
e f not, write to the
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
USA MA 02110-1301 USA
As a special exception, you may use this file as part of a free softwar As a special exception, you may use this file as part of a free softw
e are library without
library without restriction. Specifically, if other files instantiate restriction. Specifically, if other files instantiate templates or u
templates or use macros or inline functions from this file, or you comp se macros or inline
ile functions from this file, or you compile this file and link it with oth
this file and link it with other files to produce an executable, this er files to produce
file does not by itself cause the resulting executable to be covered by an executable, this file does not by itself cause the resulting execut
the GNU General Public License. This exception does not however able to be covered
invalidate any other reasons why the executable file might be covered b by the GNU General Public License. This exception does not however inva
y lidate any other
the GNU General Public License. reasons why the executable file might be covered by the GNU General Pub
lic License.
*/ */
// TODO: revise by comparing with mac_ppc.h // TODO: revise by comparing with mac_ppc.h
#if !defined(__TBB_machine_H) || defined(__TBB_machine_xbox360_ppc_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_xbox360_ppc_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_xbox360_ppc_H #define __TBB_machine_xbox360_ppc_H
 End of changes. 1 change blocks. 
28 lines changed or deleted 29 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/