You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
3.3 KiB
146 lines
3.3 KiB
// Copyright (C) 2014 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.
|
|
|
|
#include "base/Thread.h"
|
|
|
|
#include <assert.h>
|
|
|
|
namespace android {
|
|
namespace base {
|
|
|
|
Thread::Thread(ThreadFlags flags, int stackSize)
|
|
: mStackSize(stackSize), mFlags(flags) {}
|
|
|
|
Thread::~Thread() {
|
|
if (mThread) {
|
|
assert(!mStarted || mFinished);
|
|
CloseHandle(mThread);
|
|
}
|
|
}
|
|
|
|
bool Thread::start() {
|
|
if (mStarted) {
|
|
return false;
|
|
}
|
|
|
|
bool ret = true;
|
|
mStarted = true;
|
|
DWORD threadId = 0;
|
|
mThread = CreateThread(NULL, mStackSize, &Thread::thread_main, this, 0,
|
|
&threadId);
|
|
if (!mThread) {
|
|
// don't reset mStarted: we're artifically limiting the user's
|
|
// ability to retry the failed starts here.
|
|
ret = false;
|
|
mFinished = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool Thread::wait(intptr_t* exitStatus) {
|
|
if (!mStarted || (mFlags & ThreadFlags::Detach) != ThreadFlags::NoFlags) {
|
|
return false;
|
|
}
|
|
|
|
// NOTE: Do not hold lock during wait to allow thread_main to
|
|
// properly update mIsRunning and mFinished on thread exit.
|
|
if (WaitForSingleObject(mThread, INFINITE) == WAIT_FAILED) {
|
|
return false;
|
|
}
|
|
|
|
if (exitStatus) {
|
|
*exitStatus = mExitStatus;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Thread::tryWait(intptr_t* exitStatus) {
|
|
if (!mStarted || (mFlags & ThreadFlags::Detach) != ThreadFlags::NoFlags) {
|
|
return false;
|
|
}
|
|
|
|
AutoLock locker(mLock);
|
|
if (!mFinished || WaitForSingleObject(mThread, 0) != WAIT_OBJECT_0) {
|
|
return false;
|
|
}
|
|
|
|
if (exitStatus) {
|
|
*exitStatus = mExitStatus;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// static
|
|
DWORD WINAPI Thread::thread_main(void* arg) {
|
|
{
|
|
// no need to call maskAllSignals() here: we know
|
|
// that on Windows it's a noop
|
|
Thread* self = reinterpret_cast<Thread*>(arg);
|
|
auto ret = self->main();
|
|
|
|
{
|
|
AutoLock lock(self->mLock);
|
|
self->mFinished = true;
|
|
self->mExitStatus = ret;
|
|
}
|
|
|
|
self->onExit();
|
|
// |self| is not valid beyond this point
|
|
}
|
|
|
|
// This return value is ignored.
|
|
return 0;
|
|
}
|
|
|
|
// static
|
|
void Thread::maskAllSignals() {
|
|
// no such thing as signal in Windows
|
|
}
|
|
|
|
// static
|
|
void Thread::sleepMs(unsigned n) {
|
|
::Sleep(n);
|
|
}
|
|
|
|
// static
|
|
void Thread::sleepUs(unsigned n) {
|
|
// Hehe
|
|
::Sleep(n / 1000);
|
|
}
|
|
|
|
// static
|
|
void Thread::yield() {
|
|
if (!::SwitchToThread()) {
|
|
::Sleep(0);
|
|
}
|
|
}
|
|
|
|
unsigned long getCurrentThreadId() {
|
|
return static_cast<unsigned long>(GetCurrentThreadId());
|
|
}
|
|
|
|
static unsigned long sUiThreadId = 0;
|
|
void setUiThreadId(unsigned long id) {
|
|
sUiThreadId = id;
|
|
|
|
}
|
|
|
|
bool isRunningInUiThread() {
|
|
if (!sUiThreadId) return false;
|
|
return sUiThreadId == getCurrentThreadId();
|
|
}
|
|
|
|
} // namespace base
|
|
} // namespace android
|