1129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel/* Copyright (c) 2015, The Linux Foundation. All rights reserved. 2129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * 3129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * Redistribution and use in source and binary forms, with or without 4129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * modification, are permitted provided that the following conditions are 5129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * met: 6129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * * Redistributions of source code must retain the above copyright 7129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * notice, this list of conditions and the following disclaimer. 8129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * * Redistributions in binary form must reproduce the above 9129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * copyright notice, this list of conditions and the following 10129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * disclaimer in the documentation and/or other materials provided 11129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * with the distribution. 12129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * * Neither the name of The Linux Foundation, nor the names of its 13129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * contributors may be used to endorse or promote products derived 14129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * from this software without specific prior written permission. 15129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * 16129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel * 28129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel */ 29129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel#include <LocThread.h> 30129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel#include <string.h> 31129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel#include <pthread.h> 32129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel#include <platform_lib_macros.h> 33129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 34129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudelclass LocThreadDelegate { 35129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel LocRunnable* mRunnable; 36129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel bool mJoinable; 37129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel pthread_t mThandle; 38129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel pthread_mutex_t mMutex; 39129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel int mRefCount; 40129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel ~LocThreadDelegate(); 41129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel LocThreadDelegate(LocThread::tCreate creator, const char* threadName, 42129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel LocRunnable* runnable, bool joinable); 43129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel void destroy(); 44129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudelpublic: 45129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel static LocThreadDelegate* create(LocThread::tCreate creator, 46129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel const char* threadName, LocRunnable* runnable, bool joinable); 47129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel void stop(); 48129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // bye() is for the parent thread to go away. if joinable, 49129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // parent must stop the spawned thread, join, and then 50129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // destroy(); if detached, the parent can go straight 51129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // ahead to destroy() 52129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel inline void bye() { mJoinable ? stop() : destroy(); } 53129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel inline bool isRunning() { return (NULL != mRunnable); } 54129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel static void* threadMain(void* arg); 55129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel}; 56129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 57129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// it is important to note that internal members must be 58129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// initialized to values as if pthread_create succeeds. 59129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// This is to avoid the race condition between the threads, 60129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// once the thread is created, some of these values will 61129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// be check in the spawned thread, and must set correctly 62129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// then and there. 63129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// However, upon pthread_create failure, the data members 64129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// must be set to indicate failure, e.g. mRunnable, and 65129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// threashold approprietly for destroy(), e.g. mRefCount. 66129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry StrudelLocThreadDelegate::LocThreadDelegate(LocThread::tCreate creator, 67129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel const char* threadName, LocRunnable* runnable, bool joinable) : 68129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel mRunnable(runnable), mJoinable(joinable), mThandle(NULL), 69129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel mMutex(PTHREAD_MUTEX_INITIALIZER), mRefCount(2) { 70129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 71129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // set up thread name, if nothing is passed in 72129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel if (!threadName) { 73129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel threadName = "LocThread"; 74129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 75129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 76129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // create the thread here, then if successful 77129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // and a name is given, we set the thread name 78129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel if (creator) { 79129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel mThandle = creator(threadName, threadMain, this); 80129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } else if (pthread_create(&mThandle, NULL, threadMain, this)) { 81129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // pthread_create() failed 82129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel mThandle = NULL; 83129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 84129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 85129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel if (mThandle) { 86129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // set thread name 87129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel char lname[16]; 886f2a63d31df9024574b97a242c5e89e9252cb895Thierry Strudel int len = (sizeof(lname)>sizeof(threadName)) ? 896f2a63d31df9024574b97a242c5e89e9252cb895Thierry Strudel (sizeof(threadName) -1):(sizeof(lname) - 1); 906f2a63d31df9024574b97a242c5e89e9252cb895Thierry Strudel memcpy(lname, threadName, len); 916f2a63d31df9024574b97a242c5e89e9252cb895Thierry Strudel lname[len] = 0; 92129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // set the thread name here 93129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel pthread_setname_np(mThandle, lname); 94129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 95129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // detach, if not joinable 96129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel if (!joinable) { 97129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel pthread_detach(mThandle); 98129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 99129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } else { 100129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // must set these values upon failure 101129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel mRunnable = NULL; 102129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel mJoinable = false; 103129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel mRefCount = 1; 104129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 105129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel} 106129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 107129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudelinline 108129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry StrudelLocThreadDelegate::~LocThreadDelegate() { 109129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // at this point nothing should need done any more 110129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel} 111129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 112129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// factory method so that we could return NULL upon failure 113129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry StrudelLocThreadDelegate* LocThreadDelegate::create(LocThread::tCreate creator, 114129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel const char* threadName, LocRunnable* runnable, bool joinable) { 115129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel LocThreadDelegate* thread = NULL; 116129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel if (runnable) { 117129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel thread = new LocThreadDelegate(creator, threadName, runnable, joinable); 118129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel if (thread && !thread->isRunning()) { 119129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel thread->destroy(); 120129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel thread = NULL; 121129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 122129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 123129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 124129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel return thread; 125129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel} 126129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 127129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// The order is importang 128129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// NULLing mRunnalbe stops the while loop in threadMain() 129129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// join() if mJoinble must come before destroy() call, as 130129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// the obj must remain alive at this time so that mThandle 131129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// remains valud. 132129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudelvoid LocThreadDelegate::stop() { 133129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // mRunnable and mJoinable are reset on different triggers. 134129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // mRunnable may get nulled on the spawned thread's way out; 135129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // or here. 136129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // mJouinable (if ever been true) gets falsed when client 137129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // thread triggers stop, with either a stop() 138129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // call or the client releases thread obj handle. 139129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel if (mRunnable) { 140129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel mRunnable = NULL; 141129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 142129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel if (mJoinable) { 143129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel mJoinable = false; 144129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel pthread_join(mThandle, NULL); 145129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 146129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // call destroy() to possibly delete the obj 147129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel destroy(); 148129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel} 149129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 150129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// method for clients to call to release the obj 151129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// when it is a detached thread, the client thread 152129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// and the spawned thread can both try to destroy() 153129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// asynchronously. And we delete this obj when 154129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// mRefCount becomes 0. 155129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudelvoid LocThreadDelegate::destroy() { 156129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // else case shouldn't happen, unless there is a 157129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // leaking obj. But only our code here has such 158129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // obj, so if we test our code well, else case 159129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // will never happen 160129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel if (mRefCount > 0) { 161129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // we need a flag on the stack 162129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel bool callDelete = false; 163129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 164129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // critical section between threads 165129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel pthread_mutex_lock(&mMutex); 166129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // last destroy() call 167129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel callDelete = (1 == mRefCount--); 168129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel pthread_mutex_unlock(&mMutex); 169129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 170129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // upon last destroy() call we delete this obj 171129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel if (callDelete) { 172129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel delete this; 173129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 174129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 175129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel} 176129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 177129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudelvoid* LocThreadDelegate::threadMain(void* arg) { 178129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel LocThreadDelegate* locThread = (LocThreadDelegate*)(arg); 179129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 180129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel if (locThread) { 181129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel LocRunnable* runnable = locThread->mRunnable; 182129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 183129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel if (runnable) { 184129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel if (locThread->isRunning()) { 185129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel runnable->prerun(); 186129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 187129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 188129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel while (locThread->isRunning() && runnable->run()); 189129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 190129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel if (locThread->isRunning()) { 191129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel runnable->postrun(); 192129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 193129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 194129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // at this time, locThread->mRunnable may or may not be NULL 195129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // NULL it just to be safe and clean, as we want the field 196129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // in the released memory slot to be NULL. 197129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel locThread->mRunnable = NULL; 198129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel delete runnable; 199129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 200129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel locThread->destroy(); 201129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 202129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 203129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel return NULL; 204129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel} 205129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 206129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry StrudelLocThread::~LocThread() { 207129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel if (mThread) { 208129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel mThread->bye(); 209129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel mThread = NULL; 210129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 211129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel} 212129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 213129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudelbool LocThread::start(tCreate creator, const char* threadName, LocRunnable* runnable, bool joinable) { 214129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel bool success = false; 215129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel if (!mThread) { 216129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel mThread = LocThreadDelegate::create(creator, threadName, runnable, joinable); 217129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel // true only if thread is created successfully 218129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel success = (NULL != mThread); 219129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 220129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel return success; 221129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel} 222129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 223129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudelvoid LocThread::stop() { 224129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel if (mThread) { 225129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel mThread->stop(); 226129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel mThread = NULL; 227129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 228129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel} 229129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 230129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel#ifdef __LOC_DEBUG__ 231129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 232129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel#include <stdio.h> 233129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel#include <stdlib.h> 234129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel#include <unistd.h> 235129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 236129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudelclass LocRunnableTest1 : public LocRunnable { 237129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel int mID; 238129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudelpublic: 239129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel LocRunnableTest1(int id) : LocRunnable(), mID(id) {} 240129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel virtual bool run() { 241129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel printf("LocRunnableTest1: %d\n", mID++); 242129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel sleep(1); 243129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel return true; 244129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel } 245129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel}; 246129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 247129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// on linux command line: 248129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// 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 249129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// test detached thread: valgrind ./a.out 0 250129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel// test joinable thread: valgrind ./a.out 1 251129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudelint main(int argc, char** argv) { 252129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel LocRunnableTest1 test(10); 253129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 254129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel LocThread thread; 255129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel thread.start("LocThreadTest", test, atoi(argv[1])); 256129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 257129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel sleep(10); 258129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 259129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel thread.stop(); 260129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 261129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel sleep(5); 262129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 263129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel return 0; 264129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel} 265129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel 266129edaf7d0025e2828a8bee025f7b1bac7a68da6Thierry Strudel#endif 267