VIZ++ Class: Thread

 VIZ++ Class Library  VIZ++ Samples  VIZ++ ClassTree 

Source code

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



#pragma once

#include <viz++\Object.h>
#include <process.h>
#include <viz++\InvalidHandleException.h>

namespace VIZ {

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

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


private:

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

    Thread* thread = (Thread*)ptr;
    if(thread) {
      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;
  }

  // VIZ++ 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) {
    BOOL rc = FALSE;
    if (handle) {
      rc = TerminateThread(handle, exitCode);
    }
    return rc;
  }

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

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_VIZ_THREAD_CANCEL) {
        terminate(0);
        break;
      }
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }

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

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

}



Last modified: 10 Feb 2017

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