summaryrefslogtreecommitdiff
path: root/include/ruby/internal/intern/thread.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/ruby/internal/intern/thread.h')
-rw-r--r--include/ruby/internal/intern/thread.h492
1 files changed, 0 insertions, 492 deletions
diff --git a/include/ruby/internal/intern/thread.h b/include/ruby/internal/intern/thread.h
deleted file mode 100644
index 716375acd7..0000000000
--- a/include/ruby/internal/intern/thread.h
+++ /dev/null
@@ -1,492 +0,0 @@
-#ifndef RBIMPL_INTERN_THREAD_H /*-*-C++-*-vi:se ft=cpp:*/
-#define RBIMPL_INTERN_THREAD_H
-/**
- * @file
- * @author Ruby developers <ruby-core@ruby-lang.org>
- * @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.
- * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
- * implementation details. Don't take them as canon. They could
- * rapidly appear then vanish. The name (path) of this header file
- * is also an implementation detail. Do not expect it to persist
- * at the place it is now. Developers are free to move it anywhere
- * anytime at will.
- * @note To ruby-core: remember that this header can be possibly
- * recursively included from extension libraries written in C++.
- * Do not expect for instance `__VA_ARGS__` is always available.
- * We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
- * @brief Public APIs related to ::rb_cThread.
- */
-#include "ruby/internal/attr/nonnull.h"
-#include "ruby/internal/cast.h"
-#include "ruby/internal/config.h"
-#include "ruby/internal/dllexport.h"
-#include "ruby/internal/value.h"
-
-RBIMPL_SYMBOL_EXPORT_BEGIN()
-
-struct timeval;
-
-/* thread.c */
-
-/**
- * Tries to switch to another thread. This function blocks until the current
- * thread re-acquires the GVL.
- *
- * @exception rb_eInterrupt Operation interrupted.
- */
-void rb_thread_schedule(void);
-
-/**
- * Blocks the current thread until the given file descriptor is ready to be
- * read.
- *
- * @param[in] fd A file descriptor.
- * @exception rb_eIOError Closed stream.
- * @exception rb_eSystemCallError Situations like EBADF.
- */
-int rb_thread_wait_fd(int fd);
-
-/**
- * Identical to rb_thread_wait_fd(), except it blocks the current thread until
- * the given file descriptor is ready to be written.
- *
- * @param[in] fd A file descriptor.
- * @exception rb_eIOError Closed stream.
- * @exception rb_eSystemCallError Situations like EBADF.
- */
-int rb_thread_fd_writable(int fd);
-
-/**
- * Notifies a closing of a file descriptor to other threads. Multiple threads
- * can wait for the given file descriptor at once. If such file descriptor is
- * closed, threads need to start propagating their exceptions. This is the API
- * to kick that process.
- *
- * @param[in] fd A file descriptor.
- * @note This function blocks until all the threads waiting for such fd
- * have woken up.
- */
-void rb_thread_fd_close(int fd);
-
-/**
- * Checks if the thread this function is running is the only thread that is
- * currently alive.
- *
- * @retval 1 Yes it is.
- * @retval 0 No it isn't.
- *
- * @internal
- *
- * Above description is in fact inaccurate. There are Ractors these days.
- */
-int rb_thread_alone(void);
-
-/**
- * Blocks for the given period of time.
- *
- * @warning This function can be interrupted by signals.
- * @param[in] sec Duration in seconds.
- * @exception rb_eInterrupt Interrupted.
- */
-void rb_thread_sleep(int sec);
-
-/**
- * Blocks indefinitely.
- *
- * @exception rb_eInterrupt Interrupted.
- */
-void rb_thread_sleep_forever(void);
-
-/**
- * Identical to rb_thread_sleep_forever(), except the thread calling this
- * function is considered "dead" when our deadlock checker is triggered.
- *
- * @exception rb_eInterrupt Interrupted.
- */
-void rb_thread_sleep_deadly(void);
-
-/**
- * Stops the current thread. This is not the end of the thread's lifecycle. A
- * stopped thread can later be woken up.
- *
- * @exception rb_eThreadError Stopping this thread would deadlock.
- * @retval ::RUBY_Qnil Always.
- *
- * @internal
- *
- * The return value makes no sense at all.
- */
-VALUE rb_thread_stop(void);
-
-/**
- * Marks a given thread as eligible for scheduling.
- *
- * @note It may still remain blocked on I/O.
- * @note This does not invoke the scheduler itself.
- *
- * @param[out] thread Thread in question to wake up.
- * @exception rb_eThreadError Stop flogging a dead horse.
- * @return The passed thread.
- * @post The passed thread is made runnable.
- */
-VALUE rb_thread_wakeup(VALUE thread);
-
-/**
- * Identical to rb_thread_wakeup(), except it doesn't raise on an already
- * killed thread.
- *
- * @param[out] thread A thread to wake up.
- * @retval RUBY_Qnil `thread` is already killed.
- * @retval otherwise `thread` is alive.
- * @post The passed thread is made runnable, unless killed.
- */
-VALUE rb_thread_wakeup_alive(VALUE thread);
-
-/**
- * This is a rb_thread_wakeup() + rb_thread_schedule() combo.
- *
- * @note There is no guarantee that this function yields to the passed
- * thread. It may still remain blocked on I/O.
- * @param[out] thread Thread in question to wake up.
- * @exception rb_eThreadError Stop flogging a dead horse.
- * @return The passed thread.
- */
-VALUE rb_thread_run(VALUE thread);
-
-/**
- * Terminates the given thread. Unlike a stopped thread, a killed thread could
- * never be revived. This function does return, when passed e.g. an already
- * killed thread. But if the passed thread is the only one, or a special
- * thread called "main", then it also terminates the entire process.
- *
- * @param[out] thread The thread to terminate.
- * @exception rb_eFatal The passed thread is the running thread.
- * @exception rb_eSystemExit The passed thread is the last thread.
- * @return The passed thread.
- * @post Either the passed thread, or the process entirely, is killed.
- *
- * @internal
- *
- * It seems killing the main thread also kills the entire process even if there
- * are multiple running ractors. No idea why.
- */
-VALUE rb_thread_kill(VALUE thread);
-
-RBIMPL_ATTR_NONNULL((1))
-/**
- * Creates a Ruby thread that is backended by a C function.
- *
- * @param[in] f The function to run on a thread.
- * @param[in,out] g Passed through to `f`.
- * @exception rb_eThreadError Could not create a ruby thread.
- * @exception rb_eSystemCallError Situations like `EPERM`.
- * @return Allocated instance of ::rb_cThread.
- * @note This doesn't wait for anything.
- */
-VALUE rb_thread_create(VALUE (*f)(void *g), void *g);
-
-/**
- * Identical to rb_thread_sleep(), except it takes struct `timeval` instead.
- *
- * @warning This function can be interrupted by signals.
- * @param[in] time Duration.
- * @exception rb_eInterrupt Interrupted.
- */
-void rb_thread_wait_for(struct timeval time);
-
-/**
- * Obtains the "current" thread.
- *
- * @return The current thread of the current ractor of the current execution
- * context.
- * @pre This function must be called from a thread controlled by ruby.
- */
-VALUE rb_thread_current(void);
-
-/**
- * Obtains the "main" thread. There are threads called main. Historically the
- * (only) main thread was the one which runs when the process boots. Now that
- * we have Ractor, there are more than one main threads.
- *
- * @return The main thread of the current ractor of the current execution
- * context.
- * @pre This function must be called from a thread controlled by ruby.
- */
-VALUE rb_thread_main(void);
-
-/**
- * This badly named function reads from a Fiber local storage. When this
- * function was born there was no such thing like a Fiber. The world was
- * innocent. But now... This is a Fiber local storage. Sorry.
- *
- * @param[in] thread Thread that the target Fiber is running.
- * @param[in] key The name of the Fiber local storage to read.
- * @retval RUBY_Qnil No such storage.
- * @retval otherwise The value stored at `key`.
- * @note There in fact are "true" thread local storage, but Ruby doesn't
- * provide any interface of them to you, C programmers.
- */
-VALUE rb_thread_local_aref(VALUE thread, ID key);
-
-/**
- * This badly named function writes to a Fiber local storage. When this
- * function was born there was no such thing like a Fiber. The world was
- * innocent. But now... This is a Fiber local storage. Sorry.
- *
- * @param[in] thread Thread that the target Fiber is running.
- * @param[in] key The name of the Fiber local storage to write.
- * @param[in] val The new value of the storage.
- * @exception rb_eFrozenError `thread` is frozen.
- * @return The passed `val` as-is.
- * @post Fiber local storage `key` has value of `val`.
- * @note There in fact are "true" thread local storage, but Ruby doesn't
- * provide any interface of them to you, C programmers.
- */
-VALUE rb_thread_local_aset(VALUE thread, ID key, VALUE val);
-
-/**
- * A `pthread_atfork(3posix)`-like API. Ruby expects its child processes to
- * call this function at the very beginning of their processes. If you plan to
- * fork a process don't forget to call it.
- */
-void rb_thread_atfork(void);
-
-/**
- * :FIXME: situation of this function is unclear. It seems nobody uses it.
- * Maybe a good idea to KonMari.
- */
-void rb_thread_atfork_before_exec(void);
-
-/**
- * "Recursion" API entry point. This basically calls the given function with
- * the given arguments, but additionally with recursion flag. The flag is set
- * to 1 if the execution have already experienced the passed `g` parameter
- * before.
- *
- * @param[in] f The function that possibly recurs.
- * @param[in,out] g Passed as-is to `f`.
- * @param[in,out] h Passed as-is to `f`.
- * @return The return value of f.
- */
-VALUE rb_exec_recursive(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h);
-
-/**
- * Identical to rb_exec_recursive(), except it checks for the recursion on the
- * ordered pair of `{ g, p }` instead of just `g`.
- *
- * @param[in] f The function that possibly recurs.
- * @param[in,out] g Passed as-is to `f`.
- * @param[in] p Paired object for recursion detection.
- * @param[in,out] h Passed as-is to `f`.
- */
-VALUE rb_exec_recursive_paired(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE p, VALUE h);
-
-/**
- * Identical to rb_exec_recursive(), except it calls `f` for outermost
- * recursion only. Inner recursions yield calls to rb_throw_obj().
- *
- * @param[in] f The function that possibly recurs.
- * @param[in,out] g Passed as-is to `f`.
- * @param[in,out] h Passed as-is to `f`.
- * @return The return value of f.
- *
- * @internal
- *
- * It seems nobody uses the "it calls rb_throw_obj()" part of this function.
- * @shyouhei doesn't understand the needs.
- */
-VALUE rb_exec_recursive_outer(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h);
-
-/**
- * Identical to rb_exec_recursive_outer(), except it checks for the recursion
- * on the ordered pair of `{ g, p }` instead of just `g`. It can also be seen
- * as a routine identical to rb_exec_recursive_paired(), except it calls `f`
- * for outermost recursion only. Inner recursions yield calls to
- * rb_throw_obj().
- *
- * @param[in] f The function that possibly recurs.
- * @param[in,out] g Passed as-is to `f`.
- * @param[in] p Paired object for recursion detection.
- * @param[in,out] h Passed as-is to `f`.
- *
- * @internal
- *
- * It seems nobody uses the "it calls rb_throw_obj()" part of this function.
- * @shyouhei doesn't understand the needs.
- */
-VALUE rb_exec_recursive_paired_outer(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE p, VALUE h);
-
-/**
- * This is the type of UBFs. An UBF is a function that unblocks a blocking
- * region. For instance when a thread is blocking due to `pselect(3posix)`, it
- * is highly expected that `pthread_kill(3posix)` can interrupt the system call
- * and the thread could revive. Or when a thread is blocking due to
- * `waitpid(3posix)`, it is highly expected that killing the waited process
- * should suffice. An UBF is a function that does such things. Designing your
- * own UBF needs deep understanding of why your blocking region blocks, how
- * threads work in ruby, and a matter of luck. It often is the case you simply
- * cannot cancel something that had already begun.
- *
- * @see rb_thread_call_without_gvl()
- */
-typedef void rb_unblock_function_t(void *);
-
-/**
- * @private
- *
- * This is an implementation detail. Must be a mistake to be here.
- *
- * @internal
- *
- * Why is this function type different from what rb_thread_call_without_gvl()
- * takes?
- */
-typedef VALUE rb_blocking_function_t(void *);
-
-/**
- * Checks for interrupts. In ruby, signals are masked by default. You can
- * call this function at will to check if there are pending signals. In case
- * there are, they would be handled in this function.
- *
- * If your extension library has a function that takes a long time, consider
- * calling it periodically.
- *
- * @note It might switch to another thread.
- */
-void rb_thread_check_ints(void);
-
-/**
- * Checks if the thread's execution was recently interrupted. If called from
- * that thread, this function can be used to detect spurious wake-ups.
- *
- * @param[in] thval Thread in question.
- * @retval 0 The thread was not interrupted.
- * @retval otherwise The thread was interrupted recently.
- *
- * @internal
- *
- * Above description is not a lie. But actually the return value is an opaque
- * trap vector. If you know which bit means which, you can know what happened.
- */
-int rb_thread_interrupted(VALUE thval);
-
-/**
- * A special UBF for blocking IO operations. You need deep understanding of
- * what this actually do before using. Basically you should not use it from
- * extension libraries. It is too easy to mess up.
- */
-#define RUBY_UBF_IO RBIMPL_CAST((rb_unblock_function_t *)-1)
-
-/**
- * A special UBF for blocking process operations. You need deep understanding
- * of what this actually do before using. Basically you should not use it from
- * extension libraries. It is too easy to mess up.
- */
-#define RUBY_UBF_PROCESS RBIMPL_CAST((rb_unblock_function_t *)-1)
-
-/* thread_sync.c */
-
-/**
- * Creates a mutex.
- *
- * @return An allocated instance of rb_cMutex.
- */
-VALUE rb_mutex_new(void);
-
-/**
- * Queries if there are any threads that holds the lock.
- *
- * @param[in] mutex The mutex in question.
- * @retval RUBY_Qtrue The mutex is locked by someone.
- * @retval RUBY_Qfalse The mutex is not locked by anyone.
- */
-VALUE rb_mutex_locked_p(VALUE mutex);
-
-/**
- * Attempts to lock the mutex, without waiting for other threads to unlock it.
- * Failure in locking the mutex can be detected by the return value.
- *
- * @param[out] mutex The mutex to lock.
- * @retval RUBY_Qtrue Successfully locked by the current thread.
- * @retval RUBY_Qfalse Otherwise.
- * @note This function also returns ::RUBY_Qfalse when the mutex is
- * already owned by the calling thread itself.
- */
-VALUE rb_mutex_trylock(VALUE mutex);
-
-/**
- * Attempts to lock the mutex. It waits until the mutex gets available.
- *
- * @param[out] mutex The mutex to lock.
- * @exception rb_eThreadError Recursive deadlock situation.
- * @return The passed mutex.
- * @post The mutex is owned by the current thread.
- */
-VALUE rb_mutex_lock(VALUE mutex);
-
-/**
- * Releases the mutex.
- *
- * @param[out] mutex The mutex to unlock.
- * @exception rb_eThreadError The mutex is not owned by the current thread.
- * @return The passed mutex.
- * @post Upon successful return the passed mutex is no longer owned by
- * the current thread.
- */
-VALUE rb_mutex_unlock(VALUE mutex);
-
-/**
- * Releases the lock held in the mutex and waits for the period of time;
- * reacquires the lock on wakeup.
- *
- * @pre The lock has to be owned by the current thread beforehand.
- * @param[out] self The target mutex.
- * @param[in] timeout Duration, in seconds, in ::rb_cNumeric.
- * @exception rb_eArgError `timeout` is negative.
- * @exception rb_eRangeError `timeout` is out of range of `time_t`.
- * @exception rb_eThreadError The mutex is not owned by the current thread.
- * @return Number of seconds it actually slept.
- * @warning It is a failure not to check the return value. This function
- * can return spuriously for various reasons. Maybe other threads
- * can rb_thread_wakeup(). Maybe an end user can press the
- * Control and C key from the interactive console. On the other
- * hand it can also take longer than the specified. The mutex
- * could be locked by someone else. It waits then.
- * @post Upon successful return the passed mutex is owned by the current
- * thread.
- *
- * @internal
- *
- * This function is called from `ConditionVariable#wait`. So it is not a
- * deprecated feature. However @shyouhei have never seen any similar mutex
- * primitive available in any other languages than Ruby.
- *
- * EDIT: In 2021, @shyouhei asked @ko1 in person about this API. He answered
- * that it is his invention. The motivation behind its design is to eliminate
- * needs of condition variables as primitives. Unlike other languages, Ruby's
- * `ConditionVariable` class was written in pure-Ruby initially. We don't have
- * to implement machine-native condition variables in assembly each time we
- * port Ruby to a new architecture. This function made it possible. "I felt I
- * was a genius when this idea came to me", said @ko1.
- *
- * `rb_cConditionVariable` is now written in C for speed, though.
- */
-VALUE rb_mutex_sleep(VALUE self, VALUE timeout);
-
-/**
- * Obtains the lock, runs the passed function, and releases the lock when it
- * completes.
- *
- * @param[out] mutex The mutex to lock.
- * @param[in] func What to do during the mutex is locked.
- * @param[in,out] arg Passed as-is to `func`.
- */
-VALUE rb_mutex_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg);
-
-RBIMPL_SYMBOL_EXPORT_END()
-
-#endif /* RBIMPL_INTERN_THREAD_H */