diff options
author | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-29 00:39:26 +0000 |
---|---|---|
committer | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-29 00:39:26 +0000 |
commit | 3b3c6445122bf8144b08c94c42db00f6079e4c77 (patch) | |
tree | 8483986e8a9b4696543b1606c8fa1f28745dbcf0 /mojo/public/cpp/utility | |
parent | e97a6074124c0bbb4e57316e754b64e3eb0a8ee1 (diff) | |
download | chromium_src-3b3c6445122bf8144b08c94c42db00f6079e4c77.zip chromium_src-3b3c6445122bf8144b08c94c42db00f6079e4c77.tar.gz chromium_src-3b3c6445122bf8144b08c94c42db00f6079e4c77.tar.bz2 |
Mojo: Move mojo/public/utility to mojo/public/cpp/utility.
R=sky@chromium.org
Review URL: https://codereview.chromium.org/217443002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260324 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'mojo/public/cpp/utility')
-rw-r--r-- | mojo/public/cpp/utility/lib/mutex.cc | 52 | ||||
-rw-r--r-- | mojo/public/cpp/utility/lib/run_loop.cc | 224 | ||||
-rw-r--r-- | mojo/public/cpp/utility/lib/thread.cc | 69 | ||||
-rw-r--r-- | mojo/public/cpp/utility/lib/thread_local.h | 61 | ||||
-rw-r--r-- | mojo/public/cpp/utility/lib/thread_local_posix.cc | 39 | ||||
-rw-r--r-- | mojo/public/cpp/utility/lib/thread_local_win.cc | 39 | ||||
-rw-r--r-- | mojo/public/cpp/utility/mutex.h | 70 | ||||
-rw-r--r-- | mojo/public/cpp/utility/run_loop.h | 108 | ||||
-rw-r--r-- | mojo/public/cpp/utility/run_loop_handler.h | 25 | ||||
-rw-r--r-- | mojo/public/cpp/utility/thread.h | 62 |
10 files changed, 749 insertions, 0 deletions
diff --git a/mojo/public/cpp/utility/lib/mutex.cc b/mojo/public/cpp/utility/lib/mutex.cc new file mode 100644 index 0000000..23370e1 --- /dev/null +++ b/mojo/public/cpp/utility/lib/mutex.cc @@ -0,0 +1,52 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/utility/mutex.h" + +#include <assert.h> +#include <errno.h> + +namespace mojo { + +// Release builds have inlined (non-error-checking) definitions in the header. +#if !defined(NDEBUG) +Mutex::Mutex() { + pthread_mutexattr_t mutexattr; + int rv = pthread_mutexattr_init(&mutexattr); + assert(rv == 0); + rv = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK); + assert(rv == 0); + rv = pthread_mutex_init(&mutex_, &mutexattr); + assert(rv == 0); + rv = pthread_mutexattr_destroy(&mutexattr); + assert(rv == 0); +} + +Mutex::~Mutex() { + int rv = pthread_mutex_destroy(&mutex_); + assert(rv == 0); +} + +void Mutex::Lock() { + int rv = pthread_mutex_lock(&mutex_); + assert(rv == 0); +} + +void Mutex::Unlock() { + int rv = pthread_mutex_unlock(&mutex_); + assert(rv == 0); +} + +bool Mutex::TryLock() { + int rv = pthread_mutex_trylock(&mutex_); + assert(rv == 0 || rv == EBUSY); + return rv == 0; +} + +void Mutex::AssertHeld() { + assert(pthread_mutex_lock(&mutex_) == EDEADLK); +} +#endif // !defined(NDEBUG) + +} // namespace mojo diff --git a/mojo/public/cpp/utility/lib/run_loop.cc b/mojo/public/cpp/utility/lib/run_loop.cc new file mode 100644 index 0000000..2bf6a07 --- /dev/null +++ b/mojo/public/cpp/utility/lib/run_loop.cc @@ -0,0 +1,224 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/utility/run_loop.h" + +#include <assert.h> + +#include <algorithm> +#include <vector> + +#include "mojo/public/cpp/utility/lib/thread_local.h" +#include "mojo/public/cpp/utility/run_loop_handler.h" + +namespace mojo { +namespace { + +internal::ThreadLocalPointer<RunLoop> current_run_loop; + +const MojoTimeTicks kInvalidTimeTicks = static_cast<MojoTimeTicks>(0); + +} // namespace + +// State needed for one iteration of WaitMany(). +struct RunLoop::WaitState { + WaitState() : deadline(MOJO_DEADLINE_INDEFINITE) {} + + std::vector<Handle> handles; + std::vector<MojoWaitFlags> wait_flags; + MojoDeadline deadline; +}; + +struct RunLoop::RunState { + RunState() : should_quit(false) {} + + bool should_quit; +}; + +RunLoop::RunLoop() : run_state_(NULL), next_handler_id_(0) { + assert(!current()); + current_run_loop.Set(this); +} + +RunLoop::~RunLoop() { + assert(current() == this); + current_run_loop.Set(NULL); +} + +// static +void RunLoop::SetUp() { + current_run_loop.Allocate(); +} + +// static +void RunLoop::TearDown() { + assert(!current()); + current_run_loop.Free(); +} + +// static +RunLoop* RunLoop::current() { + return current_run_loop.Get(); +} + +void RunLoop::AddHandler(RunLoopHandler* handler, + const Handle& handle, + MojoWaitFlags wait_flags, + MojoDeadline deadline) { + assert(current() == this); + assert(handler); + assert(handle.is_valid()); + // Assume it's an error if someone tries to reregister an existing handle. + assert(0u == handler_data_.count(handle)); + HandlerData handler_data; + handler_data.handler = handler; + handler_data.wait_flags = wait_flags; + handler_data.deadline = (deadline == MOJO_DEADLINE_INDEFINITE) ? + kInvalidTimeTicks : + GetTimeTicksNow() + static_cast<MojoTimeTicks>(deadline); + handler_data.id = next_handler_id_++; + handler_data_[handle] = handler_data; +} + +void RunLoop::RemoveHandler(const Handle& handle) { + assert(current() == this); + handler_data_.erase(handle); +} + +bool RunLoop::HasHandler(const Handle& handle) const { + return handler_data_.find(handle) != handler_data_.end(); +} + +void RunLoop::Run() { + assert(current() == this); + // We don't currently support nesting. + assert(!run_state_); + RunState* old_state = run_state_; + RunState run_state; + run_state_ = &run_state; + while (!run_state.should_quit) + Wait(false); + run_state_ = old_state; +} + +void RunLoop::RunUntilIdle() { + assert(current() == this); + // We don't currently support nesting. + assert(!run_state_); + RunState* old_state = run_state_; + RunState run_state; + run_state_ = &run_state; + while (!run_state.should_quit) { + if (!Wait(true)) + break; + } + run_state_ = old_state; +} + +void RunLoop::Quit() { + assert(current() == this); + if (run_state_) + run_state_->should_quit = true; +} + +bool RunLoop::Wait(bool non_blocking) { + const WaitState wait_state = GetWaitState(non_blocking); + if (wait_state.handles.empty()) { + Quit(); + return false; + } + + const MojoResult result = + WaitMany(wait_state.handles, wait_state.wait_flags, wait_state.deadline); + if (result >= 0) { + const size_t index = static_cast<size_t>(result); + assert(handler_data_.find(wait_state.handles[index]) != + handler_data_.end()); + handler_data_[wait_state.handles[index]].handler->OnHandleReady( + wait_state.handles[index]); + return true; + } + + switch (result) { + case MOJO_RESULT_INVALID_ARGUMENT: + case MOJO_RESULT_FAILED_PRECONDITION: + return RemoveFirstInvalidHandle(wait_state); + case MOJO_RESULT_DEADLINE_EXCEEDED: + return NotifyDeadlineExceeded(); + } + + assert(false); + return false; +} + +bool RunLoop::NotifyDeadlineExceeded() { + bool notified = false; + + // Make a copy in case someone tries to add/remove new handlers as part of + // notifying. + const HandleToHandlerData cloned_handlers(handler_data_); + const MojoTimeTicks now(GetTimeTicksNow()); + for (HandleToHandlerData::const_iterator i = cloned_handlers.begin(); + i != cloned_handlers.end(); ++i) { + // Since we're iterating over a clone of the handlers, verify the handler is + // still valid before notifying. + if (i->second.deadline != kInvalidTimeTicks && + i->second.deadline < now && + handler_data_.find(i->first) != handler_data_.end() && + handler_data_[i->first].id == i->second.id) { + handler_data_.erase(i->first); + i->second.handler->OnHandleError(i->first, MOJO_RESULT_DEADLINE_EXCEEDED); + notified = true; + } + } + + return notified; +} + +bool RunLoop::RemoveFirstInvalidHandle(const WaitState& wait_state) { + for (size_t i = 0; i < wait_state.handles.size(); ++i) { + const MojoResult result = + mojo::Wait(wait_state.handles[i], wait_state.wait_flags[i], + static_cast<MojoDeadline>(0)); + if (result == MOJO_RESULT_INVALID_ARGUMENT || + result == MOJO_RESULT_FAILED_PRECONDITION) { + // Remove the handle first, this way if OnHandleError() tries to remove + // the handle our iterator isn't invalidated. + assert(handler_data_.find(wait_state.handles[i]) != handler_data_.end()); + RunLoopHandler* handler = + handler_data_[wait_state.handles[i]].handler; + handler_data_.erase(wait_state.handles[i]); + handler->OnHandleError(wait_state.handles[i], result); + return true; + } + assert(MOJO_RESULT_DEADLINE_EXCEEDED == result); + } + return false; +} + +RunLoop::WaitState RunLoop::GetWaitState(bool non_blocking) const { + WaitState wait_state; + MojoTimeTicks min_time = kInvalidTimeTicks; + for (HandleToHandlerData::const_iterator i = handler_data_.begin(); + i != handler_data_.end(); ++i) { + wait_state.handles.push_back(i->first); + wait_state.wait_flags.push_back(i->second.wait_flags); + if (!non_blocking && i->second.deadline != kInvalidTimeTicks && + (min_time == kInvalidTimeTicks || i->second.deadline < min_time)) { + min_time = i->second.deadline; + } + } + if (non_blocking) { + wait_state.deadline = static_cast<MojoDeadline>(0); + } else if (min_time != kInvalidTimeTicks) { + const MojoTimeTicks now = GetTimeTicksNow(); + if (min_time < now) + wait_state.deadline = static_cast<MojoDeadline>(0); + else + wait_state.deadline = static_cast<MojoDeadline>(min_time - now); + } + return wait_state; +} + +} // namespace mojo diff --git a/mojo/public/cpp/utility/lib/thread.cc b/mojo/public/cpp/utility/lib/thread.cc new file mode 100644 index 0000000..da33497 --- /dev/null +++ b/mojo/public/cpp/utility/lib/thread.cc @@ -0,0 +1,69 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/utility/thread.h" + +#include <assert.h> + +namespace mojo { + +Thread::Thread() + : options_(), + thread_(), + started_(false), + joined_(false) { +} + +Thread::Thread(const Options& options) + : options_(options), + thread_(), + started_(false), + joined_(false) { +} + +Thread::~Thread() { + // If it was started, it must have been joined. + assert(!started_ || joined_); +} + +void Thread::Start() { + assert(!started_); + assert(!joined_); + + pthread_attr_t attr; + int rv MOJO_ALLOW_UNUSED = pthread_attr_init(&attr); + assert(rv == 0); + + // Non-default stack size? + if (options_.stack_size() != 0) { + rv = pthread_attr_setstacksize(&attr, options_.stack_size()); + assert(rv == 0); + } + + started_ = true; + rv = pthread_create(&thread_, &attr, &ThreadRunTrampoline, this); + assert(rv == 0); + + rv = pthread_attr_destroy(&attr); + assert(rv == 0); +} + +void Thread::Join() { + // Must have been started but not yet joined. + assert(started_); + assert(!joined_); + + joined_ = true; + int rv MOJO_ALLOW_UNUSED = pthread_join(thread_, NULL); + assert(rv == 0); +} + +// static +void* Thread::ThreadRunTrampoline(void* arg) { + Thread* self = static_cast<Thread*>(arg); + self->Run(); + return NULL; +} + +} // namespace mojo diff --git a/mojo/public/cpp/utility/lib/thread_local.h b/mojo/public/cpp/utility/lib/thread_local.h new file mode 100644 index 0000000..4c3625d --- /dev/null +++ b/mojo/public/cpp/utility/lib/thread_local.h @@ -0,0 +1,61 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_UTILITY_LIB_THREAD_LOCAL_H_ +#define MOJO_PUBLIC_CPP_UTILITY_LIB_THREAD_LOCAL_H_ + +#ifndef _WIN32 +#include <pthread.h> +#endif + +#include "mojo/public/cpp/system/macros.h" + +namespace mojo { +namespace internal { + +// Helper functions that abstract the cross-platform APIs. +struct ThreadLocalPlatform { +#ifdef _WIN32 + typedef unsigned long SlotType; +#else + typedef pthread_key_t SlotType; +#endif + + static void AllocateSlot(SlotType* slot); + static void FreeSlot(SlotType slot); + static void* GetValueFromSlot(SlotType slot); + static void SetValueInSlot(SlotType slot, void* value); +}; + +// This class is intended to be statically allocated. +template <typename P> +class ThreadLocalPointer { + public: + ThreadLocalPointer() : slot_() { + } + + void Allocate() { + ThreadLocalPlatform::AllocateSlot(&slot_); + } + + void Free() { + ThreadLocalPlatform::FreeSlot(slot_); + } + + P* Get() { + return static_cast<P*>(ThreadLocalPlatform::GetValueFromSlot(slot_)); + } + + void Set(P* value) { + ThreadLocalPlatform::SetValueInSlot(slot_, value); + } + + private: + ThreadLocalPlatform::SlotType slot_; +}; + +} // namespace internal +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_UTILITY_LIB_THREAD_LOCAL_H_ diff --git a/mojo/public/cpp/utility/lib/thread_local_posix.cc b/mojo/public/cpp/utility/lib/thread_local_posix.cc new file mode 100644 index 0000000..b33dfc6 --- /dev/null +++ b/mojo/public/cpp/utility/lib/thread_local_posix.cc @@ -0,0 +1,39 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/utility/lib/thread_local.h" + +#include <assert.h> + +namespace mojo { +namespace internal { + +// static +void ThreadLocalPlatform::AllocateSlot(SlotType* slot) { + if (pthread_key_create(slot, NULL) != 0) { + assert(false); + } +} + +// static +void ThreadLocalPlatform::FreeSlot(SlotType slot) { + if (pthread_key_delete(slot) != 0) { + assert(false); + } +} + +// static +void* ThreadLocalPlatform::GetValueFromSlot(SlotType slot) { + return pthread_getspecific(slot); +} + +// static +void ThreadLocalPlatform::SetValueInSlot(SlotType slot, void* value) { + if (pthread_setspecific(slot, value) != 0) { + assert(false); + } +} + +} // namespace internal +} // namespace mojo diff --git a/mojo/public/cpp/utility/lib/thread_local_win.cc b/mojo/public/cpp/utility/lib/thread_local_win.cc new file mode 100644 index 0000000..98841f7 --- /dev/null +++ b/mojo/public/cpp/utility/lib/thread_local_win.cc @@ -0,0 +1,39 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/utility/lib/thread_local.h" + +#include <assert.h> +#include <windows.h> + +namespace mojo { +namespace internal { + +// static +void ThreadLocalPlatform::AllocateSlot(SlotType* slot) { + *slot = TlsAlloc(); + assert(*slot != TLS_OUT_OF_INDEXES); +} + +// static +void ThreadLocalPlatform::FreeSlot(SlotType slot) { + if (!TlsFree(slot)) { + assert(false); + } +} + +// static +void* ThreadLocalPlatform::GetValueFromSlot(SlotType slot) { + return TlsGetValue(slot); +} + +// static +void ThreadLocalPlatform::SetValueInSlot(SlotType slot, void* value) { + if (!TlsSetValue(slot, value)) { + assert(false); + } +} + +} // namespace internal +} // namespace mojo diff --git a/mojo/public/cpp/utility/mutex.h b/mojo/public/cpp/utility/mutex.h new file mode 100644 index 0000000..35611c2 --- /dev/null +++ b/mojo/public/cpp/utility/mutex.h @@ -0,0 +1,70 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_UTILITY_MUTEX_H_ +#define MOJO_PUBLIC_CPP_UTILITY_MUTEX_H_ + +#ifdef _WIN32 +#error "Not implemented: See crbug.com/342893." +#endif + +#include <pthread.h> + +#include "mojo/public/cpp/system/macros.h" + +namespace mojo { + +#ifdef NDEBUG +// Note: Make a C++ constant for |PTHREAD_MUTEX_INITIALIZER|. (We can't directly +// use the C macro in an initializer list, since it might expand to |{ ... }|.) +namespace internal { +const pthread_mutex_t kPthreadMutexInitializer = PTHREAD_MUTEX_INITIALIZER; +} +#endif + +class Mutex { + public: +#ifdef NDEBUG + Mutex() : mutex_(internal::kPthreadMutexInitializer) {} + ~Mutex() { pthread_mutex_destroy(&mutex_); } + + void Lock() { pthread_mutex_lock(&mutex_); } + void Unlock() { pthread_mutex_unlock(&mutex_); } + bool TryLock() { return pthread_mutex_trylock(&mutex_) == 0; } + + void AssertHeld() {} +#else + Mutex(); + ~Mutex(); + + void Lock(); + void Unlock(); + bool TryLock(); + + void AssertHeld(); +#endif + + private: + pthread_mutex_t mutex_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(Mutex); +}; + +class MutexLock { + public: + explicit MutexLock(Mutex* mutex) : mutex_(mutex) { mutex_->Lock(); } + ~MutexLock() { mutex_->Unlock(); } + + private: + Mutex* const mutex_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(MutexLock); +}; + +// Catch bug where variable name is omitted (e.g., |MutexLock (&mu)|). +#define MutexLock(x) MOJO_COMPILE_ASSERT(0, mutex_lock_missing_variable_name); + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_UTILITY_MUTEX_H_ diff --git a/mojo/public/cpp/utility/run_loop.h b/mojo/public/cpp/utility/run_loop.h new file mode 100644 index 0000000..288a68e --- /dev/null +++ b/mojo/public/cpp/utility/run_loop.h @@ -0,0 +1,108 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_ +#define MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_ + +#include <map> + +#include "mojo/public/cpp/system/core.h" + +namespace mojo { + +class RunLoopHandler; + +class RunLoop { + public: + RunLoop(); + ~RunLoop(); + + // Sets up state needed for RunLoop. This must be invoked before creating a + // RunLoop. + static void SetUp(); + + // Cleans state created by Setup(). + static void TearDown(); + + // Returns the RunLoop for the current thread. Returns NULL if not yet + // created. + static RunLoop* current(); + + // Registers a RunLoopHandler for the specified handle. Only one handler can + // be registered for a specified handle. + void AddHandler(RunLoopHandler* handler, + const Handle& handle, + MojoWaitFlags wait_flags, + MojoDeadline deadline); + void RemoveHandler(const Handle& handle); + bool HasHandler(const Handle& handle) const; + + // Runs the loop servicing handles as they are ready. This returns when Quit() + // is invoked, or there no more handles. + void Run(); + + // Runs the loop servicing any handles that are ready. Does not wait for + // handles to become ready before returning. Returns early if Quit() is + // invoked. + void RunUntilIdle(); + + void Quit(); + + private: + struct RunState; + struct WaitState; + + // Contains the data needed to track a request to AddHandler(). + struct HandlerData { + HandlerData() + : handler(NULL), + wait_flags(MOJO_WAIT_FLAG_NONE), + deadline(0), + id(0) {} + + RunLoopHandler* handler; + MojoWaitFlags wait_flags; + MojoTimeTicks deadline; + // See description of |RunLoop::next_handler_id_| for details. + int id; + }; + + typedef std::map<Handle, HandlerData> HandleToHandlerData; + + // Waits for a handle to be ready. Returns after servicing at least one + // handle (or there are no more handles) unless |non_blocking| is true, + // in which case it will also return if servicing at least one handle + // would require blocking. Returns true if a RunLoopHandler was notified. + bool Wait(bool non_blocking); + + // Notifies any handlers whose deadline has expired. Returns true if a + // RunLoopHandler was notified. + bool NotifyDeadlineExceeded(); + + // Removes the first invalid handle. This is called if MojoWaitMany() finds an + // invalid handle. Returns true if a RunLoopHandler was notified. + bool RemoveFirstInvalidHandle(const WaitState& wait_state); + + // Returns the state needed to pass to WaitMany(). + WaitState GetWaitState(bool non_blocking) const; + + HandleToHandlerData handler_data_; + + // If non-NULL we're running (inside Run()). Member references a value on the + // stack. + RunState* run_state_; + + // An ever increasing value assigned to each HandlerData::id. Used to detect + // uniqueness while notifying. That is, while notifying expired timers we copy + // |handler_data_| and only notify handlers whose id match. If the id does not + // match it means the handler was removed then added so that we shouldn't + // notify it. + int next_handler_id_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(RunLoop); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_ diff --git a/mojo/public/cpp/utility/run_loop_handler.h b/mojo/public/cpp/utility/run_loop_handler.h new file mode 100644 index 0000000..69838d5 --- /dev/null +++ b/mojo/public/cpp/utility/run_loop_handler.h @@ -0,0 +1,25 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_HANDLER_H_ +#define MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_HANDLER_H_ + +#include "mojo/public/cpp/system/core.h" + +namespace mojo { + +// Used by RunLoop to notify when a handle is either ready or has become +// invalid. +class RunLoopHandler { + public: + virtual void OnHandleReady(const Handle& handle) = 0; + virtual void OnHandleError(const Handle& handle, MojoResult result) = 0; + + protected: + virtual ~RunLoopHandler() {} +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_HANDLER_H_ diff --git a/mojo/public/cpp/utility/thread.h b/mojo/public/cpp/utility/thread.h new file mode 100644 index 0000000..b7d10ee --- /dev/null +++ b/mojo/public/cpp/utility/thread.h @@ -0,0 +1,62 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_UTILITY_THREAD_H_ +#define MOJO_PUBLIC_CPP_UTILITY_THREAD_H_ + +#ifdef _WIN32 +#error "Not implemented: See crbug.com/342893." +#endif + +#include <pthread.h> +#include <stddef.h> + +#include "mojo/public/cpp/system/macros.h" + +namespace mojo { + +// This class is thread-friendly, not thread-safe (e.g., you mustn't call +// |Join()| from multiple threads and/or simultaneously try to destroy the +// object). +class Thread { + public: + // TODO(vtl): Support non-joinable? priority? + class Options { + public: + Options() : stack_size_(0) {} + + // A stack size of 0 means the default. + size_t stack_size() const { return stack_size_; } + void set_stack_size(size_t stack_size) { stack_size_ = stack_size; } + + private: + size_t stack_size_; + + // Copy and assign allowed. + }; + + // TODO(vtl): Add name or name prefix? + Thread(); + explicit Thread(const Options& options); + virtual ~Thread(); + + void Start(); + void Join(); + + virtual void Run() = 0; + + private: + static void* ThreadRunTrampoline(void* arg); + + const Options options_; + pthread_t thread_; + bool started_; + bool joined_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(Thread); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_UTILITY_THREAD_H_ |