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