uvco 0.1
Loading...
Searching...
No Matches
uvco::Loop Class Reference

#include <loop.h>

Collaboration diagram for uvco::Loop:

Public Member Functions

 Loop ()
 Loop (const Loop &)=delete
 Loop (Loop &&)=delete
Loopoperator= (const Loop &)=delete
Loopoperator= (Loop &&)=delete
 ~Loop ()
uv_loop_t * uvloop () const
 Get a non-owned pointer to the loop.

Static Public Member Functions

static void enqueue (std::coroutine_handle<> handle)
static void cancel (std::coroutine_handle<> handle)
static std::coroutine_handle getNext ()

Private Member Functions

void run ()
void runOne ()

Static Private Member Functions

static SchedulercurrentScheduler ()

Private Attributes

uv_loop_t loop_
Scheduler scheduler_
bool stopped_ = false

Static Private Attributes

static LoopdefaultLoop = nullptr

Friends

void runLoop (Loop &loop)

Detailed Description

Not used by user code! Use runMain() for the top-level interface.

A wrapper around a libuv event loop. uvloop() returns a reference to the loop, and run() starts the event loop. enqueue() schedules a coroutine to run on the default loop at a later time, enabling any part of uvco to easily schedule work on the current loop.

Typically this is only used by uvco's internal machinery. User code will pass around a reference to the loop.

Constructor & Destructor Documentation

◆ Loop() [1/3]

uvco::Loop::Loop ( )
24 : loop_{} {
25
26 if (defaultLoop != nullptr) {
27 throw UvcoException(UV_EBUSY,
28 "Loop::Loop(): only one loop can be created.");
29 }
30
31 uv_loop_init(&loop_);
32
33#ifdef UV_LOOP_USE_IO_URING_SQPOLL
34 const uv_status configureStatus =
35 uv_loop_configure(&loop_, UV_LOOP_USE_IO_URING_SQPOLL);
36 if (configureStatus != 0) {
37 fmt::print(stderr, "Could not configure io_uring for file access: {}",
38 uv_strerror(configureStatus));
39 }
40#endif
41 defaultLoop = this;
42}
static Loop * defaultLoop
Definition loop.h:50
uv_loop_t loop_
Definition loop.h:62
int uv_status
Result of a libuv operation, an errno error code.
Definition internal_utils.h:22

◆ Loop() [2/3]

uvco::Loop::Loop ( const Loop & )
delete

◆ Loop() [3/3]

uvco::Loop::Loop ( Loop && )
delete

◆ ~Loop()

uvco::Loop::~Loop ( )
44 {
45 scheduler_.close();
46
47 // Run loop again so that all handles are closed.
48 // A single turn is enough.
49 runOne();
50
51 // Now run all scheduled handles
52 scheduler_.runAll();
53
54 const uv_status status = uv_loop_close(&loop_);
55 if (0 != status) {
56 fmt::print(stderr,
57 "Loop::~Loop(): uv_loop_close() failed; there were "
58 "still resources on the loop: {}\n",
59 uv_strerror(status));
60 // Walk the loop and print all handles that are still active.
61 uv_walk(&loop_, handleWalkCallbackForDebug, nullptr);
62 }
63 defaultLoop = nullptr;
64}
void runOne()
Definition loop.cc:66
Scheduler scheduler_
Definition loop.h:63

Member Function Documentation

◆ cancel()

void uvco::Loop::cancel ( std::coroutine_handle<> handle)
static
104 {
105 currentScheduler().cancel(handle);
106}
static Scheduler & currentScheduler()
Definition loop.cc:87
void cancel(std::coroutine_handle<> handle)
Definition scheduler.cc:44

◆ currentScheduler()

Scheduler & uvco::Loop::currentScheduler ( )
staticprivate
87 {
88 if (defaultLoop == nullptr) [[unlikely]] {
89 throw UvcoException(UV_EINVAL, "Loop::getDefaultLoop(): no loop created.");
90 }
91 return defaultLoop->scheduler_;
92}

◆ enqueue()

void uvco::Loop::enqueue ( std::coroutine_handle<> handle)
static
94 {
95 currentScheduler().enqueue(handle);
96 // If any handles are present, ensure that uv_run returns from waiting for I/O
97 // soon.
98 if (!defaultLoop->stopped_) [[unlikely]] {
99 uv_stop(defaultLoop->uvloop());
100 defaultLoop->stopped_ = true;
101 }
102}
void enqueue(std::coroutine_handle<> handle)
Schedule a coroutine for resumption.
Definition scheduler.cc:34

◆ getNext()

std::coroutine_handle uvco::Loop::getNext ( )
static
108{ return currentScheduler().getNext(); }
std::coroutine_handle getNext()
Definition scheduler.cc:57

◆ operator=() [1/2]

Loop & uvco::Loop::operator= ( const Loop & )
delete

◆ operator=() [2/2]

Loop & uvco::Loop::operator= ( Loop && )
delete

◆ run()

void uvco::Loop::run ( )
private

Run the event loop. This will serve all promises initialized before calling it.

68 {
69 while (!scheduler_.empty() || uv_loop_alive(&loop_) != 0) {
70 stopped_ = false;
71 runOne();
72 // Run any left-over coroutines, and check if they schedule callbacks.
73 scheduler_.runAll();
74 }
75
76 if constexpr (logSchedulerOperations) {
77 fmt::print("exiting loop due to scheduler empty? {} uv_loop_alive? {}\n",
78 scheduler_.empty() ? "yes" : "no",
79 uv_loop_alive(&loop_) != 0 ? "yes" : "no");
80 }
81}
bool stopped_
Definition loop.h:64
static constexpr bool logSchedulerOperations
If set to true, log scheduler operations to stdout.
Definition scheduler.h:17

◆ runOne()

void uvco::Loop::runOne ( )
private
66{ uv_run(&loop_, UV_RUN_ONCE); }

◆ uvloop()

uv_loop_t * uvco::Loop::uvloop ( ) const
nodiscard

Get a non-owned pointer to the loop.

83{ return &loop_; }

◆ runLoop

void runLoop ( Loop & loop)
friend
7{ loop.run(); }

Member Data Documentation

◆ defaultLoop

Loop * uvco::Loop::defaultLoop = nullptr
staticprivate

◆ loop_

uv_loop_t uvco::Loop::loop_
mutableprivate

◆ scheduler_

Scheduler uvco::Loop::scheduler_
private

◆ stopped_

bool uvco::Loop::stopped_ = false
private

The documentation for this class was generated from the following files: