added wxMessageQueue class for inter-thread communications
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@49572 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
215
tests/thread/queue.cpp
Normal file
215
tests/thread/queue.cpp
Normal file
@@ -0,0 +1,215 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: tests/thread/queue.cpp
|
||||
// Purpose: Unit test for wxMessageQueue
|
||||
// Author: Evgeniy Tarassov
|
||||
// Created: 31/10/2007
|
||||
// RCS-ID: $Id:$
|
||||
// Copyright: (c) 2007 Evgeniy Tarassov
|
||||
// Licence: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "testprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/dynarray.h"
|
||||
#include "wx/thread.h"
|
||||
#endif // WX_PRECOMP
|
||||
|
||||
#include "wx/msgqueue.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// test class
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class QueueTestCase : public CppUnit::TestCase
|
||||
{
|
||||
public:
|
||||
QueueTestCase() { }
|
||||
|
||||
private:
|
||||
typedef wxMessageQueue<int> Queue;
|
||||
|
||||
enum WaitTestType
|
||||
{
|
||||
WaitWithTimeout = 0,
|
||||
WaitInfinitlyLong
|
||||
};
|
||||
|
||||
// This class represents a thread that waits (following WaitTestType type)
|
||||
// for exactly maxMsgCount messages from its message queue and if another
|
||||
// MyThread is specified, then every message received is posted
|
||||
// to that next thread.
|
||||
class MyThread : public wxThread
|
||||
{
|
||||
public:
|
||||
MyThread(WaitTestType type, MyThread *next, int maxMsgCount)
|
||||
: wxThread(wxTHREAD_JOINABLE),
|
||||
m_type(type), m_nextThread(next), m_maxMsgCount(maxMsgCount)
|
||||
{}
|
||||
|
||||
// thread execution starts here
|
||||
virtual void *Entry();
|
||||
|
||||
// Thread message queue
|
||||
Queue& GetQueue()
|
||||
{
|
||||
return m_queue;
|
||||
}
|
||||
|
||||
private:
|
||||
WaitTestType m_type;
|
||||
MyThread* m_nextThread;
|
||||
int m_maxMsgCount;
|
||||
Queue m_queue;
|
||||
};
|
||||
|
||||
WX_DEFINE_ARRAY_PTR(MyThread *, ArrayThread);
|
||||
|
||||
CPPUNIT_TEST_SUITE( QueueTestCase );
|
||||
CPPUNIT_TEST( TestReceive );
|
||||
CPPUNIT_TEST( TestReceiveTimeout );
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
void TestReceive();
|
||||
void TestReceiveTimeout();
|
||||
|
||||
DECLARE_NO_COPY_CLASS(QueueTestCase)
|
||||
};
|
||||
|
||||
// register in the unnamed registry so that these tests are run by default
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION( QueueTestCase );
|
||||
|
||||
// also include in it's own registry so that these tests can be run alone
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( QueueTestCase, "QueueTestCase" );
|
||||
|
||||
// this function creates the given number of threads and posts msgCount
|
||||
// messages to the last created thread which, in turn, posts all the messages
|
||||
// it receives to the previously created thread which does the same and so on
|
||||
// in cascade -- at the end, each thread will have received all msgCount
|
||||
// messages directly or indirectly
|
||||
void QueueTestCase::TestReceive()
|
||||
{
|
||||
const int msgCount = 100;
|
||||
const int threadCount = 10;
|
||||
|
||||
ArrayThread threads;
|
||||
|
||||
int i;
|
||||
for ( i = 0; i < threadCount; ++i )
|
||||
{
|
||||
MyThread *previousThread = i == 0 ? NULL : threads[i-1];
|
||||
MyThread *thread =
|
||||
new MyThread(WaitInfinitlyLong, previousThread, msgCount);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL ( thread->Create(), wxTHREAD_NO_ERROR );
|
||||
threads.Add(thread);
|
||||
}
|
||||
|
||||
for ( i = 0; i < threadCount; ++i )
|
||||
{
|
||||
threads[i]->Run();
|
||||
}
|
||||
|
||||
MyThread* lastThread = threads[threadCount - 1];
|
||||
|
||||
for ( i = 0; i < msgCount; ++i )
|
||||
{
|
||||
lastThread->GetQueue().Post(i);
|
||||
}
|
||||
|
||||
for ( i = 0; i < threadCount; ++i )
|
||||
{
|
||||
// each thread should return the number of messages received.
|
||||
// if it returns a negative, then it detected some problem.
|
||||
wxThread::ExitCode code = threads[i]->Wait();
|
||||
CPPUNIT_ASSERT_EQUAL( code, (wxThread::ExitCode)wxMSGQUEUE_NO_ERROR );
|
||||
}
|
||||
}
|
||||
|
||||
// this function creates two threads, each one waiting (with a timeout) for
|
||||
// exactly two messages.
|
||||
// Exactly to messages are posted into first thread queue, but
|
||||
// only one message is posted to the second thread queue.
|
||||
// Therefore first thread should return with wxMSGQUEUE_NO_ERROR, but the second
|
||||
// should return wxMSGQUEUUE_TIMEOUT.
|
||||
void QueueTestCase::TestReceiveTimeout()
|
||||
{
|
||||
MyThread* thread1 = new MyThread(WaitWithTimeout, NULL, 2);
|
||||
MyThread* thread2 = new MyThread(WaitWithTimeout, NULL, 2);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL ( thread1->Create(), wxTHREAD_NO_ERROR );
|
||||
CPPUNIT_ASSERT_EQUAL ( thread2->Create(), wxTHREAD_NO_ERROR );
|
||||
|
||||
thread1->Run();
|
||||
thread2->Run();
|
||||
|
||||
// Post two messages to the first thread
|
||||
CPPUNIT_ASSERT_EQUAL( thread1->GetQueue().Post(0), wxMSGQUEUE_NO_ERROR );
|
||||
CPPUNIT_ASSERT_EQUAL( thread1->GetQueue().Post(1), wxMSGQUEUE_NO_ERROR );
|
||||
|
||||
// ...but only one message to the second
|
||||
CPPUNIT_ASSERT_EQUAL( thread2->GetQueue().Post(0), wxMSGQUEUE_NO_ERROR );
|
||||
|
||||
wxThread::ExitCode code1 = thread1->Wait();
|
||||
wxThread::ExitCode code2 = thread2->Wait();
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL( code1, (wxThread::ExitCode)wxMSGQUEUE_NO_ERROR );
|
||||
CPPUNIT_ASSERT_EQUAL( code2, (wxThread::ExitCode)wxMSGQUEUE_TIMEOUT );
|
||||
}
|
||||
|
||||
// every thread tries to read exactly m_maxMsgCount messages from its queue
|
||||
// following the waiting strategy specified in m_type. If it succeeds then it
|
||||
// returns 0. Otherwise it returns the error code - one of wxMessageQueueError.
|
||||
void *QueueTestCase::MyThread::Entry()
|
||||
{
|
||||
int messagesReceived = 0;
|
||||
while ( messagesReceived < m_maxMsgCount )
|
||||
{
|
||||
wxMessageQueueError result;
|
||||
int msg;
|
||||
|
||||
if ( m_type == WaitWithTimeout )
|
||||
result = m_queue.ReceiveTimeout(1000, msg);
|
||||
else
|
||||
result = m_queue.Receive(msg);
|
||||
|
||||
if ( result == wxMSGQUEUE_MISC_ERROR )
|
||||
return (wxThread::ExitCode)wxMSGQUEUE_MISC_ERROR;
|
||||
|
||||
if ( result == wxMSGQUEUE_NO_ERROR )
|
||||
{
|
||||
if ( m_nextThread != NULL )
|
||||
{
|
||||
wxMessageQueueError res = m_nextThread->GetQueue().Post(msg);
|
||||
|
||||
if ( res == wxMSGQUEUE_MISC_ERROR )
|
||||
return (wxThread::ExitCode)wxMSGQUEUE_MISC_ERROR;
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL( wxMSGQUEUE_NO_ERROR, res );
|
||||
}
|
||||
++messagesReceived;
|
||||
continue;
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL ( result, wxMSGQUEUE_TIMEOUT );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ( messagesReceived != m_maxMsgCount )
|
||||
{
|
||||
CPPUNIT_ASSERT_EQUAL( m_type, WaitWithTimeout );
|
||||
|
||||
return (wxThread::ExitCode)wxMSGQUEUE_TIMEOUT;
|
||||
}
|
||||
|
||||
return (wxThread::ExitCode)wxMSGQUEUE_NO_ERROR;
|
||||
}
|
Reference in New Issue
Block a user