`
aako
  • 浏览: 5351 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

libjingle:线程管理

 
阅读更多
先从ThreadManager类说起:
这是一个全局的线程管理类,在thread.cc中定义。
这个类的核心功能在于提供线程对象注册的功能。提供了一个很方便的函数CurrentThread,如下面的场景:
    // Check that we're being called from the channel (e.g., worker) thread.
    ASSERT(talk_base::ThreadManager::CurrentThread() == channel_thread_);
    channel_thread_->Clear(this);
注意,CurrentThread是在当前线程已经有Thread类关联的情况下,会返回该类,否则单纯返回NULL。
如果要自动生成新的Thread类,请使用WrapCurrentThread,详细看注释。
下面对该类的实现做详细的解析:
通常实现线程类,是通过在CreateThread中将对象指针最为线程函数的参数的方法来实现的。
而libjingle库则采用了Tls来实现,即将对象指针放入TLS分配的内存中。首先看TreadManager的初期化:
(方便期间用的是windows的代码,linux的实现机制是一样的)
    ThreadManager g_thmgr;
    DWORD ThreadManager::key_;
    ThreadManager::ThreadManager() {
      key_ = TlsAlloc();
      main_thread_ = WrapCurrentThread();
    }
作为全局变量的g_thmgr,在程序主线程中被初期化,并且主线程被“wrap”成了第一个Thread类对象,加入Manager的管理。
再来看WrapCurrentThread的实现:
...
    Thread* result = CurrentThread();
    if (NULL == result) {
        result = new Thread();
...
        SetCurrent(result);
    }
    reuturn result;
CurrentThread的实现:
    return static_cast<Thread *>(TlsGetValue(key_));
SetCurrent的实现:
    TlsSetValue(key_, thread);
熟悉TLS的机制的话应该明白,TlsAlloc返回的key(其实就是数组索引),在第一次被调用的时候返回NULL, 然后就会引发new Thread的, 并将这个指针放入key所指定的内存中。

接着到thread类了:
这个线程实现了OS无关的编程接口,实现模型基本类似java。你可以在Start中提供runnable,
bool Start(Runnable* runnable = NULL);
或是继承thread类,重写虚函数Run,这里Run简单的就是执行消息循环。
virtual void Run();
然后就是libjingle的比较特别的地方了,每一个thread都继承自类MessageQueue。
所谓消息队列,写过windows程序应该都很明白,无非就是一个队列,消息机制的分析以后再写。

关于AutoThread:
就是自动调用SetCurrent把AutoThread和当前线程关联起来。

总结下:
程序任何地方都可以通过Thread::Current() 或是ThreadManager::GetCurrent()获取当前线程的包装类,
同样通过这个包装类可以控制关联线程运行状态,和运行内容。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics