14035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin/* Copyright (c) 2015, The Linux Foundation. All rights reserved. 24035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * 34035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * Redistribution and use in source and binary forms, with or without 44035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * modification, are permitted provided that the following conditions are 54035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * met: 64035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * * Redistributions of source code must retain the above copyright 74035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * notice, this list of conditions and the following disclaimer. 84035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * * Redistributions in binary form must reproduce the above 94035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * copyright notice, this list of conditions and the following 104035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * disclaimer in the documentation and/or other materials provided 114035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * with the distribution. 124035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * * Neither the name of The Linux Foundation, nor the names of its 134035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * contributors may be used to endorse or promote products derived 144035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * from this software without specific prior written permission. 154035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * 164035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 174035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 184035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 194035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 204035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 214035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 224035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 234035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 244035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 254035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 264035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin * 284035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin */ 294035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin#include <LocThread.h> 304035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin#include <string.h> 314035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin#include <pthread.h> 324035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 334035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjinclass LocThreadDelegate { 344035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin LocRunnable* mRunnable; 354035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin bool mJoinable; 364035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin pthread_t mThandle; 374035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin pthread_mutex_t mMutex; 384035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin int mRefCount; 394035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin ~LocThreadDelegate(); 404035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin LocThreadDelegate(LocThread::tCreate creator, const char* threadName, 414035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin LocRunnable* runnable, bool joinable); 424035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin void destroy(); 434035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjinpublic: 444035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin static LocThreadDelegate* create(LocThread::tCreate creator, 454035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin const char* threadName, LocRunnable* runnable, bool joinable); 464035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin void stop(); 474035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // bye() is for the parent thread to go away. if joinable, 484035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // parent must stop the spawned thread, join, and then 494035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // destroy(); if detached, the parent can go straight 504035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // ahead to destroy() 514035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin inline void bye() { mJoinable ? stop() : destroy(); } 524035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin inline bool isRunning() { return (NULL != mRunnable); } 534035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin static void* threadMain(void* arg); 544035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin}; 554035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 564035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// it is important to note that internal members must be 574035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// initialized to values as if pthread_create succeeds. 584035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// This is to avoid the race condition between the threads, 594035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// once the thread is created, some of these values will 604035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// be check in the spawned thread, and must set correctly 614035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// then and there. 624035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// However, upon pthread_create failure, the data members 634035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// must be set to indicate failure, e.g. mRunnable, and 644035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// threashold approprietly for destroy(), e.g. mRefCount. 654035be28a255eaa5605dbd9abeb2340db584249cPatrick TjinLocThreadDelegate::LocThreadDelegate(LocThread::tCreate creator, 664035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin const char* threadName, LocRunnable* runnable, bool joinable) : 674035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin mRunnable(runnable), mJoinable(joinable), mThandle(NULL), 684035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin mMutex(PTHREAD_MUTEX_INITIALIZER), mRefCount(2) { 694035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 704035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // set up thread name, if nothing is passed in 714035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin if (!threadName) { 724035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin threadName = "LocThread"; 734035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 744035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 754035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // create the thread here, then if successful 764035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // and a name is given, we set the thread name 774035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin if (creator) { 784035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin mThandle = creator(threadName, threadMain, this); 794035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } else if (pthread_create(&mThandle, NULL, threadMain, this)) { 804035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // pthread_create() failed 814035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin mThandle = NULL; 824035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 834035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 844035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin if (mThandle) { 854035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // set thread name 864035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin char lname[16]; 874035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin int len = sizeof(lname) - 1; 884035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin memcpy(lname, threadName, len); 894035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin lname[len] = 0; 904035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // set the thread name here 914035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin pthread_setname_np(mThandle, lname); 924035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 934035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // detach, if not joinable 944035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin if (!joinable) { 954035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin pthread_detach(mThandle); 964035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 974035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } else { 984035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // must set these values upon failure 994035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin mRunnable = NULL; 1004035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin mJoinable = false; 1014035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin mRefCount = 1; 1024035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 1034035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin} 1044035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 1054035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjininline 1064035be28a255eaa5605dbd9abeb2340db584249cPatrick TjinLocThreadDelegate::~LocThreadDelegate() { 1074035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // at this point nothing should need done any more 1084035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin} 1094035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 1104035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// factory method so that we could return NULL upon failure 1114035be28a255eaa5605dbd9abeb2340db584249cPatrick TjinLocThreadDelegate* LocThreadDelegate::create(LocThread::tCreate creator, 1124035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin const char* threadName, LocRunnable* runnable, bool joinable) { 1134035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin LocThreadDelegate* thread = NULL; 1144035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin if (runnable) { 1154035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin thread = new LocThreadDelegate(creator, threadName, runnable, joinable); 1164035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin if (thread && !thread->isRunning()) { 1174035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin thread->destroy(); 1184035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin thread = NULL; 1194035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 1204035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 1214035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 1224035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin return thread; 1234035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin} 1244035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 1254035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// The order is importang 1264035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// NULLing mRunnalbe stops the while loop in threadMain() 1274035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// join() if mJoinble must come before destroy() call, as 1284035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// the obj must remain alive at this time so that mThandle 1294035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// remains valud. 1304035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjinvoid LocThreadDelegate::stop() { 1314035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // mRunnable and mJoinable are reset on different triggers. 1324035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // mRunnable may get nulled on the spawned thread's way out; 1334035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // or here. 1344035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // mJouinable (if ever been true) gets falsed when client 1354035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // thread triggers stop, with either a stop() 1364035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // call or the client releases thread obj handle. 1374035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin if (mRunnable) { 1384035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin mRunnable = NULL; 1394035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 1404035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin if (mJoinable) { 1414035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin mJoinable = false; 1424035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin pthread_join(mThandle, NULL); 1434035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 1444035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // call destroy() to possibly delete the obj 1454035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin destroy(); 1464035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin} 1474035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 1484035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// method for clients to call to release the obj 1494035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// when it is a detached thread, the client thread 1504035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// and the spawned thread can both try to destroy() 1514035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// asynchronously. And we delete this obj when 1524035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// mRefCount becomes 0. 1534035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjinvoid LocThreadDelegate::destroy() { 1544035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // else case shouldn't happen, unless there is a 1554035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // leaking obj. But only our code here has such 1564035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // obj, so if we test our code well, else case 1574035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // will never happen 1584035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin if (mRefCount > 0) { 1594035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // we need a flag on the stack 1604035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin bool callDelete = false; 1614035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 1624035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // critical section between threads 1634035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin pthread_mutex_lock(&mMutex); 1644035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // last destroy() call 1654035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin callDelete = (1 == mRefCount--); 1664035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin pthread_mutex_unlock(&mMutex); 1674035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 1684035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // upon last destroy() call we delete this obj 1694035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin if (callDelete) { 1704035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin delete this; 1714035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 1724035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 1734035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin} 1744035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 1754035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjinvoid* LocThreadDelegate::threadMain(void* arg) { 1764035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin LocThreadDelegate* locThread = (LocThreadDelegate*)(arg); 1774035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 1784035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin if (locThread) { 1794035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin LocRunnable* runnable = locThread->mRunnable; 1804035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 1814035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin if (runnable) { 1824035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin if (locThread->isRunning()) { 1834035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin runnable->prerun(); 1844035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 1854035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 1864035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin while (locThread->isRunning() && runnable->run()); 1874035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 1884035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin if (locThread->isRunning()) { 1894035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin runnable->postrun(); 1904035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 1914035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 1924035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // at this time, locThread->mRunnable may or may not be NULL 1934035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // NULL it just to be safe and clean, as we want the field 1944035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // in the released memory slot to be NULL. 1954035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin locThread->mRunnable = NULL; 1964035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin delete runnable; 1974035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 1984035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin locThread->destroy(); 1994035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 2004035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 2014035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin return NULL; 2024035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin} 2034035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 2044035be28a255eaa5605dbd9abeb2340db584249cPatrick TjinLocThread::~LocThread() { 2054035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin if (mThread) { 2064035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin mThread->bye(); 2074035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin mThread = NULL; 2084035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 2094035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin} 2104035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 2114035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjinbool LocThread::start(tCreate creator, const char* threadName, LocRunnable* runnable, bool joinable) { 2124035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin bool success = false; 2134035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin if (!mThread) { 2144035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin mThread = LocThreadDelegate::create(creator, threadName, runnable, joinable); 2154035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin // true only if thread is created successfully 2164035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin success = (NULL != mThread); 2174035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 2184035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin return success; 2194035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin} 2204035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 2214035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjinvoid LocThread::stop() { 2224035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin if (mThread) { 2234035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin mThread->stop(); 2244035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin mThread = NULL; 2254035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 2264035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin} 2274035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 2284035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin#ifdef __LOC_DEBUG__ 2294035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 2304035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin#include <stdio.h> 2314035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin#include <stdlib.h> 2324035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin#include <unistd.h> 2334035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 2344035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjinclass LocRunnableTest1 : public LocRunnable { 2354035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin int mID; 2364035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjinpublic: 2374035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin LocRunnableTest1(int id) : LocRunnable(), mID(id) {} 2384035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin virtual bool run() { 2394035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin printf("LocRunnableTest1: %d\n", mID++); 2404035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin sleep(1); 2414035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin return true; 2424035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin } 2434035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin}; 2444035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 2454035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// on linux command line: 2464035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// 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 2474035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// test detached thread: valgrind ./a.out 0 2484035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin// test joinable thread: valgrind ./a.out 1 2494035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjinint main(int argc, char** argv) { 2504035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin LocRunnableTest1 test(10); 2514035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 2524035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin LocThread thread; 2534035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin thread.start("LocThreadTest", test, atoi(argv[1])); 2544035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 2554035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin sleep(10); 2564035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 2574035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin thread.stop(); 2584035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 2594035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin sleep(5); 2604035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 2614035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin return 0; 2624035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin} 2634035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin 2644035be28a255eaa5605dbd9abeb2340db584249cPatrick Tjin#endif 265