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