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
4223  {
4224  _InitNew();
4225  }
std::function< _Ty()> _M_fnInitialize
Definition: ppl.h:4519
static _Ty _DefaultInit()
Definition: ppl.h:4204
void _InitNew()
Definition: ppl.h:4460
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
4247  : _M_fnInitialize(_FnInitialize)
4248  {
4249  _InitNew();
4250  }
std::function< _Ty()> _M_fnInitialize
Definition: ppl.h:4519
void _InitNew()
Definition: ppl.h:4460
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
4267  : _M_size(_Copy._M_size), _M_fnInitialize(_Copy._M_fnInitialize)
4268  {
4269  _InitCopy(_Copy);
4270  }
std::function< _Ty()> _M_fnInitialize
Definition: ppl.h:4519
size_t _M_size
Definition: ppl.h:4518
void _InitCopy(const combinable &_Copy)
Definition: ppl.h:4467
template<typename _Ty >
Concurrency::combinable< _Ty >::~combinable ( )
inline

Destroys a combinable object.

4298  {
4299  clear();
4300  delete [] _M_buckets;
4301  }
void clear()
Clears any intermediate computational results from a previous usage.
Definition: ppl.h:4361
_Node *volatile * _M_buckets
Definition: ppl.h:4517

Member Function Documentation

template<typename _Ty >
Concurrency::combinable< _Ty >::__declspec ( align(64)  )
inlineprivate
4192  {
4193  unsigned long _M_key;
4194  _Ty _M_value;
4195  _Node* _M_chain;
4196 
4197  _Node(unsigned long _Key, _Ty _InitialValue)
4198  : _M_key(_Key), _M_value(_InitialValue), _M_chain(NULL)
4199  {
4200  }
4201  };
#define NULL
Definition: corecrt.h:158
template<typename _Ty >
_Node* Concurrency::combinable< _Ty >::_AddLocalItem ( unsigned long  _Key,
size_t  _Index 
)
inlineprivate
4504  {
4505  _Node* _NewNode = new _Node(_Key, _M_fnInitialize());
4506  _Node* _TopNode;
4507  do
4508  {
4509  _TopNode = _M_buckets[_Index];
4510  _NewNode->_M_chain = _TopNode;
4511  } while (_InterlockedCompareExchangePointer(reinterpret_cast<void * volatile *>(&_M_buckets[_Index]), _NewNode, _TopNode) != _TopNode);
4512 
4513  return _NewNode;
4514  }
std::function< _Ty()> _M_fnInitialize
Definition: ppl.h:4519
_In_ size_t _In_ int _Index
Definition: time.h:102
_Node *volatile * _M_buckets
Definition: ppl.h:4517
void * _InterlockedCompareExchangePointer(void *volatile *, void *, void *)
template<typename _Ty >
static _Ty Concurrency::combinable< _Ty >::_DefaultInit ( )
inlinestaticprivate
4205  {
4206  return _Ty();
4207  }
template<typename _Ty >
_Node* Concurrency::combinable< _Ty >::_FindLocalItem ( unsigned long  _Key,
size_t _PIndex 
)
inlineprivate
4483  {
4484  _CONCRT_ASSERT(_PIndex != NULL);
4485 
4486  *_PIndex = _Key % _M_size;
4487 
4488  // Search at this index for an existing value.
4489  _Node* _CurrentNode = _M_buckets[*_PIndex];
4490  while (_CurrentNode != NULL)
4491  {
4492  if (_CurrentNode->_M_key == _Key)
4493  {
4494  return _CurrentNode;
4495  }
4496 
4497  _CurrentNode = _CurrentNode->_M_chain;
4498  }
4499 
4500  return NULL;
4501  }
size_t _M_size
Definition: ppl.h:4518
#define _CONCRT_ASSERT(x)
Definition: concrt.h:123
_Node *volatile * _M_buckets
Definition: ppl.h:4517
#define NULL
Definition: corecrt.h:158
template<typename _Ty >
void Concurrency::combinable< _Ty >::_InitCopy ( const combinable< _Ty > &  _Copy)
inlineprivate
4468  {
4469  _M_buckets = new _Node*[_M_size];
4470  for (size_t _Index = 0; _Index < _M_size; ++_Index)
4471  {
4472  _M_buckets[_Index] = NULL;
4473  for (_Node* _CurrentNode = _Copy._M_buckets[_Index]; _CurrentNode != NULL; _CurrentNode = _CurrentNode->_M_chain)
4474  {
4475  _Node* _NewNode = new _Node(_CurrentNode->_M_key, _CurrentNode->_M_value);
4476  _NewNode->_M_chain = _M_buckets[_Index];
4477  _M_buckets[_Index] = _NewNode;
4478  }
4479  }
4480  }
size_t _M_size
Definition: ppl.h:4518
_In_ size_t _In_ int _Index
Definition: time.h:102
_Node *volatile * _M_buckets
Definition: ppl.h:4517
#define NULL
Definition: corecrt.h:158
template<typename _Ty >
void Concurrency::combinable< _Ty >::_InitNew ( )
inlineprivate
4461  {
4463  _M_buckets = new _Node*[_M_size];
4464  memset((void*)_M_buckets, 0, _M_size * sizeof _M_buckets[0]);
4465  }
size_t _M_size
Definition: ppl.h:4518
_Node *volatile * _M_buckets
Definition: ppl.h:4517
_CONCRTIMP size_t __cdecl _GetCombinableSize()
template<typename _Ty >
void Concurrency::combinable< _Ty >::clear ( )
inline

Clears any intermediate computational results from a previous usage.

4362  {
4363  for (size_t _Index = 0; _Index < _M_size; ++_Index)
4364  {
4365  _Node* _CurrentNode = _M_buckets[_Index];
4366  while (_CurrentNode != NULL)
4367  {
4368  _Node* _NextNode = _CurrentNode->_M_chain;
4369  delete _CurrentNode;
4370  _CurrentNode = _NextNode;
4371  }
4372  }
4373  memset((void*)_M_buckets, 0, _M_size * sizeof _M_buckets[0]);
4374  }
size_t _M_size
Definition: ppl.h:4518
_In_ size_t _In_ int _Index
Definition: time.h:102
_Node *volatile * _M_buckets
Definition: ppl.h:4517
#define NULL
Definition: corecrt.h:158
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
4393  {
4394  _Node* _CurrentNode = NULL;
4395  size_t _Index;
4396 
4397  // Look for the first value in the set, and use (a copy of) that as the result.
4398  // This eliminates a single call (of unknown cost) to _M_fnInitialize.
4399  for (_Index = 0; _Index < _M_size; ++_Index)
4400  {
4401  _CurrentNode = _M_buckets[_Index];
4402  if (_CurrentNode != NULL)
4403  {
4404  break;
4405  }
4406  }
4407 
4408  // No values... return the initializer value.
4409  if (_CurrentNode == NULL)
4410  {
4411  return _M_fnInitialize();
4412  }
4413 
4414  // Accumulate the rest of the items in the current bucket.
4415  _Ty _Result = _CurrentNode->_M_value;
4416  for (_CurrentNode = _CurrentNode->_M_chain; _CurrentNode != NULL; _CurrentNode = _CurrentNode->_M_chain)
4417  {
4418  _Result = _FnCombine(_Result, _CurrentNode->_M_value);
4419  }
4420 
4421  // Accumulate values from the rest of the buckets.
4422  _CONCRT_ASSERT(_Index < _M_size);
4423  for (++_Index; _Index < _M_size; ++_Index)
4424  {
4425  for (_CurrentNode = _M_buckets[_Index]; _CurrentNode != NULL; _CurrentNode = _CurrentNode->_M_chain)
4426  {
4427  _Result = _FnCombine(_Result, _CurrentNode->_M_value);
4428  }
4429  }
4430 
4431  return _Result;
4432  }
std::function< _Ty()> _M_fnInitialize
Definition: ppl.h:4519
size_t _M_size
Definition: ppl.h:4518
#define _CONCRT_ASSERT(x)
Definition: concrt.h:123
_In_ size_t _In_ int _Index
Definition: time.h:102
_Node *volatile * _M_buckets
Definition: ppl.h:4517
_Result
Definition: corecrt_wconio.h:362
#define NULL
Definition: corecrt.h:158
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
4449  {
4450  for (size_t _Index = 0; _Index < _M_size; ++_Index)
4451  {
4452  for (_Node* _CurrentNode = _M_buckets[_Index]; _CurrentNode != NULL; _CurrentNode = _CurrentNode->_M_chain)
4453  {
4454  _FnCombine(_CurrentNode->_M_value);
4455  }
4456  }
4457  }
size_t _M_size
Definition: ppl.h:4518
_In_ size_t _In_ int _Index
Definition: time.h:102
_Node *volatile * _M_buckets
Definition: ppl.h:4517
#define NULL
Definition: corecrt.h:158
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
4312  {
4314  size_t _Index;
4315  _Node* _ExistingNode = _FindLocalItem(_Key, &_Index);
4316  if (_ExistingNode == NULL)
4317  {
4318  _ExistingNode = _AddLocalItem(_Key, _Index);
4319  }
4320 
4321  _CONCRT_ASSERT(_ExistingNode != NULL);
4322  return _ExistingNode->_M_value;
4323  }
_CRTIMP2 long __cdecl GetCurrentThreadId()
#define _CONCRT_ASSERT(x)
Definition: concrt.h:123
_Node * _FindLocalItem(unsigned long _Key, size_t *_PIndex)
Definition: ppl.h:4482
_In_ size_t _In_ int _Index
Definition: time.h:102
_Node * _AddLocalItem(unsigned long _Key, size_t _Index)
Definition: ppl.h:4503
#define NULL
Definition: corecrt.h:158
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
4339  {
4341  size_t _Index;
4342  _Node* _ExistingNode = _FindLocalItem(_Key, &_Index);
4343  if (_ExistingNode == NULL)
4344  {
4345  _Exists = false;
4346  _ExistingNode = _AddLocalItem(_Key, _Index);
4347  }
4348  else
4349  {
4350  _Exists = true;
4351  }
4352 
4353  _CONCRT_ASSERT(_ExistingNode != NULL);
4354  return _ExistingNode->_M_value;
4355  }
_CRTIMP2 long __cdecl GetCurrentThreadId()
#define _CONCRT_ASSERT(x)
Definition: concrt.h:123
_Node * _FindLocalItem(unsigned long _Key, size_t *_PIndex)
Definition: ppl.h:4482
_In_ size_t _In_ int _Index
Definition: time.h:102
_Node * _AddLocalItem(unsigned long _Key, size_t _Index)
Definition: ppl.h:4503
#define NULL
Definition: corecrt.h:158
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.
4283  {
4284  clear();
4285  delete [] _M_buckets;
4286  _M_fnInitialize = _Copy._M_fnInitialize;
4287  _M_size = _Copy._M_size;
4288  _InitCopy(_Copy);
4289 
4290  return *this;
4291  }
std::function< _Ty()> _M_fnInitialize
Definition: ppl.h:4519
size_t _M_size
Definition: ppl.h:4518
void clear()
Clears any intermediate computational results from a previous usage.
Definition: ppl.h:4361
void _InitCopy(const combinable &_Copy)
Definition: ppl.h:4467
_Node *volatile * _M_buckets
Definition: ppl.h:4517

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: