0

我创建了自己的线程库......当然,它是一个简单的非抢占式库,其中线程按照它们被调用的顺序执行。该程序的简要大纲如下:

class Thread
{
static Thread sched;
/*called only once*/
static void init()
{
*create a context for sched thread* 
static void schedule()
{ 
....
setcontext(current thread from the queue);
return if empty
}
Thread(function)
{
intializes the context via getcontext and sets the uc_link to the context of sched
and pushed into the queue and calls schedule function
}

单线程似乎一切都很好。但是当我初始化两个线程对象时,只有其中一个正在执行。我怀疑当第一个线程完成其工作时,它会返回到调度函数,而当调度函数看到队列为空时......它也会返回。

但是我观察到第一个线程只调用了一次构造函数!!为什么呢?

如果我不从构造函数调用调度函数,而是定义一个函数,如

void start()
{
 schedule();
}

并在所有线程都初始化后调用它,它正在正确执行。但我不想使用这种方法..

请解释一下执行路径和上述问题的解决方案。
这是它的实际代码

class thread
{

static queue<thread> Q;



    ucontext_t con;
    int u_p;
    int c_p;
static void init()
{
    flag=0;
    getcontext(&schd.con);
    //cout<<"fgh\n";
    schd.con.uc_link=0;
    schd.con.uc_stack.ss_sp=malloc(ST_S);
    schd.con.uc_stack.ss_size=ST_S;
    makecontext(&schd.con, schd.schedule, 0);

}
static thread main, schd;
static int flag;
public:

thread()
    {   }   
thread(int i){ init(); }

    static  void schedule()
    {
        //cout<<"ii\n";
        if(Q.empty()){
        flag=0;
        return;
        }
            main=Q.front();
            Q.pop();
            setcontext(&main.con);
    init();
    //cout<<"yea\n";    

    }   

    thread(void (*fn)(), int u_p=15)
    {

        getcontext(&con);
        con.uc_link=&schd.con;
        con.uc_stack.ss_sp=malloc(ST_S);  
        con.uc_stack.ss_flags=0;        
        con.uc_stack.ss_size=ST_S;
        makecontext(&con, fn, 0);
        //cout<<"hjkl\n";
        Q.push(*this);
    if(flag==0){
    flag=1;
    schedule();
    }           
    }
static void start(){ schedule(); }

    };
queue<thread> thread::Q;
thread thread::main;
thread thread::schd;
int thread::flag;
4

1 回答 1

0

似乎正在发生这种情况:

  1. 你创建一个新线程
  2. Thread::Thread()来电Thread::shedule()
  3. Thread::shedule()来电setcontext()
  4. 控制流切换到functionThread对象
  5. 这个新线程执行,而不是切换回其父上下文,因此无法创建另一个线程

我认为我见过的所有线程库和 OS API 要么创建挂起的线程,要么提供一个标志来创建处于挂起状态的线程。所以这是一个很好的方法,否则你会在创建另一个线程时丢失停止当前线程。此外,由于您使用轻量级线程,您几乎被迫创建没有任何标志的挂起线程,以便能够从主线程创建多个线程。

于 2012-08-25T05:07:22.563 回答