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
1903  :
1905  {
1907  }
volatile long _M_completion_count
Definition: ppl.h:2119
_Worker_proxy * _M_pParent_worker
Definition: ppl.h:2113
#define NULL
Definition: crtdbg.h:30
_Range< _Index_type > *volatile _M_pWorker_range
Definition: ppl.h:2122
::Concurrency::details::_Context _M_context
Definition: ppl.h:2117
static _CRTIMP _Context __cdecl _CurrentContext()
_Range< _Index_type > *volatile _M_pHelper_range
Definition: ppl.h:2110
volatile long _M_stop_iterating
Definition: ppl.h:2123
template<typename _Index_type>
Concurrency::_Worker_proxy< _Index_type >::~_Worker_proxy ( )
inline
1910  {
1911  // Make the check to avoid doing extra work in the non-exceptional cases
1913  {
1914  // On exception, notify our parent so it breaks out of its loop.
1916 
1917  // On exception, we need to set _M_completion_count to ensure that the helper breaks out of its spin wait.
1918  _Set_done();
1919  }
1920  }
volatile long _M_completion_count
Definition: ppl.h:2119
static const long _Tree_Complete
Definition: ppl.h:2107
void _Propagate_cancel()
Definition: ppl.h:2098
void _Set_done()
Definition: ppl.h:2052

Member Function Documentation

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