diff options
Diffstat (limited to 'base/thread_posix.cc')
-rw-r--r-- | base/thread_posix.cc | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/base/thread_posix.cc b/base/thread_posix.cc new file mode 100644 index 0000000..e04ebcb --- /dev/null +++ b/base/thread_posix.cc @@ -0,0 +1,102 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "base/thread.h" + +#include "base/message_loop.h" +#include "base/ref_counted.h" +#include "base/string_util.h" + +// This task is used to trigger the message loop to exit. +class ThreadQuitTask : public Task { + public: + virtual void Run() { + MessageLoop::current()->Quit(); +#ifndef NDEBUG + Thread::SetThreadWasQuitProperly(true); +#endif + } +}; + +Thread::Thread(const char *name) + : thread_id_(0), + message_loop_(NULL), + name_(name) { + DCHECK(tls_index_) << "static initializer failed"; +} + +Thread::~Thread() { + Stop(); +} + +void* ThreadFunc(void* closure) { + // TODO(pinkerton): I have no clue what to do here + + pthread_exit(NULL); +} + +// We use this thread-local variable to record whether or not a thread exited +// because its Stop method was called. This allows us to catch cases where +// MessageLoop::Quit() is called directly, which is unexpected when using a +// Thread to setup and run a MessageLoop. +// Note that if we start doing complex stuff in other static initializers +// this could cause problems. +TLSSlot Thread::tls_index_ = ThreadLocalStorage::Alloc(); + +void Thread::SetThreadWasQuitProperly(bool flag) { + ThreadLocalStorage::Set(tls_index_, reinterpret_cast<void*>(flag)); +} + +bool Thread::GetThreadWasQuitProperly() { + return (ThreadLocalStorage::Get(tls_index_) != 0); +} + + +bool Thread::Start() { + bool success = false; + int result = pthread_create(&thread_id_, NULL, ThreadFunc, &message_loop_); + if (!result) + success = true; + + return success; +} + +void Thread::Stop() { +// DCHECK_NE(thread_id_, GetCurrentThreadId()) +// << "Can't call Stop() on itself"; + + // We had better have a message loop at this point! If we do not, then it + // most likely means that the thread terminated unexpectedly, probably due + // to someone calling Quit() on our message loop directly. + DCHECK(message_loop_); + + message_loop_->PostTask(FROM_HERE, new ThreadQuitTask()); + + message_loop_ = NULL; +} |