Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tthread.h"
Toshihiro Shimizu 890ddd
#define _WIN32_WINNT 0x0400
Toshihiro Shimizu 890ddd
#include <windows.h></windows.h>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using std::list<tthread *="">;</tthread>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TThreadGroupImp;
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//    TMutex & TMutexImp
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TMutexImp {
Shinya Kitaoka 120a6e
  HANDLE id;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TMutexImp();
Shinya Kitaoka 120a6e
  ~TMutexImp();
Shinya Kitaoka 120a6e
  void lock();
Shinya Kitaoka 120a6e
  void unlock();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TThreadGroupImp {
Shinya Kitaoka 120a6e
  list<tthread *=""> threads;</tthread>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TThreadGroupImp();
Shinya Kitaoka 120a6e
  ~TThreadGroupImp();
Shinya Kitaoka 120a6e
  void add(TThread *);
Shinya Kitaoka 120a6e
  void remove(TThread *);
Shinya Kitaoka 120a6e
  void wait();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TMutexImp::TMutexImp() { id = CreateMutex(NULL, FALSE, NULL); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TMutexImp::~TMutexImp() { BOOL rc = CloseHandle(id); }
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TMutexImp::lock() { DWORD rc = WaitForSingleObject(id, INFINITE); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TMutexImp::unlock() { BOOL rc = ReleaseMutex(id); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TMutex::TMutex() : m_imp(new TMutexImp()) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TMutex::~TMutex() { delete m_imp; }
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TMutex::lock() { m_imp->lock(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TMutex::unlock() { m_imp->unlock(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//    TThread & TThreadImp
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TThreadImp {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  friend class TThreadGroupImp;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  HANDLE threadId;
Shinya Kitaoka 120a6e
  HANDLE mainThread;
Shinya Kitaoka 120a6e
  int m_refCount;
Shinya Kitaoka 120a6e
  TMutex secureLock;
Shinya Kitaoka 120a6e
  bool isRunning;
Shinya Kitaoka 120a6e
  TThreadGroupImp *owner;
Shinya Kitaoka 120a6e
  TThread *thread;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // some static stuff
Shinya Kitaoka 120a6e
  static TUINT32 nThreads;
Shinya Kitaoka 120a6e
  static TMutex mutex;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TThreadImp();
Shinya Kitaoka 120a6e
  ~TThreadImp();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void start();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool setThreadPriority(TThread::TThreadPriority p);
Shinya Kitaoka 120a6e
  bool setPreferredProcessor(int processorId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  static void incNThreads() {
Shinya Kitaoka 120a6e
    mutex.lock();
Shinya Kitaoka 120a6e
    nThreads++;
Shinya Kitaoka 120a6e
    mutex.unlock();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  static void decNThreads() {
Shinya Kitaoka 120a6e
    mutex.lock();
Shinya Kitaoka 120a6e
    nThreads--;
Shinya Kitaoka 120a6e
    mutex.unlock();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void setOwner(TThreadGroupImp *_owner) { owner = _owner; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TUINT32 TThreadImp::nThreads = 0;
Shinya Kitaoka 120a6e
TMutex TThreadImp::mutex     = TMutex();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TThreadImp::TThreadImp()
Shinya Kitaoka 120a6e
    : isRunning(false)
Shinya Kitaoka 120a6e
    , threadId(0)
Shinya Kitaoka 120a6e
    , owner(0)
Shinya Kitaoka 120a6e
    , mainThread(0)
Shinya Kitaoka 120a6e
    , thread(0)
Shinya Kitaoka 120a6e
    , secureLock()
Shinya Kitaoka 120a6e
    , m_refCount(0) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TThreadImp::~TThreadImp() {
Shinya Kitaoka 120a6e
  if (threadId) CloseHandle(threadId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static TUINT32 __stdcall fun(void *data) {
Shinya Kitaoka 120a6e
  TThreadImp *t = (TThreadImp *)data;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  t->secureLock.lock();
Shinya Kitaoka 120a6e
  if (t->isRunning) {
Shinya Kitaoka 120a6e
    t->secureLock.unlock();
Shinya Kitaoka 120a6e
    assert(!"thread is already running");
Shinya Kitaoka 120a6e
    return 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  t->isRunning = true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  t->secureLock.unlock();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  t->thread->run();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  t->decNThreads();
Shinya Kitaoka 120a6e
  if (t->owner) t->owner->remove(t->thread);
Shinya Kitaoka 120a6e
  t->thread->release();
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThreadImp::start() {
Shinya Kitaoka 120a6e
  TThreadImp::incNThreads();
Shinya Kitaoka 120a6e
  threadId = CreateThread(0, 0, fun, this, 0, 0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TThreadImp::setThreadPriority(TThread::TThreadPriority p) {
Shinya Kitaoka 120a6e
  int priority;
Shinya Kitaoka 120a6e
  switch (p) {
Shinya Kitaoka 120a6e
  case TThread::TIME_CRITICAL:
Shinya Kitaoka 120a6e
    priority = THREAD_PRIORITY_TIME_CRITICAL;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case TThread::HIGHEST:
Shinya Kitaoka 120a6e
    priority = THREAD_PRIORITY_HIGHEST;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case TThread::ABOVE_NORMAL:
Shinya Kitaoka 120a6e
    priority = THREAD_PRIORITY_ABOVE_NORMAL;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case TThread::NORMAL:
Shinya Kitaoka 120a6e
    priority = THREAD_PRIORITY_NORMAL;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case TThread::BELOW_NORMAL:
Shinya Kitaoka 120a6e
    priority = THREAD_PRIORITY_BELOW_NORMAL;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case TThread::LOWEST:
Shinya Kitaoka 120a6e
    priority = THREAD_PRIORITY_LOWEST;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case TThread::IDLE:
Shinya Kitaoka 120a6e
    priority = THREAD_PRIORITY_IDLE;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  default:
Shinya Kitaoka 120a6e
    priority = THREAD_PRIORITY_NORMAL;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return !!SetThreadPriority(threadId, priority);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TThreadImp::setPreferredProcessor(int processorId) {
Shinya Kitaoka 120a6e
  DWORD rc = SetThreadIdealProcessor(threadId, processorId);
Shinya Kitaoka 120a6e
  return (rc != -1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TThread::TThread() : m_imp(new TThreadImp()) { m_imp->thread = this; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TThread::~TThread() { delete m_imp; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThread::start() {
Shinya Kitaoka 120a6e
  addRef();
Shinya Kitaoka 120a6e
  m_imp->start();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThread::addRef() {
Shinya Kitaoka 120a6e
  m_imp->mutex.lock();
Shinya Kitaoka 120a6e
  m_imp->m_refCount++;
Shinya Kitaoka 120a6e
  m_imp->mutex.unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThread::release() {
Shinya Kitaoka 120a6e
  bool kill = false;
Shinya Kitaoka 120a6e
  m_imp->mutex.lock();
Shinya Kitaoka 120a6e
  m_imp->m_refCount--;
Shinya Kitaoka 120a6e
  if (m_imp->m_refCount <= 0) kill = true;
Shinya Kitaoka 120a6e
  m_imp->mutex.unlock();
Shinya Kitaoka 120a6e
  if (kill) delete this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TThread::getRefCount() { return m_imp->m_refCount; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TThread::setPreferredProcessor(int processorId) {
Shinya Kitaoka 120a6e
  return m_imp->setPreferredProcessor(processorId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TThread::setThreadPriority(TThread::TThreadPriority p) {
Shinya Kitaoka 120a6e
  return m_imp->setThreadPriority(p);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=======================
Toshihiro Shimizu 890ddd
//    TThreadGroupImp
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TThreadGroupImp::TThreadGroupImp() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TThreadGroupImp::~TThreadGroupImp() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Shinya Kitaoka 120a6e
void TThreadGroupImp::add(TThread *t) {
Shinya Kitaoka 120a6e
  threads.push_back(t);
Shinya Kitaoka 120a6e
  t->m_imp->setOwner(this);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThreadGroupImp::remove(TThread *t) {
Shinya Kitaoka 120a6e
  threads.remove(t);
Shinya Kitaoka 120a6e
  t->m_imp->setOwner(0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThreadGroupImp::wait() {
Shinya Kitaoka 120a6e
  DWORD count = threads.size();
Shinya Kitaoka 120a6e
  if (count == 0) return;
Shinya Kitaoka 120a6e
  HANDLE *hThreads = new HANDLE[count];
Shinya Kitaoka 120a6e
  int id           = 0;
Shinya Kitaoka 120a6e
  for (list<tthread *="">::iterator it = threads.begin(); it != threads.end();</tthread>
Shinya Kitaoka 120a6e
       it++, id++) {
Shinya Kitaoka 120a6e
    TThread *t = *it;
Shinya Kitaoka 120a6e
    if (t->m_imp->threadId == 0) t->start();
Shinya Kitaoka 120a6e
    hThreads[id] = t->m_imp->threadId;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  DWORD rc = WaitForMultipleObjects(count, hThreads, FALSE, INFINITE);
Shinya Kitaoka 120a6e
  if (rc >= WAIT_OBJECT_0 && rc <= (WAIT_OBJECT_0 + count - 1)) {
Shinya Kitaoka 120a6e
    // cout << "obj #" << rc << endl;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (rc >= WAIT_ABANDONED_0 && rc <= (WAIT_ABANDONED_0 + count - 1)) {
Shinya Kitaoka 120a6e
    // cout << "obj #" << rc << " abandoned" << endl;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (rc == WAIT_TIMEOUT) {
Shinya Kitaoka 120a6e
    // cout << "timeout" << endl;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (rc == WAIT_FAILED) {
Shinya Kitaoka 120a6e
    // cout << "failed" << endl;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  delete[] hThreads;
Shinya Kitaoka 120a6e
  wait();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TThreadGroup::TThreadGroup()
Shinya Kitaoka 120a6e
    : m_imp(new TThreadGroupImp())
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
{}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TThreadGroup::~TThreadGroup() { delete m_imp; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThreadGroup::add(TThread *t) { m_imp->add(t); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThreadGroup::wait() { m_imp->wait(); }