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