【android12】【AHandler】【4.AHandler原理篇ALooper类方法全解】

AHandler系列

【android12】【AHandler】【1.AHandler异步无回复消息原理篇】-CSDN博客

【android12】【AHandler】【2.AHandler异步回复消息原理篇】-CSDN博客

【android12】【AHandler】【3.AHandler原理篇AHandler类方法全解】-CSDN博客

其他系列

本人系列文章-CSDN博客


1.简介

前面我们主要介绍了有回复和无回复的消息的使用方法和源码解析,为了更好的理解Ahandler这个类的作用,本篇便主要对AHandler类的所有方法进行全解。

简单介绍一下Ahandler机制

AHandler是Android native层实现的一个异步消息机制,在这个机制中所有的处理都是异步的,将消息封装到一个消息AMessage结构体中,然后放到消息队列中去,后台专门有一个线程ALooper会从这个队列中取出消息然后分发执行,执行函数就是AHandler实例的onMessageReceived。

在AHandler中的消息分为不需要回复的消息和需要回复的消息。

不需要回复的消息:当被post到消息队列后,Alooper会从消息队列中取出消息,并发送给相应的Ahandler的onMessageReceived进行处理。

需要回复的消息:当被post到消息队列后,Alooper会从消息队列中取出消息,并发送给相应的Ahandler的onMessageReceived进行处理,处理完后,Ahandler会将想回复的消息返回给发送方,发送方接受返回的response消息。

1.1 主要类及其作用

**AHandler:**处理类,用于消息的处理,有一个纯虚函数onMessageReceived,一般需要继承此类并重写此方法,用于接受和处理消息。

AMessage:消息类,用于构建各种消息,通过post方法将消息发送给Alooper

**Alooper:**轮询类,用于保存消息队列,然后将消息发送到对应的AHandler

AReplyToken:这类似一个标识,表示要回复的是哪一条消息

1.2 Alooper类图

2.源码解析

2.1 Alooper类

cpp 复制代码
//Alooper.h分析
struct ALooper : public RefBase {
    typedef int32_t event_id;
    typedef int32_t handler_id;

    ALooper();

    void setName(const char *name);//设置looper的名称

    handler_id registerHandler(const sp<AHandler> &handler);//注册Handler,用map保存hadnler_id和handler信息
    void unregisterHandler(handler_id handlerID);//取消注册handler

    status_t start(bool runOnCallingThread = false,bool canCallJava = false,int32_t priority = PRIORITY_DEFAULT);//让Alooper线程运行起来

    status_t stop();//让Alooer线程停止运行

    static int64_t GetNowUs();//获取当前时间

    const char *getName() const {//获取当前Alooper的名称
        return mName.c_str();
    }

protected:
    virtual ~ALooper();//虚析构

private:
    friend struct AMessage;//友元结构体

    struct Event {int64_t mWhenUs;sp<AMessage> mMessage;};//存储Amessage的消息。

    Mutex mLock;//锁
    Condition mQueueChangedCondition;//条件变量,用于唤醒线程

    AString mName;//Alooper的名称

    List<Event> mEventQueue;//消息队列,会根据等待时间来从小到大排序

    struct LooperThread;//此处是声明。
    sp<LooperThread> mThread;//智能指针指向LooperThread
    bool mRunningLocally;//线程是否在运行

    //使用单独的锁进行回复的处理,因为它总是在另一个线程上。但是,使用中心锁可以避免为每个回复创建mutex 
    Mutex mRepliesLock;
    Condition mRepliesCondition;


	//发送一个消息到Aloope中
    void post(const sp<AMessage> &msg, int64_t delayUs);

    // 创建一个和当前looper一起使用的AReplyToken,AReplyToken主要用于回复消息
    sp<AReplyToken> createReplyToken();
    //发送方用于等待回复的消息
    status_t awaitResponse(const sp<AReplyToken> &replyToken, sp<AMessage> *response);

	
	//接收方向发送方回复消息
    status_t postReply(const sp<AReplyToken> &replyToken, const sp<AMessage> &msg);


    bool loop();//死循环,不断的从消息队列中取出消息。

    DISALLOW_EVIL_CONSTRUCTORS(ALooper);
};

2.2 ALooper::GetNowUs

cpp 复制代码
// static
int64_t ALooper::GetNowUs() {//获取当前时间
    return systemTime(SYSTEM_TIME_MONOTONIC) 
}

2.3 ALooper::ALooper构造函数

会清除旧的Ahandler

cpp 复制代码
ALooper::ALooper()
    : mRunningLocally(false) {
    gLooperRoster.unregisterStaleHandlers();//清除旧的Ahandler。从保存注册Ahandler的列表中删除
}

2.4 析构函数

调用stop函数,让looper线程停止循环,并释放线程资源

cpp 复制代码
ALooper::~ALooper() {
    stop();
}

2.5 ALooper::setName

cpp 复制代码
void ALooper::setName(const char *name) {//为looper设置名称
    mName = name;
}

2.6 ALooper::registerHandler

注册Ahandler并将其保存到一个容器中。

cpp 复制代码
ALooper::handler_id ALooper::registerHandler(const sp<AHandler> &handler) {//注册Ahandler,用一个map保存alooper和Ahandler的对应关系
    return gLooperRoster.registerHandler(this, handler);
}
cpp 复制代码
ALooper::handler_id ALooperRoster::registerHandler(const sp<ALooper> &looper, const sp<AHandler> &handler) {
    Mutex::Autolock autoLock(mLock);

    if (handler->id() != 0) {//此时handler->id()等于0
        CHECK(!"A handler must only be registered once.");
        return INVALID_OPERATION;
    }

    HandlerInfo info;
	//定义是struct HandlerInfo {
    //wp<ALooper> mLooper;
    //wp<AHandler> mHandler;
    //};
    info.mLooper = looper;//赋值looper
    info.mHandler = handler;//赋值handler
    ALooper::handler_id handlerID = mNextHandlerID++;//mNextHandlerID在构造函数是1,此时handler_id值是1,mNextHandlerID变为2
    mHandlers.add(handlerID, info);//保存信息KeyedVector<ALooper::handler_id, HandlerInfo> mHandlers;

    handler->setID(handlerID, looper);//此时handlerID等于1,handler持有looper的弱引用

    return handlerID;
}

2.7 ALooper::unregisterHandler

取消注册Ahandler,从容器中删除此Ahandler

cpp 复制代码
void ALooper::unregisterHandler(handler_id handlerID) {//取消注册handler
    gLooperRoster.unregisterHandler(handlerID);
}
cpp 复制代码
void ALooperRoster::unregisterHandler(ALooper::handler_id handlerID) {
    Mutex::Autolock autoLock(mLock);

    ssize_t index = mHandlers.indexOfKey(handlerID);//获取handlerID对应的位置

    if (index < 0) {
        return;
    }

    const HandlerInfo &info = mHandlers.valueAt(index);

    sp<AHandler> handler = info.mHandler.promote();

    if (handler != NULL) {//如果handler存在,则设置其id为0
        handler->setID(0, NULL);
    }

    mHandlers.removeItemsAt(index);//移除此handler
}

2.8 ALooper::start

主要作用为:

1.创建了一个LooperThread类对象,此类对象会创建一个线程

2.让线程运行起来。

cpp 复制代码
//如果runOnCallingThread表示,是否开启新的线程
//如果runOnCallingThread = true:那么当前线程不会再做其它工作,陷入一个死循环。用于循环执行loop()函数。
//如果runOnCallingThread = false:会创建一个子线程,并将loop()逻辑放到这个特定子线程中处理。
status_t start(bool runOnCallingThread = false,bool canCallJava = false,int32_t priority = PRIORITY_DEFAULT);
status_t ALooper::start(bool runOnCallingThread, bool canCallJava, int32_t priority) {//传入的runOnCallingThread=false,canCallJava=false,priority优先级PRIORITY_DEFAULT
     if (runOnCallingThread) {//如果不创建新的线程,则当前线程死循环调用loop
         {
             Mutex::Autolock autoLock(mLock);

             if (mThread != NULL || mRunningLocally) {
                 return INVALID_OPERATION;
             }

             mrunninglocally = true;//mrunninglocally 为true意味着当前线程陷入loop的死循环
         }

       do {
         } while (loop());

         return ok;
     }

    Mutex::Autolock autoLock(mLock);

    if (mThread != NULL || mRunningLocally) {//此时mThread为空
        return INVALID_OPERATION;//无效操作
    }

    mThread = new LooperThread(this, canCallJava);//this是ALooper指针对象,canCallJava是false,new了一个继承自Thread的类

    status_t err = mThread->run(mName.empty() ? "ALooper" : mName.c_str(), priority);//让线程跑起来。传递的参数应该是ALooper,priority为PRIORITY_DEFAULT
	//线程的threadLoop方法会执行
    if (err != OK) {
        mThread.clear();
    }

    return err;
}

此函数的后续流程如下:

2.8.1 LooperThread 构造函数

cpp 复制代码
struct ALooper::LooperThread : public Thread {
    LooperThread(ALooper *looper, bool canCallJava): Thread(canCallJava),mLooper(looper),mThreadId(NULL) {}
//this是ALooper指针对象,canCallJava是false
}

2.8.2 LooperThread构造函数

cpp 复制代码
struct ALooper::LooperThread : public Thread {
    LooperThread(ALooper *looper, bool canCallJava): Thread(canCallJava),mLooper(looper),mThreadId(NULL) {}
//this是ALooper指针对象,canCallJava是false
}

2.8.3 Thread构造函数

cpp 复制代码
Thread::Thread(bool canCallJava): 
	mCanCallJava(canCallJava),//canCallJava此时传入的是false
	mThread(thread_id_t(-1)),//定义类型是thread_id_t mThread;,代表线程id,
	//typedef android_thread_id_t thread_id_t;typedef void* android_thread_id_t;所以android_thread_id_t是一个void*的指针。
      mLock("Thread::mLock"),//互斥量
      mStatus(OK),
      mExitPending(false),
      mRunning(false)//表示此线程是否正在运行
#if defined(__ANDROID__)
      ,
      mTid(-1)
#endif
{
}

2.8.4 Thread::run

主要作用为:

1.调用androidCreateRawThreadEtc方法,此方法通过pthread创建了一个线程,并使线程分离,并执行_threadLoop方法

cpp 复制代码
status_t Thread::run(const char* name, int32_t priority, size_t stack)
//此时传入的参数是name = Alooper,
//stack默认是0,priority为PRIORITY_DEFAULT
{
    Mutex::Autolock _l(mLock);
    /*
    if (mRunning) {//此时为false
        // thread already started
        return INVALID_OPERATION;//表示线程已经start
    }
*/

	//重置status和exitPending为其默认值,
    mStatus = OK;
    mExitPending = false;
    mThread = thread_id_t(-1);

    //持有自己的强引用
    mHoldSelf = this;//定义是sp<Thread>  mHoldSelf; this 是当前mThread线程对象

    mRunning = true;

    bool res;
    if (mCanCallJava) {//此时是false
        res = createThreadEtc(_threadLoop,this, name, priority, stack, &mThread);
    } else {
        res = androidCreateRawThreadEtc(_threadLoop,this, name, priority, stack, &mThread);
		//此处的作用是通过pthread创建了一个线程,并使线程分离,并执行_threadLoop方法
    }

    // if (res == false) {//线程创建出错,正常不执行
        // mStatus = UNKNOWN_ERROR;   // something happened!
        // mRunning = false;
        // mThread = thread_id_t(-1);
        // mHoldSelf.clear();  // "this" may have gone away after this.

        // return UNKNOWN_ERROR;
    // }

    return OK;
}

2.8.5 androidCreateRawThreadEtc

主要作用为:

1.通过pthread_create创建一个分离的线程,并执行_threadLoop方法

cpp 复制代码
int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
                               void *userData,
                               const char* threadName __android_unused,
                               int32_t threadPriority,
                               size_t threadStackSize,
                               android_thread_id_t *threadId)
							   //entryFunction是_threadLoop函数,android_thread_func_t是一个函数指针
							   //定义是typedef int (*android_thread_func_t)(void*);
							   //userData是Thread的类的指针的对象
							   //__android_unused是Alooper
							   //threadPriority为PRIORITY_DEFAULT
							   //threadStackSize是0
							   //threadId = -1
{
    pthread_attr_t attr;//创建线程属性变量
    pthread_attr_init(&attr);//初始化线程属性
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);设置线程属性是否分离。PTHREAD_CREATE_DETACHED为分离

#if defined(__ANDROID__)  /* valgrind is rejecting RT-priority create reqs */
/*
    if (threadPriority != PRIORITY_DEFAULT || threadName != NULL) {//如果线程不是默认优先级
        // Now that the pthread_t has a method to find the associated
        // android_thread_id_t (pid) from pthread_t, it would be possible to avoid
        // this trampoline in some cases as the parent could set the properties
        // for the child.  However, there would be a race condition because the
        // child becomes ready immediately, and it doesn't work for the name.
        // prctl(PR_SET_NAME) only works for self; prctl(PR_SET_THREAD_NAME) was
        // proposed but not yet accepted.
        thread_data_t* t = new thread_data_t;
        t->priority = threadPriority;
        t->threadName = threadName ? strdup(threadName) : NULL;
        t->entryFunction = entryFunction;
        t->userData = userData;
        entryFunction = (android_thread_func_t)&thread_data_t::trampoline;
        userData = t;
    }*/
#endif

    // if (threadStackSize) {//此时是0,不设置
        // pthread_attr_setstacksize(&attr, threadStackSize);//设置线程属性中线程栈的大小
    // }

    errno = 0;
    pthread_t thread;
    int result = pthread_create(&thread, &attr,(android_pthread_entry)entryFunction, userData);//attr是线程属性。
	//entryFunction是线程要执行的函数_threadLoop,userData是Thread的强引用对象
    pthread_attr_destroy(&attr);//创建线程完成后,可以销毁属性。
    if (result != 0) {
        ALOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, %s)\n"
             "(android threadPriority=%d)",
            entryFunction, result, strerror(errno), threadPriority);
        return 0;
    }

    // Note that *threadID is directly available to the parent only, as it is
    // assigned after the child starts.  Use memory barrier / lock if the child
    // or other threads also need access.
    if (threadId != nullptr) {
        *threadId = (android_thread_id_t)thread; // XXX: this is not portable
    }
    return 1;
}

2.8.6 _threadLoop

主要作用为:

1.死循环调用继承类的threadLoop方法,当threadLoop方法返回true并且没有调用requsetexit函数时,会一直循环的调用threadLoop函数

cpp 复制代码
int Thread::_threadLoop(void* user)//此处传入的是Thread强引用对象
{
    Thread* const self = static_cast<Thread*>(user);//将void*类的指针转化为Thread*

    sp<Thread> strong(self->mHoldSelf);//获取Thread的强引用,此处是self->mHoldSelf是sp类型,故此处是拷贝构造,指向的对象引用会是2
    wp<Thread> weak(strong);//获取弱引用
    self->mHoldSelf.clear();//让强引用减一

#if defined(__ANDROID__)
    // this is very useful for debugging with gdb
    self->mTid = gettid();
#endif

    bool first = true;

    do {
        bool result;
        if (first) {//如果是第一次运行线程。
            first = false;
            self->mStatus = self->readyToRun();//此处就是返回一个ok
            result = (self->mStatus == OK);

            if (result && !self->exitPending()) {
                result = self->threadLoop();//此处函数是虚函数,需要类去继承。调用的是子类的threadLooper函数。
			//在此处是struct ALooper::LooperThread : public Thread类的threadLoop方法
            }
        } else {
            result = self->threadLoop();//此处函数是虚函数,需要类去继承。调用的是子类的threadLooper函数。
			//在此处是struct ALooper::LooperThread : public Thread类的threadLoop方法
        }

        // establish a scope for mLock
        {
        Mutex::Autolock _l(self->mLock);
        if (result == false || self->mExitPending) {//一般result都是true,self->mExitPending默认是false,
		//表示是否退出,在requestExit函数和requestExitAndWait函数中会设置为true
            self->mExitPending = true;
            self->mRunning = false;
            // clear thread ID so that requestExitAndWait() does not exit if
            // called by a new thread using the same thread ID as this one.
			//清除线程ID
            self->mThread = thread_id_t(-1);
            // note that interested observers blocked in requestExitAndWait are
            // awoken by broadcast, but blocked on mLock until break exits scope
            self->mThreadExitedCondition.broadcast();//mThreadExitedCondition是Condition类对象。
			//底层调用了pthread_cond_broadcast,唤醒所有在此conditon等待的线程
            break;
        }
        }

        // Release our strong reference, to let a chance to the thread
        // to die a peaceful death.
        strong.clear();//短暂的让强指针引用-1,以便有机会让线程释放。
        // And immediately, re-acquire a strong reference for the next loop
        strong = weak.promote();//立即获取强引用
    } while(strong != nullptr);//死循环

    return 0;
}

2.8.7 LooperThread::threadLoop

cpp 复制代码
//线程调用run方法后,会调用threadLoop方法,当其返回true并且没有调用requsetexit函数时,会一直循环的调用threadLoop函数
struct ALooper::LooperThread : public Thread {
virtual bool threadLoop() {return mLooper->loop();}
}

2.8.8 ALooper::loop

此函数后续仍会遇见,我们现在只介绍当前的作用。

此时,looper刚启动,所以其消息队列中的消息为空,故此时是线程在条件变量上进行了等待。

当另外一个线程生成AMessage消息,并post时,会将此消息post到消息队列中,然后唤醒此looper线程,此时消息队列存在消息,会取出消息,并执行deliver函数去运输消息,最后会执行此消息。

cpp 复制代码
bool ALooper::loop() {
    Event event;//event结构体为
	 //struct Event {
     //int64_t mWhenUs;
     //sp<AMessage> mMessage;
	 //};

    {
        Mutex::Autolock autoLock(mLock);
        if (mThread == NULL && !mRunningLocally) {//此时mThread不为空,mRunningLocally值为flase
            return false;
        }
        if (mEventQueue.empty()) {//此时消息队列应该是空的
            mQueueChangedCondition.wait(mLock);//此处定义是Condition mQueueChangedCondition;此线程阻塞在这里等待。
			//调用的是inline status_t Condition::wait(Mutex& mutex) {return -pthread_cond_wait(&mCond, &mutex.mMutex);}
            return true;
		//后面暂时不执行
        // }
        // int64_t whenUs = (*mEventQueue.begin()).mWhenUs;
        // int64_t nowUs = GetNowUs();

        // if (whenUs > nowUs) {
            // int64_t delayUs = whenUs - nowUs;
            // if (delayUs > INT64_MAX / 1000) {
                // delayUs = INT64_MAX / 1000;
            // }
            // mQueueChangedCondition.waitRelative(mLock, delayUs * 1000ll);

            // return true;
        // }

        // event = *mEventQueue.begin();
        // mEventQueue.erase(mEventQueue.begin());
    // }

    // event.mMessage->deliver();

    // // NOTE: It's important to note that at this point our "ALooper" object
    // // may no longer exist (its final reference may have gone away while
    // // delivering the message). We have made sure, however, that loop()
    // // won't be called again.

    // return true;
}
}
}

2.9 ALooper::stop

此函数内部主要会调用调用requestExit方法。此方法会将一个线程循环的flag标志设置为true,等到下一次线程循环的时候,线程便会退出循环,然后释放线程资源。

cpp 复制代码
status_t ALooper::stop() {
    sp<LooperThread> thread;
    bool runningLocally;

    {
        Mutex::Autolock autoLock(mLock);

        thread = mThread;//拷贝构造,使得强引用计数+1了
        runningLocally = mRunningLocally;
        mThread.clear();//强引用计数减1
        mRunningLocally = false;
    }

    if (thread == NULL && !runningLocally) {
        return INVALID_OPERATION;
    }

    if (thread != NULL) {//停止线程
        thread->requestExit();//调用requestExit方法。查看Thread类的结构可知,mExitPending = true会设置为true
    }
.
    mQueueChangedCondition.signal();//通知信号量等待的线程。然后会结束死循环。线程分离会自动销毁。
    {
        Mutex::Autolock autoLock(mRepliesLock);
        mRepliesCondition.broadcast();//广播唤醒在mRepliesCondition等待的所有线程
    }

    if (!runningLocally && !thread->isCurrentThread()) {
        // If not running locally and this thread _is_ the looper thread,
        // the loop() function will return and never be called again.
		//如果不是在本地运行,并且此线程_is_为looper线程,则loop()函数将返回并且不再被调用。
        thread->requestExitAndWait();
    }

    return OK;
}

此函数的后续流程为:

2.9.1 Thread::requestExit

设置mExitPending的标志位为true,线程就会退出循环,然后释放线程资源

cpp 复制代码
//requestExit() 请求退出线程,立即返回。
void Thread::requestExit()
{
    Mutex::Autolock _l(mLock);
    mExitPending = true;//设置mExitPending的值为true,此时_threadLoop会执行下面的代码块。然后退出循环。然后由于线程是分离的,_threadLoop函数执行完,会自动回收。
}

2.9.2 Thread::requestExitAndWait

当我们调用stop的时候是在A线程中,当我们设置mExitPending为ture后,表示要释放之前创建的分离的looper线程,而此时A线程需要等待looper线程释放完相关资源后,再往下走。

cpp 复制代码
status_t Thread::requestExitAndWait()
{
    Mutex::Autolock _l(mLock);
    if (mThread == getThreadId()) {//如果是之前使用当前线程作为处理消息的线程,而不是新创建了一个线程。
	//那么此时自己调用requestExitAndWait,需要返回,不需要在下面mThreadExitedCondition条件变量上进行等待,因为只有一个线程,
	//此时线程会一直等待,因为没有其他线程唤醒。
        ALOGW(
        "Thread (this=%p): don't call waitForExit() from this "
        "Thread object's thread. It's a guaranteed deadlock!",
        this);

        return WOULD_BLOCK;
    }

    mExitPending = true;

    while (mRunning == true) {
        mThreadExitedCondition.wait(mLock);
    }
    // This next line is probably not needed any more, but is being left for
    // historical reference. Note that each interested party will clear flag.
    mExitPending = false;

    return mStatus;
}

2.9.3 _threadLoop

此时我们需要回到looper线程的这个函数,此时self->mExitPending为ture,然后当前线程会退出死循环,清除线程的id,同时唤醒之前等待的A线程。由于是分离的线程,故此时分离的线程会自动释放资源。

cpp 复制代码
int Thread::_threadLoop(void* user)//此处传入的是Thread强引用对象
{
    Thread* const self = static_cast<Thread*>(user);//将void*类的指针转化为Thread*

    sp<Thread> strong(self->mHoldSelf);//获取Thread的强引用,此处是self->mHoldSelf是sp类型,故此处是拷贝构造,指向的对象引用会是2
    wp<Thread> weak(strong);//获取弱引用
    self->mHoldSelf.clear();//让强引用减一

#if defined(__ANDROID__)
    // this is very useful for debugging with gdb
    self->mTid = gettid();
#endif

    bool first = true;

    do {
        bool result;
        if (first) {//如果是第一次运行线程。
            first = false;
            self->mStatus = self->readyToRun();//此处就是返回一个ok
            result = (self->mStatus == OK);

            if (result && !self->exitPending()) {
                result = self->threadLoop();//此处函数是虚函数,需要类去继承。调用的是子类的threadLooper函数。
			//在此处是struct ALooper::LooperThread : public Thread类的threadLoop方法
            }
        } else {
            result = self->threadLoop();//此处函数是虚函数,需要类去继承。调用的是子类的threadLooper函数。
			//在此处是struct ALooper::LooperThread : public Thread类的threadLoop方法
        }

        // establish a scope for mLock
        {
        Mutex::Autolock _l(self->mLock);
        if (result == false || self->mExitPending) {//一般result都是true,self->mExitPending默认是false,
		//表示是否退出,在requestExit函数和requestExitAndWait函数中会设置为true
            self->mExitPending = true;
            self->mRunning = false;
            // clear thread ID so that requestExitAndWait() does not exit if
            // called by a new thread using the same thread ID as this one.
			//清除线程ID
            self->mThread = thread_id_t(-1);
            // note that interested observers blocked in requestExitAndWait are
            // awoken by broadcast, but blocked on mLock until break exits scope
            self->mThreadExitedCondition.broadcast();//mThreadExitedCondition是Condition类对象。
			//底层调用了pthread_cond_broadcast,唤醒所有在此conditon等待的线程
            break;
        }
        }

        // Release our strong reference, to let a chance to the thread
        // to die a peaceful death.
        strong.clear();//短暂的让强指针引用-1,以便有机会让线程释放。
        // And immediately, re-acquire a strong reference for the next loop
        strong = weak.promote();//立即获取强引用
    } while(strong != nullptr);//死循环

    return 0;
}

2.10 ALooper::post

主要作用为:

1.将消息根据时延大小放到消息队列的指定位置,然后唤醒Alooper线程。

cpp 复制代码
void ALooper::post(const sp<AMessage> &msg, int64_t delayUs) {
    Mutex::Autolock autoLock(mLock);

    int64_t whenUs;
    if (delayUs > 0) {//表示是否延时发送
        int64_t nowUs = GetNowUs();
        whenUs = (delayUs > INT64_MAX - nowUs ? INT64_MAX : nowUs + delayUs);

    } else {
        whenUs = GetNowUs();//不延时,获取当前时间
    }

    List<Event>::iterator it = mEventQueue.begin();//此处是遍历消息队列
    while (it != mEventQueue.end() && (*it).mWhenUs <= whenUs) {//遍历消息队列,按照时延从小到大排序,找到当前消息应该插入的位置。
        ++it;
    }

    Event event;
    event.mWhenUs = whenUs;
    event.mMessage = msg;//生成event

    if (it == mEventQueue.begin()) {//如果当前消息应该插入到消息队列的队首
        mQueueChangedCondition.signal();//则使用条件遍历唤醒线程
    }

    mEventQueue.insert(it, event);//插入该event到指定位置
}

2.11 ALooper::loop

主要作用为:

1.从消息队列中取出消息,然后将消息发送到指定的Ahandler处理者去处理此消息。

cpp 复制代码
bool ALooper::loop() {
    Event event;

    {
        Mutex::Autolock autoLock(mLock);
         if (mThread == NULL && !mRunningLocally) {
             return false;
         }
         if (mEventQueue.empty()) {//此时不为空,不执行
             mQueueChangedCondition.wait(mLock);
             return true;
         }
        int64_t whenUs = (*mEventQueue.begin()).mWhenUs;//获取消息队列的位于头部的event的时延,因为位于头部的event是时延最小的消息
        int64_t nowUs = GetNowUs();

        if (whenUs > nowUs) {//如果时延大于当前时间,意味着时间还没到。
            int64_t delayUs = whenUs - nowUs;
            if (delayUs > INT64_MAX / 1000) {
                delayUs = INT64_MAX / 1000;
            }
            mQueueChangedCondition.waitRelative(mLock, delayUs * 1000ll);//因为位于头部的event是时延最小的消息,所以此时需要等待时间到达,时间到达后,返回true,然后开启下一次循环

            return true;
        }

        event = *mEventQueue.begin();//取出头部的event事件
        mEventQueue.erase(mEventQueue.begin());//将此evnet从消息队列中删除
    }

    event.mMessage->deliver();//调用Amessage的deliver方法

    // NOTE: It's important to note that at this point our "ALooper" object
    // may no longer exist (its final reference may have gone away while
    // delivering the message). We have made sure, however, that loop()
    // won't be called again.

    return true;
}

2.12 ALooper::createReplyToken

主要作用为:

1.创建一个AReplyToken对象,用于表示是哪个消息需要回复。

cpp 复制代码
sp<AReplyToken> ALooper::createReplyToken() {//此时A线程发送消息,然后阻塞等待B线程发送回复消息。
//然后b线程收到消息后,发送消息到A线程。在这个流程中,AReplyToken在A线程的发送消息的时候被创建,然后保存该回复令牌到发送消息内部。
//当发送的消息到达B线程后,b线程会取出此回复令牌,然后将回复的消息,设置进此AReplyToken对象中,由于A线程也持有此对象,故A线程会死循环的拿回复的消息。
    return new AReplyToken(this);
}

2.13 ALooper::awaitResponse

死循环取回回复,到response中。取回后返回ok,未取回,则一直wait等待阻塞。

cpp 复制代码
status_t ALooper::awaitResponse(const sp<AReplyToken> &replyToken, sp<AMessage> *response) {
    // return status in case we want to handle an interrupted wait
    Mutex::Autolock autoLock(mRepliesLock);
    CHECK(replyToken != NULL);
    while (!replyToken->retrieveReply(response)) {//死循环取回回复,到response中。取回后返回ok,未取回,则一直wait等待阻塞。
        {
            Mutex::Autolock autoLock(mLock);
            if (mThread == NULL) {
                return -ENOENT;
            }
        }
        mRepliesCondition.wait(mRepliesLock);
    }
    return OK;
}

2.14 ALooper::postReply

1.将接收方Ahandler回复的Amessage设置到replyToken对象中。

2.唤醒发送方wait之前wait阻塞的地方。

cpp 复制代码
status_t ALooper::postReply(const sp<AReplyToken> &replyToken, const sp<AMessage> &reply) {
    Mutex::Autolock autoLock(mRepliesLock);
    status_t err = replyToken->setReply(reply);//将此回复消息reply设置到replyToken中
    if (err == OK) {
        mRepliesCondition.broadcast();//广播之前mRepliesCondition.wait(mRepliesLock)的地方。
    }
    return err;
}

将Amessage消息保存到AReplyToken类对象中。

cpp 复制代码
status_t AReplyToken::setReply(const sp<AMessage> &reply) {
    if (mReplied) {
        ALOGE("trying to post a duplicate reply");
        return -EBUSY;
    }
    CHECK(mReply == NULL);
    mReply = reply;//将传入的Amessage消息保存到AReplyToken中
    mReplied = true;
    return OK;
}
相关推荐
DARLING Zero two♡2 分钟前
关于我、重生到500年前凭借C语言改变世界科技vlog.15——深入理解指针(4)
c语言·开发语言·科技
毕业设计制作和分享2 分钟前
ssm公交车信息管理系统+vue
java·vue.js·spring boot·毕业设计·mybatis
混迹网络的权某3 分钟前
蓝桥杯真题——三角回文数(C语言)
c语言·开发语言·算法·蓝桥杯·改行学it
ffyyhh9955113 分钟前
SpringBoot事务管理:自调用与事务回滚行为分析
数据库
鸠摩智首席音效师4 分钟前
如何在一个 Docker 容器中运行多个进程 ?
java·docker·容器
PangPiLoLo6 分钟前
高可用架构-业务高可用
java·性能优化·架构
小光学长8 分钟前
基于vue框架的的楼盘销售管理系统6n60a(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
数据库
爱上语文9 分钟前
苍穹外卖 商家取消、派送、完成订单
java·开发语言·spring boot·后端
Francek Chen16 分钟前
【大数据技术基础 | 实验八】HBase实验:新建HBase表
大数据·数据库·hadoop·分布式·zookeeper·hbase
墨柳烟18 分钟前
ABAQUS高亮显示网格节点方法:Python为每个节点建立集合
开发语言·前端·python·abaqus