uvco 0.1
Loading...
Searching...
No Matches
Classes | Enumerations | Functions | Variables
Scheduler

Classes

class  uvco::Scheduler
 

Enumerations

enum class  uvco::Scheduler::RunMode { uvco::Scheduler::RunMode::Immediate = 0 , uvco::Scheduler::RunMode::Deferred = 1 }
 

Functions

 uvco::Scheduler::Scheduler (RunMode mode=RunMode::Deferred)
 
 uvco::Scheduler::Scheduler (const Scheduler &)=delete
 
 uvco::Scheduler::Scheduler (Scheduler &&)=delete
 
Scheduleruvco::Scheduler::operator= (const Scheduler &)=delete
 
Scheduleruvco::Scheduler::operator= (Scheduler &&)=delete
 
 uvco::Scheduler::~Scheduler ()
 
void uvco::Scheduler::setUpLoop (uv_loop_t *loop)
 
void uvco::Scheduler::enqueue (std::coroutine_handle<> handle)
 Schedule a coroutine for resumption.
 
void uvco::Scheduler::runAll ()
 Run all scheduled coroutines sequentially.
 
void uvco::Scheduler::close ()
 
bool uvco::Scheduler::empty () const
 

Variables

std::vector< std::coroutine_handle<> > uvco::Scheduler::resumableActive_
 
std::vector< std::coroutine_handle<> > uvco::Scheduler::resumableRunning_
 
RunMode uvco::Scheduler::run_mode_
 

Detailed Description

Enumeration Type Documentation

◆ RunMode

enum class uvco::Scheduler::RunMode
strong
Enumerator
Immediate 

Run an enqueued coroutine immediately, in the stack of the enqueuing function.

Deferred 

Run all enqueued coroutines sequentially, after all I/O has been completed, before the next I/O poll.

Function Documentation

◆ close()

void uvco::Scheduler::close ( )

close() should be called once the main promise has finished, and the process is preparing to exit; however, while the event loop is still running. Example: Once a user has pressed Ctrl-D in a tty application.

Otherwise, resources may be leaked. (This is usually not super important, because the event loop is finishing soon after anyway).

58{ BOOST_ASSERT(resumableActive_.empty()); }
std::vector< std::coroutine_handle<> > resumableActive_
Definition scheduler.h:93

◆ empty()

bool uvco::Scheduler::empty ( ) const
inline
89{ return resumableActive_.empty(); }

◆ enqueue()

void uvco::Scheduler::enqueue ( std::coroutine_handle<>  handle)

Schedule a coroutine for resumption.

60 {
61 // Use of moved-out Scheduler?
62 BOOST_ASSERT(resumableActive_.capacity() > 0);
63
65 handle.resume();
66 return;
67 }
68
69 resumableActive_.push_back(handle);
70}
RunMode run_mode_
Definition scheduler.h:97

◆ operator=() [1/2]

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

◆ operator=() [2/2]

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

◆ runAll()

void uvco::Scheduler::runAll ( )

Run all scheduled coroutines sequentially.

27 {
28 // In order to not delay checking for new I/O in the UV loop, we only run up
29 // to a fixed number of times.
30 static constexpr unsigned maxTurnsBeforeReturning = 5;
31 unsigned turns = 0;
32
33 while (!resumableActive_.empty() && turns < maxTurnsBeforeReturning) {
35 for (unsigned i = 0; i < resumableRunning_.size(); ++i) {
36 auto &coro = resumableRunning_[i];
37 // Defend against resuming the same coroutine twice in the same loop pass.
38 // This happens when SelectSet selects two coroutines which return at the
39 // same time. Resuming the same handle twice is not good, very bad, and
40 // will usually at least cause a heap use-after-free.
41
42 // Check if this coroutine handle has already been resumed. This has
43 // quadratic complexity, but appears to be faster than e.g. a Bloom
44 // filter, because it takes fewer calculations and is a nice linear search
45 // over a usually short vector.
46 if (findFirstIndexOf(resumableRunning_, coro) == i) {
47 // This is only true if the coroutine is a false positive in the bloom
48 // filter, and has not been run before. The linear search is slow (but
49 // not too slow), and only happens in the case of a false positive.
50 coro.resume();
51 }
52 }
53 resumableRunning_.clear();
54 ++turns;
55 }
56}
std::vector< std::coroutine_handle<> > resumableRunning_
Definition scheduler.h:95
unsigned findFirstIndexOf(std::span< const std::coroutine_handle<> > handles, std::coroutine_handle<> handle)
Definition scheduler.cc:18

◆ Scheduler() [1/3]

uvco::Scheduler::Scheduler ( const Scheduler )
delete

◆ Scheduler() [2/3]

uvco::Scheduler::Scheduler ( RunMode  mode = RunMode::Deferred)
explicit

Construct a scheduler.

If immediate_resume is true, resumed coroutines will be run immediately in the call stack of the resuming function. Otherwise the coroutine will be resumed upon the next turn of the event loop, i.e. after all activity has finished and before the next I/O poll, by call to runAll().

Call setUpLoop() to attach the scheduler to a libuv event loop.

76 : run_mode_{mode} {
77 resumableActive_.reserve(16);
78 resumableRunning_.reserve(16);
79}

◆ Scheduler() [3/3]

uvco::Scheduler::Scheduler ( Scheduler &&  )
delete

◆ setUpLoop()

void uvco::Scheduler::setUpLoop ( uv_loop_t *  loop)

Set up scheduler with event loop. This is required for all uvco code to find the scheduler.

72{ uv_loop_set_data(loop, this); }

◆ ~Scheduler()

uvco::Scheduler::~Scheduler ( )
default

Variable Documentation

◆ resumableActive_

std::vector<std::coroutine_handle<> > uvco::Scheduler::resumableActive_
private

◆ resumableRunning_

std::vector<std::coroutine_handle<> > uvco::Scheduler::resumableRunning_
private

◆ run_mode_

RunMode uvco::Scheduler::run_mode_
private