Linux 系统中,创建线程函数为:pthread_create();在 Android 中,通过调用 pthread_create() 封装了一个为线程操作的 Thread类;在创建线程的时候,只需要继承于这个 Thread 类并实现虚函数 thread_loop()。下面就简单介绍一下这个 Thread 类:
1. 头文件中的定义
// frameworks/base/include/utils/threads.h
frameworks/base/include/utils/threads.h
class Thread : virtual public RefBase
{
public:
// canCallJava 为 true
Thread(bool canCallJava = true);
virtual ~Thread();
// 线程启动函数,调用的是threadLoop
virtual status_t run(const char*name = 0, int32_t prority = PRIORITY_DEFAULT,
size_t stack = 0);
// 申请退出这个线程
virtual void requestExit();
virtual status_t readyToRun();
// 调用requestExit()等待直到这个线程退出
status_t requestExitAndWait();
// 等待直到线程退出,如果没有启动立即返回
status_t join();
protected:
// 如果调用了 requestExit() 返回true
bool exitPending() const;
private:
// 实际的线程函数,继承类必须实现该方法:threadLoop()
// 返回 true 时会一直调用,返回 false 的时会退出该线程;
virtual bool threadLoop() = 0;
// 禁止赋值
Thread& operator = (const Thread&);
// 被 run() 函数调用,实际调用threadLoop();
static int _threadLoop(void* user);
const bool mCanCallJava;
thread_id_t mThread; // thread_id_t 是 void*类型
mutable Mutex mLock;
Condition mThreadExitedCondition;
status_t mStatus;
// 注意:操作这两个变量的地方都需要上锁
volatile bool mExitPending;
volatile bool mRunning;
sp mHoldSelf;
};
2. Thread 类的构造函数
Thread::Thread(bool canCallJava)
: mCanCallJava(canCallJava),
mThread(thread_id_t(-1)),
mLock("Thrad::mLock"),
mStatus(NO_ERROR),
mExitPending(false), mRunnig(false)
{
}
3. run() 方法
status_t Thread::run(const char* name, int32_t priority, size_t stack)
{
Mutex::Autolock _l(mLock);
if (mRunning) {
// thread already started
return INVALID_OPERATION;
}
// reset status and exitPending to their default value, so we can
// try again after an error happened (either below, or in readyToRun())
mStatus = NO_ERROR;
mExitPending = false;
mThread = thread_id_t(-1);
// hold a strong reference on ourself
mHoldSelf = this; // 保存当前对象的引用
mRunning = true;
bool res;
// 如果 mCanCallJava为真,则调用createThreadEtc函数,线程函数是_threadLoop(Thread.cpp中定义的一个函数)。
if (mCanCallJava) { // 这里初始化的时候为 true; 见 3.1
res = createThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
} else { // 见 3.2
res = androidCreateRawThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
}
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;
}
// Do not refer to mStatus here: The thread is already running (may, in fact
// already have exited with a valid mStatus result). The NO_ERROR indication
// here merely indicates successfully starting the thread and does not
// imply successful termination/execution.
return NO_ERROR;
// Exiting scope of mLock is a memory barrier and allows new thread to run
}
3.1 createThreadEtc() 方法:这里 mCanCallJava 为 true 时,调用的方法;其实最终调用的方法都是同一个线程创建函数,只不过传入参数的回调函数不一样,之后会有分析:
//(1)创建线程:Create thread with lots of parameters
inline bool createThreadEtc(thread_func_t entryFunction,
void *userData,
const char* threadName = "android:unnamed_thread",
int32_t threadPriority = PRIORITY_DEFAULT,
size_t threadStackSize = 0,
thread_id_t *threadId = 0)
{
return androidCreateThreadEtc(entryFunction, userData, threadName,
threadPriority, threadStackSize, threadId) ? true : false;
}
//(2)调用的函数:
static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc; // 函数指针;
// 线程创建函数:gCreateThreadFn是函数指针,初始化时和 mCanCallJava 为 false 时使用的是同一个
int androidCreateThreadEtc(android_thread_func_t entryFunction,
void *userData,
const char* threadName,
int32_t threadPriority,
size_t threadStackSize,
android_thread_id_t *threadId)
{
return gCreateThreadFn(entryFunction, userData, threadName,
threadPriority, threadStackSize, threadId);
}
3.2 androidCreateRawThreadEtc() 方法:
//
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)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
#ifdef HAVE_ANDROID_OS /* 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) {
pthread_attr_setstacksize(&attr, threadStackSize);
}
errno = 0;
pthread_t thread;
// 从这里可以看出线程的创建最终还是通过 pthread_create() 封装而成的;
int result = pthread_create(&thread, &attr,
(android_pthread_entry)entryFunction, userData);
pthread_attr_destroy(&attr);
if (result != 0) {
ALOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n"
"(android threadPriority=%d)",
entryFunction, result, 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 != NULL) {
*threadId = (android_thread_id_t)thread; // XXX: this is not portable
}
return 1;
}
/**
简单介绍 pthread_create() :pthread_create 是(Unix、Linux、Mac OS X)等操作系统的创建线程的函
数。它的功能是创建线程(实际上就是确定调用该线程函数的入口点),在线程创建以后,就开始运行相关的线程函数。
pthread_create的返回值表示成功,返回0;表示出错,返回表示-1。
参数说明:int pthread_create (pthread_t * tid, const pthread_attr_t * attr, void * (*start_rtn)(void*), void *arg);
各个参数说明:
第一个参数为指向线程标识符的指针。
第二个参数用来设置线程属性。
第三个参数是线程运行函数的起始地址(也就是传入的entryFunction)。
最后一个参数是运行函数的参数。
**/
上述中当 mCanCallJava 为 true 时最终调用的是 gCreateThreadFn这个函数,gCreateThreadFn是个全局的函数指针(static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc),而这个与 mCanCallJava 为 false 时看上去是一模一样的,那么这两者是不是有所区别呢(答案是肯定有的,不然搞这么麻烦作甚)?
3.3 布尔变量 mCanCallJava 取值不同时的区别:
过程:
(1)mCanCallJava 为 false 时:直接调用的是 androidCreateRawThreadEtc() 这个方法;
(2)mCanCallJava 为 true 时:createThreadEtc() -> android_create_thread_fn () -> androidCreateRawThreadEtc();
区别:
在 3.1分析 mCanCallJava 为 true 的过程中其实就多执行了一步,即调用了 androidCreateThreadEtc() 方法,而在这个方法中也只是引入了 static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc 这个函数指针,并调用 gCreateThreadFn 方法创建线程;那么接下来就跟踪这个 gCreateThreadFn 变量的初始化就行了;
3.4 gCreateThreadFn() 的赋值:代码中有的地方是会修改这个函数指针的指向的,比如在 zygote 中创建线程,AndroidRuntime 调用 startReg() 的地方,就有修改这个函数指针,其代码如下所示(这里顺便简单介绍一下 zygote 进程的启动):
//(1)zygote 是由 init 进程通过解析 init.rc 文件而创建并启动的:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
//(2)frameworks/base/cmds/app_process/app_main.cpp 中的 main() 方法:
int main(int argc, char* const argv[])
{
// AppRuntime 继承 AndoirdRuntime
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// 跳过第一个参数
argc--;
argv++;
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
++i; // Skip unused "parent dir" argument.
// 解析参数
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
// 省略部分代码 ...
//设置进程名
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string());
set_process_name(niceName.string());
}
// 如果 zygote ,AndroidRuntime 执行 com.android.internal.os.ZygoteInit
if (zygote) { // 根据上面解析的脚本参数,执行的是此分支;
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}
//(3)在 zygote 的启动过程中会调用到 AndroidRuntime的 start 方法:
void AndroidRuntime::start(const char* className, const Vector& options)
{
// ...
// 创建一个虚拟机的实例
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
// JNI 方法注册
/*
* Register android functions.
*/
if (startReg(env) < 0) { // ********* 此处为下面的关注点 *********
ALOGE("Unable to register all android natives\n");
return;
}
/*
* We want to call main() with a String array with arguments in it.
* At present we have two arguments, the class name and an option string.
* Create an array to hold them.
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
// strArray= new String[options.size() + 1];
stringClass = env->FindClass("java/lang/String");
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
// strArray[0] = "com.android.internal.os.ZygoteInit"
classNameStr = env->NewStringUTF(className);
env->SetObjectArrayElement(strArray, 0, classNameStr);
// strArray[1] = "start-system-server";
// strArray[2] = "--abi-list=系统响应的cpu架构类型";
for (size_t i = 0; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}
// slashClassName = "com/android/internal/os/ZygoteInit"
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
// 获取 ZygoteInit.java 的 main 方法
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
// 执行 ZygoteInit.java 的 main 方法,从 Native 世界进入 Java 世界
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
// ...
}
//(4)Java 代码是运行在 Java 虚拟机上的,而 Java 与 native 通信采用的是 JNI ,从这里就开始进入 Java 层的代码:
public static void main(String argv[]) {
try {
// 解析参数
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
// 省略部分代码...
// 为 Zygote 注册 socket 用于通信
registerZygoteSocket(socketName);
// 预加载类和资源
preload();
// 启动 system_server
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
// 进入循环模式,等待孵化进程
runSelectLoop(abiList);
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
closeServerSocket();
throw ex;
}
}
private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
// 省略部分代码...
}
try {
FileDescriptor fd = new FileDescriptor();
// 设置文件描述符
fd.setInt$(fileDesc);
// 创建 Socket 的本地服务端
sServerSocket = new LocalServerSocket(fd);
} catch (IOException ex) {
// 省略部分代码...
}
}
}
static void preload() {
// 预加载位于 /system/etc/preloaded-classes 文件中的类
preloadClasses();
// 预加载资源,包含 drawable 和 color 资源
preloadResources();
// 预加载 OpenGL
preloadOpenGL();
// 通过 System.loadLibrary() 方法,
// 预加载 "android", "compiler_rt", "jnigraphics" 这3个共享库
preloadSharedLibraries();
// 预加载 文本连接符资源
preloadTextResources();
// 仅用于 zygote 进程,用于内存共享的进程
WebViewFactory.prepareWebViewInZygote();
}
private static boolean startSystemServer(String abiList, String socketName) throws
MethodAndArgsCaller, RuntimeException {
// 省略部分代码...
// 设置一些参数
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
// 省略部分代码...
// fork 创建 system_server 进程,后面会具体分析
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
// pid == 0 代表子进程,也就是 system_server 进程
if (pid == 0) {
// 执行初始化 system_server 进程
handleSystemServerProcess(parsedArgs);
}
return true;
}
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList fds = new ArrayList();
ArrayList peers = new ArrayList();
// sServerSocket 是 registerZygoteSocket 中创建的,即 zygote 进程。保存到 fds[0]
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
while (true) {
// 给 pollFds 设置参数,fds.size 是 1 ,也就是说 pollFds 里面只有 sServerSocket.getFileDescriptor()
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
try {
// 处理轮询状态,当 pollFds 有事件到来则往下执行,否则阻塞在这里
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
// 省略部分代码...
}
for (int i = pollFds.length - 1; i >= 0; --i) {
if (i == 0) {
// 即fds[0],代表的是 sServerSocket,则意味着有客户端连接请求;
// 则创建 ZygoteConnection 对象,并添加到 fds。
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
//添加到 fds.
fds.add(newPeer.getFileDesciptor());
} else {
// i>0,则代表通过 socket 接收来自对端的数据,并执行相应操作
boolean done = peers.get(i).runOnce();
if (done) {
peers.remove(i);
// 处理完则从fds中移除该文件描述符
fds.remove(i);
}
}
}
}
}
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
// 读取 socket 客户端发送过来的参数列表
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
// 省略部分代码...
return true;
}
// 省略部分代码...
try {
// 将 binder 客户端传递过来的参数,解析成 Arguments 对象格式
parsedArgs = new Arguments(args);
// 省略部分代码...
// fork 创建一个新的进程
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
} catch (Exception e) {
// 省略部分代码...
}
try {
if (pid == 0) {
// pid == 0 执行子进程的逻辑
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
// 进入子进程流程
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
return true;
} else {
// pid>0 执行父进程的逻辑
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
在 startReg(env) 方法中:
//(1)AndroidRuntime.cpp 中 startReg():
/*
* Register android native functions with the VM.
*/
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
/*
* This hook causes all future threads created in this process to be
* attached to the JavaVM. (This needs to go away in favor of JNI
* Attach calls.)
*/
// 这里会修改函数指针为 javaCreateThreadEtc,不再是 mCanCallJava 为 false 时调用的 androidCreateRawThreadEtc
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
ALOGV("--- registering native functions ---\n");
/*
* Every "register" function calls one or more things that return
* a local reference (e.g. FindClass). Because we haven't really
* started the VM yet, they're all getting stored in the base frame
* and never released. Use Push/Pop to manage the storage.
*/
env->PushLocalFrame(200);
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
//createJavaThread("fubar", quickTest, (void*) "hello");
return 0;
}
//(2)Threads.cpp 中 androidSetCreateThreadFunc():
void androidSetCreateThreadFunc(android_create_thread_fn func)
{
gCreateThreadFn = func; // 也就是说 gCreateThreadFn 为 javaCreateThreadEtc
}
//(3)AndroidRuntime.cpp 中 javaCreateThreadEtc():
/*static*/ int AndroidRuntime::javaCreateThreadEtc(
android_thread_func_t entryFunction,
void* userData,
const char* threadName,
int32_t threadPriority,
size_t threadStackSize,
android_thread_id_t* threadId)
{
void** args = (void**) malloc(3 * sizeof(void*)); // javaThreadShell must free
int result;
if (!threadName)
threadName = "unnamed thread";
args[0] = (void*) entryFunction;
args[1] = userData;
args[2] = (void*) strdup(threadName); // javaThreadShell must free
// 最终调用的还是 androidCreateRawThreadEtc,但把线程函数(回调函数)换成了 javaThreadShell
result = androidCreateRawThreadEtc(AndroidRuntime::javaThreadShell, args,
threadName, threadPriority, threadStackSize, threadId);
return result;
}
//(4)AndroidRuntime.cpp 中 javaThreadShell():
/*static*/ int AndroidRuntime::javaThreadShell(void* args) {
void* start = ((void**)args)[0];
void* userData = ((void **)args)[1];
char* name = (char*) ((void **)args)[2]; // we own this storage
free(args);
JNIEnv* env;
int result;
/* hook us into the VM */
//把这个线程 attach 到 JNI 环境中,调用了JavaVM* vm 的 vm->AttachCurrentThread()
if (javaAttachThread(name, &env) != JNI_OK)
return -1;
/* start the thread running */
result = (*(android_thread_func_t)start)(userData);
/* unhook us */
// 当在一个线程里面调用AttachCurrentThread后,如果不需要用的时候一定要DetachCurrentThread,否则线程无法正常退出。
javaDetachThread(); // 从JNI环境中detach出来,调用了 vm->DetachCurrentThread()
free(name);
return result; // 返回当前线程的JNIEnv,这样就可以调用 JNI 中的方法使用了
}
目的:
- 在调用线程函数之前会 attach 到 JNI 环境中,这样,线程函数就可以使用JNI中的方法了。
- 线程函数退出后,它会从 JNI 环境中 detach,释放资源。
4 _threadLoop() 与 threadLoop():
4.1 _threadLoop():前面的代码讲到了 Thread 中 mCanCallJava 取值到 zygote 启动时创建线程时通过修改函数指针 gCreateThreadFn,从而绑定到 JNI 环境中;现在回到之前的代码,跟踪一下传入创建线程时的回调函数 _threadLoop() ;
// 之前的代码:
// 从上面 3.3、 3.4 中可知,当 mCanCallJava 为 true 时,可以通过重新给 gCreateThreadFn 赋值,
// 从而执行不同的线程回调函数;
if(mCanCallJava) {
res = createThreadEtc(_threadLoop, this, name, priority,
stack,&mThread);
} else{
res = androidCreateRawThreadEtc(_threadLoop, this, name, priority,
stack,&mThread);
}
int Thread::_threadLoop(void* user)
{
Thread* const self = static_cast(user); // self代表继承Thread类的对象
sp strong(self->mHoldSelf);
wp weak(strong);
self->mHoldSelf.clear();
#ifdef HAVE_ANDROID_OS
// this is very useful for debugging with gdb
self->mTid = gettid();
#endif
bool first = true;
do { // 这段代码运行在一个do-while循环中。 即使我们的threadLoop()返回了,线程也不一定会退出
bool result;
if (first) { // 只执行一次
first = false;
self->mStatus = self->readyToRun(); // 第一次进来调用 readyToRun(),检查是否准备完成
result = (self->mStatus == NO_ERROR);
if (result && !self->exitPending()) {
result = self->threadLoop(); // 调用派生类的threadLoop
}
} else {
result = self->threadLoop(); // 如果不是第一次执行此循环
}
// 建立 mLock 的作用域
{
//线程退出的条件:
//(1)result 为 false。如果子类在 threadLoop 中返回 false,线程就可以退出,这种属于主动退出的情况;
//(2)mExitPending为true,这个变量可由Thread类的requestExit函数设置,这属于被动退出,因为由外界强制设置了退出条件。
Mutex::Autolock _l(self->mLock);
if (result == false || self->mExitPending) {
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.
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();
break;
}
}
// Release our strong reference, to let a chance to the thread
// to die a peaceful death.
strong.clear();
// And immediately, re-acquire a strong reference for the next loop
strong = weak.promote();
} while(strong != 0);
return 0;
}
4.2 threadLoop():
(1)run() -> _threadLoop() -> threadLoop():如果线程是第一次执行 _threadLoop()方法,会先行线程的readyToRun()方法,再执行threadLoop(),否则,直接执行threadLoop() ;
(2)threadLoop() 方法有返回值,如果 threadLoop() 返回 false 时,线程会做清理工作;然后退出 while 循环,结束执行;