summaryrefslogtreecommitdiff
path: root/include/ruby/ractor.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/ruby/ractor.h')
-rw-r--r--include/ruby/ractor.h278
1 files changed, 278 insertions, 0 deletions
diff --git a/include/ruby/ractor.h b/include/ruby/ractor.h
new file mode 100644
index 0000000000..8cfca21621
--- /dev/null
+++ b/include/ruby/ractor.h
@@ -0,0 +1,278 @@
+#ifndef RUBY_RACTOR_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_RACTOR_H 1
+
+/**
+ * @file
+ * @author Koichi Sasada
+ * @date Tue Nov 17 16:39:15 2020
+ * @copyright Copyright (C) 2020 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.
+ */
+#include "internal/dllexport.h" /* RUBY_EXTERN is here */
+#include "internal/fl_type.h" /* FL_TEST_RAW is here */
+#include "internal/special_consts.h" /* RB_SPECIAL_CONSTS_P is here */
+#include "internal/stdbool.h" /* bool is here */
+#include "internal/value.h" /* VALUE is here */
+
+/** Type that defines a ractor-local storage. */
+struct rb_ractor_local_storage_type {
+
+ /**
+ * A function to mark a ractor-local storage.
+ *
+ * @param[out] ptr A ractor-local storage.
+ * @post Ruby objects inside of `ptr` are marked.
+ */
+ void (*mark)(void *ptr);
+
+ /**
+ * A function to destruct a ractor-local storage.
+ *
+ * @param[out] ptr A ractor-local storage.
+ * @post `ptr` is not a valid pointer.
+ */
+ void (*free)(void *ptr);
+ // TODO: update
+};
+
+/** (Opaque) struct that holds a ractor-local storage key. */
+typedef struct rb_ractor_local_key_struct *rb_ractor_local_key_t;
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/**
+ * `Ractor` class.
+ *
+ * @ingroup object
+ */
+RUBY_EXTERN VALUE rb_cRactor;
+
+/**
+ * Queries the standard input of the current Ractor that is calling this
+ * function.
+ *
+ * @return An IO.
+ * @note This can be different from the process-global one.
+ */
+VALUE rb_ractor_stdin(void);
+
+/**
+ * Queries the standard output of the current Ractor that is calling this
+ * function.
+ *
+ * @return An IO.
+ * @note This can be different from the process-global one.
+ */
+VALUE rb_ractor_stdout(void);
+
+/**
+ * Queries the standard error of the current Ractor that is calling this
+ * function.
+ *
+ * @return An IO.
+ * @note This can be different from the process-global one.
+ */
+VALUE rb_ractor_stderr(void);
+
+/**
+ * Assigns an IO to the standard input of the Ractor that is calling this
+ * function.
+ *
+ * @param[in] io An IO.
+ * @post `io` is the standard input of the current ractor.
+ * @post In case the calling Ractor is the main Ractor, it also updates
+ * the process global ::rb_stdin.
+ */
+void rb_ractor_stdin_set(VALUE io);
+
+/**
+ * Assigns an IO to the standard output of the Ractor that is calling this
+ * function.
+ *
+ * @param[in] io An IO.
+ * @post `io` is the standard input of the current ractor.
+ * @post In case the calling Ractor is the main Ractor, it also updates
+ * the process global ::rb_stdout.
+ */
+void rb_ractor_stdout_set(VALUE io);
+
+/**
+ * Assigns an IO to the standard error of the Ractor that is calling this
+ * function.
+ *
+ * @param[in] io An IO.
+ * @post `io` is the standard input of the current ractor.
+ * @post In case the calling Ractor is the main Ractor, it also updates
+ * the process global ::rb_stderr.
+ */
+void rb_ractor_stderr_set(VALUE io);
+
+/**
+ * Issues a new key.
+ *
+ * @return A newly issued ractor-local storage key. Keys issued using this
+ * key can be associated to a Ruby object per Ractor.
+ */
+rb_ractor_local_key_t rb_ractor_local_storage_value_newkey(void);
+
+/**
+ * Queries the key.
+ *
+ * @param[in] key A ractor-local storage key to lookup.
+ * @retval RUBY_Qnil No such key.
+ * @retval otherwise A value corresponds to `key` in the current Ractor.
+ * @note This cannot distinguish between a nonexistent key and a key
+ * exists and corresponds to ::RUBY_Qnil.
+ */
+VALUE rb_ractor_local_storage_value(rb_ractor_local_key_t key);
+
+/**
+ * Queries the key.
+ *
+ * @param[in] key A ractor-local storage key to lookup.
+ * @param[out] val Return value buffer.
+ * @retval false `key` not found.
+ * @retval true `key` found.
+ * @post `val` is updated so that it has the value corresponds to `key`
+ * in the current Ractor.
+ */
+bool rb_ractor_local_storage_value_lookup(rb_ractor_local_key_t key, VALUE *val);
+
+/**
+ * Associates the passed value to the passed key.
+ *
+ * @param[in] key A ractor-local storage key.
+ * @param[in] val Arbitrary ruby object.
+ * @post `val` corresponds to `key` in the current Ractor.
+ */
+void rb_ractor_local_storage_value_set(rb_ractor_local_key_t key, VALUE val);
+
+/**
+ * A type of ractor-local storage that destructs itself using ::ruby_xfree.
+ *
+ * @internal
+ *
+ * Why it is visible from 3rd party extension libraries is not obvious to
+ * @shyouhei.
+ */
+RUBY_EXTERN const struct rb_ractor_local_storage_type rb_ractor_local_storage_type_free;
+
+/** @alias{rb_ractor_local_storage_type_free} */
+#define RB_RACTOR_LOCAL_STORAGE_TYPE_FREE (&rb_ractor_local_storage_type_free)
+
+/**
+ * Extended version of rb_ractor_local_storage_value_newkey(). It additionally
+ * takes the type of the issuing key.
+ *
+ * @param[in] type How the value associated with the issuing key should
+ * behave.
+ * @return A newly issued ractor-local storage key, of type `type`.
+ */
+rb_ractor_local_key_t rb_ractor_local_storage_ptr_newkey(const struct rb_ractor_local_storage_type *type);
+
+/**
+ * Identical to rb_ractor_local_storage_value() except the return type.
+ *
+ * @param[in] key A ractor-local storage key to lookup.
+ * @retval NULL No such key.
+ * @retval otherwise A value corresponds to `key` in the current Ractor.
+ */
+void *rb_ractor_local_storage_ptr(rb_ractor_local_key_t key);
+
+/**
+ * Identical to rb_ractor_local_storage_value_set() except the parameter type.
+ *
+ * @param[in] key A ractor-local storage key.
+ * @param[in] ptr A pointer that conforms `key`'s type.
+ * @post `ptr` corresponds to `key` in the current Ractor.
+ */
+void rb_ractor_local_storage_ptr_set(rb_ractor_local_key_t key, void *ptr);
+
+/**
+ * Destructively transforms the passed object so that multiple Ractors can
+ * share it. What is a shareable object and what is not is a nuanced concept,
+ * and @ko1 says the definition can still change. However extension library
+ * authors might interest to learn how to use #RUBY_TYPED_FROZEN_SHAREABLE.
+ *
+ * @param[out] obj Arbitrary ruby object to modify.
+ * @exception rb_eRactorError Ractors cannot share `obj` by nature.
+ * @return Passed `obj`.
+ * @post Multiple Ractors can share `obj`.
+ *
+ * @internal
+ *
+ * In case an exception is raised, `obj` remains in an intermediate state where
+ * some of its part is frozen and others are not. @shyouhei is not sure if it
+ * is either an intended behaviour, current implementation limitation, or
+ * simply a bug. Note also that there is no way to "melt" a frozen object.
+ */
+VALUE rb_ractor_make_shareable(VALUE obj);
+
+/**
+ * Identical to rb_ractor_make_shareable(), except it returns a (deep) copy of
+ * the passed one instead of modifying it in-place.
+ *
+ * @param[in] obj Arbitrary ruby object to duplicate.
+ * @exception rb_eRactorError Ractors cannot share `obj` by nature.
+ * @return A deep copy of `obj` which is shareable among Ractors.
+ */
+VALUE rb_ractor_make_shareable_copy(VALUE obj);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+/**
+ * Queries if the passed object has previously classified as shareable or not.
+ * This doesn't mean anything in practice... Objects can be shared later.
+ * Always use rb_ractor_shareable_p() instead.
+ *
+ * @param[in] obj Object in question.
+ * @retval RUBY_FL_SHAREABLE It once was shareable before.
+ * @retval 0 Otherwise.
+ */
+#define RB_OBJ_SHAREABLE_P(obj) FL_TEST_RAW((obj), RUBY_FL_SHAREABLE)
+
+/**
+ * Queries if multiple Ractors can share the passed object or not. Ractors run
+ * without protecting each other. Sharing an object among them is basically
+ * dangerous, disabled by default. However there are objects that are
+ * extremely carefully implemented to be Ractor-safe; for instance integers
+ * have such property. This function can classify that.
+ *
+ * @param[in] obj Arbitrary ruby object.
+ * @retval true `obj` is capable of shared across ractors.
+ * @retval false `obj` cannot travel across ractor boundaries.
+ */
+static inline bool
+rb_ractor_shareable_p(VALUE obj)
+{
+ bool rb_ractor_shareable_p_continue(VALUE obj);
+
+ if (RB_SPECIAL_CONST_P(obj)) {
+ return true;
+ }
+ else if (RB_OBJ_SHAREABLE_P(obj)) {
+ return true;
+ }
+ else {
+ return rb_ractor_shareable_p_continue(obj);
+ }
+}
+
+// TODO: optimize on interpreter core
+#ifndef RB_OBJ_SET_SHAREABLE
+VALUE rb_obj_set_shareable(VALUE obj); // ractor.c
+#define RB_OBJ_SET_SHAREABLE(obj) rb_obj_set_shareable(obj)
+#endif
+
+static inline VALUE
+RB_OBJ_SET_FROZEN_SHAREABLE(VALUE obj)
+{
+ RB_OBJ_FREEZE(obj);
+ RB_OBJ_SET_SHAREABLE(obj);
+ return obj;
+}
+
+#endif /* RUBY_RACTOR_H */