Note that there are some explanatory texts on larger screens.

plurals
  1. POProblem with thread-safe queue?
    text
    copied!<p>I'm trying to write a thread-safe queue using pthreads in c++. My program works 93% of the time. The other 7% of the time it other spits out garbage, OR seems to fall asleep. I'm wondering if there is some flaw in my queue where a context-switch would break it?</p> <pre><code>// thread-safe queue // inspired by http://msmvps.com/blogs/vandooren/archive/2007/01/05/creating-a-thread-safe-producer-consumer-queue-in-c-without-using-locks.aspx // only works with one producer and one consumer #include &lt;pthread.h&gt; #include &lt;exception&gt; template&lt;class T&gt; class tsqueue { private: volatile int m_ReadIndex, m_WriteIndex; volatile T *m_Data; volatile bool m_Done; const int m_Size; pthread_mutex_t m_ReadMutex, m_WriteMutex; pthread_cond_t m_ReadCond, m_WriteCond; public: tsqueue(const int &amp;size); ~tsqueue(); void push(const T &amp;elem); T pop(); void terminate(); bool isDone() const; }; template &lt;class T&gt; tsqueue&lt;T&gt;::tsqueue(const int &amp;size) : m_ReadIndex(0), m_WriteIndex(0), m_Size(size), m_Done(false) { m_Data = new T[size]; pthread_mutex_init(&amp;m_ReadMutex, NULL); pthread_mutex_init(&amp;m_WriteMutex, NULL); pthread_cond_init(&amp;m_WriteCond, NULL); pthread_cond_init(&amp;m_WriteCond, NULL); } template &lt;class T&gt; tsqueue&lt;T&gt;::~tsqueue() { delete[] m_Data; pthread_mutex_destroy(&amp;m_ReadMutex); pthread_mutex_destroy(&amp;m_WriteMutex); pthread_cond_destroy(&amp;m_ReadCond); pthread_cond_destroy(&amp;m_WriteCond); } template &lt;class T&gt; void tsqueue&lt;T&gt;::push(const T &amp;elem) { int next = (m_WriteIndex + 1) % m_Size; if(next == m_ReadIndex) { pthread_mutex_lock(&amp;m_WriteMutex); pthread_cond_wait(&amp;m_WriteCond, &amp;m_WriteMutex); pthread_mutex_unlock(&amp;m_WriteMutex); } m_Data[m_WriteIndex] = elem; m_WriteIndex = next; pthread_cond_signal(&amp;m_ReadCond); } template &lt;class T&gt; T tsqueue&lt;T&gt;::pop() { if(m_ReadIndex == m_WriteIndex) { pthread_mutex_lock(&amp;m_ReadMutex); pthread_cond_wait(&amp;m_ReadCond, &amp;m_ReadMutex); pthread_mutex_unlock(&amp;m_ReadMutex); if(m_Done &amp;&amp; m_ReadIndex == m_WriteIndex) throw "queue empty and terminated"; } int next = (m_ReadIndex +1) % m_Size; T elem = m_Data[m_ReadIndex]; m_ReadIndex = next; pthread_cond_signal(&amp;m_WriteCond); return elem; } template &lt;class T&gt; void tsqueue&lt;T&gt;::terminate() { m_Done = true; pthread_cond_signal(&amp;m_ReadCond); } template &lt;class T&gt; bool tsqueue&lt;T&gt;::isDone() const { return (m_Done &amp;&amp; m_ReadIndex == m_WriteIndex); } </code></pre> <p>This could be used like this:</p> <pre><code>// thread 1 while(cin.get(c)) { queue1.push(c); } queue1.terminate(); // thread 2 while(!queue1.isDone()) { try{ c = queue1.pop(); } catch(char const* str){break;} cout.put(c); } </code></pre> <p>If anyone sees a problem with this, please say so :)</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload