当前位置: 首页 > 工具软件 > Libjingle > 使用案例 >

Google开源框架libjingle使用分析

龙浩博
2023-12-01

线程模型简介

传统的回调机制,可控性差、容易导致死锁等问题。本模块采用异步任务机制,通过command模式,可以很好的进行多线程的协作,避免使用共享变量、加锁,有效的防止死锁与其他多线程安全问题。

实现上使用了 libjingle 库。(注:原来使用了 chrome base 的线程库,两者实现原理一致,但 libjingle 使用上方便一些。)

把要异步执行的任务信息封装在 Message 数据结构中,Post 或 PostDelay 到相应的线程去执行。在该线程执行完之后,如果需要通知发起线程,则再 Post 回原来的线程。每个线程都有自己的消息队列,线程不停地从队列中取出 Message 执行相应的任务。

 

多线程之间数据共享:

thread_A (data_A),thread_B(data_B)

从thread_A转到thread_B,在thread_A中调用:

thread_B->post(handler,msg_id,new data_B(data_A,len))

根据data_A,拷贝一份数据data_B,任务执行完毕后,释放拷贝数据data_B

注意:为了简要说明,下方代码省去了线程内部message_queue的锁操作(线程安全)。

 

线程模型:

class MessageHandler {

public:
	virtual ~MessageHandler();
	virtual void OnMessage(Message* msg) = 0;

protected:
	MessageHandler() {}

private:
	DISALLOW_COPY_AND_ASSIGN(MessageHandler);

};
class MessageData {

public:
	MessageData() {}
	virtual ~MessageData() {}

};
struct Message {

	MessageHandler *phandler;

	uint32 message_id;

	MessageData *pdata;

	uint32 ts_sensitive;

};
typedef std::list<Message> MessageList;
class MessageQueue {

	virtual bool Get(Message *pmsg, int cmsWait = kForever,
		bool process_io = true) {
			*pmsg = msgq_.front();
			msgq_.pop_front();

	}

	virtual void Post(MessageHandler *phandler, uint32 id = 0,
		MessageData *pdata = NULL, bool time_sensitive = false) {

			Message msg;
			msg.phandler = phandler;
			msg.message_id = id;
			msg.pdata = pdata;
			msgq_.push_back(msg);
	}

	virtual void Dispatch(Message *pmsg) {
		pmsg->phandler->OnMessage(pmsg);
	}

protected:
	MessageList msgq_;

}
class Thread : public MessageQueue {

public:
	bool Start(Runnable* runnable = NULL) {
		// 在各个平台上分别,通过调用底层API来创建线程,PreRun是线程函数执行体
    #if defined(WIN32)
        thread_ = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PreRun, init, flags,
                         &thread_id_);
    #elif defined(POSIX)
        pthread_create(&thread_, &attr, PreRun, init);
  
        return true;
	}

	void Run() {
		ProcessMessages(kForever);
	}

	bool ProcessMessages(int cms) {
		Message msg;
		if (!Get(&msg, cmsNext))
			return !IsQuitting();
		Dispatch(&msg);
	}

private:
	static void *PreRun(void *pv) {
		Run();
	}

#ifdef POSIX
	pthread_t thread_;
#endif

#ifdef WIN32
	HANDLE thread_;
	DWORD thread_id_;
#endif

};

 

 类似资料: