libjingle翻译之《Important Concepts(重要概念)之Threads(线程)》

来源:互联网 发布:阿尔德里奇数据 编辑:程序博客网 时间:2024/06/05 08:12

Threads(线程)

 

libjingle 考虑到使用到此库的应用程序的性能,libjingle内部支持多线程。其内组件使用12个全局线程:

signaling thread  被用作创建底层(基础)组件,

    例如:Session Management,Control,XMPP Messaging组件。

worker thread  ( 有时称作channel thread)用来集中处理p2p组件中的对象提交过来的大量资源,例如:数据流。之所以这样用另外的线程单独处理,是为了避免数据流阻塞或被XMPP/用户界面组件阻塞。使用 worker thread的类包括ChannelManage,SocketMonitor,P2PTransportChannel 和 属于Port类的对象。

若起用worker thread,使之工作,在应用中必须创建一个Thread类对象,并把此对象当作SessionManager的构造函数的参数。(如果SessionManager类对象在创建时,没有传递给它Thread对象,则SessionManager类将在内部创建一个线程,当作worker thread)CallClient::InitPhone示范了如何为底层组件(low-level components)创建一个worker thread方法。

 

另外、libjingle提供了一个基类SignalThread。扩展此类可以让一个扩展类对象存在于它自身代表的线程,此扩展类对象可以被实例化,启动,单独离开,结束时自释放。更多信息请查看signalthread.h/cc

 

注意:尽管libjingle支持多线程,但是只有几个函数通过呼叫方线程的验证来支持线程安全,并且极少函数做了线程锁定。下面的片断示范了在函数中如何安全地呼叫线程(或线程安全地被呼叫):

// Check that being called from the channel (e.g., worker) thread.

ASSERT(talk_base::Thread::Current() == channel_thread_);

channel_thread_->Clear(this);

 

libjingle中用到的所有线程,signaling threadworker thread,其它的一些线程,都是talk_base::Thread的对象(或子类的对象)。所有的Thread对象都被ThreadManager管理,当被请求时,ThreadManager会返回这些Thread对象。SessionManager被创建时通过调用ThreadManager::CurrentThread得到一个signal thread(当无worker thread 传递给SessionManager构造函数时,同时得到一个work thread)XmppPump类把当前线程当作它的signal thread来用(XmppPump uses the current thread for its signaling thread)。所以,应用程序必须为signal thread创建一个Thread 对象(或其子类对象),并在SessionManager对象创建之前或在XmppPump工作之前,把此对象放进ThreadManager的线程池里。(Signing In to a Server(登录服务器) 有示例)有两种方法创建一个Thread对象:

AutoThread    这种方式就是libjingleThread对象包装一个操作系统中的线程,并把它当作ThreadManager线程池里的当前线程(当然,Thread::CurrentThread()被调用时,此线程会被提取出来)。

Thread   这种方式将创建一个新线程并用Thread类包装,比较典型就是的创建worker thread。使此线程发生作用,应用程序必须新创建一个Thread对象,调用ThreadManager::Add()ThreadManager::SetCurrent()把它丢进线程池里,并且调用Run()使之在阻塞状态下运行或调用Start()使之处于监听状态。

 

线程为对象间或对象内部的消息沟通提供了“管道”()。例如:SocketManager可以通过其它线程向自己发送销毁一个套接字的消息,或当链接候选被产生时向SessionManager发送消息。Thread继承自MessageQueue,所以Thread的对象具有了SendPost,和一些同步或异步发送消息的函数。如果要使一个对象能够接收到MessageQueue送出的消息,那么此对象必须继承和实现MessageHandlerMessageHandler定义了一个OnMessage函数,此函数在MessageQueue送出消息时被调用,用来接收MessageQueue送出的消息。

 

你可以通过任何线程向继承自talk_base::MessageHandler的任何对象发送消息。尽管能够做到,如果你发出的消息是为了集中处理大量的数据,应用程序应该通过worker thread。调用SessionManager::worker_thread()可以得到worker thread的句柄。

调用Session::Manager::signaling_thread()可以得到 signaling thrread的句柄。

 

对象使用一个指定的线程有如下几种方式:

       对象要求一个线程指针作输入参数,并储存这个指针。

       对象在创建时取得当前线程(构造函数中调用ThreadManager::CurrentThread()取得),把取得的线程存进对象内部成员变量引用它,一般应用于获取特定的线程。(it can assume that the current thread when it is created (accessed by ThreadManager::CurrentThread in its constructor) is a particular thread and cache a member pointer to it

       对象调用SessionManger::signal_thread() SessionManager::worker_thread()获取线程。

       以上三种方法,libjingle均有用到。

 

因为一个对象可以被任意线程使用,对象可能需要验证当前调用是来自哪个线程的方法。应用可以调用Thread::Current()得到当前线程的句柄,然后与对象内部保存线程的数据成员进行比较,此数据成员的值可以是从SessionManager中暴露在外面的线程,或是对象在创建时通过构造函数传进去的初始化值。

这是一个对象通过其它线程调用自身函数时而广范使用的范例:

// Note that worker_thread_ is not initialized until someone 
// calls PseudoTcpChannel::Connect
// Also note that this method *is* thread-safe. 
bool PseudoTcpChannel::Connect(const std::string& channel_name) {
  ASSERT(signal_thread_->IsCurrent());
  CritScope lock(&cs_);
    if (channel_)
      return false;
    ASSERT(session_ != NULL);
    worker_thread_ = session_->session_manager()->worker_thread();
...
}
 
void PseudoTcpChannel::SomeFunction(){
  ...
  // Post a message to yourself over the worker thread.
  worker_thread_->Post(this, MSG_PING); // <- Goes in here....
  ...
}
 
// Handle queued requests.
void PseudoTcpChannel::OnMessage(Message *pmsg) {
  if (pmsg->message_id == MSG_SORT)
    OnSort();
  else if (pmsg->message_id == MSG_PING) // -> And comes out here!
    // Check that we're in the worker thread before proceding.
    ASSERT(worker_thread_->IsCurrent());
    OnPing();
  else if (pmsg->message_id == MSG_ALLOCATE)
    OnAllocate();
  else
    assert(false);
}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 别人的百度网盘链接打不开怎么办 百度网盘视频插件升级失败怎么办 退苹果id重新登陆照片没了怎么办 苹果升级后照片效果没了怎么办 360云盘个人云盘停止服务怎么办 小米手机账号掉了手机卡没了怎么办 百度网盘下载后不能注册怎么办 微信发出的文件无法撤回怎么办 微信群发错消息无法撤回怎么办 百度网盘登录要验证码怎么办 百度网盘备份记录怎么办能删掉 手机酷狗听歌耳机声音太小了怎么办 苹果6s微信通话声音变粗怎么办 千千静听多个列表合成一个了怎么办 别人用手机号注册了邮箱怎么办 微信身份信息验证未通过怎么办 快递地址填错了已经发到了怎么办 孩子威胁同学给她买东西吃怎么办 在超市买小孩米粉过期了怎么办 出口货物被海关扣了说仿牌怎么办 有一批仿牌被宁波海关查了怎么办 付了定金不想要车了怎么办 泥墙刮石灰上涂料现在刮腻子怎么办 月经最后一天同房了怎么办吃什么药 奶水太多了宝宝总是呛到了怎么办 婴儿刚吃完奶大量喷奶怎么办 我干活细致领导说我慢怎么办 怀孕初期吃了加明矾的粉皮怎么办 绿豆面黄豆面白面蒸馒头怎么办 画油画时把颜料染在衣服上怎么办 买的布衣柜少了一个管子怎么办 小2球刚好进2球怎么办 大2球刚好进2球怎么办 大球2进了2球怎么办 身上剩的几百块钱有掉了怎么办 刚买一天的手机电板有问题怎么办 宝宝长湿疹穿少了就感冒怎么办 照片跟视频被孩子删了怎么办 老公总是说一些不开心的话题怎么办 孩子沉迷手机篮球课不爱去怎么办 坐久了屁鼓会长疮怎么办