SOL9 2.0 Class: Thread

 SOL9 C++ Class Library  SOL9 Samples  SOL9 Tutorial  SOL9 FAQ  SOL9 ClassTree 

Source code

/*
 * Thread.h 
 * Copyright (c) 2011 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 */


// SOL++2000
// 1999.09.24 Modified to use _beginthreadex and _endthreadex insteade
// of CreateThread and ExitThread.
// SOL9 
// 2008/09/05

#pragma once

#include <sol\Object.h>
#include <process.h>
#include <sol\stdio.h>
#include <sol\InvalidHandleException.h>

namespace SOL {

typedef unsigned (__stdcall *LPTHREAD_PROC)(void*);

class Thread :public Object {
public:
    static const UINT WM_SOL_THREAD_CANCEL = (WM_USER+2009);


private:

    void*    param;
    DWORD    threadId;
    HANDLE  handle;
    static  DWORD WINAPI procedure(DWORD dword) {

        Thread* thread = (Thread*)dword;
        if(thread) {
            // SOL++2000
            thread -> run();
        }
        return True;
    }

protected:
    void setHandle(HANDLE handle1) {
        handle = handle1;
    }
    void setThreadId(int id) {
        threadId = id;
    }

public:

    Thread(DWORD stack = 0, void* param = NULL){
        this -> param = param;
        // Create a suspended thread.
        DWORD flags = CREATE_SUSPENDED;

        handle = (HANDLE)_beginthreadex((void*)NULL, (unsigned)stack, 
                (LPTHREAD_PROC)Thread::procedure,
                (void*)this, flags, (unsigned*)&threadId);
        if(handle == NULL || handle == INVALID_HANDLE_VALUE) {
            handle = NULL;
            throw InvalidHandleException("Failed to create a thread",
                GetLastError());
        }
    }

    ~Thread() {
        kill();
    }
    void*    getParam() {
            return param;
    }
    DWORD    getThreadId() {
            return threadId;
    }

    HANDLE    getHandle() {
            return handle;
    }

    void    exit(DWORD exitCode) {
        //::ExitThread(exitCode);
        _endthreadex(exitCode);
    }

    // Thread main loop
    virtual void run() {
            // Do something
            //return TRUE;
    }

    // SOL++ 3.0
    virtual DWORD start() {
            return resume();
    }
    void    sleep(DWORD time) {
            ::Sleep(time);
    }

    DWORD    resume() {
        return ::ResumeThread(handle);
    }

    void    setPriority(int priority) {
            ::SetThreadPriority(handle, priority);
    }

    DWORD    suspend() {
        //Please be carefull to use this method,
        //because this may cause a something deadlock. 
        return ::SuspendThread(handle);
    }

    BOOL    close() {
        if(handle) {
            HANDLE h = handle;
            handle = NULL;
            return ::CloseHandle(h);
        }
        return FALSE;

    }
    BOOL    post(UINT message, WPARAM wParam, LPARAM lParam) {
        if(handle) {
            return ::PostThreadMessage(threadId, message, wParam, lParam);
        }
        else {
            return FALSE;
        }
    }

     BOOL   getExitCode(DWORD* id) {
        return ::GetExitCodeThread(handle, id);
     }

     void    kill() {
        if(handle) {
            close();
            DWORD id;
            while(getExitCode(&id)) {
                if(id == STILL_ACTIVE) {
                    dispatchMessage();
                    continue;
                }
                else {
                    break;
                }
            }
        }
        handle = NULL;

     }

    BOOL    terminate(int exitCode) {
        return ::TerminateThread(handle, exitCode);
    }

    int    wait(int interval=INFINITE) {
            return ::WaitForSingleObject(handle, interval);
    }

/*
public:
    //2009/11/16
    void  msgWait(){
     while (true)   
        if (MsgWaitForMultipleObjects(1, &handle, FALSE,   
            INFINITE, QS_ALLINPUT|QS_ALLEVENTS) == WAIT_OBJECT_0+1 ) {
                dispatchMessage(); 
        }else {
            break;   
        }
    }
*/

//2009/11/16
private:
    void dispatchMessage()
    {
        MSG msg;        
        while(PeekMessage (&msg,NULL,0,0,PM_REMOVE)) {
            SleepEx(10, TRUE);

            if (msg.message == WM_SOL_THREAD_CANCEL) {
                terminate(0);
                break;
            }
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

public:
    virtual void stop() {
        post(WM_SOL_THREAD_CANCEL, 0, 0);
    }

public:
    UINT getCancelMessage() {
        return WM_SOL_THREAD_CANCEL;
    }
};

}



Last modified: 1 Feb 2012

Copyright (c) 2009-2012 Antillia.com ALL RIGHTS RESERVED.