2020-04-10 01:11:40 -04:00
|
|
|
#ifndef RUBY_THREAD_NATIVE_H /*-*-C++-*-vi:se ft=cpp:*/
|
2014-05-14 06:55:38 -04:00
|
|
|
#define RUBY_THREAD_NATIVE_H 1
|
2020-04-10 01:11:40 -04:00
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
* @author $Author: ko1 $
|
|
|
|
* @date Wed May 14 19:37:31 2014
|
|
|
|
* @copyright Copyright (C) 2014 Yukihiro Matsumoto
|
|
|
|
* @copyright This file is a part of the programming language Ruby.
|
|
|
|
* Permission is hereby granted, to either redistribute and/or
|
|
|
|
* modify this file, provided that the conditions mentioned in the
|
|
|
|
* file COPYING are met. Consult the file for details.
|
2021-06-08 04:58:25 -04:00
|
|
|
*
|
2014-05-14 06:55:38 -04:00
|
|
|
* This file contains wrapper APIs for native thread primitives
|
|
|
|
* which Ruby interpreter uses.
|
|
|
|
*
|
2020-04-05 16:56:11 -04:00
|
|
|
* Now, we only support pthread and Windows threads.
|
2014-05-14 06:55:38 -04:00
|
|
|
*
|
|
|
|
* If you want to use Ruby's Mutex and so on to synchronize Ruby Threads,
|
|
|
|
* please use Mutex directly.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
#include <windows.h>
|
|
|
|
typedef HANDLE rb_nativethread_id_t;
|
|
|
|
|
|
|
|
typedef union rb_thread_lock_union {
|
|
|
|
HANDLE mutex;
|
|
|
|
CRITICAL_SECTION crit;
|
|
|
|
} rb_nativethread_lock_t;
|
|
|
|
|
2020-11-17 02:40:47 -05:00
|
|
|
typedef struct rb_thread_cond_struct rb_nativethread_cond_t;
|
|
|
|
|
2014-05-14 06:55:38 -04:00
|
|
|
#elif defined(HAVE_PTHREAD_H)
|
2020-11-17 02:40:47 -05:00
|
|
|
|
2014-05-14 06:55:38 -04:00
|
|
|
#include <pthread.h>
|
|
|
|
typedef pthread_t rb_nativethread_id_t;
|
|
|
|
typedef pthread_mutex_t rb_nativethread_lock_t;
|
2020-11-17 02:40:47 -05:00
|
|
|
typedef pthread_cond_t rb_nativethread_cond_t;
|
2014-05-14 06:55:38 -04:00
|
|
|
|
2022-01-15 10:37:54 -05:00
|
|
|
#elif defined(__wasi__) // no-thread platforms
|
|
|
|
|
|
|
|
typedef struct rb_nativethread_id_t *rb_nativethread_id_t;
|
|
|
|
typedef struct rb_nativethread_lock_t *rb_nativethread_lock_t;
|
|
|
|
typedef struct rb_nativethread_cond_t *rb_nativethread_cond_t;
|
|
|
|
|
2021-06-08 04:58:25 -04:00
|
|
|
#elif defined(__DOXYGEN__)
|
|
|
|
|
|
|
|
/** Opaque type that holds an ID of a native thread. */
|
|
|
|
struct rb_nativethread_id_t;
|
|
|
|
|
|
|
|
/** Opaque type that holds a lock. */
|
|
|
|
struct rb_nativethread_lock_t;
|
|
|
|
|
|
|
|
/** Opaque type that holds a condition variable. */
|
|
|
|
struct rb_nativethread_cond_t;
|
|
|
|
|
2014-05-14 06:55:38 -04:00
|
|
|
#else
|
|
|
|
#error "unsupported thread type"
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2021-06-08 04:58:25 -04:00
|
|
|
RBIMPL_SYMBOL_EXPORT_BEGIN()
|
2014-05-14 06:55:38 -04:00
|
|
|
|
2021-06-08 04:58:25 -04:00
|
|
|
/**
|
|
|
|
* Queries the ID of the native thread that is calling this function.
|
|
|
|
*
|
|
|
|
* @return The caller thread's native ID.
|
|
|
|
*/
|
2021-05-06 11:04:36 -04:00
|
|
|
rb_nativethread_id_t rb_nativethread_self(void);
|
2014-05-14 06:55:38 -04:00
|
|
|
|
2021-06-08 04:58:25 -04:00
|
|
|
/**
|
|
|
|
* Fills the passed lock with an initial value.
|
|
|
|
*
|
|
|
|
* @param[out] lock A mutex to initialise.
|
|
|
|
* @post `lock` is updated to its initial state.
|
|
|
|
*
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* There is no data structure that analogous to pthread_once_t in ruby. It is
|
|
|
|
* pretty much tricky (if not impossible) to properly initialise a mutex
|
|
|
|
* exactly once.
|
|
|
|
*/
|
2014-05-14 06:55:38 -04:00
|
|
|
void rb_nativethread_lock_initialize(rb_nativethread_lock_t *lock);
|
2021-06-08 04:58:25 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Destroys the passed mutex.
|
|
|
|
*
|
|
|
|
* @param[out] lock A mutex to kill.
|
|
|
|
* @post `lock` is no longer eligible for other functions.
|
|
|
|
*
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* It is an undefined behaviour (see `pthread_mutex_destroy(3posix)`) to
|
|
|
|
* destroy a locked mutex. So it has to be unlocked. But an unlocked mutex
|
|
|
|
* can of course be locked by another thread. That's the ultimate reason why
|
|
|
|
* we do mutex. There is an inevitable race condition here. 2017 edition of
|
|
|
|
* IEEE 1003.1 issue 7 says in its rationale that "care must be taken". Care?
|
|
|
|
* How?
|
|
|
|
*
|
|
|
|
* @shyouhei thinks that POSIX is broken by design.
|
|
|
|
*/
|
2014-05-14 06:55:38 -04:00
|
|
|
void rb_nativethread_lock_destroy(rb_nativethread_lock_t *lock);
|
2021-06-08 04:58:25 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Blocks until the current thread obtains a lock.
|
|
|
|
*
|
|
|
|
* @param[out] lock A mutex to lock.
|
|
|
|
* @post `lock` is owned by the current native thread.
|
|
|
|
*/
|
2014-05-14 06:55:38 -04:00
|
|
|
void rb_nativethread_lock_lock(rb_nativethread_lock_t *lock);
|
2021-06-08 04:58:25 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Releases a lock.
|
|
|
|
*
|
|
|
|
* @param[out] lock A mutex to unlock.
|
|
|
|
* @pre `lock` is owned by the current native thread.
|
|
|
|
* @post `lock` is not owned by the current native thread.
|
|
|
|
*/
|
2014-05-14 06:55:38 -04:00
|
|
|
void rb_nativethread_lock_unlock(rb_nativethread_lock_t *lock);
|
|
|
|
|
2021-06-08 04:58:25 -04:00
|
|
|
/** @alias{rb_nativethread_lock_lock} */
|
2020-11-17 02:40:47 -05:00
|
|
|
void rb_native_mutex_lock(rb_nativethread_lock_t *lock);
|
2021-06-08 04:58:25 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Identical to rb_native_mutex_lock(), except it doesn't block in case
|
|
|
|
* rb_native_mutex_lock() would.
|
|
|
|
*
|
|
|
|
* @param[out] lock A mutex to lock.
|
|
|
|
* @retval 0 `lock` is successfully owned by the current thread.
|
|
|
|
* @retval EBUSY `lock` is owned by someone else.
|
|
|
|
*/
|
2020-11-17 02:40:47 -05:00
|
|
|
int rb_native_mutex_trylock(rb_nativethread_lock_t *lock);
|
2021-06-08 04:58:25 -04:00
|
|
|
|
|
|
|
/** @alias{rb_nativethread_lock_unlock} */
|
2020-11-17 02:40:47 -05:00
|
|
|
void rb_native_mutex_unlock(rb_nativethread_lock_t *lock);
|
2021-06-08 04:58:25 -04:00
|
|
|
|
|
|
|
/** @alias{rb_nativethread_lock_initialize} */
|
2020-11-17 02:40:47 -05:00
|
|
|
void rb_native_mutex_initialize(rb_nativethread_lock_t *lock);
|
2021-06-08 04:58:25 -04:00
|
|
|
|
|
|
|
/** @alias{rb_nativethread_lock_destroy} */
|
2020-11-17 02:40:47 -05:00
|
|
|
void rb_native_mutex_destroy(rb_nativethread_lock_t *lock);
|
|
|
|
|
2021-06-08 04:58:25 -04:00
|
|
|
/**
|
|
|
|
* Signals a condition variable.
|
|
|
|
*
|
|
|
|
* @param[out] cond A condition variable to ping.
|
|
|
|
* @post More than one threads waiting for `cond` gets signalled.
|
|
|
|
* @note This function can spuriously wake multiple threads up.
|
|
|
|
* `pthread_cond_signal(3posix)` says it can even be "impossible
|
|
|
|
* to avoid the unblocking of more than one thread blocked on a
|
|
|
|
* condition variable". Just brace spurious wakeups.
|
|
|
|
*/
|
2020-11-17 02:40:47 -05:00
|
|
|
void rb_native_cond_signal(rb_nativethread_cond_t *cond);
|
2021-06-08 04:58:25 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Signals a condition variable.
|
|
|
|
*
|
|
|
|
* @param[out] cond A condition variable to ping.
|
|
|
|
* @post All threads waiting for `cond` gets signalled.
|
|
|
|
*/
|
2020-11-17 02:40:47 -05:00
|
|
|
void rb_native_cond_broadcast(rb_nativethread_cond_t *cond);
|
2021-06-08 04:58:25 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Waits for the passed condition variable to be signalled.
|
|
|
|
*
|
|
|
|
* @param[out] cond A condition variable to wait.
|
|
|
|
* @param[out] mutex A mutex.
|
|
|
|
* @pre `mutex` is owned by the current thread.
|
|
|
|
* @post `mutex` is owned by the current thread.
|
|
|
|
* @note This can wake up spuriously.
|
|
|
|
*/
|
2020-11-17 02:40:47 -05:00
|
|
|
void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex);
|
2021-06-08 04:58:25 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Identical to rb_native_cond_wait(), except it additionally takes timeout in
|
|
|
|
* msec resolution. Timeouts can be detected by catching exceptions.
|
|
|
|
*
|
|
|
|
* @param[out] cond A condition variable to wait.
|
|
|
|
* @param[out] mutex A mutex.
|
|
|
|
* @param[in] msec Timeout.
|
|
|
|
* @exception rb_eSystemCallError `Errno::ETIMEDOUT` for timeout.
|
|
|
|
* @pre `mutex` is owned by the current thread.
|
|
|
|
* @post `mutex` is owned by the current thread.
|
|
|
|
* @note This can wake up spuriously.
|
|
|
|
*/
|
2020-11-17 02:40:47 -05:00
|
|
|
void rb_native_cond_timedwait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex, unsigned long msec);
|
2021-06-08 04:58:25 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Fills the passed condition variable with an initial value.
|
|
|
|
*
|
|
|
|
* @param[out] cond A condition variable to initialise.
|
|
|
|
* @post `cond` is updated to its initial state.
|
|
|
|
*/
|
2020-11-17 02:40:47 -05:00
|
|
|
void rb_native_cond_initialize(rb_nativethread_cond_t *cond);
|
|
|
|
|
2021-06-08 04:58:25 -04:00
|
|
|
/**
|
|
|
|
* Destroys the passed condition variable.
|
|
|
|
*
|
|
|
|
* @param[out] cond A condition variable to kill.
|
|
|
|
* @post `cond` is no longer eligible for other functions.
|
|
|
|
*/
|
|
|
|
void rb_native_cond_destroy(rb_nativethread_cond_t *cond);
|
2014-05-14 06:55:38 -04:00
|
|
|
|
2021-06-08 04:58:25 -04:00
|
|
|
RBIMPL_SYMBOL_EXPORT_END()
|
2014-05-14 06:55:38 -04:00
|
|
|
#endif
|