1. 程式人生 > >Google開源框架libjingle使用分析

Google開源框架libjingle使用分析

執行緒模型簡介

傳統的回撥機制,可控性差、容易導致死鎖等問題。本模組採用非同步任務機制,通過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

執行緒模型:

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) {
		PreRun();
	}

	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

};