gem5  v22.1.0.0
coroutine.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions are
16  * met: redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer;
18  * redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution;
21  * neither the name of the copyright holders nor the names of its
22  * contributors may be used to endorse or promote products derived from
23  * this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 #ifndef __BASE_COROUTINE_HH__
39 #define __BASE_COROUTINE_HH__
40 
41 #include <functional>
42 #include <stack>
43 
44 #include "base/compiler.hh"
45 #include "base/fiber.hh"
46 
48 namespace gem5
49 {
50 
63 template <typename Arg, typename Ret>
64 class Coroutine : public Fiber
65 {
66 
67  // This empty struct type is meant to replace coroutine channels
68  // in case the channel should be void (Coroutine template parameters
69  // are void. (See following ArgChannel, RetChannel typedef)
70  struct Empty {};
71  using ArgChannel = typename std::conditional_t<
72  std::is_same_v<Arg, void>, Empty, std::stack<Arg>>;
73 
74  using RetChannel = typename std::conditional_t<
75  std::is_same_v<Ret, void>, Empty, std::stack<Ret>>;
76 
77  public:
85  class CallerType
86  {
87  friend class Coroutine;
88  protected:
89  CallerType(Coroutine& _coro) : coro(_coro), callerFiber(nullptr) {}
90 
91  public:
101  template <typename T = Ret>
102  CallerType&
103  operator()(typename std::enable_if_t<
104  !std::is_same_v<T, void>, T> param)
105  {
106  retChannel.push(param);
107  callerFiber->run();
108  return *this;
109  }
110 
119  template <typename T = Ret>
120  typename std::enable_if_t<std::is_same_v<T, void>,
121  CallerType> &
123  {
124  callerFiber->run();
125  return *this;
126  }
127 
140  template <typename T = Arg>
141  typename std::enable_if_t<!std::is_same_v<T, void>, T>
142  get()
143  {
144  auto& args_channel = coro.argsChannel;
145  while (args_channel.empty()) {
146  callerFiber->run();
147  }
148 
149  auto ret = args_channel.top();
150  args_channel.pop();
151  return ret;
152  }
153 
154  private:
158  };
159 
164  Coroutine() = delete;
165  Coroutine(const Coroutine& rhs) = delete;
166  Coroutine& operator=(const Coroutine& rhs) = delete; // end of api_coroutine
168 
186  Coroutine(std::function<void(CallerType&)> f, bool run_coroutine = true)
187  : Fiber(), task(f), caller(*this)
188  {
189  // When desired, run the Coroutine after it is created
190  if (run_coroutine)
191  this->call();
192  }
193 
197  virtual ~Coroutine() {}
198 
199  public:
211  template <typename T = Arg>
212  Coroutine&
213  operator()(typename std::enable_if_t<!std::is_same_v<T, void>, T> param)
214  {
215  argsChannel.push(param);
216  this->call();
217  return *this;
218  }
219 
228  template <typename T = Arg>
229  typename std::enable_if_t<std::is_same_v<T, void>, Coroutine> &
231  {
232  this->call();
233  return *this;
234  }
235 
248  template <typename T = Ret>
249  typename std::enable_if_t<!std::is_same_v<T, void>, T>
250  get()
251  {
252  auto& ret_channel = caller.retChannel;
253  while (ret_channel.empty()) {
254  this->call();
255  }
256 
257  auto ret = ret_channel.top();
258  ret_channel.pop();
259  return ret;
260  }
261 
267  operator bool() const { return !this->finished(); }
268 
269  private:
276  void main() override { this->task(caller); }
277 
278  void
280  {
282  run();
283  }
284 
285  private:
288 
290  std::function<void(CallerType&)> task;
291 
294 };
295 
296 } //namespace gem5
297 
298 #endif // __BASE_COROUTINE_HH__
CallerType: A reference to an object of this class will be passed to the coroutine task.
Definition: coroutine.hh:86
CallerType(Coroutine &_coro)
Definition: coroutine.hh:89
This template defines a Coroutine wrapper type with a Boost-like interface.
Definition: coroutine.hh:65
void main() override
Overriding base (Fiber) main.
Definition: coroutine.hh:276
std::function< void(CallerType &)> task
Coroutine task.
Definition: coroutine.hh:290
CallerType caller
Coroutine caller.
Definition: coroutine.hh:293
typename std::conditional_t< std::is_same_v< Ret, void >, Empty, std::stack< Ret > > RetChannel
Definition: coroutine.hh:75
typename std::conditional_t< std::is_same_v< Arg, void >, Empty, std::stack< Arg > > ArgChannel
Definition: coroutine.hh:72
ArgChannel argsChannel
Arguments for the coroutine.
Definition: coroutine.hh:287
This class represents a fiber, which is a light weight sort of thread which is cooperatively schedule...
Definition: fiber.hh:72
GEM5_DEPRECATED_NAMESPACE(m5, gem5)
std::enable_if_t< std::is_same_v< T, void >, Coroutine > & operator()()
operator() is the way we can jump inside the coroutine.
Definition: coroutine.hh:230
CallerType & operator()(typename std::enable_if_t< !std::is_same_v< T, void >, T > param)
operator() is the way we can jump outside the coroutine and return a value to the caller.
Definition: coroutine.hh:103
Coroutine & operator()(typename std::enable_if_t<!std::is_same_v< T, void >, T > param)
Coroutine interface.
Definition: coroutine.hh:213
std::enable_if_t<!std::is_same_v< T, void >, T > get()
get() is the way we can extrapolate arguments from the coroutine caller.
Definition: coroutine.hh:142
std::enable_if_t< std::is_same_v< T, void >, CallerType > & operator()()
operator() is the way we can jump outside the coroutine
Definition: coroutine.hh:122
virtual ~Coroutine()
Definition: coroutine.hh:197
Coroutine & operator=(const Coroutine &rhs)=delete
std::enable_if_t<!std::is_same_v< T, void >, T > get()
get() is the way we can extrapolate return values (yielded) from the coroutine.
Definition: coroutine.hh:250
Coroutine()=delete
Coroutine(const Coroutine &rhs)=delete
Coroutine(std::function< void(CallerType &)> f, bool run_coroutine=true)
Coroutine constructor.
Definition: coroutine.hh:186
static Fiber * currentFiber()
Get a pointer to the current running Fiber.
Definition: fiber.cc:185
bool finished() const
Returns whether the "main" function of this fiber has finished.
Definition: fiber.hh:109
void run()
Start executing the fiber represented by this object.
Definition: fiber.cc:166
Bitfield< 56 > f
Definition: pagetable.hh:53
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....

Generated on Wed Dec 21 2022 10:22:28 for gem5 by doxygen 1.9.1