| /*---------------------------------------------------------------------------* |
| * ptrd.h * |
| * * |
| * Copyright 2007, 2008 Nuance Communciations, Inc. * |
| * * |
| * 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 PTRD_H |
| #define PTRD_H |
| |
| |
| |
| |
| #ifdef USE_THREAD |
| |
| #include "PortPrefix.h" |
| #include "ptypes.h" |
| #include "ESR_ReturnCode.h" |
| |
| #define STACKSIZE_S2G_SINKER 12*1024 |
| #define STACKSIZE_S2G_RECOGNIZER 25*1024 |
| #define STACKSIZE_DEFAULT 18*1024 |
| |
| #ifdef _WIN32 |
| typedef unsigned int PTHREAD_ID; |
| #define PtrdGetCurrentThreadId GetCurrentThreadId |
| #elif defined(POSIX) |
| |
| #if defined(__vxworks) && !defined(REAL_PTHREADS) |
| #include "pthread_vx.h" |
| #else |
| #include <pthread.h> |
| |
| #ifndef _POSIX_THREADS |
| #error "Thread is not defined!" |
| #endif |
| #endif /* #if defined(__vxworks) && !defined(REAL_PTHREADS) */ |
| |
| typedef pthread_t PTHREAD_ID; |
| #define PtrdGetCurrentThreadId pthread_self |
| #else |
| #error Portable Synchronization not defined for this OS! |
| #endif /* os dependant basic types */ |
| |
| /** |
| * @addtogroup PtrdModule PThread API functions |
| * Library for basic thread and monitor functionality to ensure portability. |
| * Call PtrdInit() to initialize and PtrdShutdown() to shutdown module. |
| * |
| * Every thread has a priority. Threads with higher priority are executed in preference |
| * to threads with lower priority. When code running in some thread creates a new Thread |
| * object, the new thread has its priority initially set equal to the priority of the creating |
| * thread. |
| * |
| * |
| * @{ |
| */ |
| |
| /** Typedef */ |
| typedef struct PtrdMonitor_t PtrdMonitor; |
| /** Typedef */ |
| typedef struct PtrdMutex_t PtrdMutex; |
| /** Typedef */ |
| typedef struct PtrdSemaphore_t PtrdSemaphore; |
| /** Typedef */ |
| typedef struct PtrdThread_t PtrdThread; |
| |
| |
| /** |
| * Blocks the current thread for the specified amount of time. |
| * |
| * @param sleepTimeMs number of milliseconds to sleep. A value of 0 is |
| * equivalent to a thread yield. |
| * |
| * @return ESR_SUCCESS if success, or something else to indicate a failure. |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdSleep(asr_uint32_t sleepTimeMs); |
| |
| /** |
| * Creates a thread monitor. Thread monitors can be locked, unlocked, can be |
| * waited on and can be notified. Monitors implement so-called recursive |
| * locking, meaning that a thread owning the monitor can call lock without |
| * blocking and will have to call unlock() as many times as lock() was called. |
| * |
| * @param monitor Handle to the created monitor |
| * |
| * @return ESR_SUCCESS if succes, or something else to indicate a failure. In |
| * particular, it will return ESR_INVALID_STATE if the threading API is not |
| * properly initialized. |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdMonitorCreate(PtrdMonitor **monitor); |
| |
| /** |
| * Destroys a monitor. |
| * |
| * @param monitor Handle to the monitor to destroy |
| * |
| * @return ESR_SUCCESS if success; ESR_INVALID_STATE if this function is called after the thread |
| * library is shutdown, or cannot lock on mutex; ESR_INVALID_ARGUMENT if monitor is null |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdMonitorDestroy(PtrdMonitor *monitor); |
| |
| /** |
| * Locks a monitor. |
| * |
| * @param monitor Handle to the monitor to lock |
| * @param fname Filename of code requesting a lock |
| * @param line Line of code requesting a lock |
| * |
| * @return ESR_SUCCESS if success; ESR_INVALID_ARGUMENT if monitor is null; ESR_FATAL_ERROR if waiting on the mutex failed |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdMonitorLockWithLine(PtrdMonitor *monitor, const LCHAR *fname, int line); |
| /** |
| * Locks a monitor. |
| * |
| * @param monitor Handle to the monitor to lock |
| * |
| * @return ESR_SUCCESS if success, or an an error indicating the cause of the |
| * failure. |
| */ |
| #define PtrdMonitorLock(monitor) PtrdMonitorLockWithLine(monitor, L(__FILE__), __LINE__) |
| |
| /** |
| * Unlock a Monitor |
| * |
| * @param monitor Handle to the monitor to unlock |
| * |
| * @return ESR_SUCCESS if success, or an an error indicating the cause of the |
| * failure. In particular, it will return ESR_INVALID_STATE if the current |
| * thread does not hold the monitor. |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdMonitorUnlock(PtrdMonitor *monitor); |
| |
| /** |
| * Causes current thread to wait until another thread invokes the |
| * <code>PtrdMonitorNotify()</code> method or the |
| * <code>PtrdMonitorNotifyAll()</code> method for this monitor. |
| * |
| * <p> |
| * |
| * The current thread must own this monitor. The thread releases ownership of |
| * this monitor and waits until another thread notifies threads waiting on |
| * this object's monitor to wake up either through a call to the |
| * <code>PtrdMonitorNotify</code> method or the |
| * <code>PtrdMonitorNotifyAll</code> method. The thread then waits until it |
| * can re-obtain ownership of the monitor and resumes execution. |
| * |
| * @param monitor The monitor on which to wait. |
| * |
| * @return ESR_SUCCESS if success, or an an error indicating the cause of the |
| * failure. In particular, it will return ESR_INVALID_STATE if the current |
| * thread does not hold the monitor. |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdMonitorWait(PtrdMonitor *monitor); |
| |
| |
| /** |
| * Causes current thread to wait until either another thread invokes the |
| * <code>PtrdMonitorNotify()</code> method or the |
| * <code>PtrdMonitorNotifyAll()</code> method for this monitor, or a specified |
| * amount of time has elapsed. |
| * |
| * @param monitor The monitor on which to wait. |
| * |
| * @param timeoutMs The amount of time (in millisecs) to wait for |
| * notification. |
| * |
| * @return ESR_SUCCESS if success, or an an error indicating the cause of the |
| * failure. In particular, it will return ESR_INVALID_STATE if the current |
| * thread does not hold the monitor, or ESR_TIMED_OUT if the timeout expired |
| * without a notification. |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdMonitorWaitTimeout(PtrdMonitor *monitor, |
| asr_uint32_t timeoutMs); |
| |
| /** |
| * Wakes up a single thread that is waiting on this monitor. If more than one |
| * thread are waiting on this object, one of them is arbitrarily chosen to be |
| * awakened. A thread waits on the monitor by calling |
| * <code>PtrdMonitorWait</code> or <code>PtrdMonitorWaitTimeout</code>. |
| * |
| * <p> |
| * |
| * The awakened thread will not be able to proceed until the current thread |
| * relinquishes the lock on this object. The awakened thread will compete in |
| * the usual manner with any other threads that might be actively competing to |
| * synchronize on this object; for example, the awakened thread enjoys no |
| * reliable privilege or disadvantage in being the next thread to lock this |
| * monitor. |
| * |
| * <p> |
| * |
| * This method should only be called by a thread that is the owner of this |
| * monitor. |
| * |
| * @return ESR_SUCCESS if success, or an an error indicating the cause of the |
| * failure. In particular, it will return ESR_INVALID_STATE if the current |
| * thread does not hold the monitor, or ESR_TIMED_OUT if the timeout expired |
| * without a notification. |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdMonitorNotify(PtrdMonitor *monitor); |
| |
| /** |
| * Wakes up all threads that are waiting on this monitor. A thread waits on |
| * a monitor by calling <code>PtrdMonitorWait</code> or |
| * <code>PtrdMonitorWaitTimeout</code> |
| * |
| * <p> |
| * |
| * The awakened threads will not be able to proceed until the current thread |
| * relinquishes the monitor. The awakened threads will compete in the usual |
| * manner with any other threads that might be actively competing to |
| * synchronize on this monitor; for example, the awakened threads enjoy no |
| * reliable privilege or disadvantage in being the next thread to lock this |
| * object. |
| * |
| * <p> |
| * |
| * This method should only be called by a thread that is the owner of this |
| * object's monitor. |
| * |
| * @param monitor The monitor on which to wait. |
| * |
| * @return ESR_SUCCESS if success, or an an error indicating the cause of the |
| * failure. In particular, it will return ESR_INVALID_STATE if the current |
| * thread does not hold the monitor. |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdMonitorNotifyAll(PtrdMonitor *monitor); |
| |
| /** |
| * Creates a thread mutex. Thread mutexes are similar to thread monitors |
| * except that they do not support wait and notify mechanism and require less |
| * resources from the OS. In situations where this mechanism is not required, |
| * using mutexes instead of monitors is preferable. Mutexes implement |
| * so-called recursive locking, meaning that a thread owning the mutex can |
| * call lock without blocking and will have to call unlock() as many times as |
| * lock() was called. |
| * |
| * @param mutex Handle to the created mutex |
| * |
| * @return ESR_SUCCESS if success, or an an error indicating the cause of the |
| * failure. |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdMutexCreate(PtrdMutex **mutex); |
| |
| /** |
| * Destroys a mutex. |
| * |
| * @param mutex Handle to the mutex to destroy |
| * |
| * @return ESR_ReturnCode 0 on success |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdMutexDestroy(PtrdMutex *mutex); |
| |
| /** |
| * Lock a mutex |
| * |
| * @param mutex Handle to the mutex to lock |
| * @param fname Filename of code requesting a lock |
| * @param line Line of code requesting a lock |
| * |
| * @return ESR_SUCCESS if success, or an an error indicating the cause of the |
| * failure. |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdMutexLockWithLine(PtrdMutex *mutex, const LCHAR *fname, int line); |
| /** |
| * Lock a mutex |
| * |
| * @param mutex Handle to the mutex to lock |
| * |
| * @return ESR_SUCCESS if success, or an an error indicating the cause of the |
| * failure. |
| */ |
| #define PtrdMutexLock(mutex) PtrdMutexLockWithLine(mutex, L(__FILE__), __LINE__) |
| |
| /** |
| * Unlock a Mutex |
| * |
| * @param mutex Handle to the mutex to unlock |
| * |
| * @return ESR_SUCCESS if success, or an an error indicating the cause of the |
| * failure. In particular, it will return ESR_INVALID_STATE if the current |
| * thread does not hold the mutex. |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdMutexUnlock(PtrdMutex *mutex); |
| |
| |
| /** |
| * Creates a thread semaphore. |
| * |
| * @param semaphore Handle to the created semaphore. |
| * @param initValue Initial semaphore value |
| * @param maxValue Maximum semaphore value |
| * |
| * @return ESR_SUCCESS if success, or an an error indicating the cause of the |
| * failure. |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdSemaphoreCreate(unsigned int initValue, |
| unsigned int maxValue, |
| PtrdSemaphore **semaphore); |
| |
| /** |
| * Destroy a semaphore |
| * |
| * @param semaphore Handle to the semaphore to destroy |
| * |
| * @return ESR_SUCCESS if success, or an an error indicating the cause of the |
| * failure. |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdSemaphoreDestroy(PtrdSemaphore *semaphore); |
| |
| /** |
| * Decrements the semaphore. If the semaphore's current value is 0, the |
| * current thread waits until the semaphore's value is greater than 0. |
| * |
| * @param semaphore Handle to the semaphore to acquire. |
| * |
| * @return ESR_SUCCESS if successful, or a status code indicating the nature of |
| * the error. |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdSemaphoreAcquire(PtrdSemaphore *semaphore); |
| |
| |
| /** |
| * Decrements the semaphore. If the semaphore's current value is 0, the |
| * current thread waits until the semaphore's value is greater than 0 or until |
| * the timeout expires. |
| * |
| * @param semaphore Handle to the semaphore to acquire. |
| * @param timeoutMs Timeout in milliseconds. |
| * |
| * @return ESR_SUCCESS if wait is successful, ESR_TIMED_OUT if timed out, or an |
| * error status indicating the nature of the error in other situations. |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdSemaphoreAcquireTimeout(PtrdSemaphore *semaphore, |
| asr_uint32_t timeoutMs); |
| |
| /** |
| * Increments a semaphore. |
| * |
| * @param semaphore Handle to the semaphore to release. |
| * |
| * @return ESR_SUCCESS success or an error status indicating the nature of the |
| * error. In particular, it will return ESR_INVALID_STATE if the semaphore is |
| * currently at its maximum value. |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdSemaphoreRelease(PtrdSemaphore *semaphore); |
| |
| |
| /** |
| * Function signature invoked on the new thread by PtrdThreadCreate(), and |
| * the argument to that function. |
| */ |
| typedef void* PtrdThreadArg; |
| /** |
| * Function prototype that launched threads must conform to. |
| * |
| * @param userData Data passed in by caller of PtrdThreadCreate |
| */ |
| typedef void(*PtrdThreadStartFunc)(PtrdThreadArg userData); |
| |
| /** |
| * Minimum thread priority. |
| */ |
| #define PtrdThreadMinPriority 0 |
| |
| /** |
| * Maximum thread priority. |
| */ |
| #define PtrdThreadMaxPriority UINT16_TMAX |
| |
| /** |
| * Normal thread priority. |
| */ |
| #define PtrdThreadNormalPriority (PtrdThreadMaxPriority / 2) |
| |
| /** |
| * Creates a thread. |
| * |
| * Execution starts on the thread immediately. To pause execution use a |
| * monitor or a mutex between the thread and the thread creator. |
| * |
| * @param thread Handle to the thread that is created |
| * @param startFunc Function for the thread to start execution on |
| * @param arg Argument to the thread function |
| * |
| * @return ESR_INVALID_ARGUMENT if thread or startFunc are null; ESR_OUT_OF_MEMORY if system is out of memory; |
| * ESR_THREAD_CREATION_ERROR if thread cannot be created |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdThreadCreate(PtrdThreadStartFunc startFunc, PtrdThreadArg arg, |
| PtrdThread** thread); |
| |
| /** |
| * Destroys a thread handle. |
| * |
| * Note: this does NOT stop or destroy the thread, it just releases |
| * the handle for accessing it. If this is not done, a memory leak |
| * occurs, so if the creator of the thread never needs to communicate |
| * with the thread again it should call this immediately after the |
| * create if the create was successful. |
| * |
| * @return ESR_SUCCESS on failure or an error indicating the nature of the |
| * error. |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdThreadDestroy(PtrdThread *thread); |
| |
| /** |
| * Wait for the termination of a specified thread |
| * |
| * @param thread Handle to the thread to wait for |
| * |
| * @return ESR_INVALID_ARGUMENT if thread is null |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdThreadJoin(PtrdThread *thread); |
| |
| /** |
| * Returns the thread priority. |
| * |
| * @param thread PtrdThread handle |
| * @param value [out] Thread priority |
| * |
| * @return ESR_INVALID_ARGUMENT if thread or value are null; ESR_INVALID_STATE if thread priority cannot be |
| * retrieved |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdThreadGetPriority(PtrdThread *thread, asr_uint16_t* value); |
| |
| /** |
| * Sets the thread priority. |
| * |
| * @param thread PtrdThread handle |
| * @param value Thread priority |
| * |
| * @return ESR_INVALID_ARGUMENT if thread or value are null; ESR_INVALID_STATE if thread priority cannot be |
| * set |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdThreadSetPriority(PtrdThread *thread, asr_uint16_t value); |
| |
| /** |
| * Yields execution of the current thread to other threads. |
| * |
| * @return ESR_SUCCESS |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdThreadYield(void); |
| |
| /** |
| * Initializes the thread library. This should be called before creating the |
| * first thread or the first monitor. |
| * |
| * @return ESR_INVALID_STATE if the Ptrd module has already been initialized; |
| * ESR_MUTEX_CREATION_ERROR if mutex cannot be created |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdInit(void); |
| |
| /** |
| * Indicates if thread library has been initialized. |
| * |
| * @param enabled [out] True if library is initialized |
| * @return ESR_INVALID_ARGUMENT if enabled is null |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdIsEnabled(ESR_BOOL* enabled); |
| |
| /** |
| * Shutdowns the thread library. All thread and monitor should be terminated |
| * and destroyed before calling this function. |
| * |
| * @return ESR_INVALID_STATE if Ptrd module is not running |
| * error. |
| */ |
| PORTABLE_API ESR_ReturnCode PtrdShutdown(void); |
| |
| /** |
| * @} |
| */ |
| |
| #else |
| |
| |
| //#error "Including ptrd.h on a non-threaded platform." |
| |
| |
| #endif /* USE_THREAD */ |
| #endif |