Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1029329
  • 博文数量: 177
  • 博客积分: 3629
  • 博客等级: 中校
  • 技术积分: 1839
  • 用 户 组: 普通用户
  • 注册时间: 2005-02-23 21:21
文章分类

全部博文(177)

文章存档

2021年(1)

2020年(5)

2019年(4)

2018年(7)

2017年(1)

2016年(4)

2014年(1)

2013年(8)

2012年(10)

2011年(50)

2009年(12)

2008年(10)

2006年(56)

2005年(8)

分类: C/C++

2006-04-09 13:31:38


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) |
0

上一篇:Socket库分析之四

下一篇:Socket库尝试之六

给主人留下些什么吧!~~