Worker.h 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /*
  2. This file is part of cpp-ethereum.
  3. cpp-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. cpp-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /** @file Worker.h
  15. * @author Gav Wood <i@gavwood.com>
  16. * @date 2014
  17. */
  18. #pragma once
  19. #include <string>
  20. #include <thread>
  21. #include <atomic>
  22. #include "Guards.h"
  23. namespace dev
  24. {
  25. enum class IfRunning
  26. {
  27. Fail,
  28. Join,
  29. Detach
  30. };
  31. enum class WorkerState
  32. {
  33. Starting,
  34. Started,
  35. Stopping,
  36. Stopped,
  37. Killing
  38. };
  39. class Worker
  40. {
  41. protected:
  42. Worker(std::string const& _name = "anon", unsigned _idleWaitMs = 30): m_name(_name), m_idleWaitMs(_idleWaitMs) {}
  43. /// Move-constructor.
  44. Worker(Worker&& _m) { std::swap(m_name, _m.m_name); }
  45. /// Move-assignment.
  46. Worker& operator=(Worker&& _m)
  47. {
  48. assert(&_m != this);
  49. std::swap(m_name, _m.m_name);
  50. return *this;
  51. }
  52. virtual ~Worker() { terminate(); }
  53. /// Allows changing worker name if work is stopped.
  54. void setName(std::string _n) { if (!isWorking()) m_name = _n; }
  55. /// Starts worker thread; causes startedWorking() to be called.
  56. void startWorking();
  57. /// Stop worker thread; causes call to stopWorking().
  58. void stopWorking();
  59. /// Returns if worker thread is present.
  60. bool isWorking() const { Guard l(x_work); return m_state == WorkerState::Started; }
  61. /// Called after thread is started from startWorking().
  62. virtual void startedWorking() {}
  63. /// Called continuously following sleep for m_idleWaitMs.
  64. virtual void doWork() {}
  65. /// Overrides doWork(); should call shouldStop() often and exit when true.
  66. virtual void workLoop();
  67. bool shouldStop() const { return m_state != WorkerState::Started; }
  68. /// Called when is to be stopped, just prior to thread being joined.
  69. virtual void doneWorking() {}
  70. /// Blocks caller into worker thread has finished.
  71. // void join() const { Guard l(x_work); try { if (m_work) m_work->join(); } catch (...) {} }
  72. private:
  73. /// Stop and never start again.
  74. void terminate();
  75. std::string m_name;
  76. unsigned m_idleWaitMs = 0;
  77. mutable Mutex x_work; ///< Lock for the network existance.
  78. std::unique_ptr<std::thread> m_work; ///< The network thread.
  79. std::atomic<WorkerState> m_state = {WorkerState::Starting};
  80. };
  81. }