2013-02-04 46 views
1

好吧,我正在嘗試某種隊列。我有一個IO線程,它專門用於彈出std ::隊列中的數據,但問題是我正在使用Sleep()以防止100%cpu常量檢查。 當然還有其他線程會將項目添加到std :: queue。檢查std :: queue事件的另一種方法是什麼?

我怎麼能做出事件使線程處於休眠狀態,並只有啓動時的std ::隊列不爲空?

IO線程

Sleep(100); 
while (!myqueue.empty()) 
    { 
    //process data FIFO 
    myqueue.pop(); //pop out and continue 
    } 

非常感謝,謝謝!哦,這是用於c + + 11或c + + 03它無所謂 - 在Windows上。

+0

C++ 11與否?如果沒有,哪個操作系統? –

+2

它被稱爲信號量... –

+1

執行此操作的典型方法是使用['condition_variable'](http://en.cppreference.com/w/cpp/thread/condition_variable)。安東尼威廉姆斯回顧了這種實現的一些細節[這裏](http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html)。 –

回答

6

std::queue絕對與線程無關。完全一樣。它的.empty()成員不是線程安全的(僅限可重入)!其他成員也是如此。因此,多個線程可以使用不同的隊列,不管他們喜歡什麼隊列,但每次只有一個線程可以對每個實例執行任何操作。

C++ 11或C++ 03很重要很多。因爲C++ 11定義了線程同步原語,而C++ 03沒有,所以你必須使用OS API。

在C++ 11中,您會對std::condition_variable感興趣。

在C++ 03中,您會對Boost.Thread(大多數與C++ 11兼容)EventsSemaphores感興趣。

無論在哪種情況下,std::queue::push()std::queue::pop()本身必須受互斥排除。 std::condition_variable甚至強制你使用一個(std::mutex),在Windows API中你會使用Critical Section

在Windows上,C++ 11類僅在Visual Studio 2012和Windows 8中可用。對於較早的編譯器,使用Boost(優點是它將是可移植的)或本機API。

0

我的建議是先看看如何使用線程安全隊列,然後考慮使用boost :: condition信號來提供更多的控制。

這裏是你如何能建立一個線程安全的隊列的例子:

#pragma once                    
#include <queue>                  

template<typename T>                  
class thread_safe_queue                  
{                       
    queue<T> m_queue;                  
    pthread_mutex_t m_mutex;                
    pthread_cond_t m_condv;                

    public:                     
    thread_safe_queue() {                 
     pthread_mutex_init(&m_mutex, NULL);             
     pthread_cond_init(&m_condv, NULL);             
    }                      
    ~thread_safe_queue() {                 
     pthread_mutex_destroy(&m_mutex);             
     pthread_cond_destroy(&m_condv);              
    }                      
    void push(T& item) {                 
     pthread_mutex_lock(&m_mutex);              

     T itemcpy = std::move(item);              
     m_queue.push(std::move(itemcpy));             

     pthread_cond_signal(&m_condv);              
     pthread_mutex_unlock(&m_mutex);              
    }                      
    T pop() {                    
     pthread_mutex_lock(&m_mutex);              
     while (m_queue.size() == 0) {              
      pthread_cond_wait(&m_condv, &m_mutex);           
     }                     

     T& _item = m_queue.front();               
     T itemcpy = std::move(_item);              

     m_queue.pop();                  
     pthread_mutex_unlock(&m_mutex);              
     return itemcpy;                  
    }                      
    int size() {                   
     pthread_mutex_lock(&m_mutex);              
     int size = m_queue.size();               
     pthread_mutex_unlock(&m_mutex);              
     return size;                  
    }                      
};                    

你這是怎麼實例化它:

thread_safe_queue<myclass> myqueue; 
如果你想使用的事件信號再考慮使用

boost :: condition - fx。像這樣:

#include <boost/thread/condition.hpp> 
#include <boost/thread/mutex.hpp> 

boost::mutex mtxWait; 
boost::condition cndSignalQueueHasNewEntry; 

bool WaitForQueueSignal(long milliseconds) 
{ 
    boost::mutex::scoped_lock mtxWaitLock(mtxWait); 
    boost::posix_time::time_duration wait_duration = boost::posix_time::milliseconds(milliseconds); // http://www.boost.org/doc/libs/1_34_0/doc/html/date_time/posix_time.html 
    boost::system_time const timeout=boost::get_system_time()+wait_duration; // http://www.justsoftwaresolutions.co.uk/threading/condition-variable-spurious-wakes.html 
    return cndSignalQueueHasNewEntry.timed_wait(mtxWait,timeout); // wait until signal notify_one or timeout 
} 

這是你如何信號

cndSignalQueueHasNewEntry.notify_one(); 

這是你可以等待信號

bool bResult = WaitForQueueSignal(10000); // timeout after 10 seconds 
相關問題