Thread线程类
现在是想一步步把整个库结构弄透,有些没搞懂的细节在过程中会慢慢解决的.所以有些语犹未尽......
线程类
线程类很简单,这儿列一下:
class Thread
{
public:
Thread(bool release = true);
virtual ~Thread();
static threadfunc_t STDPREFIX StartThread(threadparam_t);
virtual void Run() = 0; //SocketThread实现了这个接口, 看下面
bool IsRunning();
void SetRunning(bool x);
bool IsReleased();
void SetRelease(bool x);
bool DeleteOnExit();
void SetDeleteOnExit(bool x = true);
bool IsDestructor();
private:
Thread(const Thread& ) {}
Thread& operator=(const Thread& ) { return *this; }
#ifdef _WIN32
HANDLE m_thread;
unsigned m_dwThreadId;
#else
pthread_t m_thread;
#endif
bool m_running; //与m_release控制是否开始Run函数,Run函数才是这儿的重点.
bool m_release; //通过设m_release为true,使循环结束,开始执行Run
bool m_b_delete_on_exit;
bool m_b_destructor;
};
SocketThread看名字就知道是Thread的子类.
先看构造函数:
SocketThread::SocketThread(Socket *p)
:Thread(false)
,m_socket(p)
{
}
必须以一个Socket类指针作为参数传给m_socket,先放放,后边会说到m_socket,而Thread(false)会引起一个线程的创建,看下面:
Thread的构造函数
Thread::Thread(bool release)
:m_thread(0)
,m_running(true)
,m_release(false)
,m_b_delete_on_exit(false)
,m_b_destructor(false)
{
m_thread = (HANDLE)_beginthreadex(NULL, 0, &StartThread, this, 0, &m_dwThreadId);
m_release = release;
}
注意这儿m_release已被赋值,而且是从SocketThread传过来的,当然,是false,这个false在下面的循环中做为一票否决的条件之一决定是否继续循环(看代码就知道了).
下一步是新线程的主代码: StartThread():
threadfunc_t STDPREFIX Thread::StartThread(threadparam_t zz)
{
Thread *p = (Thread *)zz;
while (p -> m_running && !p -> m_release)
{ //一般是通过设定m_release为真使循环结束,进行下一步Run
Sleep(1000);
}
if (p -> m_running)
{
p -> Run(); //调用SocketThread的Run(),看下面
}
p -> SetRunning(false); //呵呵,到这里就不是Running,而是Over了
if (p -> DeleteOnExit() && !p -> IsDestructor())
{
delete p;
}
_endthreadex(0);
return (threadfunc_t)NULL;
}
这儿用到上面说的m_socket了.
看Run的实现代码:
void SocketThread::Run()
{
SocketHandler h;
h.SetSlave();
h.Add(m_socket);
DEB( printf("slave: OnDetached()\n");)
m_socket -> SetSlaveHandler(&h); //指示这是从线程,不是主线程
m_socket -> SetDetached(); //是说与主线程分离(detach)?
m_socket -> OnDetached(); //回调函数
while (h.GetCount() && IsRunning())
{ //想退出也可以p -> SetRunning(false);
h.Select(0, 500000);
}
// m_socket now deleted oops
// yeah oops m_socket delete its socket thread, that means this
// so Socket will no longer delete its socket thread, instead we do this:
SetDeleteOnExit();
}
这儿又是一个Select循环调用,参考前面的Select说明可以明白,这等于是在一个新线程里开始了原始select调用,因为它会阻塞线程,所以不能放在主线程里.当有SOCKET可读写事件发生时,Select当然也会象前文说的调用定义好的
Socket::OnRead/OnWrite/OnRawData
类似的回调函数.结果就是代码共享了.所以在多线程的时候,对OnRawData之类的处理要考虑多一些才成.
现在看起来这个类在同步和安全方面做的不咋样,实际应用价值好象不大.
阅读(1558) | 评论(1) | 转发(0) |