I am trying to implement coroutines (had to reinvent the wheel as part of my project) in c++. Every coroutine is an instance of a workpackage class and stored in a packagequeue. When a workpackage(coroutine) is being executed, it is removed from the queue. Now when i call the yeild function inside this workpackage, it should jump to another workpackage in the packagequeue. This is what i am trying to do
1 2 3 4 5
myworkpackage(){
//do some stuff
yield()
// do remaing stuff
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
yield(){
Get the context of workpackage that called yield() // Every workpackage has its own context. I dont know how to do that because workpackage is not in the packagequeue anymore and i //cant access its data members.
if (there is another package in the waitingqueue){ // Two queues for every thread i.e. waitngqueue and packagequeue
Get its context
Add the workpackage to the waitingqueue.
jump_context(oldpackage, newpackage) // switching the context here
}
else {
Add the workpackage to the waitingqueue.
}
If(packagequeue is not empty)
grab ane execute another workpackage
else
steal the packe from another thread queue and execute it
}
Considering full scenario, does it make sense what i am trying to do or is there a better way to accomplish it??
I am writing a library for real time systems and its bare metal implementation which involves thread management and scheduling. I am not allowed to use any library what so ever for that purpose. However i am using lowest level functions (make_fcontext and jump_fcontext) for switching context between coroutines, from boost::context but and do not depend on boost
Note that work_queue can be implemented as a fixed-length circular buffer. You only need to resize its capacity when coroutines are created or destroyed.
Both package_queue and waiting_queue are implemented as fix length circular buffers. How is it possible to get the context of coroutine keeping in mind that its not in package_queue because when i pop the coroutine from queue for execution, queue indexes are getting updated.(I have to resize queue at pop because other threads might steal work from it)
I am emulating physical cores of real system via pthreads. Each Pthread(Core) has two queues. One is where normal "running" coroutines are stored(In case a coroutine creates more coroutines) and other is where i want to store waiting coroutines(which got yield). Normally when a core's own queue is empty it steals from the other core queue. When yield is called, core will continue executing those packages first that are in its waitng_queue(from previous yield calls). If its empty then execute coroutines in its package_queue otherwise steal from other cores
Each Pthread(Core) has two queues. One is where normal "running" coroutines are stored(In case a coroutine creates more coroutines)
What do you mean? As I understand coroutines, they have only two states:
1. Running: the coroutine has accepted the yield() from a different coroutine and has not yet yielded.
2. Suspended: the coroutine has yielded to a different coroutine, or has yet to be started for the first time.
A single thread can't be running more than a single coroutine at any given time. Even if a coroutine creates more coroutines, those coroutines must be in the suspended state until the coroutine that's currently running yields to them.
Why would you need a queue to store the coroutines that a single thread is currently running, when they can't ever be more than one?