2013-02-04 23 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 
相关问题