5.3.4 Server进程开启线程池

在mediaserver进程中通过以下代码开启线程池:


ProcessState:self()->startThreadPool();

IPCThreadState:self()->joinThreadPool();


这里又涉及ProcessState方法和IPCThreadState方法,因此很可能需要Binder通信。

1.startThreadPool

ProcessState的startThreadPool方法代码如下:


void ProcessState:startThreadPool()

{

AutoMutex_l(mLock);

if(!mThreadPoolStarted){

mThreadPoolStarted=true;//线程池启动标记

spawnPooledThread(true);

}

}


startThreadPool首先将全局变量mThreadPoolStarted赋值为true,然后调用spawnPooledThread,其代码如下:


void ProcessState:spawnPooledThread(bool isMain)

{

if(mThreadPoolStarted){//已经设为true

int32_t s=android_atomic_add(1,&mThreadPoolSeq);

char buf[16];

//创建PoolThread,并调用其run方法

sp<Thread>t=new PoolThread(isMain);

t->run(buf);

}

}


PoolThread是Thread的子类,创建一个PoolThread相当于创建一个新的线程,然后执行新线程的run方法运行该线程,其代码如下:


class PoolThread:public Thread

{

public:

PoolThread(bool isMain)

:mIsMain(isMain)

{

}

protected:

virtual bool threadLoop()

{

IPCThreadState:self()->joinThreadPool(mIsMain);

return false;

}

const bool mIsMain;//内部保存了传入的isMain参数,此时为true

};


Thread类定义于frameworks/native/libs/utils/Threads.cpp,执行其run方法时,会调用其内部createThreadEtc方法进而执行线程函数_threadLoop,最终执行Thread.threadLoop函数。因此ProcessState的startThreadPool方法的作用是创建一个新线程,并调用IPCThreadState的joinThreadPool将新线程加入到线程池中。

2.joinThreadPool

最后,在mediaserver的主线程中调用IPCThreadState的joinThreadPool方法将主线程也加入到线程池中。joinThreadPool代码如下:


void IPCThreadState:joinThreadPool(bool isMain)

{

/根据isMain选择BC_ENTER_LOOPER存入输出缓冲区mOut/

mOut.writeInt32(isMain?BC_ENTER_LOOPER:BC_REGISTER_LOOPER);

set_sched_policy(mMyThreadId, SP_FOREGROUND);

status_t result;

do{

int32_t cmd;

if(mIn.dataPosition()>=mIn.dataSize()){

……

}

//发起一次Binder通信

result=talkWithDriver();

if(result>=NO_ERROR){

size_t IN=mIn.dataAvail();//获取Binder驱动返回的BR指令

if(IN<sizeof(int32_t))continue;

cmd=mIn.readInt32();

result=executeCommand(cmd);//处理BR指令

}

set_sched_policy(mMyThreadId, SP_FOREGROUND);

if(result==TIMED_OUT&&!isMain){

break;

}

}while(result!=-ECONNREFUSED&&result!=-EBADF);

//退出线程池时,需要以BC指令通知Binder驱动

mOut.writeInt32(BC_EXIT_LOOPER);

talkWithDriver(false);

}


可见将线程加入线程池,需要通过BC指令通知Binder驱动程序。完成这个过程后,mediaserver中将初始化两个Binder线程来处理客户端请求。