STLdoc
STLdocumentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Public Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
Concurrency::combinable< _Ty > Class Template Reference

The combinable<T> object is intended to provide thread-private copies of data, to perform lock-free thread-local sub-computations during parallel algorithms. At the end of the parallel operation, the thread-private sub-computations can then be merged into a final result. This class can be used instead of a shared variable, and can result in a performance improvement if there would otherwise be a lot of contention on that shared variable. More...

#include <ppl.h>

Public Member Functions

 combinable ()
 Constructs a new combinable object. More...
 
template<typename _Function >
 combinable (_Function _FnInitialize)
 Constructs a new combinable object. More...
 
 combinable (const combinable &_Copy)
 Constructs a new combinable object. More...
 
combinableoperator= (const combinable &_Copy)
 Assigns to a combinable object from another combinable object. More...
 
 ~combinable ()
 Destroys a combinable object. More...
 
_Ty & local ()
 Returns a reference to the thread-private sub-computation. More...
 
_Ty & local (bool &_Exists)
 Returns a reference to the thread-private sub-computation. More...
 
void clear ()
 Clears any intermediate computational results from a previous usage. More...
 
template<typename _Function >
_Ty combine (_Function _FnCombine) const
 Computes a final value from the set of thread-local sub-computations by calling the supplied combine functor. More...
 
template<typename _Function >
void combine_each (_Function _FnCombine) const
 Computes a final value from the set of thread-local sub-computations by calling the supplied combine functor once per thread-local sub-computation. The final result is accumulated by the function object. More...
 

Private Member Functions

 __declspec (align(64)) struct _Node
 
void _InitNew ()
 
void _InitCopy (const combinable &_Copy)
 
_Node * _FindLocalItem (unsigned long _Key, size_t *_PIndex)
 
_Node * _AddLocalItem (unsigned long _Key, size_t _Index)
 

Static Private Member Functions

static _Ty _DefaultInit ()
 

Private Attributes

_Node *volatile * _M_buckets
 
size_t _M_size
 
std::function< _Ty()> _M_fnInitialize
 

Detailed Description

template<typename _Ty>
class Concurrency::combinable< _Ty >

The combinable<T> object is intended to provide thread-private copies of data, to perform lock-free thread-local sub-computations during parallel algorithms. At the end of the parallel operation, the thread-private sub-computations can then be merged into a final result. This class can be used instead of a shared variable, and can result in a performance improvement if there would otherwise be a lot of contention on that shared variable.

Template Parameters
_TyThe data type of the final merged result. The type must have a copy constructor and a default constructor.

For more information, see Parallel Containers and Objects.

Constructor & Destructor Documentation

template<typename _Ty >
Concurrency::combinable< _Ty >::combinable ( )
inline

Constructs a new combinable object.

The first constructor initializes new elements with the default constructor for the type _Ty .

The second constructor initializes new elements using the initialization functor supplied as the _FnInitialize parameter.

The third constructor is the copy constructor.

See also
Parallel Containers and Objects
4221  {
4222  _InitNew();
4223  }
std::function< _Ty()> _M_fnInitialize
Definition: ppl.h:4517
static _Ty _DefaultInit()
Definition: ppl.h:4202
void _InitNew()
Definition: ppl.h:4458
template<typename _Ty >
template<typename _Function >
Concurrency::combinable< _Ty >::combinable ( _Function  _FnInitialize)
inlineexplicit

Constructs a new combinable object.

Template Parameters
_FunctionThe type of the initialization functor object.
Parameters
_FnInitializeA function which will be called to initialize each new thread-private value of the type _Ty . It must support a function call operator with the signature _Ty ().

The first constructor initializes new elements with the default constructor for the type _Ty .

The second constructor initializes new elements using the initialization functor supplied as the _FnInitialize parameter.

The third constructor is the copy constructor.

See also
Parallel Containers and Objects
4245  : _M_fnInitialize(_FnInitialize)
4246  {
4247  _InitNew();
4248  }
std::function< _Ty()> _M_fnInitialize
Definition: ppl.h:4517
void _InitNew()
Definition: ppl.h:4458
template<typename _Ty >
Concurrency::combinable< _Ty >::combinable ( const combinable< _Ty > &  _Copy)
inline

Constructs a new combinable object.

Parameters
_CopyAn existing combinable object to be copied into this one.

The first constructor initializes new elements with the default constructor for the type _Ty .

The second constructor initializes new elements using the initialization functor supplied as the _FnInitialize parameter.

The third constructor is the copy constructor.

See also
Parallel Containers and Objects
4265  : _M_size(_Copy._M_size), _M_fnInitialize(_Copy._M_fnInitialize)
4266  {
4267  _InitCopy(_Copy);
4268  }
std::function< _Ty()> _M_fnInitialize
Definition: ppl.h:4517
size_t _M_size
Definition: ppl.h:4516
void _InitCopy(const combinable &_Copy)
Definition: ppl.h:4465
template<typename _Ty >
Concurrency::combinable< _Ty >::~combinable ( )
inline

Destroys a combinable object.

4296  {
4297  clear();
4298  delete [] _M_buckets;
4299  }
void clear()
Clears any intermediate computational results from a previous usage.
Definition: ppl.h:4359
_Node *volatile * _M_buckets
Definition: ppl.h:4515

Member Function Documentation

template<typename _Ty >
Concurrency::combinable< _Ty >::__declspec ( align(64)  )
inlineprivate
4190  {
4191  unsigned long _M_key;
4192  _Ty _M_value;
4193  _Node* _M_chain;
4194 
4195  _Node(unsigned long _Key, _Ty _InitialValue)
4196  : _M_key(_Key), _M_value(_InitialValue), _M_chain(NULL)
4197  {
4198  }
4199  };
#define NULL
Definition: vcruntime.h:236
template<typename _Ty >
_Node* Concurrency::combinable< _Ty >::_AddLocalItem ( unsigned long  _Key,
size_t  _Index 
)
inlineprivate
4502  {
4503  _Node* _NewNode = new _Node(_Key, _M_fnInitialize());
4504  _Node* _TopNode;
4505  do
4506  {
4507  _TopNode = _M_buckets[_Index];
4508  _NewNode->_M_chain = _TopNode;
4509  } while (_InterlockedCompareExchangePointer(reinterpret_cast<void * volatile *>(&_M_buckets[_Index]), _NewNode, _TopNode) != _TopNode);
4510 
4511  return _NewNode;
4512  }
std::function< _Ty()> _M_fnInitialize
Definition: ppl.h:4517
_Node *volatile * _M_buckets
Definition: ppl.h:4515
void * _InterlockedCompareExchangePointer(void *volatile *, void *, void *)
template<typename _Ty >
static _Ty Concurrency::combinable< _Ty >::_DefaultInit ( )
inlinestaticprivate
4203  {
4204  return _Ty();
4205  }
template<typename _Ty >
_Node* Concurrency::combinable< _Ty >::_FindLocalItem ( unsigned long  _Key,
size_t _PIndex 
)
inlineprivate
4481  {
4482  _CONCRT_ASSERT(_PIndex != NULL);
4483 
4484  *_PIndex = _Key % _M_size;
4485 
4486  // Search at this index for an existing value.
4487  _Node* _CurrentNode = _M_buckets[*_PIndex];
4488  while (_CurrentNode != NULL)
4489  {
4490  if (_CurrentNode->_M_key == _Key)
4491  {
4492  return _CurrentNode;
4493  }
4494 
4495  _CurrentNode = _CurrentNode->_M_chain;
4496  }
4497 
4498  return NULL;
4499  }
#define NULL
Definition: vcruntime.h:236
size_t _M_size
Definition: ppl.h:4516
#define _CONCRT_ASSERT(x)
Definition: concrt.h:123
_Node *volatile * _M_buckets
Definition: ppl.h:4515
template<typename _Ty >
void Concurrency::combinable< _Ty >::_InitCopy ( const combinable< _Ty > &  _Copy)
inlineprivate
4466  {
4467  _M_buckets = new _Node*[_M_size];
4468  for (size_t _Index = 0; _Index < _M_size; ++_Index)
4469  {
4470  _M_buckets[_Index] = NULL;
4471  for (_Node* _CurrentNode = _Copy._M_buckets[_Index]; _CurrentNode != NULL; _CurrentNode = _CurrentNode->_M_chain)
4472  {
4473  _Node* _NewNode = new _Node(_CurrentNode->_M_key, _CurrentNode->_M_value);
4474  _NewNode->_M_chain = _M_buckets[_Index];
4475  _M_buckets[_Index] = _NewNode;
4476  }
4477  }
4478  }
#define NULL
Definition: vcruntime.h:236
size_t _M_size
Definition: ppl.h:4516
_Node *volatile * _M_buckets
Definition: ppl.h:4515
template<typename _Ty >
void Concurrency::combinable< _Ty >::_InitNew ( )
inlineprivate
4459  {
4461  _M_buckets = new _Node*[_M_size];
4462  memset((void*)_M_buckets, 0, _M_size * sizeof _M_buckets[0]);
4463  }
size_t _M_size
Definition: ppl.h:4516
_Node *volatile * _M_buckets
Definition: ppl.h:4515
_CONCRTIMP size_t __cdecl _GetCombinableSize()
template<typename _Ty >
void Concurrency::combinable< _Ty >::clear ( )
inline

Clears any intermediate computational results from a previous usage.

4360  {
4361  for (size_t _Index = 0; _Index < _M_size; ++_Index)
4362  {
4363  _Node* _CurrentNode = _M_buckets[_Index];
4364  while (_CurrentNode != NULL)
4365  {
4366  _Node* _NextNode = _CurrentNode->_M_chain;
4367  delete _CurrentNode;
4368  _CurrentNode = _NextNode;
4369  }
4370  }
4371  memset((void*)_M_buckets, 0, _M_size * sizeof _M_buckets[0]);
4372  }
#define NULL
Definition: vcruntime.h:236
size_t _M_size
Definition: ppl.h:4516
_Node *volatile * _M_buckets
Definition: ppl.h:4515
template<typename _Ty >
template<typename _Function >
_Ty Concurrency::combinable< _Ty >::combine ( _Function  _FnCombine) const
inline

Computes a final value from the set of thread-local sub-computations by calling the supplied combine functor.

Template Parameters
_FunctionThe type of the function object that will be invoked to combine two thread-local sub-computations.
Parameters
_FnCombineThe functor that is used to combine the sub-computations. Its signature is T (T, T) or T (const T&, const T&), and it must be associative and commutative.
Returns
The final result of combining all the thread-private sub-computations.
See also
Parallel Containers and Objects
4391  {
4392  _Node* _CurrentNode = NULL;
4393  size_t _Index;
4394 
4395  // Look for the first value in the set, and use (a copy of) that as the result.
4396  // This eliminates a single call (of unknown cost) to _M_fnInitialize.
4397  for (_Index = 0; _Index < _M_size; ++_Index)
4398  {
4399  _CurrentNode = _M_buckets[_Index];
4400  if (_CurrentNode != NULL)
4401  {
4402  break;
4403  }
4404  }
4405 
4406  // No values... return the initializer value.
4407  if (_CurrentNode == NULL)
4408  {
4409  return _M_fnInitialize();
4410  }
4411 
4412  // Accumulate the rest of the items in the current bucket.
4413  _Ty _Result = _CurrentNode->_M_value;
4414  for (_CurrentNode = _CurrentNode->_M_chain; _CurrentNode != NULL; _CurrentNode = _CurrentNode->_M_chain)
4415  {
4416  _Result = _FnCombine(_Result, _CurrentNode->_M_value);
4417  }
4418 
4419  // Accumulate values from the rest of the buckets.
4420  _CONCRT_ASSERT(_Index < _M_size);
4421  for (++_Index; _Index < _M_size; ++_Index)
4422  {
4423  for (_CurrentNode = _M_buckets[_Index]; _CurrentNode != NULL; _CurrentNode = _CurrentNode->_M_chain)
4424  {
4425  _Result = _FnCombine(_Result, _CurrentNode->_M_value);
4426  }
4427  }
4428 
4429  return _Result;
4430  }
std::function< _Ty()> _M_fnInitialize
Definition: ppl.h:4517
#define NULL
Definition: vcruntime.h:236
size_t _M_size
Definition: ppl.h:4516
#define _CONCRT_ASSERT(x)
Definition: concrt.h:123
_Node *volatile * _M_buckets
Definition: ppl.h:4515
template<typename _Ty >
template<typename _Function >
void Concurrency::combinable< _Ty >::combine_each ( _Function  _FnCombine) const
inline

Computes a final value from the set of thread-local sub-computations by calling the supplied combine functor once per thread-local sub-computation. The final result is accumulated by the function object.

Template Parameters
_FunctionThe type of the function object that will be invoked to combine a single thread-local sub-computation.
Parameters
_FnCombineThe functor that is used to combine one sub-computation. Its signature is void (T) or void (const T&), and must be associative and commutative.
See also
Parallel Containers and Objects
4447  {
4448  for (size_t _Index = 0; _Index < _M_size; ++_Index)
4449  {
4450  for (_Node* _CurrentNode = _M_buckets[_Index]; _CurrentNode != NULL; _CurrentNode = _CurrentNode->_M_chain)
4451  {
4452  _FnCombine(_CurrentNode->_M_value);
4453  }
4454  }
4455  }
#define NULL
Definition: vcruntime.h:236
size_t _M_size
Definition: ppl.h:4516
_Node *volatile * _M_buckets
Definition: ppl.h:4515
template<typename _Ty >
_Ty& Concurrency::combinable< _Ty >::local ( )
inline

Returns a reference to the thread-private sub-computation.

Returns
A reference to the thread-private sub-computation.
See also
Parallel Containers and Objects
4310  {
4312  size_t _Index;
4313  _Node* _ExistingNode = _FindLocalItem(_Key, &_Index);
4314  if (_ExistingNode == NULL)
4315  {
4316  _ExistingNode = _AddLocalItem(_Key, _Index);
4317  }
4318 
4319  _CONCRT_ASSERT(_ExistingNode != NULL);
4320  return _ExistingNode->_M_value;
4321  }
_CRTIMP2 long __cdecl GetCurrentThreadId()
#define NULL
Definition: vcruntime.h:236
#define _CONCRT_ASSERT(x)
Definition: concrt.h:123
_Node * _FindLocalItem(unsigned long _Key, size_t *_PIndex)
Definition: ppl.h:4480
_Node * _AddLocalItem(unsigned long _Key, size_t _Index)
Definition: ppl.h:4501
template<typename _Ty >
_Ty& Concurrency::combinable< _Ty >::local ( bool _Exists)
inline

Returns a reference to the thread-private sub-computation.

Parameters
_ExistsA reference to a boolean. The boolean value referenced by this argument will be set to true if the sub-computation already existed on this thread, and set to false if this was the first sub-computation on this thread.
Returns
A reference to the thread-private sub-computation.
See also
Parallel Containers and Objects
4337  {
4339  size_t _Index;
4340  _Node* _ExistingNode = _FindLocalItem(_Key, &_Index);
4341  if (_ExistingNode == NULL)
4342  {
4343  _Exists = false;
4344  _ExistingNode = _AddLocalItem(_Key, _Index);
4345  }
4346  else
4347  {
4348  _Exists = true;
4349  }
4350 
4351  _CONCRT_ASSERT(_ExistingNode != NULL);
4352  return _ExistingNode->_M_value;
4353  }
_CRTIMP2 long __cdecl GetCurrentThreadId()
#define NULL
Definition: vcruntime.h:236
#define _CONCRT_ASSERT(x)
Definition: concrt.h:123
_Node * _FindLocalItem(unsigned long _Key, size_t *_PIndex)
Definition: ppl.h:4480
_Node * _AddLocalItem(unsigned long _Key, size_t _Index)
Definition: ppl.h:4501
template<typename _Ty >
combinable& Concurrency::combinable< _Ty >::operator= ( const combinable< _Ty > &  _Copy)
inline

Assigns to a combinable object from another combinable object.

Parameters
_CopyAn existing combinable object to be copied into this one.
Returns
A reference to this combinable object.
4281  {
4282  clear();
4283  delete [] _M_buckets;
4284  _M_fnInitialize = _Copy._M_fnInitialize;
4285  _M_size = _Copy._M_size;
4286  _InitCopy(_Copy);
4287 
4288  return *this;
4289  }
std::function< _Ty()> _M_fnInitialize
Definition: ppl.h:4517
size_t _M_size
Definition: ppl.h:4516
void clear()
Clears any intermediate computational results from a previous usage.
Definition: ppl.h:4359
void _InitCopy(const combinable &_Copy)
Definition: ppl.h:4465
_Node *volatile * _M_buckets
Definition: ppl.h:4515

Member Data Documentation

template<typename _Ty >
_Node* volatile* Concurrency::combinable< _Ty >::_M_buckets
private
template<typename _Ty >
std::function<_Ty ()> Concurrency::combinable< _Ty >::_M_fnInitialize
private
template<typename _Ty >
size_t Concurrency::combinable< _Ty >::_M_size
private

The documentation for this class was generated from the following file: