[前][次][番号順一覧][スレッド一覧]

ruby-changes:67822

From: =E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3 <ko1@a...>
Date: Fri, 10 Sep 2021 20:02:25 +0900 (JST)
Subject: [ruby-changes:67822] a50287ab03 (master): include/ruby/thread.h: add doxygen

https://git.ruby-lang.org/ruby.git/commit/?id=a50287ab03

From a50287ab03ce9cf871d307cc619e394d9a736466 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3?=
 <shyouhei@r...>
Date: Wed, 9 Jun 2021 13:59:32 +0900
Subject: include/ruby/thread.h: add doxygen

Must not be a bad idea to improve documents. [ci skip]
---
 include/ruby/thread.h | 157 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 155 insertions(+), 2 deletions(-)

diff --git a/include/ruby/thread.h b/include/ruby/thread.h
index b05537b..18c792b 100644
--- a/include/ruby/thread.h
+++ b/include/ruby/thread.h
@@ -10,19 +10,147 @@ https://github.com/ruby/ruby/blob/trunk/include/ruby/thread.h#L10
  *             modify this file, provided that  the conditions mentioned in the
  *             file COPYING are met.  Consult the file for details.
  */
-#include "ruby/intern.h"
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/intern/thread.h" /* rb_unblock_function_t */
 #include "ruby/internal/dllexport.h"
 
-/* flags for rb_nogvl */
+/**
+ * @name Flags for rb_nogvl()
+ *
+ * @{
+ */
+
+/**
+ * Passing  this  flag to  rb_nogvl()  prevents  it from  checking  interrupts.
+ * Interrupts  can  impact  your  program negatively.   For  instance  consider
+ * following callback function:
+ *
+ * ```CXX
+ * static inline int fd; // set elsewhere.
+ * static inline auto callback(auto buf) {
+ *   auto tmp = ruby_xmalloc(BUFSIZ);
+ *   auto ret = ruby_xmalloc(sizeof(ssize_t));  // (a)
+ *   auto n = read(fd, tmp, BUFSIZ);            // (b)
+ *   memcpy(buf, tmp, n);                       // (c)
+ *   memcpy(ret, n, sizeof(n));
+ *   ruby_xfree(tmp);
+ *   return ret;
+ * }
+ * ```
+ *
+ * Here, if it gets interrupted at (a)  or (b), `read(2)` is cancelled and this
+ * function leaks memory (which is not a good thing of course, but...).  But if
+ * it gets interrupted at (c), where `read(2)` is already done, interruption is
+ * way more catastrophic because what was read gets lost.  To reroute this kind
+ * of problem you should set this flag.  And check interrupts elsewhere at your
+ * own risk.
+ */
 #define RB_NOGVL_INTR_FAIL       (0x1)
+
+/**
+ * Passing  this  flag   to  rb_nogvl()  indicates  that  the   passed  UBF  is
+ * async-signal-safe.   An UBF  could  be  async safe,  and  that makes  things
+ * simpler.   However async  unsafe UBFs  are just  okay.  If  unsure, you  can
+ * safely leave it unspecified.
+ *
+ * @internal
+ *
+ * This makes sense only in case of POSIX threads.
+ */
 #define RB_NOGVL_UBF_ASYNC_SAFE  (0x2)
 
+/** @} */
+
 RBIMPL_SYMBOL_EXPORT_BEGIN()
 
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * (Re-)acquires the GVL.   This manoeuvre makes it possible  for an out-of-GVL
+ * routine to one-shot call a ruby method.
+ *
+ * What this function does:
+ *
+ *  1. Blocks until it acquires the GVL.
+ *  2. Calls the passed function.
+ *  3. Releases the GVL.
+ *  4. Returns what was returned form the passed function.
+ *
+ * @param[in]      func   What to call with GVL.
+ * @param[in,out]  data1  Passed as-is to `func`.
+ * @return         What was returned from `func`.
+ * @warning        `func` must not return a Ruby object.  If it did such return
+ *                 value would escape from GC's scope; would not be marked.
+ * @warning        Global escapes from this  function just yield whatever fatal
+ *                 undefined behaviours.   You must make sure  that `func` does
+ *                 not   raise,   by   properly   rescuing   everything   using
+ *                 e.g. rb_protect().
+ * @warning        You  cannot convert  a non-Ruby  thread into  a Ruby  thread
+ *                 using this API.  This function  makes sense only from inside
+ *                 of a rb_thread_call_without_gvl()'s callback.
+ */
 void *rb_thread_call_with_gvl(void *(*func)(void *), void *data1);
 
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Allows the passed function to run in parallel with other Ruby threads.
+ *
+ * What this function does:
+ *
+ *  1. Checks (and handles) pending interrupts.
+ *  2. Releases the GVL. (Others can run here in parallel...)
+ *  3. Calls the passed function.
+ *  4. Blocks until it re-acquires the GVL.
+ *  5. Checks interrupts that happened between 2 to 4.
+ *
+ * In case  other threads  interfaced with  this thread  using rb_thread_kill()
+ * etc., the  passed UBF  is additionally called.   See ::rb_unblock_function_t
+ * for details.
+ *
+ * Unlike rb_thread_call_without_gvl2()  this function  also reacts  to signals
+ * etc.
+ *
+ * @param[in]      func   A function to call without GVL.
+ * @param[in,out]  data1  Passed as-is to `func`.
+ * @param[in]      ubf    An UBF to cancel `func`.
+ * @param[in,out]  data2  Passed as-is to `ubf`.
+ * @return         What `func` returned, or 0 in case `ubf` cancelled `func`.
+ * @warning        You cannot use  most of Ruby C APIs like  calling methods or
+ *                 raising exceptions from  any of the functions  passed to it.
+ *                 If that  is dead necessary use  rb_thread_call_with_gvl() to
+ *                 re-acquire the GVL.
+ * @warning        In short, this API is difficult.  @ko1 recommends you to use
+ *                 other ways if any.  We lack experiences to use this API.  If
+ *                 you  find any  corner cases  etc., please  report it  to the
+ *                 devs.
+ * @warning        Releasing and re-acquiring the GVL are expensive operations.
+ *                 For a short-running `func`, it  might be faster to just call
+ *                 `func` with blocking everything  else.  Be sure to benchmark
+ *                 your code to see if it is actually worth releasing the GVL.
+ */
 void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
 				 rb_unblock_function_t *ubf, void *data2);
+
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Identical to rb_thread_call_without_gvl(), except it does not interface with
+ * signals etc.  As described in  #RB_NOGVL_INTR_FAIL, interrupts can hurt you.
+ * In case this function detects an interrupt, it returns immediately.  You can
+ * record progress  of your  callback and  check it  after returning  from this
+ * function.
+ *
+ * What this function does:
+ *
+ *  1. Checks for pending interrupts and if any, just returns.
+ *  2. Releases the GVL. (Others can run here in parallel...)
+ *  3. Calls the passed function.
+ *  4. Blocks until it re-acquires the GVL.
+ *
+ * @param[in]      func   A function to call without GVL.
+ * @param[in,out]  data1  Passed as-is to `func`.
+ * @param[in]      ubf    An UBF to cancel `func`.
+ * @param[in,out]  data2  Passed as-is to `ubf`.
+ * @return         What `func` returned, or 0 in case `func` did not return.
+ */
 void *rb_thread_call_without_gvl2(void *(*func)(void *), void *data1,
 				  rb_unblock_function_t *ubf, void *data2);
 
@@ -30,11 +158,36 @@ void *rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, https://github.com/ruby/ruby/blob/trunk/include/ruby/thread.h#L158
  * XXX: unstable/unapproved - out-of-tree code should NOT not depend
  * on this until it hits Ruby 2.6.1
  */
+
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Identical  to  rb_thread_call_without_gvl(),  except it  additionally  takes
+ * "flags" that change the behaviour.
+ *
+ * @param[in]      func   A function to call without GVL.
+ * @param[in,out]  data1  Passed as-is to `func`.
+ * @param[in]      ubf    An UBF to cancel `func`.
+ * @param[in,out]  data2  Passed as-is to `ubf`.
+ * @param[in]      flags  Flags.
+ * @return         What `func` returned, or 0 in case `func` did not return.
+ */
 void *rb_nogvl(void *(*func)(void *), void *data1,
                rb_unblock_function_t *ubf, void *data2,
                int flags);
 
+/**
+ * @private
+ *
+ * @deprecated  This macro once was a thing in the old days, but makes no sense
+ *              any  longer today.   Exists  here  for backwards  compatibility
+ *              only.  You can safely forget about it.
+ */
 #define RUBY_CALL_WO_GVL_FLAG_SKIP_CHECK_INTS_AFTER 0x01
+
+/**
+ * @private
+ * @deprecated  It seems even in the old days it made no sense...?
+ */
 #define RUBY_CALL_WO_GVL_FLAG_SKIP_CHECK_INTS_
 
 RBIMPL_SYMBOL_EXPORT_END()
-- 
cgit v1.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]