在webrtc 任务中有3种不同的异步处理方式,用于解决不同的问题,如下
1)taskqueue 每个队列上有一个线程执行,线程不需要指定
2)asyncTask 在指定的线程上执行,需要指定线程
3)SynchronousMethodCall 在指定线程执行完成后,同步等待结果(跨线程同步调用)
TaskQueue :是TaskQueueBase 的代理封装,是依赖注入的方法实现。
TaskQueueBase : 抽象接口
TaskQueueWin:
1、创建一个线程,并启动,每个任务队列有一个线程
2、在线程不断的读取task, 并执行
3、可以支持延迟任务
// 创建线程
TaskQueueWin::TaskQueueWin(absl::string_view queue_name,
rtc::ThreadPriority priority)
: thread_(&TaskQueueWin::ThreadMain, this, queue_name, priority),
in_queue_(::CreateEvent(nullptr, true, false, nullptr)) {
RTC_DCHECK(in_queue_);
thread_.Start();
//启动线程
rtc::Event event(false, false);
RTC_CHECK(thread_.QueueAPC(&InitializeQueueThread,
reinterpret_cast<ULONG_PTR>(&event)));
//等待线程初始化完成
event.Wait(rtc::Event::kForever);
}
//线程主循环
void TaskQueueWin::RunThreadMain() {
CurrentTaskQueueSetter set_current(this);
HANDLE handles[2] = {*timer_.event_for_wait(), in_queue_};
while (true) {
// Make sure we do an alertable wait as that's required to allow APCs to run
// (e.g. required for InitializeQueueThread and stopping the thread in
// PlatformThread).
DWORD result = ::MsgWaitForMultipleObjectsEx(
arraysize(handles), handles, INFINITE, QS_ALLEVENTS, MWMO_ALERTABLE);
RTC_CHECK_NE(WAIT_FAILED, result);
if (result == (WAIT_OBJECT_0 + 2)) {
// There are messages in the message queue that need to be handled.
// PeekMessage
if (!ProcessQueuedMessages())
break;
}
if (result == WAIT_OBJECT_0 ||
(!timer_tasks_.empty() &&
::WaitForSingleObject(*timer_.event_for_wait(), 0) == WAIT_OBJECT_0)) {
// The multimedia timer was signaled.
timer_.Cancel();
RunDueTasks();//延迟
ScheduleNextTimer();
}
//
if (result == (WAIT_OBJECT_0 + 1)) {
::ResetEvent(in_queue_);
RunPendingTasks(); //异步任务
}
}
}
异步调用,实现就是调用了thread->Post 方法
1、使用的时候可以在指定线程运行
if (!network_thread_) {
owned_network_thread_ = rtc::Thread::CreateWithSocketServer();
owned_network_thread_->SetName("pc_network_thread", nullptr);
owned_network_thread_->Start();
network_thread_ = owned_network_thread_.get();
}
// 异步调用,在network_thread_ 上执行
invoker_.AsyncInvoke<void>(RTC_FROM_HERE, network_thread_, [this, channel_id, frame] {
other_->OnData(channel_id, frame);
});
2、异步执行的实现
1、利用继承,AsyncClosure模板类进行类型擦除,保存FunctorT
2、调用 thread->Post
// 异步调用的实现
template <class ReturnT, class FunctorT>
void AsyncInvoke(const Location& posted_from,
Thread* thread,
FunctorT&& functor,
uint32_t id = 0) {
//类型擦除,保存function
std::unique_ptr<AsyncClosure> closure(
new FireAndForgetAsyncClosure<FunctorT>(
this, std::forward<FunctorT>(functor)));
DoInvoke(posted_from, thread, std::move(closure), id);
}
void AsyncInvoker::DoInvoke(const Location& posted_from,
Thread* thread,
std::unique_ptr<AsyncClosure> closure,
uint32_t id) {
if (destroying_.load(std::memory_order_relaxed)) {
// Note that this may be expected, if the application is AsyncInvoking
// tasks that AsyncInvoke other tasks. But otherwise it indicates a race
// between a thread destroying the AsyncInvoker and a thread still trying
// to use it.
RTC_LOG(LS_WARNING) << "Tried to invoke while destroying the invoker.";
return;
}
thread->Post(posted_from, this, id,
new ScopedMessageData<AsyncClosure>(std::move(closure)));
}
3、调用线程Post 方法(继承与MessageQueue)
1、存储msg 在队列中
2、msqqueue 利用SocketServer 做的同步
void MessageQueue::Post(const Location& posted_from,
MessageHandler* phandler,
uint32_t id,
MessageData* pdata,
bool time_sensitive) {
if (IsQuitting()) {
delete pdata;
return;
}
// Keep thread safe
// Add the message to the end of the queue
// Signal for the multiplexer to return
{
CritScope cs(&crit_);
Message msg;
msg.posted_from = posted_from;
msg.phandler = phandler;
msg.message_id = id;
msg.pdata = pdata;
if (time_sensitive) {
msg.ts_sensitive = TimeMillis() + kMaxMsgLatency;
}
msgq_.push_back(msg);
}
WakeUpSocketServer();
}
4、thread 的处理函数
1、thread 启动后,bool Thread::ProcessMessages(int cmsLoop)
2、获取消息队列的信息
bool Thread::ProcessMessages(int cmsLoop) {
while (true) {
#if defined(WEBRTC_MAC)
ScopedAutoReleasePool pool;
#endif
Message msg;
if (!Get(&msg, cmsNext)) // 同步获取消息
return !IsQuitting();
Dispatch(&msg);
if (cmsLoop != kForever) {
cmsNext = static_cast<int>(TimeUntil(msEnd));
if (cmsNext < 0)
return true;
}
}
}
// 分发消息
void MessageQueue::Dispatch(Message* pmsg) {
TRACE_EVENT2("webrtc", "MessageQueue::Dispatch", "src_file_and_line",
pmsg->posted_from.file_and_line(), "src_func",
pmsg->posted_from.function_name());
int64_t start_time = TimeMillis();
pmsg->phandler->OnMessage(pmsg); //符号
int64_t end_time = TimeMillis();
int64_t diff = TimeDiff(end_time, start_time);
if (diff >= kSlowDispatchLoggingThreshold) {
RTC_LOG(LS_INFO) << "Message took " << diff
<< "ms to dispatch. Posted from: "
<< pmsg->posted_from.ToString();
}
}
非常简单,封装了线程,然后利用信号等待执行完成
SynchronousMethodCall::SynchronousMethodCall(rtc::MessageHandler* proxy)
: proxy_(proxy) {}
SynchronousMethodCall::~SynchronousMethodCall() = default;
void SynchronousMethodCall::Invoke(const rtc::Location& posted_from,
rtc::Thread* t) {
if (t->IsCurrent()) {
proxy_->OnMessage(nullptr);
} else {
t->Post(posted_from, this, 0);
e_.Wait(rtc::Event::kForever); //等执行结果
}
}
void SynchronousMethodCall::OnMessage(rtc::Message*) {
proxy_->OnMessage(nullptr);
e_.Set(); //执行完成,发送信号
}
提供了helper 类MethodCall*
调用示例
MethodCall0<PeerConnectionFactory, bool> call(
pc_factory.get(), &PeerConnectionFactory::Initialize);
bool result = call.Marshal(RTC_FROM_HERE, pc_factory->signaling_thread());
MethodCall* 主要的功能
1、利用模板类,构造函数封装了执行函数
2、调用 SynchronousMethodCall::Invoke
3、线程执行OnMessage,执行{ r_.Invoke(c_, m_); } 结果保存在r_中
4、在执行线程执行完成后,返回结果r_.moved_result();
template <typename C, typename R>
class MethodCall0 : public rtc::Message, public rtc::MessageHandler {
public:
typedef R (C::*Method)();
MethodCall0(C* c, Method m) : c_(c), m_(m) {}
R Marshal(const rtc::Location& posted_from, rtc::Thread* t) {
internal::SynchronousMethodCall(this).Invoke(posted_from, t);
return r_.moved_result();
}
private:
void OnMessage(rtc::Message*) { r_.Invoke(c_, m_); }
C* c_;
Method m_;
ReturnType<R> r_;
};