2012-10-23 39 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對其進行初始化,以便進行內部進程使用。