2012-10-23 38 views
7

我想在Linux中实现非常简单的Windows事件。仅适用于我的场景 - 3个线程,1个主要和2个辅助。每个辅助线程通过SetEvent引发1个事件,主线程等待它。例如:使用条件变量在Linux中执行Windows事件?

int main() 
{ 
    void* Events[2]; 
    Events[0] = CreateEvent(); 
    Events[1] = CreateEvent(); 

    pthread_start(Thread, Events[0]); 
    pthread_start(Thread, Events[1]); 

    WaitForMultipleObjects(2, Events, 30000) // 30 seconds timeout 

    return 0; 
} 

int* thread(void* Event) 
{ 
    // Do something 
    SetEvent(Event); 
    // Do something 
} 

所以,要实现它,我使用条件变量。但我的问题是 - 这是一种正确的方式吗?或者我做错了什么?我的实现:

// Actually, this function return pointer to struct with mutex and cond 
// here i just simplified example 
void* CreateEvent(mutex, condition) 
{ 
    pthread_mutex_init(mutex, NULL); 
    pthread_cond_init(condition, NULL); 
} 

bool SetEvent (mutex, condition) 
{ 
    pthread_mutex_lock(mutex); 
    pthread_cond_signal(condition); 
    pthread_mutex_unlock(mutex); 
} 

int WaitForSingleObject(mutex, condition, timeout) 
{ 
    pthread_mutex_lock(mutex); 
    pthread_cond_timedwait(condition, mutex, timeout); 
    pthread_mutex_unlock(mutex); 
} 

// Call WaitForSingleObject for each event. 
// Yes, i know, that its a wrong way, but it should work in my example. 
int WaitForMultipleObjects(count, mutex[], condition[], timeout); 

而且一切似乎不错,但我认为,当我打电话WaitFor的..在辅助线程SetEvent的前主线程函数会被这个问题就会出现。在Windows中,它运行良好,但在Linux中 - 只有想法如上所述。

也许你告诉我解决问题的更好方法?谢谢。

UPD:超时非常重要,因为其中一个辅助线程可能无法通过SetEvent()。

+0

我们有一个开源的(MIT授权)库,名为'pevents',它在linux上实现了WIN32手动和自动重置事件,并包含WaitForSingleObject和WaitForMultipleObjects克隆:https://github.com/NeoSmart/PEvents –

+0

可能重复的[pthread-like windows手动重置事件](http://stackoverflow.com/questions/178114/pthread-like-windows-manual-reset-event) – jww

回答

1

有在计算器类似的问题已经:WaitForSingleObject and WaitForMultipleObjects equivalent in linux

此外,还可以使用信号灯:

sem_t semOne ; 
sem_t semTwo ; 
sem_t semMain ; 

在主线程:

sem_init(semOne,0,0) ; 
sem_init(semTwo,0,0) ; 
sem_init(semMain,0,0) ; 

... 


sem_wait(&semMain); 

// Thread 1 
sem_wait(&semOne); 
sem_post(&semMain); 


// Thread 2 
sem_wait(&semTwo); 
sem_post(&semMain); 

详细说明和各种实例可寻这里:http://www.ibm.com/developerworks/linux/library/l-ipc2lin3/index.html

+0

谢谢,但超时?据我所知,信号灯没有它。 – DeniDoman

+0

您可以简单地使用sem_timedwait()而不是sem_wait()。 – codewarrior

+0

我想,那个信号灯不能等待...谢谢) – DeniDoman

3

立足本上的WaitForSingleObject

描述的WaitForSingleObject的功能检查指定对象的当前状态。如果对象的状态为非信号,则调用线程将进入等待状态,直到对象发出信号或超时时间间隔过去。

这种行为和代码之间的区别是,该代码会一直等待条件变量,因为它不检查一个谓语。这引入了pthread_condt_timewaitpthread_cond_signal调用之间的同步问题。

信令条件变量一般成语是:

lock mutex 
set predicate 
unlock mutex 
signal condition variable 

并等待条件变量时:

lock mutex 
while (!predicate) 
{ 
    wait on condition variable 
} 
unlock mutex

基于什么努力来完成,单独bool可能用作每个Event的谓词。通过引入一个谓词,WaitForSingleObject应该只在条件变量上等待,如果Event尚未发送信号。该代码将类似于以下内容:

bool SetEvent (mutex, condition) 
{ 
    pthread_mutex_lock(mutex);     // lock mutex 
    bool& signalled = find_signal(condition); // find predicate 
    signalled = true;       // set predicate 
    pthread_mutex_unlock(mutex);    // unlock mutex 
    pthread_cond_signal(condition);   // signal condition variable 
} 

int WaitForSingleObject(mutex, condition, timeout) 
{ 
    pthread_mutex_lock(mutex);       // lock mutex 
    bool& signalled = find_signal(condition);   // find predicate 
    while (!signalled) 
    { 
     pthread_cond_timedwait(condition, mutex, timeout); 
    } 
    signalled = false;         // reset predicate 
    pthread_mutex_unlock(mutex);      // unlock mutex 
} 
+0

谢谢你的帮助! – DeniDoman

0

我认为信号是一种更好的解决方案在这里,因为它可以用于进程间。 如果未提供名称,则可以封装接口,然后使用pthread_将其初始化以供进程内使用,这可以缩短资源使用情况,但是当名称使用时,请尝试使用sem对其进行初始化,以便进行内部进程使用。