gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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  * Authors: Giacomo Travaglini
38  */
39 
40 #ifndef __BASE_COROUTINE_HH__
41 #define __BASE_COROUTINE_HH__
42 
43 #include <functional>
44 #include <stack>
45 
46 #include "base/fiber.hh"
47 
48 namespace m5
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<
72  std::is_same<Arg, void>::value, Empty, std::stack<Arg>>::type;
73 
74  using RetChannel = typename std::conditional<
75  std::is_same<Ret, void>::value, Empty, std::stack<Ret>>::type;
76 
77  public:
85  class CallerType
86  {
87  friend class Coroutine;
88  protected:
89  CallerType(Coroutine& _coro) : coro(_coro), callerFiber(nullptr) {}
90 
91  public:
99  template <typename T = Ret>
100  CallerType&
101  operator()(typename std::enable_if<
102  !std::is_same<T, void>::value, T>::type param)
103  {
104  retChannel.push(param);
105  callerFiber->run();
106  return *this;
107  }
108 
115  template <typename T = Ret>
116  typename std::enable_if<std::is_same<T, void>::value,
117  CallerType>::type&
119  {
120  callerFiber->run();
121  return *this;
122  }
123 
134  template <typename T = Arg>
135  typename std::enable_if<!std::is_same<T, void>::value, T>::type
136  get()
137  {
138  auto& args_channel = coro.argsChannel;
139  while (args_channel.empty()) {
140  callerFiber->run();
141  }
142 
143  auto ret = args_channel.top();
144  args_channel.pop();
145  return ret;
146  }
147 
148  private:
152  };
153 
154  Coroutine() = delete;
155  Coroutine(const Coroutine& rhs) = delete;
156  Coroutine& operator=(const Coroutine& rhs) = delete;
157 
173  Coroutine(std::function<void(CallerType&)> f, bool run_coroutine = true)
174  : Fiber(), task(f), caller(*this)
175  {
176  // When desired, run the Coroutine after it is created
177  if (run_coroutine)
178  this->call();
179  }
180 
181  virtual ~Coroutine() {}
182 
183  public:
193  template <typename T = Arg>
194  Coroutine&
195  operator()(typename std::enable_if<
196  !std::is_same<T, void>::value, T>::type param)
197  {
198  argsChannel.push(param);
199  this->call();
200  return *this;
201  }
202 
209  template <typename T = Arg>
210  typename std::enable_if<std::is_same<T, void>::value, Coroutine>::type&
212  {
213  this->call();
214  return *this;
215  }
216 
227  template <typename T = Ret>
228  typename std::enable_if<!std::is_same<T, void>::value, T>::type
229  get()
230  {
231  auto& ret_channel = caller.retChannel;
232  while (ret_channel.empty()) {
233  this->call();
234  }
235 
236  auto ret = ret_channel.top();
237  ret_channel.pop();
238  return ret;
239  }
240 
242  operator bool() const { return !this->finished(); }
243 
244  private:
251  void main() override { this->task(caller); }
252 
253  void
255  {
257  run();
258  }
259 
260  private:
263 
265  std::function<void(CallerType&)> task;
266 
269 };
270 
271 } //namespace m5
272 
273 #endif // __BASE_COROUTINE_HH__
void run()
Start executing the fiber represented by this object.
Definition: fiber.cc:165
bool finished() const
Returns whether the "main" function of this fiber has finished.
Definition: fiber.hh:83
void main() override
Overriding base (Fiber) main.
Definition: coroutine.hh:251
CallerType caller
Coroutine caller.
Definition: coroutine.hh:268
std::enable_if< std::is_same< T, void >::value, Coroutine >::type & operator()()
operator() is the way we can jump inside the coroutine.
Definition: coroutine.hh:211
Coroutine(std::function< void(CallerType &)> f, bool run_coroutine=true)
Coroutine constructor.
Definition: coroutine.hh:173
CallerType: A reference to an object of this class will be passed to the coroutine task...
Definition: coroutine.hh:85
Bitfield< 6 > f
Coroutine & operator()(typename std::enable_if< !std::is_same< T, void >::value, T >::type param)
Coroutine interface.
Definition: coroutine.hh:195
uint8_t type
Definition: inet.hh:333
CallerType & operator()(typename std::enable_if< !std::is_same< T, void >::value, T >::type param)
operator() is the way we can jump outside the coroutine and return a value to the caller...
Definition: coroutine.hh:101
This template defines a Coroutine wrapper type with a Boost-like interface.
Definition: coroutine.hh:64
std::enable_if< std::is_same< T, void >::value, CallerType >::type & operator()()
operator() is the way we can jump outside the coroutine
Definition: coroutine.hh:118
Coroutine & operator=(const Coroutine &rhs)=delete
CallerType(Coroutine &_coro)
Definition: coroutine.hh:89
virtual ~Coroutine()
Definition: coroutine.hh:181
std::function< void(CallerType &)> task
Coroutine task.
Definition: coroutine.hh:265
This class represents a fiber, which is a light weight sort of thread which is cooperatively schedule...
Definition: fiber.hh:64
Coroutine()=delete
ArgChannel argsChannel
Arguments for the coroutine.
Definition: coroutine.hh:262
Definition: compiler.hh:92
static Fiber * currentFiber()
Get a pointer to the current running Fiber.
Definition: fiber.cc:183
typename std::conditional< std::is_same< Arg, void >::value, Empty, std::stack< Arg > >::type ArgChannel
Definition: coroutine.hh:72
typename std::conditional< std::is_same< Ret, void >::value, Empty, std::stack< Ret > >::type RetChannel
Definition: coroutine.hh:75

Generated on Fri Feb 28 2020 16:26:58 for gem5 by doxygen 1.8.13