There are SEVERAL problems with this code, some of which Joachim Pileborg points out.
Another problem is that you only have one context
, which you are using multiple times to store different data, yet expect the data to be there when you come back.
The solution is to split your ThreadSystem
and your Thread
(the actual context of a thread) into separate objects:
struct Thread
{
jmp_buf context; // saved context of this thread
void* arg;
ThreadFunc func; // function that this thread started executing
};
After removing stuff that isn't currently used, the ThreadSystem
looks like this:
struct ThreadSystem
{
queue<Thread*> ready_queue;
};
The thread creation/exit functions now look like this:
void t_start(ThreadFunc f, void* v)
{
if(!sys.ready_queue.empty()){
cout<<"sorry thread already started now you have to create by t_fork:"<<endl;
}
else{
Thread* th = new Thread;
sys.ready_queue.push(th);
if(!setjmp(th->context)){
th->arg=v;
th->func=f;
cout << "&th->context=" << &th->context << endl;
th->func(th->arg);
}
}
}
void t_fork(ThreadFunc f, void* v){
Thread* th = new Thread;
th->func = f;
th->arg = v;
if(!setjmp(th->context))
{
cout << "&th->context=" << &th->context << endl;
f(v);
sys.ready_queue.push(th);
}
}//end of t_fork
void t_exit(int val){
cout<<"before long jump in t_exit"<<endl;
Thread* th=sys.ready_queue.front();
sys.ready_queue.pop();
// Memory leak here. We can't delete `th`, and still have a context.
longjmp(th->context,2);
}
But as you can see, there is a problem in destroying the thread - so some other solution would have to be found for this. I'm not sure this is a great solution, but this works (to the limited degree of executing the test-code posted), where the original code didn't.