// QueueImplementation.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <windows.h> #include <iostream> #include <queue> #include <string> #include <process.h> using namespace std; struct DataBlock { string m_szText; //sample data }; class CDataQueue { private: queue<DataBlock> m_oQueue; //contains the actual data CRITICAL_SECTION m_csData; //to synchroize access to m_csData among multiple threads HANDLE m_hEvent; //for signalling presence of absence of data public: //create a manual reset event initially signalled. //This event will be signalled and shall remain so whenever there is data in the queue and //it shall be reset as long as queue is empty CDataQueue() { InitializeCriticalSection(&m_csData); m_hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); }; //close the event handle ~CDataQueue() { DeleteCriticalSection(&m_csData); CloseHandle(m_hEvent); }; //public methods to Push data to queue void Push(DataBlock& oNewData) { EnterCriticalSection(&m_csData); //push new element to queue m_oQueue.push(oNewData); //now that there is atleast one element, set the event SetEvent(m_hEvent); LeaveCriticalSection(&m_csData); }; //public methods to Pop data from queue DataBlock Pop() { EnterCriticalSection(&m_csData); //first get the topmost data block DataBlock popData = m_oQueue.front(); //next remove it from queue m_oQueue.pop(); //now, check for new size.. if no more elements in queue //reset the event if(!m_oQueue.size()) ResetEvent(m_hEvent); LeaveCriticalSection(&m_csData); return popData; }; //helper method to get the event handle HANDLE GetEvent(){return m_hEvent;}; }; CDataQueue g_oQueue; HANDLE g_hExitEvent; unsigned __stdcall ProcessData (void * ) { HANDLE hEvents[] = { g_hExitEvent, g_oQueue.GetEvent()}; DWORD dwRet; BOOL bContinue = TRUE; while(bContinue) { dwRet = WaitForMultipleObjects(sizeof(hEvents)/sizeof(hEvents[0]),hEvents,FALSE,INFINITE); switch(dwRet) { case WAIT_OBJECT_0 : { //exit signalled.. time to quit the thread bContinue = FALSE; } break; case WAIT_OBJECT_0 + 1: { //some data got.. DataBlock oData = g_oQueue.Pop(); //echo data to screen cout << "Data typed in is .. " << oData.m_szText << "/n"; } break; default:break; } } return 0; } int main(int argc, char* argv[]) { DWORD dwThreadID = 0; HANDLE hThread = NULL; //create an event to signal worker thread to exit g_hExitEvent = CreateEvent(NULL,TRUE,FALSE,NULL);//not signalled initially.. //spawn a thread for processing the input hThread = (HANDLE)_beginthreadex(NULL,0,ProcessData,NULL,0,(unsigned int *)&dwThreadID); if(hThread) { cout << "enter sentence to process /nOR /nenter /"exit/" to quit/n"; do { DataBlock oData; cin >> oData.m_szText; //if exit typed in.. quit if(0 == oData.m_szText.compare("exit")) break; g_oQueue.Push(oData); } while(1); //time to close ..set the exit event SetEvent(g_hExitEvent); //wait for worker thread to close WaitForSingleObject(hThread,INFINITE); //close the thread handle CloseHandle(hThread); } CloseHandle(g_hExitEvent); return 0; } template<typename Data> class concurrent_queue { private: std::queue<Data> the_queue; mutable boost::mutex the_mutex; boost::condition_variable the_condition_variable; public: void push(Data const& data) { boost::mutex::scoped_lock lock(the_mutex); the_queue.push(data); lock.unlock(); the_condition_variable.notify_one(); } bool empty() const { boost::mutex::scoped_lock lock(the_mutex); return the_queue.empty(); } bool try_pop(Data& popped_value) { boost::mutex::scoped_lock lock(the_mutex); if(the_queue.empty()) { return false; } popped_value=the_queue.front(); the_queue.pop(); return true; } void wait_and_pop(Data& popped_value) { boost::mutex::scoped_lock lock(the_mutex); while(the_queue.empty()) { the_condition_variable.wait(lock); } popped_value=the_queue.front(); the_queue.pop(); } };