blob: 2ad100662d2a86b47ce98d548a0a78fed83772b1 [file] [log] [blame]
// Copyright 2015 Google Inc. All Rights Reserved.
// 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
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Thread creation and cleanup.
#include "starboard/export.h"
#include "starboard/thread_types.h"
#include "starboard/time.h"
#include "starboard/types.h"
#ifdef __cplusplus
extern "C" {
// A spectrum of thread priorities. Platforms map them appropriately to their
// own priority system. Note that scheduling is platform-specific, and what
// these priorities mean, if they mean anything at all, is also
// platform-specific.
// In particular, several of these priority values can map to the same priority
// on a given platform. The only guarantee is that each lower priority should be
// treated less-than-or-equal-to a higher priority.
typedef enum SbThreadPriority {
// The lowest thread priority available on the current platform.
// A lower-than-normal thread priority, if available on the current platform.
// Really, what is normal? You should spend time pondering that question more
// than you consider less-important things, but less than you think about
// more-important things.
// A higher-than-normal thread priority, if available on the current platform.
// The highest thread priority available on the current platform that isn't
// considered "real-time" or "time-critical," if those terms have any meaning
// on the current platform.
// If the platform provides any kind of real-time or time-critical scheduling,
// this priority will request that treatment. Real-time scheduling generally
// means that the thread will have more consistency in scheduling than
// non-real-time scheduled threads, often by being more deterministic in how
// threads run in relation to each other. But exactly how being real-time
// affects the thread scheduling is platform-specific.
// For platforms where that is not offered, or otherwise not meaningful, this
// will just be the highest priority available in the platform's scheme, which
// may be the same as kThreadPriority_Highest.
// Well-defined constant value to mean "no priority." This means to use the
// default priority assignment method of that platform. This may mean to
// inherit the priority of the spawning thread, or it may mean a specific
// default priority, or it may mean something else, depending on the platform.
kSbThreadNoPriority = kSbInvalidInt,
} SbThreadPriority;
// An ID type that is unique per thread.
typedef int32_t SbThreadId;
// Function pointer type for SbThreadCreate. |context| is a pointer-sized bit
// of data passed in from the calling thread.
typedef void* (*SbThreadEntryPoint)(void* context);
// Function pointer type for Thread-Local destructors.
typedef void (*SbThreadLocalDestructor)(void* value);
// Type for thread core affinity. This generally will be a single cpu (or core
// or hyperthread) identifier. Some platforms may not support affinity, and some
// may have specific rules about how it must be used.
typedef int32_t SbThreadAffinity;
// Private structure representing a thread-local key.
typedef struct SbThreadLocalKeyPrivate SbThreadLocalKeyPrivate;
// A handle to a thread-local key.
typedef SbThreadLocalKeyPrivate* SbThreadLocalKey;
// Well-defined constant value to mean "no thread ID."
#define kSbThreadInvalidId (SbThreadId)0
// Well-defined constant value to mean "no affinity."
#define kSbThreadNoAffinity (SbThreadAffinity) kSbInvalidInt
// Well-defined constant value to mean "no thread local key."
#define kSbThreadLocalKeyInvalid (SbThreadLocalKey) NULL
// Returns whether the given thread handle is valid.
static SB_C_INLINE bool SbThreadIsValid(SbThread thread) {
return thread != kSbThreadInvalid;
// Returns whether the given thread ID is valid.
static SB_C_INLINE bool SbThreadIsValidId(SbThreadId id) {
return id != kSbThreadInvalidId;
// Returns whether the given thread priority is valid.
static SB_C_INLINE bool SbThreadIsValidPriority(SbThreadPriority priority) {
return priority != kSbThreadNoPriority;
// Returns whether the given thread affinity is valid.
static SB_C_INLINE bool SbThreadIsValidAffinity(SbThreadAffinity affinity) {
return affinity != kSbThreadNoAffinity;
// Returns whether the given thread local variable key is valid.
static SB_C_INLINE bool SbThreadIsValidLocalKey(SbThreadLocalKey key) {
return key != kSbThreadLocalKeyInvalid;
// Creates a new thread, which starts immediately. The |stack_size| parameter
// can be 0 to indicate that the default stack size should be used. |priority|
// can be set to kSbThreadNoPriority to use the default priority for the
// platform (e.g. possibly a fixed, standard priority, or possibly a priority
// inherited from the thread that is calling SbThreadCreate()). |affinity| can
// be set to kSbThreadNoAffinity to use the default affinity for the platform.
// |joinable| sets whether the thread can be joined, or should start out
// "detached." |name| is mainly used for debugging, may be NULL, and may not
// even be used in production builds. Returns a handle to the newly created
// thread upon success, and returns kSbThreadInvalid if not. |entry_point| will
// be executed on the newly created thread, and passed |context|.
// NOTE: For joinable threads, when you are done with the thread handle, you
// must call SbThreadJoin to release system resources associated with the
// thread. This is not necessary for detached threads, but a detached thread
// cannot be joined.
SB_EXPORT SbThread SbThreadCreate(int64_t stack_size,
SbThreadPriority priority,
SbThreadAffinity affinity,
bool joinable,
const char* name,
SbThreadEntryPoint entry_point,
void* context);
// Joins with joinable |thread|, created with SbThreadCreate. This function
// blocks the caller until the designated thread exits, and then cleans up that
// thread's resources. Returns true on success, false if |thread| is invalid or
// detached. This will essentially detach |thread|. Each joinable thread must be
// joined to be fully cleaned up. If |out_return| is not NULL, the return value
// of the thread's main function is placed there.
// Each joinable thread can only be joined once. Once SbThreadJoin is called,
// the thread behaves as if it was detached to all threads other than the
// joining thread.
SB_EXPORT bool SbThreadJoin(SbThread thread, void** out_return);
// Detaches |thread|, which prevents it from being joined. This is sort of like
// a non-blocking join. Does nothing if the thread is already detached, or is
// already being joined by another thread.
SB_EXPORT void SbThreadDetach(SbThread thread);
// Yields the currently executing thread, so another thread has a chance to run.
SB_EXPORT void SbThreadYield();
// Sleeps the currently executing thread for at least the given |duration| in
// microseconds. A negative duration does nothing.
SB_EXPORT void SbThreadSleep(SbTime duration);
// Gets the handle of the currently executing thread.
SB_EXPORT SbThread SbThreadGetCurrent();
// Gets the Thread ID of the currently executing thread.
SB_EXPORT SbThreadId SbThreadGetId();
// Returns whether |thread1| and |thread2| refer to the same thread.
SB_EXPORT bool SbThreadIsEqual(SbThread thread1, SbThread thread2);
// Gets the debug name of the currently executing thread.
SB_EXPORT void SbThreadGetName(char* buffer, int buffer_size);
// Sets the debug name of the currently executing thread. Will copy the
// specified name string.
SB_EXPORT void SbThreadSetName(const char* name);
// Creates a new, unique key for thread local data with given optional
// |destructor|. |destructor| may be NULL if there is no clean up
// needed. Returns kSbThreadLocalKeyInvalid if creation was unsuccessful.
// When does |destructor| get called? It can only be called in the owning
// thread, and let's just say thread interruption isn't viable. The destructor,
// if specified, is called on every thread's local values when the thread exits,
// if and only if the value in the key is non-NULL.
SB_EXPORT SbThreadLocalKey
SbThreadCreateLocalKey(SbThreadLocalDestructor destructor);
// Destroys thread local data |key|. Does nothing if key is
// kSbThreadLocalKeyInvalid or has already been destroyed. This does NOT call
// the destructor on any stored values.
SB_EXPORT void SbThreadDestroyLocalKey(SbThreadLocalKey key);
// Gets the pointer-sized value for |key| in the currently executing thread's
// local storage. Returns NULL if key is kSbThreadLocalKeyInvalid or has already
// been destroyed.
SB_EXPORT void* SbThreadGetLocalValue(SbThreadLocalKey key);
// Sets the pointer-sized value for |key| in the currently executing thread's
// local storage. Returns whether |key| is valid and has not already been
// destroyed.
SB_EXPORT bool SbThreadSetLocalValue(SbThreadLocalKey key, void* value);
// Returns whether |thread| is the current thread.
SB_C_INLINE bool SbThreadIsCurrent(SbThread thread) {
return SbThreadGetCurrent() == thread;
#ifdef __cplusplus
} // extern "C"