SimpleThread class for windows. See also: boost::thread and thread class in C++0x
// Copyright (C) 2009, Thiago Adams (thiago.adams@gmail.com)
// http://www.thradams.com/codeblog/simplethread.htm
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
namespace Detail
{
template<class F>
class SimpleThreadData0
{
F m_f;
public:
SimpleThreadData0(const F& f) : m_f(f) { }
void Run() { m_f(); }
};
template<class F, class A1>
class SimpleThreadData1
{
F m_f;
A1 m_a1;
public:
SimpleThreadData1(const F& f, const A1& a1) : m_f(f), m_a1(a1) { }
void Run() { m_f(m_a1); }
};
} //namespace Detail
class SimpleThread
{
HANDLE m_hThread;
template<class T>
static DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
DWORD r = 0;
T *p = reinterpret_cast<T*>(lpParameter);
try
{
p->Run();
}
catch (...)
{
r = 1;
}
delete p;
return r;
}
template<class T>
static HANDLE StartThread(T* p)
{
HANDLE hThread = CreateThread(NULL, // default security attributes
0, // use default stack size
&ThreadProc<T>, // thread function
p, // argument to thread function
0, // use default creation flags
0); // returns the thread identifier
if (hThread == 0)
{
DWORD dwError = GetLastError();
delete p;
throw std::exception("SimpleThread creation failed");
}
//release will be made in the other thread.
return hThread;
}
public:
template <class F>
SimpleThread(const F& f) : m_hThread(NULL)
{
m_hThread = StartThread(new Detail::SimpleThreadData0<F>(f));
}
template <class F, class A1>
SimpleThread(const F& f, const A1& a1) : m_hThread(NULL)
{
m_hThread = StartThread(new Detail::SimpleThreadData1<F, A1>(f, a1));
}
~SimpleThread()
{
Join();
}
void Join()
{
::WaitForSingleObject(m_hThread, INFINITE);
CloseHandle(m_hThread);
m_hThread = 0;
}
};
}}}
Sample
{{{cpp
void f(const std::string& }
{
}
int main()
{
SimpleThread thread3(&f, std::string("test"));
}
Member functions
class X
{
std::auto_ptr<SimpleThread> m_pThread;
public:
X() : m_pThread(nullptr)
{
}
void Start()
{
m_pThread.reset(new SimpleThread(std::tr1::bind(&X::ThreadProc, this)));
}
void ThreadProc()
{
cout << "hi!";
}
};
}}}
Version 2 - Requires tr1::bind avaiable in VC++ 2008
{{{cpp
// Copyright (C) 2009, Thiago Adams (thiago.adams@gmail.com)
// http://www.thradams.com/codeblog/simplethread.htm
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
class SimpleThread
{
HANDLE m_hThread;
template<class F>
struct SimpleThreadData0
{
F m_f;
SimpleThreadData0(const F& f) : m_f(f) { }
};
template<class T>
static DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
DWORD r = 0;
T *p = reinterpret_cast<T*>(lpParameter);
try
{
p->m_f();
}
catch (...)
{
r = 1;
}
delete p;
return r;
}
template <class F>
HANDLE SimpleThreadInit(const F& f)
{
std::auto_ptr<SimpleThreadData0<F> > sp(new SimpleThreadData0<F>(f));
HANDLE hThread = CreateThread(NULL, // default security attributes
0, // use default stack size
&ThreadProc<SimpleThreadData0<F> >, // thread function
sp.get(), // argument to thread function
0, // use default creation flags
0); // returns the thread identifier
if (hThread == 0)
{
DWORD dwError = GetLastError();
throw std::exception("SimpleThread creation failed");
}
sp.release();
return hThread;
}
public:
template <class F>
SimpleThread(const F& f) : m_hThread(NULL)
{
m_hThread = SimpleThreadInit(f);
}
template <class F, class A1>
SimpleThread(const F& f, const A1& a1) : m_hThread(NULL)
{
m_hThread = SimpleThreadInit(std::tr1::bind(f, a1));
}
template <class F, class A1, class A2>
SimpleThread(const F& f, const A1& a1, const A2& a2) : m_hThread(NULL)
{
m_hThread = SimpleThreadInit(std::tr1::bind(f, a1, a2));
}
~SimpleThread()
{
Join();
}
void Join()
{
::WaitForSingleObject(m_hThread, INFINITE);
CloseHandle(m_hThread);
m_hThread = 0;
}
};
Sample2
class X
{
std::auto_ptr<SimpleThread> m_pThread;
public:
X() : m_pThread(nullptr)
{
}
void Start()
{
//no need for manual bind here
m_pThread.reset(new SimpleThread(&X::ThreadProc, this, "start"));
}
void ThreadProc(const std::string& s)
{
std::cout << "hi!" << s;
}
};