split utils/threads.h into multiple headers
AndroidDefs.h - C/C++ enums and types Mutex.h - Mutex class declaration Condition.h - Condition class declaration RWLock.h - RWLock class declaration Thread.h - Thread class declaration AndroidThreads.h - low-level thread creation functions threads.h - includes all the above for backward source compatibility Change-Id: Ia2f80c175333b59a41d1720985810bb2346e94cb Note: implementations are still in Threads.cpp
This commit is contained in:
parent
2ccfe1a060
commit
2bd99599bb
7 changed files with 781 additions and 546 deletions
136
include/utils/AndroidThreads.h
Normal file
136
include/utils/AndroidThreads.h
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _LIBS_UTILS_ANDROID_THREADS_H
|
||||
#define _LIBS_UTILS_ANDROID_THREADS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined(HAVE_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <utils/ThreadDefs.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// C API
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Create and run a new thread.
|
||||
extern int androidCreateThread(android_thread_func_t, void *);
|
||||
|
||||
// Create thread with lots of parameters
|
||||
extern int androidCreateThreadEtc(android_thread_func_t entryFunction,
|
||||
void *userData,
|
||||
const char* threadName,
|
||||
int32_t threadPriority,
|
||||
size_t threadStackSize,
|
||||
android_thread_id_t *threadId);
|
||||
|
||||
// Get some sort of unique identifier for the current thread.
|
||||
extern android_thread_id_t androidGetThreadId();
|
||||
|
||||
// Low-level thread creation -- never creates threads that can
|
||||
// interact with the Java VM.
|
||||
extern int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
|
||||
void *userData,
|
||||
const char* threadName,
|
||||
int32_t threadPriority,
|
||||
size_t threadStackSize,
|
||||
android_thread_id_t *threadId);
|
||||
|
||||
// Used by the Java Runtime to control how threads are created, so that
|
||||
// they can be proper and lovely Java threads.
|
||||
typedef int (*android_create_thread_fn)(android_thread_func_t entryFunction,
|
||||
void *userData,
|
||||
const char* threadName,
|
||||
int32_t threadPriority,
|
||||
size_t threadStackSize,
|
||||
android_thread_id_t *threadId);
|
||||
|
||||
extern void androidSetCreateThreadFunc(android_create_thread_fn func);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Extra functions working with raw pids.
|
||||
|
||||
// Get pid for the current thread.
|
||||
extern pid_t androidGetTid();
|
||||
|
||||
// Change the scheduling group of a particular thread. The group
|
||||
// should be one of the ANDROID_TGROUP constants. Returns BAD_VALUE if
|
||||
// grp is out of range, else another non-zero value with errno set if
|
||||
// the operation failed. Thread ID zero means current thread.
|
||||
extern int androidSetThreadSchedulingGroup(pid_t tid, int grp);
|
||||
|
||||
// Change the priority AND scheduling group of a particular thread. The priority
|
||||
// should be one of the ANDROID_PRIORITY constants. Returns INVALID_OPERATION
|
||||
// if the priority set failed, else another value if just the group set failed;
|
||||
// in either case errno is set. Thread ID zero means current thread.
|
||||
extern int androidSetThreadPriority(pid_t tid, int prio);
|
||||
|
||||
// Get the current priority of a particular thread. Returns one of the
|
||||
// ANDROID_PRIORITY constants or a negative result in case of error.
|
||||
extern int androidGetThreadPriority(pid_t tid);
|
||||
|
||||
// Get the current scheduling group of a particular thread. Normally returns
|
||||
// one of the ANDROID_TGROUP constants other than ANDROID_TGROUP_DEFAULT.
|
||||
// Returns ANDROID_TGROUP_DEFAULT if no pthread support (e.g. on host) or if
|
||||
// scheduling groups are disabled. Returns INVALID_OPERATION if unexpected error.
|
||||
// Thread ID zero means current thread.
|
||||
extern int androidGetThreadSchedulingGroup(pid_t tid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// C++ API
|
||||
#ifdef __cplusplus
|
||||
namespace android {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Create and run a new thread.
|
||||
inline bool createThread(thread_func_t f, void *a) {
|
||||
return androidCreateThread(f, a) ? true : false;
|
||||
}
|
||||
|
||||
// Create thread with lots of parameters
|
||||
inline bool createThreadEtc(thread_func_t entryFunction,
|
||||
void *userData,
|
||||
const char* threadName = "android:unnamed_thread",
|
||||
int32_t threadPriority = PRIORITY_DEFAULT,
|
||||
size_t threadStackSize = 0,
|
||||
thread_id_t *threadId = 0)
|
||||
{
|
||||
return androidCreateThreadEtc(entryFunction, userData, threadName,
|
||||
threadPriority, threadStackSize, threadId) ? true : false;
|
||||
}
|
||||
|
||||
// Get some sort of unique identifier for the current thread.
|
||||
inline thread_id_t getThreadId() {
|
||||
return androidGetThreadId();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
#endif // __cplusplus
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#endif // _LIBS_UTILS_ANDROID_THREADS_H
|
134
include/utils/Condition.h
Normal file
134
include/utils/Condition.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _LIBS_UTILS_CONDITION_H
|
||||
#define _LIBS_UTILS_CONDITION_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#if defined(HAVE_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Mutex.h>
|
||||
#include <utils/Timers.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Condition variable class. The implementation is system-dependent.
|
||||
*
|
||||
* Condition variables are paired up with mutexes. Lock the mutex,
|
||||
* call wait(), then either re-wait() if things aren't quite what you want,
|
||||
* or unlock the mutex and continue. All threads calling wait() must
|
||||
* use the same mutex for a given Condition.
|
||||
*/
|
||||
class Condition {
|
||||
public:
|
||||
enum {
|
||||
PRIVATE = 0,
|
||||
SHARED = 1
|
||||
};
|
||||
|
||||
Condition();
|
||||
Condition(int type);
|
||||
~Condition();
|
||||
// Wait on the condition variable. Lock the mutex before calling.
|
||||
status_t wait(Mutex& mutex);
|
||||
// same with relative timeout
|
||||
status_t waitRelative(Mutex& mutex, nsecs_t reltime);
|
||||
// Signal the condition variable, allowing one thread to continue.
|
||||
void signal();
|
||||
// Signal the condition variable, allowing all threads to continue.
|
||||
void broadcast();
|
||||
|
||||
private:
|
||||
#if defined(HAVE_PTHREADS)
|
||||
pthread_cond_t mCond;
|
||||
#else
|
||||
void* mState;
|
||||
#endif
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#if defined(HAVE_PTHREADS)
|
||||
|
||||
inline Condition::Condition() {
|
||||
pthread_cond_init(&mCond, NULL);
|
||||
}
|
||||
inline Condition::Condition(int type) {
|
||||
if (type == SHARED) {
|
||||
pthread_condattr_t attr;
|
||||
pthread_condattr_init(&attr);
|
||||
pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
|
||||
pthread_cond_init(&mCond, &attr);
|
||||
pthread_condattr_destroy(&attr);
|
||||
} else {
|
||||
pthread_cond_init(&mCond, NULL);
|
||||
}
|
||||
}
|
||||
inline Condition::~Condition() {
|
||||
pthread_cond_destroy(&mCond);
|
||||
}
|
||||
inline status_t Condition::wait(Mutex& mutex) {
|
||||
return -pthread_cond_wait(&mCond, &mutex.mMutex);
|
||||
}
|
||||
inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) {
|
||||
#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
|
||||
struct timespec ts;
|
||||
ts.tv_sec = reltime/1000000000;
|
||||
ts.tv_nsec = reltime%1000000000;
|
||||
return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
|
||||
#else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
|
||||
struct timespec ts;
|
||||
#if defined(HAVE_POSIX_CLOCKS)
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
#else // HAVE_POSIX_CLOCKS
|
||||
// we don't support the clocks here.
|
||||
struct timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
ts.tv_sec = t.tv_sec;
|
||||
ts.tv_nsec= t.tv_usec*1000;
|
||||
#endif // HAVE_POSIX_CLOCKS
|
||||
ts.tv_sec += reltime/1000000000;
|
||||
ts.tv_nsec+= reltime%1000000000;
|
||||
if (ts.tv_nsec >= 1000000000) {
|
||||
ts.tv_nsec -= 1000000000;
|
||||
ts.tv_sec += 1;
|
||||
}
|
||||
return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
|
||||
#endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
|
||||
}
|
||||
inline void Condition::signal() {
|
||||
pthread_cond_signal(&mCond);
|
||||
}
|
||||
inline void Condition::broadcast() {
|
||||
pthread_cond_broadcast(&mCond);
|
||||
}
|
||||
|
||||
#endif // HAVE_PTHREADS
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // _LIBS_UTILS_CONDITON_H
|
137
include/utils/Mutex.h
Normal file
137
include/utils/Mutex.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _LIBS_UTILS_MUTEX_H
|
||||
#define _LIBS_UTILS_MUTEX_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#if defined(HAVE_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <utils/Errors.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class Condition;
|
||||
|
||||
/*
|
||||
* Simple mutex class. The implementation is system-dependent.
|
||||
*
|
||||
* The mutex must be unlocked by the thread that locked it. They are not
|
||||
* recursive, i.e. the same thread can't lock it multiple times.
|
||||
*/
|
||||
class Mutex {
|
||||
public:
|
||||
enum {
|
||||
PRIVATE = 0,
|
||||
SHARED = 1
|
||||
};
|
||||
|
||||
Mutex();
|
||||
Mutex(const char* name);
|
||||
Mutex(int type, const char* name = NULL);
|
||||
~Mutex();
|
||||
|
||||
// lock or unlock the mutex
|
||||
status_t lock();
|
||||
void unlock();
|
||||
|
||||
// lock if possible; returns 0 on success, error otherwise
|
||||
status_t tryLock();
|
||||
|
||||
// Manages the mutex automatically. It'll be locked when Autolock is
|
||||
// constructed and released when Autolock goes out of scope.
|
||||
class Autolock {
|
||||
public:
|
||||
inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); }
|
||||
inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
|
||||
inline ~Autolock() { mLock.unlock(); }
|
||||
private:
|
||||
Mutex& mLock;
|
||||
};
|
||||
|
||||
private:
|
||||
friend class Condition;
|
||||
|
||||
// A mutex cannot be copied
|
||||
Mutex(const Mutex&);
|
||||
Mutex& operator = (const Mutex&);
|
||||
|
||||
#if defined(HAVE_PTHREADS)
|
||||
pthread_mutex_t mMutex;
|
||||
#else
|
||||
void _init();
|
||||
void* mState;
|
||||
#endif
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#if defined(HAVE_PTHREADS)
|
||||
|
||||
inline Mutex::Mutex() {
|
||||
pthread_mutex_init(&mMutex, NULL);
|
||||
}
|
||||
inline Mutex::Mutex(const char* name) {
|
||||
pthread_mutex_init(&mMutex, NULL);
|
||||
}
|
||||
inline Mutex::Mutex(int type, const char* name) {
|
||||
if (type == SHARED) {
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
|
||||
pthread_mutex_init(&mMutex, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
} else {
|
||||
pthread_mutex_init(&mMutex, NULL);
|
||||
}
|
||||
}
|
||||
inline Mutex::~Mutex() {
|
||||
pthread_mutex_destroy(&mMutex);
|
||||
}
|
||||
inline status_t Mutex::lock() {
|
||||
return -pthread_mutex_lock(&mMutex);
|
||||
}
|
||||
inline void Mutex::unlock() {
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
}
|
||||
inline status_t Mutex::tryLock() {
|
||||
return -pthread_mutex_trylock(&mMutex);
|
||||
}
|
||||
|
||||
#endif // HAVE_PTHREADS
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Automatic mutex. Declare one of these at the top of a function.
|
||||
* When the function returns, it will go out of scope, and release the
|
||||
* mutex.
|
||||
*/
|
||||
|
||||
typedef Mutex::Autolock AutoMutex;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // _LIBS_UTILS_MUTEX_H
|
126
include/utils/RWLock.h
Normal file
126
include/utils/RWLock.h
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _LIBS_UTILS_RWLOCK_H
|
||||
#define _LIBS_UTILS_RWLOCK_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined(HAVE_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/ThreadDefs.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#if defined(HAVE_PTHREADS)
|
||||
|
||||
/*
|
||||
* Simple mutex class. The implementation is system-dependent.
|
||||
*
|
||||
* The mutex must be unlocked by the thread that locked it. They are not
|
||||
* recursive, i.e. the same thread can't lock it multiple times.
|
||||
*/
|
||||
class RWLock {
|
||||
public:
|
||||
enum {
|
||||
PRIVATE = 0,
|
||||
SHARED = 1
|
||||
};
|
||||
|
||||
RWLock();
|
||||
RWLock(const char* name);
|
||||
RWLock(int type, const char* name = NULL);
|
||||
~RWLock();
|
||||
|
||||
status_t readLock();
|
||||
status_t tryReadLock();
|
||||
status_t writeLock();
|
||||
status_t tryWriteLock();
|
||||
void unlock();
|
||||
|
||||
class AutoRLock {
|
||||
public:
|
||||
inline AutoRLock(RWLock& rwlock) : mLock(rwlock) { mLock.readLock(); }
|
||||
inline ~AutoRLock() { mLock.unlock(); }
|
||||
private:
|
||||
RWLock& mLock;
|
||||
};
|
||||
|
||||
class AutoWLock {
|
||||
public:
|
||||
inline AutoWLock(RWLock& rwlock) : mLock(rwlock) { mLock.writeLock(); }
|
||||
inline ~AutoWLock() { mLock.unlock(); }
|
||||
private:
|
||||
RWLock& mLock;
|
||||
};
|
||||
|
||||
private:
|
||||
// A RWLock cannot be copied
|
||||
RWLock(const RWLock&);
|
||||
RWLock& operator = (const RWLock&);
|
||||
|
||||
pthread_rwlock_t mRWLock;
|
||||
};
|
||||
|
||||
inline RWLock::RWLock() {
|
||||
pthread_rwlock_init(&mRWLock, NULL);
|
||||
}
|
||||
inline RWLock::RWLock(const char* name) {
|
||||
pthread_rwlock_init(&mRWLock, NULL);
|
||||
}
|
||||
inline RWLock::RWLock(int type, const char* name) {
|
||||
if (type == SHARED) {
|
||||
pthread_rwlockattr_t attr;
|
||||
pthread_rwlockattr_init(&attr);
|
||||
pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
|
||||
pthread_rwlock_init(&mRWLock, &attr);
|
||||
pthread_rwlockattr_destroy(&attr);
|
||||
} else {
|
||||
pthread_rwlock_init(&mRWLock, NULL);
|
||||
}
|
||||
}
|
||||
inline RWLock::~RWLock() {
|
||||
pthread_rwlock_destroy(&mRWLock);
|
||||
}
|
||||
inline status_t RWLock::readLock() {
|
||||
return -pthread_rwlock_rdlock(&mRWLock);
|
||||
}
|
||||
inline status_t RWLock::tryReadLock() {
|
||||
return -pthread_rwlock_tryrdlock(&mRWLock);
|
||||
}
|
||||
inline status_t RWLock::writeLock() {
|
||||
return -pthread_rwlock_wrlock(&mRWLock);
|
||||
}
|
||||
inline status_t RWLock::tryWriteLock() {
|
||||
return -pthread_rwlock_trywrlock(&mRWLock);
|
||||
}
|
||||
inline void RWLock::unlock() {
|
||||
pthread_rwlock_unlock(&mRWLock);
|
||||
}
|
||||
|
||||
#endif // HAVE_PTHREADS
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // _LIBS_UTILS_RWLOCK_H
|
113
include/utils/Thread.h
Normal file
113
include/utils/Thread.h
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _LIBS_UTILS_THREAD_H
|
||||
#define _LIBS_UTILS_THREAD_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#if defined(HAVE_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <utils/Condition.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Mutex.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/Timers.h>
|
||||
#include <utils/ThreadDefs.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class Thread : virtual public RefBase
|
||||
{
|
||||
public:
|
||||
// Create a Thread object, but doesn't create or start the associated
|
||||
// thread. See the run() method.
|
||||
Thread(bool canCallJava = true);
|
||||
virtual ~Thread();
|
||||
|
||||
// Start the thread in threadLoop() which needs to be implemented.
|
||||
virtual status_t run( const char* name = 0,
|
||||
int32_t priority = PRIORITY_DEFAULT,
|
||||
size_t stack = 0);
|
||||
|
||||
// Ask this object's thread to exit. This function is asynchronous, when the
|
||||
// function returns the thread might still be running. Of course, this
|
||||
// function can be called from a different thread.
|
||||
virtual void requestExit();
|
||||
|
||||
// Good place to do one-time initializations
|
||||
virtual status_t readyToRun();
|
||||
|
||||
// Call requestExit() and wait until this object's thread exits.
|
||||
// BE VERY CAREFUL of deadlocks. In particular, it would be silly to call
|
||||
// this function from this object's thread. Will return WOULD_BLOCK in
|
||||
// that case.
|
||||
status_t requestExitAndWait();
|
||||
|
||||
// Wait until this object's thread exits. Returns immediately if not yet running.
|
||||
// Do not call from this object's thread; will return WOULD_BLOCK in that case.
|
||||
status_t join();
|
||||
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
// Return the thread's kernel ID, same as the thread itself calling gettid() or
|
||||
// androidGetTid(), or -1 if the thread is not running.
|
||||
pid_t getTid() const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// exitPending() returns true if requestExit() has been called.
|
||||
bool exitPending() const;
|
||||
|
||||
private:
|
||||
// Derived class must implement threadLoop(). The thread starts its life
|
||||
// here. There are two ways of using the Thread object:
|
||||
// 1) loop: if threadLoop() returns true, it will be called again if
|
||||
// requestExit() wasn't called.
|
||||
// 2) once: if threadLoop() returns false, the thread will exit upon return.
|
||||
virtual bool threadLoop() = 0;
|
||||
|
||||
private:
|
||||
Thread& operator=(const Thread&);
|
||||
static int _threadLoop(void* user);
|
||||
const bool mCanCallJava;
|
||||
// always hold mLock when reading or writing
|
||||
thread_id_t mThread;
|
||||
mutable Mutex mLock;
|
||||
Condition mThreadExitedCondition;
|
||||
status_t mStatus;
|
||||
// note that all accesses of mExitPending and mRunning need to hold mLock
|
||||
volatile bool mExitPending;
|
||||
volatile bool mRunning;
|
||||
sp<Thread> mHoldSelf;
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
// legacy for debugging, not used by getTid() as it is set by the child thread
|
||||
// and so is not initialized until the child reaches that point
|
||||
pid_t mTid;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
}; // namespace android
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
#endif // _LIBS_UTILS_THREAD_H
|
||||
// ---------------------------------------------------------------------------
|
123
include/utils/ThreadDefs.h
Normal file
123
include/utils/ThreadDefs.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _LIBS_UTILS_THREAD_DEFS_H
|
||||
#define _LIBS_UTILS_THREAD_DEFS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <system/graphics.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// C API
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void* android_thread_id_t;
|
||||
|
||||
typedef int (*android_thread_func_t)(void*);
|
||||
|
||||
enum {
|
||||
/*
|
||||
* ***********************************************
|
||||
* ** Keep in sync with android.os.Process.java **
|
||||
* ***********************************************
|
||||
*
|
||||
* This maps directly to the "nice" priorities we use in Android.
|
||||
* A thread priority should be chosen inverse-proportionally to
|
||||
* the amount of work the thread is expected to do. The more work
|
||||
* a thread will do, the less favorable priority it should get so that
|
||||
* it doesn't starve the system. Threads not behaving properly might
|
||||
* be "punished" by the kernel.
|
||||
* Use the levels below when appropriate. Intermediate values are
|
||||
* acceptable, preferably use the {MORE|LESS}_FAVORABLE constants below.
|
||||
*/
|
||||
ANDROID_PRIORITY_LOWEST = 19,
|
||||
|
||||
/* use for background tasks */
|
||||
ANDROID_PRIORITY_BACKGROUND = 10,
|
||||
|
||||
/* most threads run at normal priority */
|
||||
ANDROID_PRIORITY_NORMAL = 0,
|
||||
|
||||
/* threads currently running a UI that the user is interacting with */
|
||||
ANDROID_PRIORITY_FOREGROUND = -2,
|
||||
|
||||
/* the main UI thread has a slightly more favorable priority */
|
||||
ANDROID_PRIORITY_DISPLAY = -4,
|
||||
|
||||
/* ui service treads might want to run at a urgent display (uncommon) */
|
||||
ANDROID_PRIORITY_URGENT_DISPLAY = HAL_PRIORITY_URGENT_DISPLAY,
|
||||
|
||||
/* all normal audio threads */
|
||||
ANDROID_PRIORITY_AUDIO = -16,
|
||||
|
||||
/* service audio threads (uncommon) */
|
||||
ANDROID_PRIORITY_URGENT_AUDIO = -19,
|
||||
|
||||
/* should never be used in practice. regular process might not
|
||||
* be allowed to use this level */
|
||||
ANDROID_PRIORITY_HIGHEST = -20,
|
||||
|
||||
ANDROID_PRIORITY_DEFAULT = ANDROID_PRIORITY_NORMAL,
|
||||
ANDROID_PRIORITY_MORE_FAVORABLE = -1,
|
||||
ANDROID_PRIORITY_LESS_FAVORABLE = +1,
|
||||
};
|
||||
|
||||
enum {
|
||||
ANDROID_TGROUP_DEFAULT = 0,
|
||||
ANDROID_TGROUP_BG_NONINTERACT = 1,
|
||||
ANDROID_TGROUP_FG_BOOST = 2,
|
||||
ANDROID_TGROUP_MAX = ANDROID_TGROUP_FG_BOOST,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// C++ API
|
||||
#ifdef __cplusplus
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
typedef android_thread_id_t thread_id_t;
|
||||
typedef android_thread_func_t thread_func_t;
|
||||
|
||||
enum {
|
||||
PRIORITY_LOWEST = ANDROID_PRIORITY_LOWEST,
|
||||
PRIORITY_BACKGROUND = ANDROID_PRIORITY_BACKGROUND,
|
||||
PRIORITY_NORMAL = ANDROID_PRIORITY_NORMAL,
|
||||
PRIORITY_FOREGROUND = ANDROID_PRIORITY_FOREGROUND,
|
||||
PRIORITY_DISPLAY = ANDROID_PRIORITY_DISPLAY,
|
||||
PRIORITY_URGENT_DISPLAY = ANDROID_PRIORITY_URGENT_DISPLAY,
|
||||
PRIORITY_AUDIO = ANDROID_PRIORITY_AUDIO,
|
||||
PRIORITY_URGENT_AUDIO = ANDROID_PRIORITY_URGENT_AUDIO,
|
||||
PRIORITY_HIGHEST = ANDROID_PRIORITY_HIGHEST,
|
||||
PRIORITY_DEFAULT = ANDROID_PRIORITY_DEFAULT,
|
||||
PRIORITY_MORE_FAVORABLE = ANDROID_PRIORITY_MORE_FAVORABLE,
|
||||
PRIORITY_LESS_FAVORABLE = ANDROID_PRIORITY_LESS_FAVORABLE,
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
#endif // __cplusplus
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif // _LIBS_UTILS_THREAD_DEFS_H
|
|
@ -17,556 +17,22 @@
|
|||
#ifndef _LIBS_UTILS_THREADS_H
|
||||
#define _LIBS_UTILS_THREADS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <system/graphics.h>
|
||||
/*
|
||||
* Please, DO NOT USE!
|
||||
*
|
||||
* This file is here only for legacy reasons. Instead, include directly
|
||||
* the headers you need below.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(HAVE_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// C API
|
||||
#include <utils/AndroidThreads.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void* android_thread_id_t;
|
||||
|
||||
typedef int (*android_thread_func_t)(void*);
|
||||
|
||||
enum {
|
||||
/*
|
||||
* ***********************************************
|
||||
* ** Keep in sync with android.os.Process.java **
|
||||
* ***********************************************
|
||||
*
|
||||
* This maps directly to the "nice" priorities we use in Android.
|
||||
* A thread priority should be chosen inverse-proportionally to
|
||||
* the amount of work the thread is expected to do. The more work
|
||||
* a thread will do, the less favorable priority it should get so that
|
||||
* it doesn't starve the system. Threads not behaving properly might
|
||||
* be "punished" by the kernel.
|
||||
* Use the levels below when appropriate. Intermediate values are
|
||||
* acceptable, preferably use the {MORE|LESS}_FAVORABLE constants below.
|
||||
*/
|
||||
ANDROID_PRIORITY_LOWEST = 19,
|
||||
|
||||
/* use for background tasks */
|
||||
ANDROID_PRIORITY_BACKGROUND = 10,
|
||||
|
||||
/* most threads run at normal priority */
|
||||
ANDROID_PRIORITY_NORMAL = 0,
|
||||
|
||||
/* threads currently running a UI that the user is interacting with */
|
||||
ANDROID_PRIORITY_FOREGROUND = -2,
|
||||
|
||||
/* the main UI thread has a slightly more favorable priority */
|
||||
ANDROID_PRIORITY_DISPLAY = -4,
|
||||
|
||||
/* ui service treads might want to run at a urgent display (uncommon) */
|
||||
ANDROID_PRIORITY_URGENT_DISPLAY = HAL_PRIORITY_URGENT_DISPLAY,
|
||||
|
||||
/* all normal audio threads */
|
||||
ANDROID_PRIORITY_AUDIO = -16,
|
||||
|
||||
/* service audio threads (uncommon) */
|
||||
ANDROID_PRIORITY_URGENT_AUDIO = -19,
|
||||
|
||||
/* should never be used in practice. regular process might not
|
||||
* be allowed to use this level */
|
||||
ANDROID_PRIORITY_HIGHEST = -20,
|
||||
|
||||
ANDROID_PRIORITY_DEFAULT = ANDROID_PRIORITY_NORMAL,
|
||||
ANDROID_PRIORITY_MORE_FAVORABLE = -1,
|
||||
ANDROID_PRIORITY_LESS_FAVORABLE = +1,
|
||||
};
|
||||
|
||||
enum {
|
||||
ANDROID_TGROUP_DEFAULT = 0,
|
||||
ANDROID_TGROUP_BG_NONINTERACT = 1,
|
||||
ANDROID_TGROUP_FG_BOOST = 2,
|
||||
ANDROID_TGROUP_MAX = ANDROID_TGROUP_FG_BOOST,
|
||||
};
|
||||
|
||||
// Create and run a new thread.
|
||||
extern int androidCreateThread(android_thread_func_t, void *);
|
||||
|
||||
// Create thread with lots of parameters
|
||||
extern int androidCreateThreadEtc(android_thread_func_t entryFunction,
|
||||
void *userData,
|
||||
const char* threadName,
|
||||
int32_t threadPriority,
|
||||
size_t threadStackSize,
|
||||
android_thread_id_t *threadId);
|
||||
|
||||
// Get some sort of unique identifier for the current thread.
|
||||
extern android_thread_id_t androidGetThreadId();
|
||||
|
||||
// Low-level thread creation -- never creates threads that can
|
||||
// interact with the Java VM.
|
||||
extern int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
|
||||
void *userData,
|
||||
const char* threadName,
|
||||
int32_t threadPriority,
|
||||
size_t threadStackSize,
|
||||
android_thread_id_t *threadId);
|
||||
|
||||
// Used by the Java Runtime to control how threads are created, so that
|
||||
// they can be proper and lovely Java threads.
|
||||
typedef int (*android_create_thread_fn)(android_thread_func_t entryFunction,
|
||||
void *userData,
|
||||
const char* threadName,
|
||||
int32_t threadPriority,
|
||||
size_t threadStackSize,
|
||||
android_thread_id_t *threadId);
|
||||
|
||||
extern void androidSetCreateThreadFunc(android_create_thread_fn func);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Extra functions working with raw pids.
|
||||
|
||||
// Get pid for the current thread.
|
||||
extern pid_t androidGetTid();
|
||||
|
||||
// Change the scheduling group of a particular thread. The group
|
||||
// should be one of the ANDROID_TGROUP constants. Returns BAD_VALUE if
|
||||
// grp is out of range, else another non-zero value with errno set if
|
||||
// the operation failed. Thread ID zero means current thread.
|
||||
extern int androidSetThreadSchedulingGroup(pid_t tid, int grp);
|
||||
|
||||
// Change the priority AND scheduling group of a particular thread. The priority
|
||||
// should be one of the ANDROID_PRIORITY constants. Returns INVALID_OPERATION
|
||||
// if the priority set failed, else another value if just the group set failed;
|
||||
// in either case errno is set. Thread ID zero means current thread.
|
||||
extern int androidSetThreadPriority(pid_t tid, int prio);
|
||||
|
||||
// Get the current priority of a particular thread. Returns one of the
|
||||
// ANDROID_PRIORITY constants or a negative result in case of error.
|
||||
extern int androidGetThreadPriority(pid_t tid);
|
||||
|
||||
// Get the current scheduling group of a particular thread. Normally returns
|
||||
// one of the ANDROID_TGROUP constants other than ANDROID_TGROUP_DEFAULT.
|
||||
// Returns ANDROID_TGROUP_DEFAULT if no pthread support (e.g. on host) or if
|
||||
// scheduling groups are disabled. Returns INVALID_OPERATION if unexpected error.
|
||||
// Thread ID zero means current thread.
|
||||
extern int androidGetThreadSchedulingGroup(pid_t tid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// C++ API
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <utils/Condition.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/Timers.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
typedef android_thread_id_t thread_id_t;
|
||||
|
||||
typedef android_thread_func_t thread_func_t;
|
||||
|
||||
enum {
|
||||
PRIORITY_LOWEST = ANDROID_PRIORITY_LOWEST,
|
||||
PRIORITY_BACKGROUND = ANDROID_PRIORITY_BACKGROUND,
|
||||
PRIORITY_NORMAL = ANDROID_PRIORITY_NORMAL,
|
||||
PRIORITY_FOREGROUND = ANDROID_PRIORITY_FOREGROUND,
|
||||
PRIORITY_DISPLAY = ANDROID_PRIORITY_DISPLAY,
|
||||
PRIORITY_URGENT_DISPLAY = ANDROID_PRIORITY_URGENT_DISPLAY,
|
||||
PRIORITY_AUDIO = ANDROID_PRIORITY_AUDIO,
|
||||
PRIORITY_URGENT_AUDIO = ANDROID_PRIORITY_URGENT_AUDIO,
|
||||
PRIORITY_HIGHEST = ANDROID_PRIORITY_HIGHEST,
|
||||
PRIORITY_DEFAULT = ANDROID_PRIORITY_DEFAULT,
|
||||
PRIORITY_MORE_FAVORABLE = ANDROID_PRIORITY_MORE_FAVORABLE,
|
||||
PRIORITY_LESS_FAVORABLE = ANDROID_PRIORITY_LESS_FAVORABLE,
|
||||
};
|
||||
|
||||
// Create and run a new thread.
|
||||
inline bool createThread(thread_func_t f, void *a) {
|
||||
return androidCreateThread(f, a) ? true : false;
|
||||
}
|
||||
|
||||
// Create thread with lots of parameters
|
||||
inline bool createThreadEtc(thread_func_t entryFunction,
|
||||
void *userData,
|
||||
const char* threadName = "android:unnamed_thread",
|
||||
int32_t threadPriority = PRIORITY_DEFAULT,
|
||||
size_t threadStackSize = 0,
|
||||
thread_id_t *threadId = 0)
|
||||
{
|
||||
return androidCreateThreadEtc(entryFunction, userData, threadName,
|
||||
threadPriority, threadStackSize, threadId) ? true : false;
|
||||
}
|
||||
|
||||
// Get some sort of unique identifier for the current thread.
|
||||
inline thread_id_t getThreadId() {
|
||||
return androidGetThreadId();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Simple mutex class. The implementation is system-dependent.
|
||||
*
|
||||
* The mutex must be unlocked by the thread that locked it. They are not
|
||||
* recursive, i.e. the same thread can't lock it multiple times.
|
||||
*/
|
||||
class Mutex {
|
||||
public:
|
||||
enum {
|
||||
PRIVATE = 0,
|
||||
SHARED = 1
|
||||
};
|
||||
|
||||
Mutex();
|
||||
Mutex(const char* name);
|
||||
Mutex(int type, const char* name = NULL);
|
||||
~Mutex();
|
||||
|
||||
// lock or unlock the mutex
|
||||
status_t lock();
|
||||
void unlock();
|
||||
|
||||
// lock if possible; returns 0 on success, error otherwise
|
||||
status_t tryLock();
|
||||
|
||||
// Manages the mutex automatically. It'll be locked when Autolock is
|
||||
// constructed and released when Autolock goes out of scope.
|
||||
class Autolock {
|
||||
public:
|
||||
inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); }
|
||||
inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
|
||||
inline ~Autolock() { mLock.unlock(); }
|
||||
private:
|
||||
Mutex& mLock;
|
||||
};
|
||||
|
||||
private:
|
||||
friend class Condition;
|
||||
|
||||
// A mutex cannot be copied
|
||||
Mutex(const Mutex&);
|
||||
Mutex& operator = (const Mutex&);
|
||||
|
||||
#if defined(HAVE_PTHREADS)
|
||||
pthread_mutex_t mMutex;
|
||||
#else
|
||||
void _init();
|
||||
void* mState;
|
||||
#include <utils/Mutex.h>
|
||||
#include <utils/RWLock.h>
|
||||
#include <utils/Thread.h>
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(HAVE_PTHREADS)
|
||||
|
||||
inline Mutex::Mutex() {
|
||||
pthread_mutex_init(&mMutex, NULL);
|
||||
}
|
||||
inline Mutex::Mutex(const char* name) {
|
||||
pthread_mutex_init(&mMutex, NULL);
|
||||
}
|
||||
inline Mutex::Mutex(int type, const char* name) {
|
||||
if (type == SHARED) {
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
|
||||
pthread_mutex_init(&mMutex, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
} else {
|
||||
pthread_mutex_init(&mMutex, NULL);
|
||||
}
|
||||
}
|
||||
inline Mutex::~Mutex() {
|
||||
pthread_mutex_destroy(&mMutex);
|
||||
}
|
||||
inline status_t Mutex::lock() {
|
||||
return -pthread_mutex_lock(&mMutex);
|
||||
}
|
||||
inline void Mutex::unlock() {
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
}
|
||||
inline status_t Mutex::tryLock() {
|
||||
return -pthread_mutex_trylock(&mMutex);
|
||||
}
|
||||
|
||||
#endif // HAVE_PTHREADS
|
||||
|
||||
/*
|
||||
* Automatic mutex. Declare one of these at the top of a function.
|
||||
* When the function returns, it will go out of scope, and release the
|
||||
* mutex.
|
||||
*/
|
||||
|
||||
typedef Mutex::Autolock AutoMutex;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if defined(HAVE_PTHREADS)
|
||||
|
||||
/*
|
||||
* Simple mutex class. The implementation is system-dependent.
|
||||
*
|
||||
* The mutex must be unlocked by the thread that locked it. They are not
|
||||
* recursive, i.e. the same thread can't lock it multiple times.
|
||||
*/
|
||||
class RWLock {
|
||||
public:
|
||||
enum {
|
||||
PRIVATE = 0,
|
||||
SHARED = 1
|
||||
};
|
||||
|
||||
RWLock();
|
||||
RWLock(const char* name);
|
||||
RWLock(int type, const char* name = NULL);
|
||||
~RWLock();
|
||||
|
||||
status_t readLock();
|
||||
status_t tryReadLock();
|
||||
status_t writeLock();
|
||||
status_t tryWriteLock();
|
||||
void unlock();
|
||||
|
||||
class AutoRLock {
|
||||
public:
|
||||
inline AutoRLock(RWLock& rwlock) : mLock(rwlock) { mLock.readLock(); }
|
||||
inline ~AutoRLock() { mLock.unlock(); }
|
||||
private:
|
||||
RWLock& mLock;
|
||||
};
|
||||
|
||||
class AutoWLock {
|
||||
public:
|
||||
inline AutoWLock(RWLock& rwlock) : mLock(rwlock) { mLock.writeLock(); }
|
||||
inline ~AutoWLock() { mLock.unlock(); }
|
||||
private:
|
||||
RWLock& mLock;
|
||||
};
|
||||
|
||||
private:
|
||||
// A RWLock cannot be copied
|
||||
RWLock(const RWLock&);
|
||||
RWLock& operator = (const RWLock&);
|
||||
|
||||
pthread_rwlock_t mRWLock;
|
||||
};
|
||||
|
||||
inline RWLock::RWLock() {
|
||||
pthread_rwlock_init(&mRWLock, NULL);
|
||||
}
|
||||
inline RWLock::RWLock(const char* name) {
|
||||
pthread_rwlock_init(&mRWLock, NULL);
|
||||
}
|
||||
inline RWLock::RWLock(int type, const char* name) {
|
||||
if (type == SHARED) {
|
||||
pthread_rwlockattr_t attr;
|
||||
pthread_rwlockattr_init(&attr);
|
||||
pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
|
||||
pthread_rwlock_init(&mRWLock, &attr);
|
||||
pthread_rwlockattr_destroy(&attr);
|
||||
} else {
|
||||
pthread_rwlock_init(&mRWLock, NULL);
|
||||
}
|
||||
}
|
||||
inline RWLock::~RWLock() {
|
||||
pthread_rwlock_destroy(&mRWLock);
|
||||
}
|
||||
inline status_t RWLock::readLock() {
|
||||
return -pthread_rwlock_rdlock(&mRWLock);
|
||||
}
|
||||
inline status_t RWLock::tryReadLock() {
|
||||
return -pthread_rwlock_tryrdlock(&mRWLock);
|
||||
}
|
||||
inline status_t RWLock::writeLock() {
|
||||
return -pthread_rwlock_wrlock(&mRWLock);
|
||||
}
|
||||
inline status_t RWLock::tryWriteLock() {
|
||||
return -pthread_rwlock_trywrlock(&mRWLock);
|
||||
}
|
||||
inline void RWLock::unlock() {
|
||||
pthread_rwlock_unlock(&mRWLock);
|
||||
}
|
||||
|
||||
#endif // HAVE_PTHREADS
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Condition variable class. The implementation is system-dependent.
|
||||
*
|
||||
* Condition variables are paired up with mutexes. Lock the mutex,
|
||||
* call wait(), then either re-wait() if things aren't quite what you want,
|
||||
* or unlock the mutex and continue. All threads calling wait() must
|
||||
* use the same mutex for a given Condition.
|
||||
*/
|
||||
class Condition {
|
||||
public:
|
||||
enum {
|
||||
PRIVATE = 0,
|
||||
SHARED = 1
|
||||
};
|
||||
|
||||
Condition();
|
||||
Condition(int type);
|
||||
~Condition();
|
||||
// Wait on the condition variable. Lock the mutex before calling.
|
||||
status_t wait(Mutex& mutex);
|
||||
// same with relative timeout
|
||||
status_t waitRelative(Mutex& mutex, nsecs_t reltime);
|
||||
// Signal the condition variable, allowing one thread to continue.
|
||||
void signal();
|
||||
// Signal the condition variable, allowing all threads to continue.
|
||||
void broadcast();
|
||||
|
||||
private:
|
||||
#if defined(HAVE_PTHREADS)
|
||||
pthread_cond_t mCond;
|
||||
#else
|
||||
void* mState;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(HAVE_PTHREADS)
|
||||
|
||||
inline Condition::Condition() {
|
||||
pthread_cond_init(&mCond, NULL);
|
||||
}
|
||||
inline Condition::Condition(int type) {
|
||||
if (type == SHARED) {
|
||||
pthread_condattr_t attr;
|
||||
pthread_condattr_init(&attr);
|
||||
pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
|
||||
pthread_cond_init(&mCond, &attr);
|
||||
pthread_condattr_destroy(&attr);
|
||||
} else {
|
||||
pthread_cond_init(&mCond, NULL);
|
||||
}
|
||||
}
|
||||
inline Condition::~Condition() {
|
||||
pthread_cond_destroy(&mCond);
|
||||
}
|
||||
inline status_t Condition::wait(Mutex& mutex) {
|
||||
return -pthread_cond_wait(&mCond, &mutex.mMutex);
|
||||
}
|
||||
inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) {
|
||||
#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
|
||||
struct timespec ts;
|
||||
ts.tv_sec = reltime/1000000000;
|
||||
ts.tv_nsec = reltime%1000000000;
|
||||
return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
|
||||
#else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
|
||||
struct timespec ts;
|
||||
#if defined(HAVE_POSIX_CLOCKS)
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
#else // HAVE_POSIX_CLOCKS
|
||||
// we don't support the clocks here.
|
||||
struct timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
ts.tv_sec = t.tv_sec;
|
||||
ts.tv_nsec= t.tv_usec*1000;
|
||||
#endif // HAVE_POSIX_CLOCKS
|
||||
ts.tv_sec += reltime/1000000000;
|
||||
ts.tv_nsec+= reltime%1000000000;
|
||||
if (ts.tv_nsec >= 1000000000) {
|
||||
ts.tv_nsec -= 1000000000;
|
||||
ts.tv_sec += 1;
|
||||
}
|
||||
return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
|
||||
#endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
|
||||
}
|
||||
inline void Condition::signal() {
|
||||
pthread_cond_signal(&mCond);
|
||||
}
|
||||
inline void Condition::broadcast() {
|
||||
pthread_cond_broadcast(&mCond);
|
||||
}
|
||||
|
||||
#endif // HAVE_PTHREADS
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
* This is our spiffy thread object!
|
||||
*/
|
||||
|
||||
class Thread : virtual public RefBase
|
||||
{
|
||||
public:
|
||||
// Create a Thread object, but doesn't create or start the associated
|
||||
// thread. See the run() method.
|
||||
Thread(bool canCallJava = true);
|
||||
virtual ~Thread();
|
||||
|
||||
// Start the thread in threadLoop() which needs to be implemented.
|
||||
virtual status_t run( const char* name = 0,
|
||||
int32_t priority = PRIORITY_DEFAULT,
|
||||
size_t stack = 0);
|
||||
|
||||
// Ask this object's thread to exit. This function is asynchronous, when the
|
||||
// function returns the thread might still be running. Of course, this
|
||||
// function can be called from a different thread.
|
||||
virtual void requestExit();
|
||||
|
||||
// Good place to do one-time initializations
|
||||
virtual status_t readyToRun();
|
||||
|
||||
// Call requestExit() and wait until this object's thread exits.
|
||||
// BE VERY CAREFUL of deadlocks. In particular, it would be silly to call
|
||||
// this function from this object's thread. Will return WOULD_BLOCK in
|
||||
// that case.
|
||||
status_t requestExitAndWait();
|
||||
|
||||
// Wait until this object's thread exits. Returns immediately if not yet running.
|
||||
// Do not call from this object's thread; will return WOULD_BLOCK in that case.
|
||||
status_t join();
|
||||
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
// Return the thread's kernel ID, same as the thread itself calling gettid() or
|
||||
// androidGetTid(), or -1 if the thread is not running.
|
||||
pid_t getTid() const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// exitPending() returns true if requestExit() has been called.
|
||||
bool exitPending() const;
|
||||
|
||||
private:
|
||||
// Derived class must implement threadLoop(). The thread starts its life
|
||||
// here. There are two ways of using the Thread object:
|
||||
// 1) loop: if threadLoop() returns true, it will be called again if
|
||||
// requestExit() wasn't called.
|
||||
// 2) once: if threadLoop() returns false, the thread will exit upon return.
|
||||
virtual bool threadLoop() = 0;
|
||||
|
||||
private:
|
||||
Thread& operator=(const Thread&);
|
||||
static int _threadLoop(void* user);
|
||||
const bool mCanCallJava;
|
||||
// always hold mLock when reading or writing
|
||||
thread_id_t mThread;
|
||||
mutable Mutex mLock;
|
||||
Condition mThreadExitedCondition;
|
||||
status_t mStatus;
|
||||
// note that all accesses of mExitPending and mRunning need to hold mLock
|
||||
volatile bool mExitPending;
|
||||
volatile bool mRunning;
|
||||
sp<Thread> mHoldSelf;
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
// legacy for debugging, not used by getTid() as it is set by the child thread
|
||||
// and so is not initialized until the child reaches that point
|
||||
pid_t mTid;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // _LIBS_UTILS_THREADS_H
|
||||
|
|
Loading…
Reference in a new issue