_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), ©_array); | internal_copy(vector, sizeof(T), ©_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), ©_a rray); | internal_copy(vector.internal_vector_base(), sizeof(T), ©_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, ©_array); | internal_assign(vector, sizeof(T), &destroy_array, &assign_arra y, ©_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, ©_array); | sizeof(T), &destroy_array, &assign_array, ©_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), ©_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<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 | |||