summaryrefslogtreecommitdiff
path: root/doc/extension.rdoc
diff options
context:
space:
mode:
Diffstat (limited to 'doc/extension.rdoc')
-rw-r--r--doc/extension.rdoc149
1 files changed, 81 insertions, 68 deletions
diff --git a/doc/extension.rdoc b/doc/extension.rdoc
index 5089272599..ba59d107ab 100644
--- a/doc/extension.rdoc
+++ b/doc/extension.rdoc
@@ -747,18 +747,24 @@ RUBY_TYPED_WB_PROTECTED ::
barriers in all implementations of methods of that object as
appropriate. Otherwise Ruby might crash while running.
- More about write barriers can be found in "Generational GC" in
- Appendix D.
+ More about write barriers can be found in {Generational
+ GC}[rdoc-ref:@Appendix+D.+Generational+GC].
RUBY_TYPED_FROZEN_SHAREABLE ::
- This flag indicates that the object is shareable object
- if the object is frozen. See Appendix F more details.
+ This flag indicates that the object is shareable object if the object
+ is frozen. See {Ractor support}[rdoc-ref:@Appendix+F.+Ractor+support]
+ more details.
If this flag is not set, the object can not become a shareable
object by Ractor.make_shareable() method.
-You can allocate and wrap the structure in one step.
+Note that this macro can raise an exception. If sval to be wrapped
+holds a resource needs to be released (e.g., allocated memory, handle
+from an external library, and etc), you will have to use rb_protect.
+
+You can allocate and wrap the structure in one step, in more
+preferable manner.
TypedData_Make_Struct(klass, type, data_type, sval)
@@ -767,6 +773,10 @@ the structure, which is also allocated. This macro works like:
(sval = ZALLOC(type), TypedData_Wrap_Struct(klass, data_type, sval))
+However, you should use this macro instead of "allocation then wrap"
+like the above code if it is simply allocated, because the latter can
+raise a NoMemoryError and sval will be memory leaked in that case.
+
Arguments klass and data_type work like their counterparts in
TypedData_Wrap_Struct(). A pointer to the allocated structure will
be assigned to sval, which should be a pointer of the type specified.
@@ -779,26 +789,26 @@ approach to marking and reference updating is provided, by declaring offset
references to the VALUES in your struct.
Doing this allows the Ruby GC to support marking these references and GC
-compaction without the need to define the `dmark` and `dcompact` callbacks.
+compaction without the need to define the +dmark+ and +dcompact+ callbacks.
You must define a static list of VALUE pointers to the offsets within your
struct where the references are located, and set the "data" member to point to
-this reference list. The reference list must end with `END_REFS`
+this reference list. The reference list must end with +RUBY_END_REFS+.
Some Macros have been provided to make edge referencing easier:
-* <code>RUBY_TYPED_DECL_MARKING</code> =A flag that can be set on the `ruby_data_type_t` to indicate that references are being declared as edges.
+* <code>RUBY_TYPED_DECL_MARKING</code> =A flag that can be set on the +ruby_data_type_t+ to indicate that references are being declared as edges.
-* <code>RUBY_REFERENCES_START(ref_list_name)</code> - Define `ref_list_name` as a list of references
+* <code>RUBY_REFERENCES(ref_list_name)</code> - Define _ref_list_name_ as a list of references
-* <code>RUBY_REFERENCES_END</code> - Mark the end of the references list. This will take care of terminating the list correctly
+* <code>RUBY_REF_END</code> - The end mark of the references list.
-* <code>RUBY_REF_EDGE\(struct, member\)</code> - Declare `member` as a VALUE edge from `struct`. Use this after `RUBY_REFERENCES_START`
+* <code>RUBY_REF_EDGE(struct, member)</code> - Declare _member_ as a VALUE edge from _struct_. Use this after +RUBY_REFERENCES_START+
-* +REFS_LIST_PTR+ - Coerce the reference list into a format that can be
- accepted by the existing `dmark` interface.
+* +RUBY_REFS_LIST_PTR+ - Coerce the reference list into a format that can be
+ accepted by the existing +dmark+ interface.
-The example below is from `Dir` (defined in `dir.c`)
+The example below is from Dir (defined in +dir.c+)
// The struct being wrapped. Notice this contains 3 members of which the second
// is a VALUE reference to another ruby object.
@@ -808,18 +818,19 @@ The example below is from `Dir` (defined in `dir.c`)
rb_encoding *enc;
}
- // Define a reference list `dir_refs` containing a single entry to `path`, and
- // terminating with RUBY_REF_END
- RUBY_REFERENCES_START(dir_refs)
- REF_EDGE(dir_data, path),
- RUBY_REFERENCES_END
+ // Define a reference list `dir_refs` containing a single entry to `path`.
+ // Needs terminating with RUBY_REF_END
+ RUBY_REFERENCES(dir_refs) = {
+ RUBY_REF_EDGE(dir_data, path),
+ RUBY_REF_END
+ };
// Override the "dmark" field with the defined reference list now that we
// no longer need a marking callback and add RUBY_TYPED_DECL_MARKING to the
// flags field
static const rb_data_type_t dir_data_type = {
"dir",
- {REFS_LIST_PTR(dir_refs), dir_free, dir_memsize,},
+ {RUBY_REFS_LIST_PTR(dir_refs), dir_free, dir_memsize,},
0, NULL, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_DECL_MARKING
};
@@ -2208,70 +2219,72 @@ Ractor safety around C extensions has the following properties:
To make a "Ractor-safe" C extension, we need to check the following points:
-(1) Do not share unshareable objects between ractors
+1. Do not share unshareable objects between ractors
-For example, C's global variable can lead sharing an unshareable objects
-between ractors.
+ For example, C's global variable can lead sharing an unshareable objects
+ between ractors.
- VALUE g_var;
- VALUE set(VALUE self, VALUE v){ return g_var = v; }
- VALUE get(VALUE self){ return g_var; }
+ VALUE g_var;
+ VALUE set(VALUE self, VALUE v){ return g_var = v; }
+ VALUE get(VALUE self){ return g_var; }
-set() and get() pair can share an unshareable objects using g_var, and
-it is Ractor-unsafe.
+ set() and get() pair can share an unshareable objects using g_var, and
+ it is Ractor-unsafe.
-Not only using global variables directly, some indirect data structure
-such as global st_table can share the objects, so please take care.
+ Not only using global variables directly, some indirect data structure
+ such as global st_table can share the objects, so please take care.
-Note that class and module objects are shareable objects, so you can
-keep the code "cFoo = rb_define_class(...)" with C's global variables.
+ Note that class and module objects are shareable objects, so you can
+ keep the code "cFoo = rb_define_class(...)" with C's global variables.
-(2) Check the thread-safety of the extension
+2. Check the thread-safety of the extension
-An extension should be thread-safe. For example, the following code is
-not thread-safe:
+ An extension should be thread-safe. For example, the following code is
+ not thread-safe:
- bool g_called = false;
- VALUE call(VALUE self) {
- if (g_called) rb_raise("recursive call is not allowed.");
- g_called = true;
- VALUE ret = do_something();
- g_called = false;
- return ret;
- }
+ bool g_called = false;
+ VALUE call(VALUE self) {
+ if (g_called) rb_raise("recursive call is not allowed.");
+ g_called = true;
+ VALUE ret = do_something();
+ g_called = false;
+ return ret;
+ }
-because g_called global variable should be synchronized by other
-ractor's threads. To avoid such data-race, some synchronization should
-be used. Check include/ruby/thread_native.h and include/ruby/atomic.h.
+ because g_called global variable should be synchronized by other
+ ractor's threads. To avoid such data-race, some synchronization should
+ be used. Check include/ruby/thread_native.h and include/ruby/atomic.h.
-With Ractors, all objects given as method parameters and the receiver (self)
-are guaranteed to be from the current Ractor or to be shareable. As a
-consequence, it is easier to make code ractor-safe than to make code generally
-thread-safe. For example, we don't need to lock an array object to access the
-element of it.
+ With Ractors, all objects given as method parameters and the receiver (self)
+ are guaranteed to be from the current Ractor or to be shareable. As a
+ consequence, it is easier to make code ractor-safe than to make code generally
+ thread-safe. For example, we don't need to lock an array object to access the
+ element of it.
-(3) Check the thread-safety of any used library
+3. Check the thread-safety of any used library
-If the extension relies on an external library, such as a function foo() from
-a library libfoo, the function libfoo foo() should be thread safe.
+ If the extension relies on an external library, such as a function foo() from
+ a library libfoo, the function libfoo foo() should be thread safe.
-(4) Make an object shareable
+4. Make an object shareable
-This is not required to make an extension Ractor-safe.
+ This is not required to make an extension Ractor-safe.
-If an extension provides special objects defined by rb_data_type_t,
-consider these objects can become shareable or not.
+ If an extension provides special objects defined by rb_data_type_t,
+ consider these objects can become shareable or not.
-RUBY_TYPED_FROZEN_SHAREABLE flag indicates that these objects can be
-shareable objects if the object is frozen. This means that if the object
-is frozen, the mutation of wrapped data is not allowed.
+ RUBY_TYPED_FROZEN_SHAREABLE flag indicates that these objects can be
+ shareable objects if the object is frozen. This means that if the object
+ is frozen, the mutation of wrapped data is not allowed.
-(5) Others
+5. Others
-There are possibly other points or requirements which must be considered in the
-making of a Ractor-safe extension. This document will be extended as they are
-discovered.
+ There are possibly other points or requirements which must be considered in the
+ making of a Ractor-safe extension. This document will be extended as they are
+ discovered.
-:enddoc: Local variables:
-:enddoc: fill-column: 70
-:enddoc: end:
+--
+Local variables:
+fill-column: 70
+end:
+++