Coroutine implementation in c++

Oct 3, 2018 at 12:02pm
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??
Last edited on Oct 3, 2018 at 12:22pm
Oct 3, 2018 at 2:27pm
Is there any reason not to use Boost.Coroutine?
Oct 3, 2018 at 2:47pm
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
Last edited on Oct 3, 2018 at 2:48pm
Oct 3, 2018 at 3:52pm
It seems to me like the correct implementation would be
1
2
3
4
void yield(){
    work_queue.push(get_current_context());
    jump_fcontext(work_queue.pop());
}
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.
Last edited on Oct 3, 2018 at 3:57pm
Oct 3, 2018 at 8:51pm
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)
Oct 3, 2018 at 8:58pm
Why do you have two queues? What do they contain?
Oct 3, 2018 at 9:14pm
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
Last edited on Oct 3, 2018 at 9:19pm
Oct 4, 2018 at 12:04am
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?
Last edited on Oct 4, 2018 at 12:53pm
Topic archived. No new replies allowed.