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

#include <ppl.h>

Public Member Functions

 _Worker_proxy (_Worker_proxy *_PParent_worker=NULL)
 
 ~_Worker_proxy ()
 
bool _Receive_range (_Range< _Index_type > *_Helper_range)
 
bool _Send_range (_Range< _Index_type > *_Worker_range)
 
void _Enable_intrusive_steal (_Range< _Index_type > *_Worker_range)
 
void _Disable_intrusive_steal ()
 
bool _Is_helper_registered ()
 
bool _Is_done ()
 
void _Set_done ()
 
void _Set_tree_done ()
 
bool _Is_beacon_signaled ()
 
bool _Verify_beacon_cancellation ()
 

Private Member Functions

void _Wait_on_intrusive_steal ()
 
void _NotifyCancel ()
 
void _Propagate_cancel ()
 
_Worker_proxy const & operator= (_Worker_proxy const &)
 

Private Attributes

_Range< _Index_type > *volatile _M_pHelper_range
 
_Worker_proxy_M_pParent_worker
 
::Concurrency::details::_Cancellation_beacon _M_beacon
 
::Concurrency::details::_Context _M_context
 
volatile long _M_completion_count
 
_Range< _Index_type > *volatile _M_pWorker_range
 
volatile long _M_stop_iterating
 

Static Private Attributes

static const long _Tree_Complete = 2
 

Constructor & Destructor Documentation

template<typename _Index_type>
Concurrency::_Worker_proxy< _Index_type >::_Worker_proxy ( _Worker_proxy< _Index_type > *  _PParent_worker = NULL)
inline
1899  :
1901  {
1903  }
volatile long _M_completion_count
Definition: ppl.h:2115
_Worker_proxy * _M_pParent_worker
Definition: ppl.h:2109
static _CONCRTIMP _Context __cdecl _CurrentContext()
_Range< _Index_type > *volatile _M_pWorker_range
Definition: ppl.h:2118
::Concurrency::details::_Context _M_context
Definition: ppl.h:2113
_Range< _Index_type > *volatile _M_pHelper_range
Definition: ppl.h:2106
#define NULL
Definition: corecrt.h:158
volatile long _M_stop_iterating
Definition: ppl.h:2119
template<typename _Index_type>
Concurrency::_Worker_proxy< _Index_type >::~_Worker_proxy ( )
inline
1906  {
1907  // Make the check to avoid doing extra work in the non-exceptional cases
1909  {
1910  // On exception, notify our parent so it breaks out of its loop.
1912 
1913  // On exception, we need to set _M_completion_count to ensure that the helper breaks out of its spin wait.
1914  _Set_done();
1915  }
1916  }
volatile long _M_completion_count
Definition: ppl.h:2115
static const long _Tree_Complete
Definition: ppl.h:2103
void _Propagate_cancel()
Definition: ppl.h:2094
void _Set_done()
Definition: ppl.h:2048

Member Function Documentation

template<typename _Index_type>
void Concurrency::_Worker_proxy< _Index_type >::_Disable_intrusive_steal ( )
inline
2033  {
2036  }
void _Wait_on_intrusive_steal()
Definition: ppl.h:2075
_Range< _Index_type > *volatile _M_pWorker_range
Definition: ppl.h:2118
#define NULL
Definition: corecrt.h:158
template<typename _Index_type>
void Concurrency::_Worker_proxy< _Index_type >::_Enable_intrusive_steal ( _Range< _Index_type > *  _Worker_range)
inline
2027  {
2028  _M_pWorker_range = _Worker_range;
2029  }
_Range< _Index_type > *volatile _M_pWorker_range
Definition: ppl.h:2118
template<typename _Index_type>
bool Concurrency::_Worker_proxy< _Index_type >::_Is_beacon_signaled ( )
inline
2063  {
2064  return _M_beacon._Is_signaled();
2065  }
::Concurrency::details::_Cancellation_beacon _M_beacon
Definition: ppl.h:2112
bool _Is_signaled() const
Definition: concrt.h:5307
template<typename _Index_type>
bool Concurrency::_Worker_proxy< _Index_type >::_Is_done ( )
inline
2044  {
2045  return (_M_completion_count != 0);
2046  }
volatile long _M_completion_count
Definition: ppl.h:2115
template<typename _Index_type>
bool Concurrency::_Worker_proxy< _Index_type >::_Is_helper_registered ( )
inline
2039  {
2040  return (_M_pHelper_range != NULL);
2041  }
_Range< _Index_type > *volatile _M_pHelper_range
Definition: ppl.h:2106
#define NULL
Definition: corecrt.h:158
template<typename _Index_type>
void Concurrency::_Worker_proxy< _Index_type >::_NotifyCancel ( )
inlineprivate
2090  {
2091  _M_beacon._Raise();
2092  }
void _Raise()
Definition: concrt.h:5316
::Concurrency::details::_Cancellation_beacon _M_beacon
Definition: ppl.h:2112
template<typename _Index_type>
void Concurrency::_Worker_proxy< _Index_type >::_Propagate_cancel ( )
inlineprivate
2095  {
2096  if (_M_pParent_worker != NULL)
2097  {
2099  }
2100  }
void _NotifyCancel()
Definition: ppl.h:2089
_Worker_proxy * _M_pParent_worker
Definition: ppl.h:2109
#define NULL
Definition: corecrt.h:158
template<typename _Index_type>
bool Concurrency::_Worker_proxy< _Index_type >::_Receive_range ( _Range< _Index_type > *  _Helper_range)
inline
1920  {
1921  // If the worker already finished, then there is no work left for the helper
1922  if (_M_completion_count)
1923  {
1924  return false;
1925  }
1926 
1927  _CONCRT_ASSERT(_Helper_range != NULL);
1928 
1929  // There are two special values for _M_current_iteration that are not valid: one is the
1930  // initial value of the working class which it will never share, and the other is
1931  // the last exclusive iteration of the working class, which has no work to be done.
1932  // We use the former value so that we can understand worker's response.
1933  _Index_type _Cached_first_iteration = _Helper_range->_M_current_iteration;
1934 
1935  // Following operation is not done via interlocked operation because it does not have to.
1936  // Helper lazily registers that it would like to help the worker, but it allows for some
1937  // time to elapse before that information has made it over to the worker. The idea
1938  // is not to disturb the worker if it is not necessary. It is possible to add interlocked
1939  // operation in the future if the time spent in the busy wait loop is too big.
1941  _M_pHelper_range = _Helper_range;
1942 
1944 
1945  // If the worker is done, it will flush the store buffer and signal the helper by
1946  // changing _M_current_iteration in the helper's range.
1947  while ((_Helper_range->_M_current_iteration == _Cached_first_iteration) && !_M_completion_count)
1948  {
1950  {
1951  // Attempt to steal the entire range from the worker if it is synchronously blocked.
1952 
1953  // Make sure that worker makes no forward progress while helper is attempting to
1954  // steal its range. If worker does get unblocked, simply back off in the helper.
1955  // Note that there could be another helper running if a range has already been
1956  // sent to us.
1957  long _Stop_iterating = _InterlockedIncrement(&_M_stop_iterating);
1958  _CONCRT_ASSERT(_Stop_iterating > 0);
1959 
1960  // We need to make a local copy as the pointer could be changed by the worker.
1961  _Range<_Index_type> * _Worker_range = _M_pWorker_range;
1962 
1963  // The order of comparison needs to be preserved. If the parent is blocked, then
1964  // it cannot send a range (because _M_stop_iterating is already set). If it sent a range
1965  // before being synchronously blocked, then we are no longer the helper. Refrain
1966  // from intrusively stealing the range.
1967  if ((_Worker_range != NULL) && _M_context._IsSynchronouslyBlocked()
1968  && (_Helper_range->_M_current_iteration == _Cached_first_iteration) && !_M_completion_count)
1969  {
1970  _CONCRT_ASSERT(_M_pHelper_range == _Helper_range);
1971 
1973  _Worker_range->_Steal_range(_Helper_range);
1974 
1975  _CONCRT_ASSERT(_Helper_range->_M_current_iteration != _Cached_first_iteration);
1976  }
1977 
1978  // At this point, worker is either:
1979  //
1980  // a) no longer blocked so range will come to the helper naturally, or
1981  // b) out of iterations because helper stole all of it
1982  _Stop_iterating = _InterlockedDecrement(&_M_stop_iterating);
1983  _CONCRT_ASSERT(_Stop_iterating >= 0);
1984  }
1985  else
1986  {
1987  // If there is no work received in a full spin, then start yielding the context
1988  spinWait._SpinOnce();
1989  }
1990  }
1991 
1992  // If the initial iteration is the same as the original first iteration then the
1993  // worker class is sending the signal that it does not need any help.
1994  if (_Helper_range->_M_current_iteration == _Cached_first_iteration)
1995  {
1996  return false;
1997  }
1998 
1999  return (_Helper_range->_Number_of_iterations() > 0);
2000  }
volatile long _M_completion_count
Definition: ppl.h:2115
static _CONCRTIMP void __cdecl _Yield()
Implements busy wait with no backoff
Definition: concrt.h:578
#define _CONCRT_ASSERT(x)
Definition: concrt.h:123
_CONCRTIMP bool _IsSynchronouslyBlocked() const
_Range< _Index_type > *volatile _M_pWorker_range
Definition: ppl.h:2118
long __cdecl _InterlockedDecrement(long volatile *)
::Concurrency::details::_Context _M_context
Definition: ppl.h:2113
long __cdecl _InterlockedIncrement(long volatile *)
_Range< _Index_type > *volatile _M_pHelper_range
Definition: ppl.h:2106
#define NULL
Definition: corecrt.h:158
volatile long _M_stop_iterating
Definition: ppl.h:2119
template<typename _Index_type>
bool Concurrency::_Worker_proxy< _Index_type >::_Send_range ( _Range< _Index_type > *  _Worker_range)
inline
2004  {
2005  // Worker range shall not be available for stealing at this time.
2007 
2008  // Helper shall be registered.
2010 
2011  // Send the range
2012  _Worker_range->_Send_range(_M_pHelper_range);
2013 
2014  // Notify the helper. The fence ensures that the prior updates are visible.
2015  _InterlockedExchangePointer(reinterpret_cast<void * volatile *>(&_M_pHelper_range), NULL);
2016 
2017  // The current iteration should still be left
2018  _CONCRT_ASSERT(_Worker_range->_Number_of_iterations() >= 1);
2019 
2020  // Indicate if we need another helper
2021  return (_Worker_range->_Number_of_iterations() > 1);
2022  }
#define _CONCRT_ASSERT(x)
Definition: concrt.h:123
_Range< _Index_type > *volatile _M_pWorker_range
Definition: ppl.h:2118
_Range< _Index_type > *volatile _M_pHelper_range
Definition: ppl.h:2106
#define NULL
Definition: corecrt.h:158
template<typename _Index_type>
void Concurrency::_Worker_proxy< _Index_type >::_Set_done ( )
inline
2049  {
2050  // Let the helper know that this class is done with work and flush the store buffer. This operation
2051  // ensures that any buffered store to helper range in _Send_range is flushed and
2052  // available in _Receive_range (so there will be no lost ranges).
2053  _InterlockedExchange(&_M_completion_count, 1);
2054  }
volatile long _M_completion_count
Definition: ppl.h:2115
template<typename _Index_type>
void Concurrency::_Worker_proxy< _Index_type >::_Set_tree_done ( )
inline
2057  {
2058  // Make sure that **WE** know when our destructor hits that the entire tree is complete.
2060  }
volatile long _M_completion_count
Definition: ppl.h:2115
static const long _Tree_Complete
Definition: ppl.h:2103
template<typename _Index_type>
bool Concurrency::_Worker_proxy< _Index_type >::_Verify_beacon_cancellation ( )
inline
2068  {
2069  return _M_beacon._Confirm_cancel();
2070  }
::Concurrency::details::_Cancellation_beacon _M_beacon
Definition: ppl.h:2112
template<typename _Index_type>
void Concurrency::_Worker_proxy< _Index_type >::_Wait_on_intrusive_steal ( )
inlineprivate
2076  {
2077  // This code is used to synchronize with helper in case of worker cooperative blocking.
2078  if (_M_stop_iterating != 0)
2079  {
2081 
2082  while (_M_stop_iterating != 0)
2083  {
2084  spinWait._SpinOnce();
2085  }
2086  }
2087  }
Implements busy wait with no backoff
Definition: concrt.h:578
bool _SpinOnce()
Spins for one time quantum,until a maximum spin is reached.
Definition: concrt.h:626
volatile long _M_stop_iterating
Definition: ppl.h:2119
template<typename _Index_type>
_Worker_proxy const& Concurrency::_Worker_proxy< _Index_type >::operator= ( _Worker_proxy< _Index_type > const &  )
private

Member Data Documentation

template<typename _Index_type>
::Concurrency::details::_Cancellation_beacon Concurrency::_Worker_proxy< _Index_type >::_M_beacon
private
template<typename _Index_type>
volatile long Concurrency::_Worker_proxy< _Index_type >::_M_completion_count
private
template<typename _Index_type>
::Concurrency::details::_Context Concurrency::_Worker_proxy< _Index_type >::_M_context
private
template<typename _Index_type>
_Range<_Index_type>* volatile Concurrency::_Worker_proxy< _Index_type >::_M_pHelper_range
private
template<typename _Index_type>
_Worker_proxy* Concurrency::_Worker_proxy< _Index_type >::_M_pParent_worker
private
template<typename _Index_type>
_Range<_Index_type>* volatile Concurrency::_Worker_proxy< _Index_type >::_M_pWorker_range
private
template<typename _Index_type>
volatile long Concurrency::_Worker_proxy< _Index_type >::_M_stop_iterating
private
template<typename _Index_type>
const long Concurrency::_Worker_proxy< _Index_type >::_Tree_Complete = 2
staticprivate

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