Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tthread.h"
Toshihiro Shimizu 890ddd
#include "tthreadP.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "boost/thread/thread.hpp"
Toshihiro Shimizu 890ddd
#include "boost/thread/condition.hpp"
Toshihiro Shimizu 890ddd
#include "boost/thread/tss.hpp"
Toshihiro Shimizu 890ddd
#include "boost/thread/xtime.hpp"
Toshihiro Shimizu 890ddd
#include <queue></queue>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef WIN32
Toshihiro Shimizu 890ddd
#include <windows.h></windows.h>
Toshihiro Shimizu 890ddd
#define WM_THREAD_NOTIFICATION (WM_USER + 10)
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DEFINE_CLASS_CODE(TThread::Runnable, 21)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
#ifdef WIN32
Toshihiro Shimizu 890ddd
HWND MainHandle;
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
Display *TheDisplay;
Toshihiro Shimizu 890ddd
Window TheMainWindow;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class Thread {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  Thread();
Shinya Kitaoka 120a6e
  Thread(const TThread::RunnableP &runnable);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ~Thread();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void join();
Shinya Kitaoka 120a6e
  void cancel();
Toshihiro Shimizu 890ddd
e280ae
#if defined(_MSC_VER) && (_MSC_VER == 1200)
Toshihiro Shimizu 890ddd
#pragma warning(disable : 4290)
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  static void milestone() throw(TThread::Interrupt);
Toshihiro Shimizu 890ddd
e280ae
#if defined(_MSC_VER) && (_MSC_VER == 1200)
Toshihiro Shimizu 890ddd
#pragma warning(default : 4290)
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  class Imp;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  friend class ThreadGroup;
Shinya Kitaoka 120a6e
  Imp *m_imp;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class ThreadGroup {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  ThreadGroup();
Shinya Kitaoka 120a6e
  ~ThreadGroup();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void add(Thread *thread);
Shinya Kitaoka 120a6e
  void joinAll();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  class Imp;
Shinya Kitaoka 120a6e
  Imp *m_imp;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
class QueueT {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  QueueT(int slotCount)
Shinya Kitaoka 120a6e
      : m_items()
Shinya Kitaoka 120a6e
      , m_slotCount(slotCount)
Shinya Kitaoka 120a6e
      , m_notEmpty()
Shinya Kitaoka 120a6e
      , m_notFull()
Shinya Kitaoka 120a6e
      , m_mutex() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~QueueT() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void put(const T &item) {
Shinya Kitaoka 120a6e
    TThread::ScopedLock sl(m_mutex);
Shinya Kitaoka 120a6e
    while (m_items.size() == m_slotCount) m_notFull.wait(sl);
Shinya Kitaoka 120a6e
    m_items.push(item);
Shinya Kitaoka 120a6e
    m_notEmpty.notify_one();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  T get() {
Shinya Kitaoka 120a6e
    TThread::ScopedLock sl(m_mutex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    while (m_items.size() == 0) m_notEmpty.wait(sl);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_notFull.notify_one();
Shinya Kitaoka 120a6e
    T item = m_items.front();
Shinya Kitaoka 120a6e
    m_items.pop();
Shinya Kitaoka 120a6e
    return item;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int size() {
Shinya Kitaoka 120a6e
    TThread::ScopedLock sl(m_mutex);
Shinya Kitaoka 120a6e
    int size = m_items.size();
Shinya Kitaoka 120a6e
    return size;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  std::queue<t> m_items;</t>
Shinya Kitaoka 120a6e
  TThread::Condition m_notEmpty;
Shinya Kitaoka 120a6e
  TThread::Condition m_notFull;
Shinya Kitaoka 120a6e
  TThread::Mutex m_mutex;
Shinya Kitaoka 120a6e
  int m_slotCount;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // anonymous namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThread::setMainThreadId(TThread::ThreadInfo *info) {
Shinya Kitaoka 120a6e
  assert(info);
Toshihiro Shimizu 890ddd
#ifdef WIN32
Shinya Kitaoka 120a6e
  MainHandle = info->mainHandle;
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
  TheDisplay    = info->dpy;
Shinya Kitaoka 120a6e
  TheMainWindow = info->win;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef WIN32
Shinya Kitaoka 120a6e
ULONG TThread::getMainShellHandle() { return ULONG(MainHandle); }
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class BoostRunnable {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  BoostRunnable(const TThread::RunnableP &runnable, Thread::Imp *threadImp)
Shinya Kitaoka 120a6e
      : m_runnable(runnable), m_threadImp(threadImp) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void operator()();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TThread::RunnableP m_runnable;
Shinya Kitaoka 120a6e
  Thread::Imp *m_threadImp;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class Thread::Imp {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  Imp() : m_boostThread(0), m_isCanceled(false), m_stateMutex() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Imp(const TThread::RunnableP &runnable)
Shinya Kitaoka 120a6e
      : m_isCanceled(false), m_stateMutex() {
Shinya Kitaoka 120a6e
    m_boostThread = new boost::thread(BoostRunnable(runnable, this));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~Imp() {
Shinya Kitaoka 120a6e
    if (m_boostThread) delete m_boostThread;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  boost::thread *m_boostThread;
Shinya Kitaoka 120a6e
  boost::mutex m_stateMutex;
Shinya Kitaoka 120a6e
  bool m_isCanceled;
Shinya Kitaoka 120a6e
  long m_kkkk;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  enum State { Running, Canceled };
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  static boost::mutex m_mutex;
Shinya Kitaoka 120a6e
  static std::map<long, state=""> m_state;</long,>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  class Key {
Shinya Kitaoka 120a6e
  public:
Shinya Kitaoka 120a6e
    Key(long id) : m_id(id) {}
Shinya Kitaoka 120a6e
    long m_id;
Shinya Kitaoka 120a6e
  };
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  static boost::thread_specific_ptr<key> m_key;</key>
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
boost::mutex Thread::Imp::m_mutex;
Toshihiro Shimizu 890ddd
std::map<long, thread::imp::state=""> Thread::Imp::m_state;</long,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
boost::thread_specific_ptr<thread::imp::key> Thread::Imp::m_key;</thread::imp::key>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void BoostRunnable::operator()() {
Shinya Kitaoka 120a6e
  Thread::Imp::m_key.reset(new Thread::Imp::Key(reinterpret_cast<long>(this)));</long>
Shinya Kitaoka 120a6e
  m_threadImp->m_kkkk = reinterpret_cast<long>(this);</long>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    boost::mutex::scoped_lock sl(Thread::Imp::m_mutex);
Shinya Kitaoka 120a6e
    Thread::Imp::m_state[m_threadImp->m_kkkk] = Thread::Imp::Running;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(m_runnable);
Shinya Kitaoka 120a6e
  m_runnable->run();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    boost::mutex::scoped_lock sl(Thread::Imp::m_mutex);
Shinya Kitaoka 120a6e
    Thread::Imp::m_state.erase(reinterpret_cast<long>(this));</long>
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Thread::Thread() : m_imp(new Thread::Imp) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Thread::Thread(const TThread::RunnableP &runnable) : m_imp(new Imp(runnable)) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Thread::~Thread() { delete m_imp; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Thread::join() {
Shinya Kitaoka 120a6e
  assert(m_imp->m_boostThread);
Shinya Kitaoka 120a6e
  m_imp->m_boostThread->join();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Thread::cancel() {
Shinya Kitaoka 120a6e
  boost::mutex::scoped_lock sl(Thread::Imp::m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::map<long, thread::imp::state="">::iterator it =</long,>
Shinya Kitaoka 120a6e
      Thread::Imp::m_state.find(m_imp->m_kkkk);
Shinya Kitaoka 120a6e
  if (it != Thread::Imp::m_state.end())
Shinya Kitaoka 120a6e
    Thread::Imp::m_state[m_imp->m_kkkk] = Thread::Imp::Canceled;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
// static member function
e280ae
#if defined(_MSC_VER) && (_MSC_VER == 1200)
Toshihiro Shimizu 890ddd
#pragma warning(disable : 4290)
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Thread::milestone() throw(TThread::Interrupt) {
Shinya Kitaoka 120a6e
  boost::mutex::scoped_lock sl(Thread::Imp::m_mutex);
Shinya Kitaoka 120a6e
  Thread::Imp::Key key = *Thread::Imp::m_key.get();
Shinya Kitaoka 120a6e
  Thread::Imp::m_state.find(key.m_id);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (Thread::Imp::m_state[key.m_id]) throw TThread::Interrupt();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
e280ae
#if defined(_MSC_VER) && (_MSC_VER == 1200)
Toshihiro Shimizu 890ddd
#pragma warning(default : 4290)
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class ThreadGroup::Imp {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  Imp() : m_boostThreadGroup() {}
Shinya Kitaoka 120a6e
  ~Imp() {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  boost::thread_group m_boostThreadGroup;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
ThreadGroup::ThreadGroup() : m_imp(new Imp) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
ThreadGroup::~ThreadGroup() { delete m_imp; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ThreadGroup::add(Thread *thread) {
Shinya Kitaoka 120a6e
  m_imp->m_boostThreadGroup.add_thread(thread->m_imp->m_boostThread);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ThreadGroup::joinAll() { m_imp->m_boostThreadGroup.join_all(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
e280ae
#if defined(_MSC_VER) && (_MSC_VER == 1200)
Toshihiro Shimizu 890ddd
#pragma warning(disable : 4290)
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThread::milestone() throw(TThread::Interrupt) { Thread::milestone(); }
Toshihiro Shimizu 890ddd
e280ae
#if defined(_MSC_VER) && (_MSC_VER == 1200)
Toshihiro Shimizu 890ddd
#pragma warning(default : 4290)
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TThread::Mutex::Imp {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  boost::mutex m_mutex;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Imp() : m_mutex() {}
Shinya Kitaoka 120a6e
  ~Imp() {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TThread::Mutex::Mutex() : m_imp(new Imp) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TThread::Mutex::~Mutex() { delete m_imp; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TThread::ScopedLock::Imp {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  boost::mutex::scoped_lock *m_sl;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Imp(boost::mutex &mutex) : m_sl(new boost::mutex::scoped_lock(mutex)) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ~Imp() {
Shinya Kitaoka 120a6e
    m_sl->unlock();
Shinya Kitaoka 120a6e
    delete m_sl;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TThread::ScopedLock::ScopedLock(Mutex &mutex)
Shinya Kitaoka 120a6e
    : m_imp(new Imp(mutex.m_imp->m_mutex)) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TThread::ScopedLock::~ScopedLock() { delete m_imp; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TThread::Condition::Imp {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  boost::condition m_condition;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Imp() : m_condition() {}
Shinya Kitaoka 120a6e
  ~Imp() {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TThread::Condition::Condition() : m_imp(new Imp()) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TThread::Condition::~Condition() { delete m_imp; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThread::Condition::wait(ScopedLock &lock) {
Shinya Kitaoka 120a6e
  m_imp->m_condition.wait(*(lock.m_imp->m_sl));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TThread::Condition::wait(ScopedLock &lock, long timeout) {
Shinya Kitaoka 120a6e
  boost::xtime xt;
Shinya Kitaoka 120a6e
  boost::xtime_get(&xt, boost::TIME_UTC);
Shinya Kitaoka 120a6e
  xt.nsec += timeout * 1000;
Shinya Kitaoka 120a6e
  xt.sec += timeout / 1000;
Shinya Kitaoka 120a6e
  return m_imp->m_condition.timed_wait(*(lock.m_imp->m_sl), xt);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThread::Condition::notifyOne() { m_imp->m_condition.notify_one(); }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThread::Condition::notifyAll() { m_imp->m_condition.notify_all(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TThread::Msg::Msg() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThread::Msg::send() {
Shinya Kitaoka 120a6e
  Msg *msg = clone();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef WIN32
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
Non viene utilizzato PostThreadMessage perche' se l'applicazione
Shinya Kitaoka 120a6e
si trova in un modal loop (esempio MessageBox) oppure si sta
Toshihiro Shimizu 890ddd
facendo move o resize di una finestra i messaggi non giungono al
Toshihiro Shimizu 890ddd
message loop.
Shinya Kitaoka 120a6e
http://support.microsoft.com/default.aspx?scid=KB;EN-US;q183116&
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
BOOL rc = PostThreadMessage(
Shinya Kitaoka 120a6e
getMainThreadId(),      // thread identifier
Shinya Kitaoka 120a6e
WM_THREAD_NOTIFICATION, // message
Shinya Kitaoka 120a6e
WPARAM(msg),            // first message parameter
Shinya Kitaoka 120a6e
0);                     // second message parameter
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
  PostMessage(HWND(getMainShellHandle()), WM_THREAD_NOTIFICATION, WPARAM(msg),
Shinya Kitaoka 120a6e
              0);
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
  XClientMessageEvent clientMsg;
Shinya Kitaoka 120a6e
  clientMsg.type         = ClientMessage;
Shinya Kitaoka 120a6e
  clientMsg.window       = TheMainWindow;
Shinya Kitaoka 120a6e
  clientMsg.format       = 32;
Shinya Kitaoka 120a6e
  clientMsg.message_type = Msg::MsgId();
Shinya Kitaoka 120a6e
  clientMsg.data.l[0]    = (long)msg;
Shinya Kitaoka 120a6e
  // Status status =
Shinya Kitaoka 120a6e
  XSendEvent(TheDisplay, TheMainWindow, 0, NoEventMask, (XEvent *)&clientMsg);
Shinya Kitaoka 120a6e
  XFlush(TheDisplay);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// statica
Shinya Kitaoka 120a6e
UINT TThread::Msg::MsgId() {
Toshihiro Shimizu 890ddd
#ifdef WIN32
Shinya Kitaoka 120a6e
  return WM_THREAD_NOTIFICATION;
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
  static Atom atom = 0;
Shinya Kitaoka 120a6e
  if (!atom) {
Shinya Kitaoka 120a6e
    atom = XInternAtom(TheDisplay, "ThreadMessage", false);
Shinya Kitaoka 120a6e
    assert(atom);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return atom;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TThread::Executor::Imp : public TSmartObject {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  typedef TSmartPointerT<tthread::executor::imp> ImpP;</tthread::executor::imp>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //---------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  class Worker : public Runnable {
Shinya Kitaoka 120a6e
  public:
Shinya Kitaoka 120a6e
    Worker(ImpP owner) : Runnable(), m_owner(owner) {}
Shinya Kitaoka 120a6e
    ~Worker() {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    void run();
Shinya Kitaoka 120a6e
    void doCleanup();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    ImpP m_owner;
Shinya Kitaoka 120a6e
  };
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //---------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool m_suspend;
Shinya Kitaoka 120a6e
  bool m_threadHasToDie;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  UINT m_threadCount;
Shinya Kitaoka 120a6e
  Mutex m_mutex;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Condition m_cond;
Shinya Kitaoka 120a6e
  Condition m_taskQueueEmpty;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //------
Shinya Kitaoka 120a6e
  Condition m_taskQueueNotEmpty;
Shinya Kitaoka 120a6e
  //------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::queue<tthread::runnablep> m_tasks;</tthread::runnablep>
Shinya Kitaoka 120a6e
  std::map<long, *="" thread=""> m_workerThreads;</long,>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Imp(int threadsCount, bool suspend)
Shinya Kitaoka 120a6e
      : TSmartObject()
Shinya Kitaoka 120a6e
      , m_suspend(suspend)
Shinya Kitaoka 120a6e
      , m_threadHasToDie(false)
Shinya Kitaoka 120a6e
      , m_threadCount(threadsCount)
Shinya Kitaoka 120a6e
      , m_tasks()
Shinya Kitaoka 120a6e
      , m_workerThreads()
Shinya Kitaoka 120a6e
      , m_mutex()
Shinya Kitaoka 120a6e
      , m_cond(){};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ~Imp() {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TThread::Executor::Executor(int threadsCount, bool suspend)
Shinya Kitaoka 120a6e
    : m_imp(new Imp(threadsCount, suspend)) {
Shinya Kitaoka 120a6e
  m_imp->addRef();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TThread::Executor::~Executor() {
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    TThread::ScopedLock sl(m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (m_imp->m_suspend) {
Shinya Kitaoka 120a6e
      m_imp->m_threadHasToDie = true;
Shinya Kitaoka 120a6e
      m_imp->m_taskQueueNotEmpty.notifyAll();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->release();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThread::Executor::Imp::Worker::run() {
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    while (true) {
Shinya Kitaoka 120a6e
      // check if thread has been canceled
Shinya Kitaoka 120a6e
      Thread::milestone();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // get the next task
Shinya Kitaoka 120a6e
      RunnableP task = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
        ScopedLock sl(m_owner->m_mutex);
Shinya Kitaoka 120a6e
        if (m_owner->m_tasks.empty()) {
Shinya Kitaoka 120a6e
          // la lista di task e' stata esaurita
Shinya Kitaoka 120a6e
          if (m_owner->m_suspend) {
Shinya Kitaoka 120a6e
            // il thread deve sospendersi
Shinya Kitaoka 120a6e
            m_owner->m_taskQueueNotEmpty.wait(sl);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
            // a questo punto il thread e' stato risvegliato
Shinya Kitaoka 120a6e
            if (m_owner->m_threadHasToDie) {
Shinya Kitaoka 120a6e
              doCleanup();
Shinya Kitaoka 120a6e
              return;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
          } else {
Shinya Kitaoka 120a6e
            // il thread sta per morire -> bisogna eliminarlo dalla lista dei
Shinya Kitaoka 120a6e
            // worker thread
Shinya Kitaoka 120a6e
            doCleanup();
Shinya Kitaoka 120a6e
            return;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (!m_owner->m_tasks.empty()) {
Shinya Kitaoka 120a6e
          task = m_owner->m_tasks.front();
Shinya Kitaoka 120a6e
          m_owner->m_tasks.pop();
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (task) task->run();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // check if thread has been canceled
Shinya Kitaoka 120a6e
      Thread::milestone();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } catch (TThread::Interrupt &) {
Shinya Kitaoka 120a6e
    // m_owner->m_cond.notifyOne();
Shinya Kitaoka 120a6e
  } catch (...) {
Shinya Kitaoka 120a6e
    // eccezione non prevista --> bisogna eliminare il thread
Shinya Kitaoka 120a6e
    // dalla lista dei worker thread
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ScopedLock sl(m_owner->m_mutex);
Shinya Kitaoka 120a6e
    doCleanup();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThread::Executor::Imp::Worker::doCleanup() {
Shinya Kitaoka 120a6e
  std::map<long, *="" thread="">::iterator it =</long,>
Shinya Kitaoka 120a6e
      m_owner->m_workerThreads.find(reinterpret_cast<long>(this));</long>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (it != m_owner->m_workerThreads.end()) {
Shinya Kitaoka 120a6e
    Thread *thread = it->second;
Shinya Kitaoka 120a6e
    delete thread;
Shinya Kitaoka 120a6e
    m_owner->m_workerThreads.erase(it);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_owner->m_workerThreads.size() == 0)
Shinya Kitaoka 120a6e
    m_owner->m_taskQueueEmpty.notifyAll();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThread::Executor::addTask(const RunnableP &task) {
Shinya Kitaoka 120a6e
  TThread::ScopedLock sl(m_imp->m_mutex);
Shinya Kitaoka 120a6e
  m_imp->m_tasks.push(task);
Shinya Kitaoka 120a6e
  if (m_imp->m_workerThreads.size() < m_imp->m_threadCount) {
Shinya Kitaoka 120a6e
    TThread::Executor::Imp::Worker *worker =
Shinya Kitaoka 120a6e
        new TThread::Executor::Imp::Worker(m_imp);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_imp->m_workerThreads[reinterpret_cast<long>(worker)] = new Thread(worker);</long>
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    if (m_imp->m_suspend)
Shinya Kitaoka 120a6e
      // risveglia uno dei thread in attesa
Shinya Kitaoka 120a6e
      m_imp->m_taskQueueNotEmpty.notifyOne();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThread::Executor::clear() {
Shinya Kitaoka 120a6e
  ScopedLock sl(m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  while (!m_imp->m_tasks.empty()) m_imp->m_tasks.pop();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThread::Executor::cancel() {
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    ScopedLock sl(m_imp->m_mutex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    while (!m_imp->m_tasks.empty()) m_imp->m_tasks.pop();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  while (true) {
Shinya Kitaoka 120a6e
    Thread *thread = 0;
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      ScopedLock sl(m_imp->m_mutex);
Shinya Kitaoka 120a6e
      if (m_imp->m_workerThreads.empty())
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        std::map<long, *="" thread="">::iterator it = m_imp->m_workerThreads.begin();</long,>
Shinya Kitaoka 120a6e
        thread = it->second;
Shinya Kitaoka 120a6e
        m_imp->m_workerThreads.erase(it);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (thread) thread->cancel();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TThread::Executor::wait() {
Shinya Kitaoka 120a6e
  TThread::ScopedLock sl(m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  while (m_imp->m_workerThreads.size()) m_imp->m_taskQueueEmpty.wait(sl);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TThread::Executor::wait(long timeout) {
Shinya Kitaoka 120a6e
  TThread::ScopedLock sl(m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool expired = false;
Shinya Kitaoka 120a6e
  while (m_imp->m_workerThreads.size())
Shinya Kitaoka 120a6e
    expired = m_imp->m_taskQueueEmpty.wait(sl, timeout);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return expired;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TThread::Executor::getThreadCount() {
Shinya Kitaoka 120a6e
  TThread::ScopedLock sl(m_imp->m_mutex);
Shinya Kitaoka 120a6e
  return m_imp->m_workerThreads.size();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TThread::Executor::getTaskCount() {
Shinya Kitaoka 120a6e
  TThread::ScopedLock sl(m_imp->m_mutex);
Shinya Kitaoka 120a6e
  return m_imp->m_tasks.size();
Toshihiro Shimizu 890ddd
}