在创建AndroidShellHolder的过程中,会通过ThreadHost创建UI、GPU、IO线程,这些线程属于fml:thread
//./fml/thred.h
class Thread{
private:
std::unique_ptr<std::thread> thread_;
fml::RefPtr<fml::TaskRunner> task_runner_;
}
来看一个线程是如何创建的
//thread_host.cc
ui_thread = std::make_unique<fml::Thread>(name_prefix + ".ui);
现在回到./fml/thread.cc
Thread::Thread(cost std::string& name) : joined_(false){
fml::AutoResetWaitableEvent latch;
fml::RefPtr<fml::TaskRunner> runner;
thread = std::make_unique<std::thread>()[&latch, &runner, name]() -> void {
//设置线程名
SetCurrentThreadName(name);
//创建MessageLooper
fml::MessageLoop::EnsureInitializedForCurrentThread();
auto& loop = MessageLoop::GetCurrent();
//runner赋值
runner = loop.GetTaskRunner();
latch.Singal();
looper.Run();
};
latch.Wait();
task_runner_ = runner;
}
核心还是在MessageLooper的创建;
先来看数据结构
//message_loop.h
class MessageLoop {
private:
fml::RefPtr<MessageLoopImpl> loop_;
fml::RefPtr<fml::TaskRunner> task_runner_;
}
//message_loop_impl.h
class MessageLoopImpl : public Weakable {
private:
fml::RefPtr<MessageLooperTaskQueue> task_queue_;
TaskQueueId queue_id_;
}
看完了数据结构,可以找到MessageLoopImpl是作为成员变量在MessageLoop中提供,
//message_loop.cc
FML_THREAD_LOCAL ThreadLocalUniquePtr<MessageLoop> tls_message_loop;
void MessageLoop::EnsureInitializedForCurrentThread(){
//可以看到MessageLoop是ThreadLocal的
if(tls_message_loop.get() != nullptr){
return;
}
tls_message_loop.reset(new MessageLoop());
}
MessageLoop::MessageLoop()
: loop_(MessageLoopImpl::Create()),
task_runner_(fml::MakeRefCounted<fml::TaskRunner>(loop_)){
}
//message_loop_impl.cc
fml::RefPtr<MessageLoopImpl> MessageLoopImpl::Create(){
#if OS_MACOSX
return fml::MakeRefCounted<MessageLoopDarwin>();
#elif OS_ANDROID
return fml::MakeRefCounted<MessageLoopAndroid>();
#elif OS_LINUX
return fml::MakeRefCounted<MessageLoopLinux>();
#elif OS_WIN
return fml::MakeRefCounted<MessageLoopWin>();
#else
return nullptr;
#endif
}
- loop_
因为我们讨论的是Android平台,因此这边MessageLoop中的loop_编程为MessageLoopAndroid对象。
//message_loop_android.h
class MessageLoopAndroid: public MessageLoopImpl {
private:
fml::UniqueObject<ALooper* UniqueLooperTraits> looper_;
fml::UniqueFD timer_fd_;
}
//message_loop_android.cc
MessageLoopAndroid::MessageLoopAndroid()
: looper_(AcquireLooperForThread()),
timer_fd(::timerfd_create(kClokType, TFD_NONBLOCK | TFD_CLOEXEC)){
static const int kWakeEvent = ALOOPER_EVENT_INPUT;
ALooper_callbackFunc read_event_fd = [](int,int events, void* data) -> int {
if(events & kWakeEvents){
reinterpret_Cast<MessageLoopAndroid*>(data)->OnEventFired();
}
return 1;
}
int add_result = ::ALooper_addFd(looper_.get(), //loop
timer_fd_.get(), //fd
ALOOPER_POLL_CALLBACK, //ident
kWakeEvents, //event
read_event_fd, //callback
this); //baton
}
static ALooper* AcquireLooperForThread(){
ALooper* looper = ALooper_forThread();
if(looper = nullptr){
looper = ALooper_prepar(0);
}
ALooper_acquire(looper);
rerturn looper;
}
这里有关键的几个点,首先通过AcquireLooperForThread()产生一个looper_对象,随后通过::timefd_create()创建一个timer_fd, 构造一个回调read_event_fd,将timer_fd添加到looper_,回调为read_event_fd,关键的事件是ALOOPER_EVENT_INPIT;这里要先熟悉Android中native端的looper机制才可以。
以下代码是在android端源码framework中
//./native/include/utils/Looper.h
class Looper: public ALooper
//./base/native/android/looper.cpp
sp<Looper> Looper::getForThread(){
//可以看到 looper是从ThreadLocal中获取的
return (Looper*)pthread_getspecific(gTLSKey);
}
ALooper* ALooper_prepare(int opts){
return Looper::prepare(opts).get();
}
//./native/libs/utils/Looper.cpp
sp<Looper> Looper::prepare(int opts){
bool allowNonCallbacks = opts & ALOOPER_PREPARE_ALLOW_NOW_CALLBACKS;
sp<looper> looper = Looper::getForThread();
if(looper == NULL){
looper = new Looper(allowNonCallbacks);
Looper::setFotThread(loop);
}
return looper;
}
关于native的Looper,看这一篇文章,
至此,我们得知,MessageLoopImpl中有MessageLooperAndroid变量作为loop_,MessageLooperAndroid有一个Android端的Looper变量作为looper_;
- timer_fd
获得timer_fd的方式为
static constexpr int kClockType = CLOCK_MONOTONIC;
::timerfd_create(kClockType, TFD_NONBLOCK | TFD_CLOEXEC);
//./fml/platform/linux/timerfd.cc
int timerfd_create(int clockid, int flags){
return syscall(__NR_timerfd_create, clockid, flags);
}
//framework/base/native/android/looper.cpp
int ALooper+addFd(ALooper* looper, int fd, int ident, int events, ALooper_callbackFunc callback, void* data){
retiurn static_cast<Looper*>(looper)->addFd(fd, ident, event, callback, data);
}
这里是利用Liunx的系统调用返回一个定时器的文件描述符,可以预料到,Flutter在android端是利用定时器(timer_fd)与原始looper的epoll机制(addFd()@looper)进行事件分发。##
接下里还有一个关键的点,那就是MessageLoopImpl, MessageLoopAndroid派生自MessageLoopImpl
//message_loop_impl.h
class MessageLoopImpl : public Wakeable{
private:
flm::RefPtr<MessageLoopTaskQueue> task_queue_;
TaskQueueId queue_id
}
//message_loop_impl.cc
MessageLoopImpl::MessageLoopImpl()
: task_queue_(MessageLoopTaskQueues::GetInstance()),
queue_id(task_queue_->CreateTaskQueue()){
task_queue_->SetWakeable(queue_id, this);
}
//message_loop+task_queue.h
class MessageLoopTaskQueue{
std::map<TaskQueueId, std::unique_ptr<TaskQueueEntry>> queue_entries_;
}
class TaskQueueEntry{
public:
using TaskObservers = std::map<intptr_t, fml::closure>;
Wakeable* wakeable;
TaskObsevers task_observers;
//从后面可以看到,是一个元素为DelayedTask的优先队列
DelayedTaskQueue delayed_tasks;
}
//delayed_task.h
class DelayedTask{
private:
fml::closure task_;
}
using DelayedTaskQueue = std::priotiry_queue<DelayedTask, std::deque<DelayedTask>,std::greater<DelayedTask>>;
于是MessageLoopTaskQueue拥有一个键为TaskQueueId,值为TaskQueueEntry的Map,后者的核心是一个元素为DelayedTask的优先队列。
//messahe_loop_task_queue.cc
fml::RefPtr<MessageLoopTaskQueue> MessageLoopTaskQueues::GetInstance(){
//可以看到,MessageLoopTaskQueues是全局单例
std::scoped_lock creation(creation_mutex_);
if(!instance_){
instance_=fml::MakeRefCounted<MessageLoopTaskQueue>();
}
return isntance_();
}
TaskQueueId MessageLoopTaskQueues::CreateTaskQueue(){
fml::UniqueueLock lock(*queue_meta_mutext_);
TaskQueueId loop_id = TaskQueueId(task_queue_id_counter);
++task_queue_d_counter_;
queue_entries_[loop_id] = std::make_unique<TaskQueueEntry>();
queue_locks_[loop_id]=std::make_unique<std::mutex>();
return loop_id;
}
可以看到,在MessageLoopTaskQueues中,创建的队列是以TaskQueueEntry的对象,以TaskQueueId最为key保存在map中的,因此可以将MessageLoopTaskQueues看为TaskQueueEntry的管理者。每一个MessageLoopImpl实际上是与自己的那个TaskQueueEntry进行打交道的。
当我们想向某一个线程抛去一个任务时,一般是这样的
thread_host.ui_thread->GetTaskRunner()->PostTask(jni_exit_task);
//taskRunner.cc
void TaskRUnner::PostTask(const fml::closure& task){
loop_->PostTask(task, fml::TImePoint::Now());
}
//message_loop_impl.cc
void MessageLoopImpl::PostTask(const flm::closure& task, fml::TimePoint target_time){
task_queue->RegisterTask(queue_id_,task, target_time);
}
//message_loop_task_queue.cc
void MessageLoopTaskQueues::RegisterTask(TaskQueueId queue_ud, const fml::closure& task,fml::TimePoint target_time){
//获得自己关联的的TaskQueueEntry
size_t order = order++;
const auto& queue_entry = queue_entries_[queue_id];
//往自己关联的DelayedTaskQueue队列推一个任务
queue_entry->delayed_tasks.push({order, task, target_time});
TaskQueueId loop_to_wake = queue_id;
WakeUpUnlocked(loop_to_wake, queue_entry->delayed_tasks.top().getTargetTime());
}
void MessageLoopTaskQueues::WakeUpUnlocked(TaskQueueId queue_id, fml::TimePoint time) const {
queue_entries_.at(queue_id)->wakeable->WakeUp(time);
}
细心的话,可以发现这里的wakeable就是MessageLoopImpl本身(构造函数赋值),在这里是MessageLoopAndroid
//message_loop_android.cc
void MessageLoopAndroid::WakeUp(fml::TimePoint time_point){
bool result = TimerRearm(timer_fd_.get(),time_point);
}
//timerfd.cc
bool TimerRearm(int fd, fml::TimePoint time_point){
const uint64_t nano_secs = time_point.ToEpochDelta().ToNanoseconds();
struct itimerspec spec = {};
...
int result = ::timerfd_settime(fd, TFD_TIMER_ABSTIME, &spec, nullptr);
}
利用timerfd_settime来启动定时器,于是在指定时间后,timer_fd将会有事件可以读取,就会唤醒由于epoll机制阻塞的loop,就会发生OnEventFired()@MessageLoopAndroid的回调,###
//message_loop_android.cc
void MessageLoopAndroid::OnEventFired(){
if(TimerDrain(timer_fd_.get())){
RunExpiredTasksNow();
}
}
//mesage_loop.cc
void MessageLoop::RunExpiredTaskNow(){
loop_->RunExpiredTaskNow();
}
//message_loop_impl.cc
void MessageLoopImpl::RunExpiredTaskNow(){
FlushTasks(FlushType::kAll);
}
void MessageLoopImpl::FlushTasks(FlushType type){
std::vector<fml::closure> invocations;
//这里就不分析,这里就是将符合本次执行的task放入invocations,然后根据不符合运行条件的第一个task或空的队列的目标时间再次设置进行唤醒。
task_queue_->GetTaskToRunNow(queue_id_,type, invocations);
for(const auto& invocation : invocations){
invocation();
//这里可以看到,observer是对task的一种监听,每有一个task完成,所有的observer都会被执行
//从flutter的源码看的时候,可以看到对observers的注册
std::Vector<fml::closure> observers = task_queue_->GetObserverToNotify(queue_id_);
for(const auto& observer : observers){
observer();
}
}
}
这么一个循环,Flutter Engine中的Android事件模型就摸清楚了,可以看到其他的平台如iOS,只是Looper的实现不一样,原理还是一样的利用定时器。
网友评论