CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
List of all members | Classes | Public Member Functions | Private Member Functions | Private Attributes
edm::WaitingTaskList Class Reference

#include <WaitingTaskList.h>

Classes

struct  WaitNode
 

Public Member Functions

void add (tbb::task *)
 Adds task to the waiting list. More...
 
void doneWaiting ()
 Signals that the resource is now available and tasks should be spawned. More...
 
void reset ()
 Resets access to the resource so that added tasks will wait. More...
 
 WaitingTaskList (unsigned int iInitialSize=2)
 Constructor. More...
 
 ~WaitingTaskList ()
 

Private Member Functions

void announce ()
 
WaitNodecreateNode (tbb::task *iTask)
 
const WaitingTaskListoperator= (const WaitingTaskList &)=delete
 
 WaitingTaskList (const WaitingTaskList &)=delete
 

Private Attributes

std::atomic< WaitNode * > m_head
 
std::atomic< unsigned int > m_lastAssignedCacheIndex
 
WaitNodem_nodeCache
 
unsigned int m_nodeCacheSize
 
std::atomic< bool > m_waiting
 

Detailed Description

Definition at line 79 of file WaitingTaskList.h.

Constructor & Destructor Documentation

WaitingTaskList::WaitingTaskList ( unsigned int  iInitialSize = 2)

Constructor.

The WaitingTaskList is initial set to waiting.

Parameters
[in]iInitialSizespecifies the initial size of the cache used to hold waiting tasks. The value is only useful for optimization as the object can resize itself.

Definition at line 35 of file WaitingTaskList.cc.

35  :
36 m_head{0},
37 m_nodeCache{new WaitNode[iInitialSize]},
38 m_nodeCacheSize{iInitialSize},
40 m_waiting{true}
41 {
42  for(auto it = m_nodeCache, itEnd = m_nodeCache+m_nodeCacheSize; it!=itEnd; ++it) {
43  it->m_fromCache=true;
44  }
45 }
std::atomic< bool > m_waiting
std::atomic< unsigned int > m_lastAssignedCacheIndex
std::atomic< WaitNode * > m_head
unsigned int m_nodeCacheSize
WaitingTaskList::~WaitingTaskList ( )

Definition at line 52 of file WaitingTaskList.cc.

References m_nodeCache.

53 {
54  delete [] m_nodeCache;
55 }
edm::WaitingTaskList::WaitingTaskList ( const WaitingTaskList )
privatedelete

Member Function Documentation

void WaitingTaskList::add ( tbb::task *  iTask)

Adds task to the waiting list.

If doneWaiting() has already been called then the added task will immediately be spawned. If that is not the case then the task will be held until doneWaiting() is called and will then be spawned. Calls to add() and doneWaiting() can safely be done concurrently.

Definition at line 111 of file WaitingTaskList.cc.

References announce(), createNode(), m_head, m_waiting, and edm::WaitingTaskList::WaitNode::setNextNode().

Referenced by counter.Counter::register().

111  {
112  iTask->increment_ref_count();
113  if(!m_waiting) {
114  if(0==iTask->decrement_ref_count()) {
115  tbb::task::spawn(*iTask);
116  }
117  } else {
118  WaitNode* newHead = createNode(iTask);
119  WaitNode* oldHead = m_head.exchange(newHead);
120  if(oldHead) {
121  newHead->setNextNode(oldHead);
122  //NOTE: even if 'm_waiting' changed, we don't
123  // have to recheck since we beat 'announce()' in
124  // the ordering of 'm_head.exchange' call so iTask
125  // is guaranteed to be in the link list
126  } else {
127  newHead->setNextNode(0);
128  if(!m_waiting) {
129  //if finished waiting right before we did the
130  // exchange our task will not be spawned. Also,
131  // additional threads may be calling add() and swapping
132  // heads and linking us to the new head.
133  // It is safe to call announce from multiple threads
134  announce();
135  }
136 
137  }
138  }
139 }
WaitNode * createNode(tbb::task *iTask)
std::atomic< bool > m_waiting
std::atomic< WaitNode * > m_head
void WaitingTaskList::announce ( )
private

Handles spawning the tasks, safe to call from multiple threads

Definition at line 142 of file WaitingTaskList.cc.

References edm::WaitingTaskList::WaitNode::m_fromCache, m_head, edm::WaitingTaskList::WaitNode::m_task, gen::n, GetRecoTauVFromDQM_MC_cff::next, edm::WaitingTaskList::WaitNode::nextNode(), and edmStreamStallGrapher::t.

Referenced by add(), and doneWaiting().

143 {
144  //Need a temporary storage since one of these tasks could
145  // cause the next event to start processing which would refill
146  // this waiting list after it has been reset
147  WaitNode* n = m_head.exchange(0);
148  WaitNode* next;
149  while(n) {
150  //it is possible that 'WaitingTaskList::add' is running in a different
151  // thread and we have a new 'head' but the old head has not yet been
152  // attached to the new head (we identify this since 'nextNode' will return itself).
153  // In that case we have to wait until the link has been established before going on.
154  while(n == (next=n->nextNode())) {
155  hardware_pause();
156  }
157  auto t = n->m_task;
158  if(0==t->decrement_ref_count()){
159  tbb::task::spawn(*t);
160  }
161  if(!n->m_fromCache ) {
162  delete n;
163  }
164  n=next;
165  }
166 }
std::atomic< WaitNode * > m_head
WaitingTaskList::WaitNode * WaitingTaskList::createNode ( tbb::task *  iTask)
private

Definition at line 92 of file WaitingTaskList.cc.

References cmsHarvester::index, edm::WaitingTaskList::WaitNode::m_fromCache, m_lastAssignedCacheIndex, edm::WaitingTaskList::WaitNode::m_next, m_nodeCache, m_nodeCacheSize, and edm::WaitingTaskList::WaitNode::m_task.

Referenced by add().

93 {
94  unsigned int index = m_lastAssignedCacheIndex++;
95 
96  WaitNode* returnValue;
97  if( index < m_nodeCacheSize) {
98  returnValue = m_nodeCache+index;
99  } else {
100  returnValue = new WaitNode;
101  returnValue->m_fromCache=false;
102  }
103  returnValue->m_task = iTask;
104  returnValue->m_next = returnValue;
105 
106  return returnValue;
107 }
std::atomic< unsigned int > m_lastAssignedCacheIndex
unsigned int m_nodeCacheSize
void WaitingTaskList::doneWaiting ( )

Signals that the resource is now available and tasks should be spawned.

The owner of the resource calls this function to allow the waiting tasks to start accessing it. To have tasks wait again one must call reset(). Calls to add() and doneWaiting() can safely be done concurrently.

Definition at line 169 of file WaitingTaskList.cc.

References announce(), and m_waiting.

170 {
171  m_waiting=false;
172  announce();
173 }
std::atomic< bool > m_waiting
const WaitingTaskList& edm::WaitingTaskList::operator= ( const WaitingTaskList )
privatedelete
void WaitingTaskList::reset ( void  )

Resets access to the resource so that added tasks will wait.

The owner of the resouce calls reset() to make tasks wait. Calling reset() is NOT thread safe. The system must guarantee that no tasks are using the resource when reset() is called and neither add() nor doneWaiting() call be called concurrently with reset().

Definition at line 73 of file WaitingTaskList.cc.

References assert(), edm::WaitingTaskList::WaitNode::m_fromCache, m_head, m_lastAssignedCacheIndex, m_nodeCache, m_nodeCacheSize, and m_waiting.

74 {
75  m_waiting = true;
76  unsigned int nSeenTasks = m_lastAssignedCacheIndex;
78  assert(m_head == 0);
79  if (nSeenTasks > m_nodeCacheSize) {
80  //need to expand so next time we don't have to do any
81  // memory requests
82  delete [] m_nodeCache;
83  m_nodeCacheSize = nSeenTasks;
84  m_nodeCache = new WaitNode[nSeenTasks];
85  for(auto it = m_nodeCache, itEnd = m_nodeCache+m_nodeCacheSize; it!=itEnd; ++it) {
86  it->m_fromCache=true;
87  }
88  }
89 }
std::atomic< bool > m_waiting
assert(m_qm.get())
std::atomic< unsigned int > m_lastAssignedCacheIndex
std::atomic< WaitNode * > m_head
unsigned int m_nodeCacheSize

Member Data Documentation

std::atomic<WaitNode*> edm::WaitingTaskList::m_head
private

Definition at line 144 of file WaitingTaskList.h.

Referenced by add(), announce(), and reset().

std::atomic<unsigned int> edm::WaitingTaskList::m_lastAssignedCacheIndex
private

Definition at line 147 of file WaitingTaskList.h.

Referenced by createNode(), and reset().

WaitNode* edm::WaitingTaskList::m_nodeCache
private

Definition at line 145 of file WaitingTaskList.h.

Referenced by createNode(), reset(), and ~WaitingTaskList().

unsigned int edm::WaitingTaskList::m_nodeCacheSize
private

Definition at line 146 of file WaitingTaskList.h.

Referenced by createNode(), and reset().

std::atomic<bool> edm::WaitingTaskList::m_waiting
private

Definition at line 148 of file WaitingTaskList.h.

Referenced by add(), doneWaiting(), and reset().