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