CMS 3D CMS Logo

SerialTaskQueue.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: Concurrency
4 // Class : SerialTaskQueue
5 //
6 // Implementation:
7 // [Notes on implementation]
8 //
9 // Original Author: Chris Jones
10 // Created: Thu Feb 21 11:31:52 CST 2013
11 // $Id$
12 //
13 
14 // system include files
15 
16 // user include files
18 
20 
21 using namespace edm;
22 
23 //
24 // member functions
25 //
27 {
28  //be certain all tasks have completed
29  bool isEmpty = m_tasks.empty();
30  bool isTaskChosen = m_taskChosen;
31  if ( (not isEmpty and not isPaused()) or isTaskChosen) {
32  pushAndWait([]() {return;});
33  }
34 }
35 
36 bool
38  if(0==--m_pauseCount) {
39  tbb::task* t = pickNextTask();
40  if(nullptr != t) {
41  tbb::task::spawn(*t);
42  }
43  return true;
44  }
45  return false;
46 }
47 
48 void
50  tbb::task* t = pushAndGetNextTask(iTask);
51  if(nullptr!=t) {
52  tbb::task::spawn(*t);
53  }
54 }
55 
56 tbb::task*
58  tbb::task* returnValue{nullptr};
59  if LIKELY(nullptr!=iTask) {
60  m_tasks.push(iTask);
61  returnValue = pickNextTask();
62  }
63  return returnValue;
64 }
65 
66 
67 tbb::task*
69  m_taskChosen.store(false);
70  return pickNextTask();
71 }
72 
75 
76  bool expect = false;
77  if LIKELY(0 == m_pauseCount and m_taskChosen.compare_exchange_strong(expect,true)) {
78  TaskBase* t=nullptr;
79  if LIKELY(m_tasks.try_pop(t)) {
80  return t;
81  }
82  //no task was actually pulled
83  m_taskChosen.store(false);
84 
85  //was a new entry added after we called 'try_pop' but before we did the clear?
86  expect = false;
87  if(not m_tasks.empty() and m_taskChosen.compare_exchange_strong(expect,true)) {
88  TaskBase* t=nullptr;
89  if(m_tasks.try_pop(t)) {
90  return t;
91  }
92  //no task was still pulled since a different thread beat us to it
93  m_taskChosen.store(false);
94 
95  }
96  }
97  return nullptr;
98 }
99 
100 void SerialTaskQueue::pushAndWait(tbb::empty_task* iWait, TaskBase* iTask) {
101  auto nextTask = pushAndGetNextTask(iTask);
102  if LIKELY(nullptr != nextTask) {
103  if LIKELY(nextTask == iTask) {
104  //spawn and wait for all requires the task to have its parent set
105  iWait->spawn_and_wait_for_all(*nextTask);
106  } else {
107  tbb::task::spawn(*nextTask);
108  iWait->wait_for_all();
109  }
110  } else {
111  //a task must already be running in this queue
112  iWait->wait_for_all();
113  }
114  tbb::task::destroy(*iWait);
115 }
116 
117 
118 //
119 // const member functions
120 //
121 
122 //
123 // static member functions
124 //
tbb::task * finishedTask()
void pushAndWait(const T &iAction)
synchronously pushes functor iAction into queue
std::atomic< unsigned long > m_pauseCount
def destroy(e)
Definition: pyrootRender.py:14
tbb::task * pushAndGetNextTask(TaskBase *)
void pushTask(TaskBase *)
bool resume()
Resumes processing if the queue was paused.
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
bool isPaused() const
Checks to see if the queue has been paused.
TaskBase * pickNextTask()
std::atomic< bool > m_taskChosen
HLT enums.
#define LIKELY(x)
tbb::concurrent_queue< TaskBase * > m_tasks