emilib
coroutine.hpp
1 // By Emil Ernerfeldt 2014-2016
2 // LICENSE:
3 // This software is dual-licensed to the public domain and under the following
4 // license: you are granted a perpetual, irrevocable license to copy, modify,
5 // publish, and distribute this file as you see fit.
6 // HISTORY
7 // Originally made for Ghostel in 2014.
8 
9 #pragma once
10 
11 #include <atomic>
12 #include <condition_variable>
13 #include <functional>
14 #include <mutex>
15 #include <string>
16 #include <vector>
17 
18 namespace emilib {
19 
32 namespace cr {
33 
34 class InnerControl;
35 
36 // ----------------------------------------------------------------------------
37 
39 class Coroutine
40 {
41 public:
44  Coroutine(const char* debug_name, std::function<void(InnerControl& ic)> fun);
45 
47  ~Coroutine();
48 
50  void stop();
51 
53  void poll(double dt);
54 
56  bool done() const { return _is_done; }
57 
58 private:
59  Coroutine(Coroutine&) = delete;
60  Coroutine(Coroutine&&) = delete;
61  Coroutine& operator=(Coroutine&) = delete;
62  Coroutine& operator=(Coroutine&&) = delete;
63 
64  class Thread;
65  friend class InnerControl;
66 
67  std::string _debug_name = "";
68  std::unique_ptr<InnerControl> _inner;
69  std::unique_ptr<Thread> _thread;
70  std::atomic<bool> _is_done { false };
71  std::mutex _mutex;
72  std::condition_variable _cond;
73  std::atomic<bool> _control_is_outer { true };
74  std::atomic<bool> _abort { false };
75 };
76 
78 
81 {
82 public:
83  InnerControl(Coroutine& cr) : _cr(cr) { }
84 
86  double time() const { return _time; }
87 
89  template<typename Fun>
90  void wait_for(const Fun& fun)
91  {
92  while (!fun()) {
93  yield();
94  }
95  }
96 
98  void wait_sec(double s);
99 
101  void yield();
102 
104  void poll(double dt);
105 
106 private:
107  Coroutine& _cr;
108  double _time = 0;
109 };
110 
111 // ----------------------------------------------------------------------------
112 
115 {
116 public:
117  bool empty() const { return _list.empty(); }
118  size_t size() const { return _list.size(); }
119 
121  void clear();
122 
124  std::shared_ptr<Coroutine> start(const char* debug_name, std::function<void(InnerControl& ic)> fun);
125 
128  bool erase(const std::shared_ptr<Coroutine>& cr);
129 
132  void poll(double dt);
133 
134 private:
135  std::vector<std::shared_ptr<Coroutine>> _list;
136 };
137 
138 } // namespace cr
139 } // namespace emilib
~Coroutine()
Will stop() the coroutine, if not already done().
double time() const
Total running time of this coroutine (sum of all dt).
Definition: coroutine.hpp:86
void wait_for(const Fun &fun)
Inner thread: return execution to Outer thread until fun() is true.
Definition: coroutine.hpp:90
void stop()
Abort the inner thread, if not done().
void poll(double dt)
dt = elapsed time since last call in seconds.
bool done() const
Has the inner thread finished its execution?
Definition: coroutine.hpp:56
Coroutine(const char *debug_name, std::function< void(InnerControl &ic)> fun)
Definition: coroutine.hpp:80
This acts like a coroutine, but is implemented as a separate thread.
Definition: coroutine.hpp:39
Helper for handling several coroutines.
Definition: coroutine.hpp:114
Definition: coroutine.hpp:18