Ethereum  PoC-8
The C++ Implementation of Ethereum
Worker.cpp
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
22 #include "Worker.h"
23 
24 #include <chrono>
25 #include <thread>
26 #include "Log.h"
27 using namespace std;
28 using namespace dev;
29 
30 void Worker::startWorking()
31 {
32 // cnote << "startWorking for thread" << m_name;
33  std::unique_lock<std::mutex> l(x_work);
34  if (m_work)
35  {
36  WorkerState ex = WorkerState::Stopped;
37  m_state.compare_exchange_strong(ex, WorkerState::Starting);
38  m_state_notifier.notify_all();
39  }
40  else
41  {
42  m_state = WorkerState::Starting;
43  m_state_notifier.notify_all();
44  m_work.reset(new thread([&]()
45  {
46  setThreadName(m_name.c_str());
47 // cnote << "Thread begins";
48  while (m_state != WorkerState::Killing)
49  {
50  WorkerState ex = WorkerState::Starting;
51  {
52  // the condition variable-related lock
53  unique_lock<mutex> l(x_work);
54  m_state = WorkerState::Started;
55  }
56 // cnote << "Trying to set Started: Thread was" << (unsigned)ex << "; " << ok;
57  m_state_notifier.notify_all();
58 
59  try
60  {
61  startedWorking();
62  workLoop();
63  doneWorking();
64  }
65  catch (std::exception const& _e)
66  {
67  cwarn << "Exception thrown in Worker thread: " << _e.what();
68  }
69 
70 // ex = WorkerState::Stopping;
71 // m_state.compare_exchange_strong(ex, WorkerState::Stopped);
72 
73  {
74  // the condition variable-related lock
75  unique_lock<mutex> l(x_work);
76  ex = m_state.exchange(WorkerState::Stopped);
77 // cnote << "State: Stopped: Thread was" << (unsigned)ex;
78  if (ex == WorkerState::Killing || ex == WorkerState::Starting)
79  m_state.exchange(ex);
80  }
81  m_state_notifier.notify_all();
82 // cnote << "Waiting until not Stopped...";
83 
84  {
85  unique_lock<mutex> l(x_work);
86  DEV_TIMED_ABOVE("Worker stopping", 100)
87  while (m_state == WorkerState::Stopped)
88  m_state_notifier.wait(l);
89  }
90  }
91  }));
92 // cnote << "Spawning" << m_name;
93  }
94 
95  DEV_TIMED_ABOVE("Start worker", 100)
96  while (m_state == WorkerState::Starting)
97  m_state_notifier.wait(l);
98 }
99 
100 void Worker::stopWorking()
101 {
102  std::unique_lock<Mutex> l(x_work);
103  if (m_work)
104  {
105  WorkerState ex = WorkerState::Started;
106  if (!m_state.compare_exchange_strong(ex, WorkerState::Stopping))
107  return;
108  m_state_notifier.notify_all();
109 
110  DEV_TIMED_ABOVE("Stop worker", 100)
111  while (m_state != WorkerState::Stopped)
112  m_state_notifier.wait(l); // but yes who can wake this up, when the mutex is taken.
113  }
114 }
115 
116 void Worker::terminate()
117 {
118 // cnote << "stopWorking for thread" << m_name;
119  std::unique_lock<Mutex> l(x_work);
120  if (m_work)
121  {
122  if (m_state.exchange(WorkerState::Killing) == WorkerState::Killing)
123  return; // Somebody else is doing this
124  l.unlock();
125  m_state_notifier.notify_all();
126  DEV_TIMED_ABOVE("Terminate worker", 100)
127  m_work->join();
128 
129  l.lock();
130  m_work.reset();
131  }
132 }
133 
134 void Worker::workLoop()
135 {
136  while (m_state == WorkerState::Started)
137  {
138  if (m_idleWaitMs)
139  this_thread::sleep_for(chrono::milliseconds(m_idleWaitMs));
140  doWork();
141  }
142 }
Worker.h
DEV_TIMED_ABOVE
#define DEV_TIMED_ABOVE(S, MS)
Definition: Common.h:276
m_name
boost::thread_specific_ptr< std::string > m_name
Definition: Log.cpp:62
std
Definition: FixedHash.h:393
dev
Definition: Address.cpp:21
cwarn
#define cwarn
dev::WorkerState
WorkerState
Definition: Worker.h:40
dev::setThreadName
void setThreadName(std::string const &_n)
Definition: Log.cpp:119
Log.h