1eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh/* Copyright (c) 2015, The Linux Foundation. All rights reserved. 2eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * 3eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * Redistribution and use in source and binary forms, with or without 4eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * modification, are permitted provided that the following conditions are 5eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * met: 6eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * * Redistributions of source code must retain the above copyright 7eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * notice, this list of conditions and the following disclaimer. 8eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * * Redistributions in binary form must reproduce the above 9eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * copyright notice, this list of conditions and the following 10eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * disclaimer in the documentation and/or other materials provided 11eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * with the distribution. 12eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * * Neither the name of The Linux Foundation, nor the names of its 13eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * contributors may be used to endorse or promote products derived 14eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * from this software without specific prior written permission. 15eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * 16eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * 28eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh */ 29eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh#include <LocThread.h> 30eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh#include <string.h> 31eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh#include <pthread.h> 32eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh#include <platform_lib_macros.h> 33eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 34eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhclass LocThreadDelegate { 35eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh LocRunnable* mRunnable; 36eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh bool mJoinable; 37eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh pthread_t mThandle; 38eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh pthread_mutex_t mMutex; 39eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh int mRefCount; 40eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh ~LocThreadDelegate(); 41eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh LocThreadDelegate(LocThread::tCreate creator, const char* threadName, 42eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh LocRunnable* runnable, bool joinable); 43eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh void destroy(); 44eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhpublic: 45eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh static LocThreadDelegate* create(LocThread::tCreate creator, 46eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh const char* threadName, LocRunnable* runnable, bool joinable); 47eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh void stop(); 48eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // bye() is for the parent thread to go away. if joinable, 49eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // parent must stop the spawned thread, join, and then 50eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // destroy(); if detached, the parent can go straight 51eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // ahead to destroy() 52eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh inline void bye() { mJoinable ? stop() : destroy(); } 53eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh inline bool isRunning() { return (NULL != mRunnable); } 54eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh static void* threadMain(void* arg); 55eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}; 56eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 57eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// it is important to note that internal members must be 58eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// initialized to values as if pthread_create succeeds. 59eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// This is to avoid the race condition between the threads, 60eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// once the thread is created, some of these values will 61eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// be check in the spawned thread, and must set correctly 62eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// then and there. 63eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// However, upon pthread_create failure, the data members 64eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// must be set to indicate failure, e.g. mRunnable, and 65eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// threashold approprietly for destroy(), e.g. mRefCount. 66eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocThreadDelegate::LocThreadDelegate(LocThread::tCreate creator, 67eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh const char* threadName, LocRunnable* runnable, bool joinable) : 68eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh mRunnable(runnable), mJoinable(joinable), mThandle((pthread_t)NULL), 69eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh mMutex(PTHREAD_MUTEX_INITIALIZER), mRefCount(2) { 70eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 71eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // set up thread name, if nothing is passed in 72eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh if (!threadName) { 73eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh threadName = "LocThread"; 74eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 75eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 76eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // create the thread here, then if successful 77eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // and a name is given, we set the thread name 78eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh if (creator) { 79eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh mThandle = creator(threadName, threadMain, this); 80eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } else if (pthread_create(&mThandle, NULL, threadMain, this)) { 81eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // pthread_create() failed 82eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh mThandle = (pthread_t)NULL; 83eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 84eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 85eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh if (mThandle) { 86eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // set thread name 87eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh char lname[16]; 88eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh int len = (sizeof(lname)>sizeof(threadName)) ? 89eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh (sizeof(threadName) -1):(sizeof(lname) - 1); 90eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh memcpy(lname, threadName, len); 91eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh lname[len] = 0; 92eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // set the thread name here 93eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh pthread_setname_np(mThandle, lname); 94eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 95eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // detach, if not joinable 96eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh if (!joinable) { 97eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh pthread_detach(mThandle); 98eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 99eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } else { 100eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // must set these values upon failure 101eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh mRunnable = NULL; 102eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh mJoinable = false; 103eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh mRefCount = 1; 104eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 105eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh} 106eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 107eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhinline 108eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocThreadDelegate::~LocThreadDelegate() { 109eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // at this point nothing should need done any more 110eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh} 111eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 112eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// factory method so that we could return NULL upon failure 113eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocThreadDelegate* LocThreadDelegate::create(LocThread::tCreate creator, 114eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh const char* threadName, LocRunnable* runnable, bool joinable) { 115eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh LocThreadDelegate* thread = NULL; 116eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh if (runnable) { 117eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh thread = new LocThreadDelegate(creator, threadName, runnable, joinable); 118eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh if (thread && !thread->isRunning()) { 119eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh thread->destroy(); 120eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh thread = NULL; 121eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 122eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 123eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 124eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh return thread; 125eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh} 126eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 127eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// The order is importang 128eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// NULLing mRunnalbe stops the while loop in threadMain() 129eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// join() if mJoinble must come before destroy() call, as 130eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// the obj must remain alive at this time so that mThandle 131eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// remains valud. 132eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid LocThreadDelegate::stop() { 133eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // mRunnable and mJoinable are reset on different triggers. 134eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // mRunnable may get nulled on the spawned thread's way out; 135eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // or here. 136eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // mJouinable (if ever been true) gets falsed when client 137eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // thread triggers stop, with either a stop() 138eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // call or the client releases thread obj handle. 139eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh if (mRunnable) { 140eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh mRunnable = NULL; 141eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 142eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh if (mJoinable) { 143eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh mJoinable = false; 144eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh pthread_join(mThandle, NULL); 145eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 146eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // call destroy() to possibly delete the obj 147eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh destroy(); 148eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh} 149eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 150eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// method for clients to call to release the obj 151eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// when it is a detached thread, the client thread 152eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// and the spawned thread can both try to destroy() 153eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// asynchronously. And we delete this obj when 154eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// mRefCount becomes 0. 155eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid LocThreadDelegate::destroy() { 156eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // else case shouldn't happen, unless there is a 157eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // leaking obj. But only our code here has such 158eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // obj, so if we test our code well, else case 159eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // will never happen 160eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh if (mRefCount > 0) { 161eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // we need a flag on the stack 162eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh bool callDelete = false; 163eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 164eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // critical section between threads 165eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh pthread_mutex_lock(&mMutex); 166eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // last destroy() call 167eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh callDelete = (1 == mRefCount--); 168eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh pthread_mutex_unlock(&mMutex); 169eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 170eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // upon last destroy() call we delete this obj 171eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh if (callDelete) { 172eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh delete this; 173eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 174eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 175eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh} 176eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 177eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid* LocThreadDelegate::threadMain(void* arg) { 178eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh LocThreadDelegate* locThread = (LocThreadDelegate*)(arg); 179eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 180eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh if (locThread) { 181eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh LocRunnable* runnable = locThread->mRunnable; 182eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 183eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh if (runnable) { 184eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh if (locThread->isRunning()) { 185eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh runnable->prerun(); 186eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 187eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 188eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh while (locThread->isRunning() && runnable->run()); 189eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 190eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh if (locThread->isRunning()) { 191eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh runnable->postrun(); 192eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 193eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 194eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // at this time, locThread->mRunnable may or may not be NULL 195eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // NULL it just to be safe and clean, as we want the field 196eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // in the released memory slot to be NULL. 197eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh locThread->mRunnable = NULL; 198eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh delete runnable; 199eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 200eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh locThread->destroy(); 201eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 202eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 203eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh return NULL; 204eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh} 205eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 206eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocThread::~LocThread() { 207eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh if (mThread) { 208eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh mThread->bye(); 209eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh mThread = NULL; 210eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 211eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh} 212eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 213eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhbool LocThread::start(tCreate creator, const char* threadName, LocRunnable* runnable, bool joinable) { 214eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh bool success = false; 215eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh if (!mThread) { 216eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh mThread = LocThreadDelegate::create(creator, threadName, runnable, joinable); 217eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh // true only if thread is created successfully 218eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh success = (NULL != mThread); 219eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 220eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh return success; 221eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh} 222eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 223eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid LocThread::stop() { 224eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh if (mThread) { 225eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh mThread->stop(); 226eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh mThread = NULL; 227eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 228eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh} 229eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 230eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh#ifdef __LOC_DEBUG__ 231eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 232eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh#include <stdio.h> 233eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh#include <stdlib.h> 234eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh#include <unistd.h> 235eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 236eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhclass LocRunnableTest1 : public LocRunnable { 237eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh int mID; 238eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhpublic: 239eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh LocRunnableTest1(int id) : LocRunnable(), mID(id) {} 240eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh virtual bool run() { 241eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh printf("LocRunnableTest1: %d\n", mID++); 242eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh sleep(1); 243eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh return true; 244eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh } 245eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}; 246eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 247eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// on linux command line: 248eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// compile: g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -std=c++0x -I. -I../../../../vendor/qcom/proprietary/gps-internal/unit-tests/fakes_for_host -I../../../../system/core/include -lpthread LocThread.cpp 249eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// test detached thread: valgrind ./a.out 0 250eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh// test joinable thread: valgrind ./a.out 1 251eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhint main(int argc, char** argv) { 252eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh LocRunnableTest1 test(10); 253eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 254eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh LocThread thread; 255eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh thread.start("LocThreadTest", test, atoi(argv[1])); 256eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 257eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh sleep(10); 258eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 259eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh thread.stop(); 260eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 261eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh sleep(5); 262eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 263eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh return 0; 264eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh} 265eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh 266eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh#endif 267