Click here to Skip to main content
15,885,546 members
Articles / Programming Languages / C++

Threading is easy (A simple thread, thread pool, object pool, and more)

Rate me:
Please Sign up or sign in to vote.
4.55/5 (10 votes)
9 Oct 2007CPOL4 min read 51.8K   686   54  
This simple library provides an implementation of almost all aspects of multithreaded programming.
#ifndef _TESTCASES_H_
#define _TESTCASES_H_
#include "stdafx.h"
#include "time.h"
#define MY_MAX_ITER 1000000
#define MY_SLEEP_TIME 200
#pragma warning(disable:4239)

//namespace system_utils
class CMyThreadWithMsgLoop: public mb_thread_lib::CThreadInterface<_bstr_t> 
{
protected:
    void Notify(mb_thread_lib::NOTIFY_EVENT_TYPE evt)
    {
        if(evt == mb_thread_lib::TERMINATE_THREAD_EVENT)
        ::PostThreadMessage(this->GetThreadId(),WM_QUIT,0,0);
    };
	virtual void Thread(mb_thread_lib::smart_ptr<_bstr_t> sp)
	{
		char* sz = (char*)(*sp);
		printf("begin thread: %s\n",sz);
		MSG msg;
		long lMsgCount = 0;
		::PostThreadMessage(this->GetThreadId(), WM_USER + 1, 0, lMsgCount);
		while(GetMessage(&msg,NULL,0,0))
		{
			++lMsgCount;
			if(lMsgCount == MY_MAX_ITER)
				break;
			TranslateMessage(&msg);
			DispatchMessage(&msg);
			::PostThreadMessage(this->GetThreadId(), WM_USER + 1, 0, lMsgCount);
		}
        printf("thread %s: lMsgCount = %d\n",sz,lMsgCount); 
		printf("exiting CMyThreadWithMsgLoop thread......\n");
        printf("end thread: %s\n",sz);
	}
};

class CMyThreadWithOutMsgLoop: public mb_thread_lib::CThreadInterface<_bstr_t> 
{
    volatile bool m_bStop;
protected:
    void Notify(mb_thread_lib::NOTIFY_EVENT_TYPE evt)
    {
        switch(evt)
        {
        case mb_thread_lib::BEGIN_THREAD_EVENT:
            m_bStop = false;
            break;
        case mb_thread_lib::TERMINATE_THREAD_EVENT:
            m_bStop = true;
            break;
        default:
            break;
        }
    };
	void Thread(mb_thread_lib::smart_ptr<_bstr_t> sp)
	{
		char* sz = (char*)(*sp);
		printf("begin thread: %s\n",sz);
		bool bTerminated = false;
		int i;
        for(i = 0; i < MY_MAX_ITER; ++i)
		{
			if(m_bStop)//must check if the thread is terminating!
			{
				bTerminated = true;
				break;
			}
		}
        printf("thread %s: i = %d\n",sz,i);
		printf("Terminating == %s\n",(bTerminated?"true":"false"));
		printf("exiting CMyThreadWithOutMsgLoop thread......\n");
		printf("end thread: %s\n",sz);
	}
};

class CMyThreadWithOutMsgLoopWithEventObject: public mb_thread_lib::CThreadInterface<_bstr_t> 
{
    volatile bool m_bStop;
public:
	HANDLE m_hMyEventObject;
	CMyThreadWithOutMsgLoopWithEventObject()
	{
		//our test waitable object
		m_hMyEventObject = ::CreateEvent(NULL, FALSE, FALSE,NULL);
	}
	~CMyThreadWithOutMsgLoopWithEventObject()
	{
		CloseHandle(m_hMyEventObject);
	}

protected:
	void Thread(mb_thread_lib::smart_ptr<_bstr_t> sp)
	{
		char* sz = (char*)(*sp);
		printf("begin thread: %s\n",sz);

_NEXT:
		::WaitForSingleObject(m_hMyEventObject, INFINITE);
		//must check if the thread is terminating!
		if(!m_bStop)
		{
			//it is not request to terminate this thread, so continue
			//...
			printf("Terminating == false\n");
			goto _NEXT;
		}
		else
			printf("Terminating == true\n");
		
        printf("exiting CMyThreadWithOutMsgLoopWithEventObject thread......\n");
		printf("end thread: %s\n",sz);
	}

	virtual void Notify(mb_thread_lib::NOTIFY_EVENT_TYPE evt)
	{
        switch(evt)
        {
        case mb_thread_lib::BEGIN_THREAD_EVENT:
            m_bStop = false;
            break;
        case mb_thread_lib::TERMINATE_THREAD_EVENT:
            //must notify m_hMyEventObject          
            m_bStop = true;
            ::SetEvent(m_hMyEventObject);
            break;
        default:
            break;
        }

	}
};

class CTestWorkItem: public mb_thread_lib::CWorkItemInterface
{
    bool bPrcessing;
public:
    CTestWorkItem():bPrcessing(false)
	{
	}
	~CTestWorkItem()
	{
	}
	void ProcessWorkItem()
	{
		//Sleep(1);
        mb_thread_lib::smart_ptr<mb_thread_lib::CCriticalSecInterface> spG(mb_thread_lib::CCriticalSecFactory::Query(_bstr_t("GLOBAL"), mb_thread_lib::CS_GLOBAL));
        spG->Lock();
        bPrcessing = true;
		printf("work item: %s, THREAD: %d\n",(char*)m_bstr,::GetCurrentThreadId());
        bPrcessing = false;
        spG->Unlock();
        Sleep(1);
	}
    void AbortWorkItem()
    {
        mb_thread_lib::smart_ptr<mb_thread_lib::CCriticalSecInterface> spG(mb_thread_lib::CCriticalSecFactory::Query(_bstr_t("GLOBAL"), mb_thread_lib::CS_GLOBAL));
        spG->Lock();
        if(bPrcessing)
            printf("\nABORT: work item: %s\n",(char*)m_bstr);
        spG->Unlock();
    };
	_bstr_t	m_bstr;
};

class CPushThread: public mb_thread_lib::CThreadInterface<mb_thread_lib::CSafeThread<mb_thread_lib::CSequentialObjectPool<_bstr_t>, _bstr_t> >
{
    volatile bool m_bStop;
protected:
    void Notify(mb_thread_lib::NOTIFY_EVENT_TYPE evt)
    {
        switch(evt)
        {
        case mb_thread_lib::BEGIN_THREAD_EVENT:
            m_bStop = false;
            break;
        case mb_thread_lib::TERMINATE_THREAD_EVENT:
            m_bStop = true;
            break;
        default:
            break;
        }

    };

public:
	void Thread(mb_thread_lib::smart_ptr<mb_thread_lib::CSafeThread<mb_thread_lib::CSequentialObjectPool<_bstr_t>, _bstr_t> > spWorkQueue)
	{
		for(int i = 0; ((!m_bStop)&&(i < MY_MAX_ITER*2)); ++i)
		{
			_bstr_t bstr("Val: ");
			_variant_t var;
			var = i;
			var.ChangeType(VT_BSTR);
			bstr = bstr + var.bstrVal;

			CTestWorkItem *pWorkItem = new CTestWorkItem();
			pWorkItem->m_bstr = bstr;
			mb_thread_lib::smart_ptr< mb_thread_lib::CWorkItemInterface > spWorkItem(dynamic_cast<mb_thread_lib::CWorkItemInterface*>(pWorkItem));
			
			if(!spWorkQueue->QueueWorkItem(spWorkItem))
                break;
		}
	}
};

void TestThreadPool();
void TestSequentialObjectPool();
void TestWaitThreadWithMessageLoop();
void TestWaitThreadWithOutMessageLoop();
void TestDeleteThreadWithMessageLoop();
void TestDeleteThreadWithOutMessageLoop();
void TestWaitThreadWithOutMsgLoopWithEventObject();
void TestDeleteThreadWithOutMsgLoopWithEventObject();
void TestTimerObject();

#endif//_TESTCASES_H_

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions