gem5 v24.0.0.0
Loading...
Searching...
No Matches
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
47namespace gem5
48{
49
62template <typename Arg, typename Ret>
63class Coroutine : public Fiber
64{
65
66 // This empty struct type is meant to replace coroutine channels
67 // in case the channel should be void (Coroutine template parameters
68 // are void. (See following ArgChannel, RetChannel typedef)
69 struct Empty {};
70 using ArgChannel = typename std::conditional_t<
71 std::is_same_v<Arg, void>, Empty, std::stack<Arg>>;
72
73 using RetChannel = typename std::conditional_t<
74 std::is_same_v<Ret, void>, Empty, std::stack<Ret>>;
75
76 public:
85 {
86 friend class Coroutine;
87 protected:
88 CallerType(Coroutine& _coro) : coro(_coro), callerFiber(nullptr) {}
89
90 public:
100 template <typename T = Ret>
102 operator()(typename std::enable_if_t<
103 !std::is_same_v<T, void>, T> param)
104 {
105 retChannel.push(param);
106 callerFiber->run();
107 return *this;
108 }
109
118 template <typename T = Ret>
119 typename std::enable_if_t<std::is_same_v<T, void>,
120 CallerType> &
122 {
123 callerFiber->run();
124 return *this;
125 }
126
139 template <typename T = Arg>
140 typename std::enable_if_t<!std::is_same_v<T, void>, T>
142 {
143 auto& args_channel = coro.argsChannel;
144 while (args_channel.empty()) {
145 callerFiber->run();
146 }
147
148 auto ret = args_channel.top();
149 args_channel.pop();
150 return ret;
151 }
152
153 private:
157 };
158
163 Coroutine() = delete;
164 Coroutine(const Coroutine& rhs) = delete;
165 Coroutine& operator=(const Coroutine& rhs) = delete;
166 // end of api_coroutine
167
185 Coroutine(std::function<void(CallerType&)> f, bool run_coroutine = true)
186 : Fiber(), task(f), caller(*this)
187 {
188 // When desired, run the Coroutine after it is created
189 if (run_coroutine)
190 this->call();
191 }
192
196 virtual ~Coroutine() {}
197
198 public:
210 template <typename T = Arg>
211 Coroutine&
212 operator()(typename std::enable_if_t<!std::is_same_v<T, void>, T> param)
213 {
214 argsChannel.push(param);
215 this->call();
216 return *this;
217 }
218
227 template <typename T = Arg>
228 typename std::enable_if_t<std::is_same_v<T, void>, Coroutine> &
230 {
231 this->call();
232 return *this;
233 }
234
247 template <typename T = Ret>
248 typename std::enable_if_t<!std::is_same_v<T, void>, T>
250 {
251 auto& ret_channel = caller.retChannel;
252 while (ret_channel.empty()) {
253 this->call();
254 }
255
256 auto ret = ret_channel.top();
257 ret_channel.pop();
258 return ret;
259 }
260
266 operator bool() const { return !this->finished(); }
267
268 private:
275 void main() override { this->task(caller); }
276
277 void
279 {
281 run();
282 }
283
284 private:
287
289 std::function<void(CallerType&)> task;
290
293};
294
295} //namespace gem5
296
297#endif // __BASE_COROUTINE_HH__
CallerType: A reference to an object of this class will be passed to the coroutine task.
Definition coroutine.hh:85
CallerType(Coroutine &_coro)
Definition coroutine.hh:88
This template defines a Coroutine wrapper type with a Boost-like interface.
Definition coroutine.hh:64
void main() override
Overriding base (Fiber) main.
Definition coroutine.hh:275
std::function< void(CallerType &)> task
Coroutine task.
Definition coroutine.hh:289
typename std::conditional_t< std::is_same_v< Ret, void >, Empty, std::stack< Ret > > RetChannel
Definition coroutine.hh:73
CallerType caller
Coroutine caller.
Definition coroutine.hh:292
ArgChannel argsChannel
Arguments for the coroutine.
Definition coroutine.hh:286
typename std::conditional_t< std::is_same_v< Arg, void >, Empty, std::stack< Arg > > ArgChannel
Definition coroutine.hh:70
This class represents a fiber, which is a light weight sort of thread which is cooperatively schedule...
Definition fiber.hh:72
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:249
Coroutine & operator=(const Coroutine &rhs)=delete
virtual ~Coroutine()
Definition coroutine.hh:196
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:121
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:102
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:141
Coroutine & operator()(typename std::enable_if_t<!std::is_same_v< T, void >, T > param)
Coroutine interface.
Definition coroutine.hh:212
Coroutine()=delete
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:229
Coroutine(const Coroutine &rhs)=delete
Coroutine(std::function< void(CallerType &)> f, bool run_coroutine=true)
Coroutine constructor.
Definition coroutine.hh:185
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< 6 > f
Definition misc_types.hh:68
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36

Generated on Tue Jun 18 2024 16:24:00 for gem5 by doxygen 1.11.0