Ruby 4.1.0dev (2026-09-15 revision 16fd986706d84da6bb993b8c1b976a9cd9b6ddf0)
rtypeddata.h
Go to the documentation of this file.
1#ifndef RBIMPL_RTYPEDDATA_H /*-*-C++-*-vi:se ft=cpp:*/
2#define RBIMPL_RTYPEDDATA_H
23#include "ruby/internal/config.h"
24
25#ifdef STDC_HEADERS
26# include <stddef.h>
27#endif
28
29#include "ruby/assert.h"
35#include "ruby/internal/cast.h"
39#include "ruby/internal/error.h"
44
52#define HAVE_TYPE_RB_DATA_TYPE_T 1
53
61#define HAVE_RB_DATA_TYPE_T_FUNCTION 1
62
70#define HAVE_RB_DATA_TYPE_T_PARENT 1
71
81#define RUBY_TYPED_DEFAULT_FREE RUBY_DEFAULT_FREE
82
88#define RUBY_TYPED_NEVER_FREE RUBY_NEVER_FREE
89
96#define RTYPEDDATA(obj) RBIMPL_CAST((struct RTypedData *)(obj))
97
99
106#define RTYPEDDATA_DATA(v) (RTYPEDDATA(rbimpl_check_external_typeddata(v))->data)
107
109#define Check_TypedStruct(v, t) \
110 rb_check_typeddata(RBIMPL_CAST((VALUE)(v)), (t))
111
113#define RTYPEDDATA_P RTYPEDDATA_P
114#define RTYPEDDATA_TYPE RTYPEDDATA_TYPE
115#define TYPED_DATA_EMBEDDED ((VALUE)1)
116#define TYPED_DATA_PTR_MASK (~(TYPED_DATA_EMBEDDED))
122#define RUBY_TYPED_FREE_IMMEDIATELY RUBY_TYPED_FREE_IMMEDIATELY
123#define RUBY_TYPED_THREAD_SAFE_FREE RUBY_TYPED_THREAD_SAFE_FREE
124#define RUBY_TYPED_FROZEN_SHAREABLE RUBY_TYPED_FROZEN_SHAREABLE
125#define RUBY_TYPED_WB_PROTECTED RUBY_TYPED_WB_PROTECTED
126#define RUBY_TYPED_EMBEDDABLE RUBY_TYPED_EMBEDDABLE
127#define RUBY_TYPED_PROMOTED1 RUBY_TYPED_PROMOTED1
128
134enum
136rbimpl_typeddata_flags {
151
163 RUBY_TYPED_THREAD_SAFE_FREE = 4,
164
179 RUBY_TYPED_EMBEDDABLE = 2,
180
193 RUBY_TYPED_FROZEN_SHAREABLE = RUBY_FL_SHAREABLE,
194
195 // experimental flag
196 // Similar to RUBY_TYPED_FROZEN_SHAREABLE, but doesn't make shareable
197 // reachable objects from this T_DATA object on the Ractor.make_shareable.
198 // If it refers to unshareable objects, simply raise an error.
199 // RUBY_TYPED_FROZEN_SHAREABLE_NO_REC = RUBY_FL_FINALIZE,
200
220 RUBY_TYPED_WB_PROTECTED = RUBY_FL_WB_PROTECTED, /* THIS FLAG DEPENDS ON Ruby version */
221
227 RUBY_TYPED_DECL_MARKING = RUBY_FL_USER2
228};
229
236
239
245 const char *wrap_struct_name;
246
248 struct {
249
260
269
278 size_t (*dsize)(const void *);
279
290
294 void (*handle_weak_references)(void *);
295
300 void *reserved[7]; /* For future extension.
301 This array *must* be filled with ZERO. */
303
334
339 void *data; /* This area can be used for any purpose
340 by a programmer who define the type. */
341
352 VALUE flags; /* RUBY_FL_WB_PROTECTED */
353};
354
394
396 struct RBasic basic;
397
400
410 const VALUE type;
411
413 void *data;
414};
415
416#if !defined(__cplusplus) || __cplusplus >= 201103L
417RBIMPL_STATIC_ASSERT(fields_obj_in_rdata, offsetof(struct RData, fields_obj) == offsetof(struct RTypedData, fields_obj));
418RBIMPL_STATIC_ASSERT(data_in_rtypeddata, offsetof(struct RData, data) == offsetof(struct RTypedData, data));
419#endif
420
427#define RDATA(obj) RTYPEDDATA(obj)
428
435#define DATA_PTR(obj) RTYPEDDATA_DATA(obj)
436
449VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *type);
450
465
479int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent);
480
490int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type);
491
503void *rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type);
504
518void rb_unexpected_object_type(VALUE obj, const char *expected);
519
533void rb_unexpected_typeddata(const rb_data_type_t *actual, const rb_data_type_t *expected);
535
536#if RUBY_DEBUG
537# define RBIMPL_TYPEDDATA_PRECONDITION(obj, unreachable) \
538 while (RB_UNLIKELY(!RB_TYPE_P(obj, RUBY_T_DATA))) { \
539 rb_unexpected_object_type(obj, "Data"); \
540 unreachable; \
541 }
542#else
543# define RBIMPL_TYPEDDATA_PRECONDITION(obj, unreachable) \
544 RBIMPL_ASSERT_NOTHING
545#endif
546
557#define TypedData_Wrap_Struct(klass,data_type,sval)\
558 rb_data_typed_object_wrap((klass),(sval),(data_type))
559
573#define TypedData_Make_Struct0(result, klass, type, size, data_type, sval) \
574 VALUE result = rb_data_typed_object_zalloc(klass, size, data_type); \
575 (sval) = RBIMPL_CAST((type *)rbimpl_typeddata_get_data(result)); \
576 RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval))
577
591#ifdef HAVE_STMT_AND_DECL_IN_EXPR
592#define TypedData_Make_Struct(klass, type, data_type, sval) \
593 RB_GNUC_EXTENSION({ \
594 TypedData_Make_Struct0( \
595 data_struct_obj, \
596 klass, \
597 type, \
598 sizeof(type), \
599 data_type, \
600 sval); \
601 data_struct_obj; \
602 })
603#else
604#define TypedData_Make_Struct(klass, type, data_type, sval) \
605 rb_data_typed_object_make( \
606 (klass), \
607 (data_type), \
608 RBIMPL_CAST((void **)&(sval)), \
609 sizeof(type))
610#endif
611
612static inline bool
613rbimpl_typeddata_embedded_p(VALUE obj)
614{
615 return (RTYPEDDATA(obj)->type) & TYPED_DATA_EMBEDDED;
616}
617
618RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY()
619static inline bool
620RTYPEDDATA_EMBEDDED_P(VALUE obj)
621{
622 RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(false));
623
624 return rbimpl_typeddata_embedded_p(obj);
625}
626
627static inline void *
628rbimpl_typeddata_get_data(VALUE obj)
629{
630 /* We reuse the data pointer in embedded TypedData. */
631 return rbimpl_typeddata_embedded_p(obj) ?
632 RBIMPL_CAST((void *)&RTYPEDDATA(obj)->data) :
633 RTYPEDDATA_DATA(obj);
634}
635
636static inline void *
637RTYPEDDATA_GET_DATA(VALUE obj)
638{
639 RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(NULL));
640
641 return rbimpl_typeddata_get_data(obj);
642}
643
658static inline bool
659rbimpl_obj_typeddata_p(VALUE obj)
660{
661 return RB_TYPE_P(obj, RUBY_T_DATA);
662}
663
673static inline bool
675{
676 RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(false));
677
678 return true;
679}
680
691static inline const rb_data_type_t *
693{
694 RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(NULL));
695
696 VALUE type = RTYPEDDATA(obj)->type & TYPED_DATA_PTR_MASK;
697 const rb_data_type_t *ptr = RBIMPL_CAST((const rb_data_type_t *)type);
699 return ptr;
700}
701
704static inline bool
705rbimpl_typeddata_inherited_p_inline(const rb_data_type_t *child, const rb_data_type_t *parent)
706{
707 do {
708 if (RB_LIKELY(child == parent)) return true;
709 } while ((child = child->parent) != NULL);
710 return false;
711}
712#define rb_typeddata_inherited_p rbimpl_typeddata_inherited_p_inline
713
716static inline bool
717rbimpl_typeddata_is_kind_of_inline(VALUE obj, const rb_data_type_t *data_type)
718{
719 if (RB_UNLIKELY(!rbimpl_obj_typeddata_p(obj))) return false;
720 return rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type);
721}
722#define rb_typeddata_is_kind_of rbimpl_typeddata_is_kind_of_inline
723
732static inline void *
733rbimpl_check_typeddata(VALUE obj, const rb_data_type_t *expected_type)
734{
735 if (RB_UNLIKELY(!rbimpl_obj_typeddata_p(obj))) {
736 rb_unexpected_object_type(obj, expected_type->wrap_struct_name);
737 }
738
739 const rb_data_type_t *actual_type = RTYPEDDATA_TYPE(obj);
740 if (RB_UNLIKELY(!rb_typeddata_inherited_p(actual_type, expected_type))){
741 rb_unexpected_typeddata(actual_type, expected_type);
742 }
743
744 return RTYPEDDATA_GET_DATA(obj);
745}
746
755static inline VALUE
757{
758 RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(false));
759 RUBY_ASSERT(!rbimpl_typeddata_embedded_p(obj));
760 return obj;
761}
762
773#define TypedData_Get_Struct(obj,type,data_type,sval) \
774 ((sval) = RBIMPL_CAST((type *)rbimpl_check_typeddata((obj), (data_type))))
775
791static inline VALUE
792rb_data_typed_object_make(VALUE klass, const rb_data_type_t *type, void **datap, size_t size)
793{
794 TypedData_Make_Struct0(result, klass, void, size, type, *datap);
795 return result;
796}
797
798#endif /* RBIMPL_RTYPEDDATA_H */
Defines RBIMPL_ATTR_ARTIFICIAL.
#define RBIMPL_ATTR_ARTIFICIAL()
Wraps (or simulates) __attribute__((artificial))
Definition artificial.h:43
#define RBIMPL_ASSERT_OR_ASSUME(...)
This is either RUBY_ASSERT or RBIMPL_ASSUME, depending on RUBY_DEBUG.
Definition assert.h:311
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition assert.h:219
Tweaking visibility of C variables/functions.
#define RBIMPL_SYMBOL_EXPORT_END()
Counterpart of RBIMPL_SYMBOL_EXPORT_BEGIN.
Definition dllexport.h:74
#define RBIMPL_SYMBOL_EXPORT_BEGIN()
Shortcut macro equivalent to RUBY_SYMBOL_EXPORT_BEGIN extern "C" {.
Definition dllexport.h:65
Defines enum ruby_fl_type.
@ RUBY_FL_WB_PROTECTED
Definition fl_type.h:186
@ RUBY_FL_USER2
User-defined flag.
Definition fl_type.h:284
@ RUBY_FL_SHAREABLE
This flag has something to do with Ractor.
Definition fl_type.h:253
Defines RBIMPL_ATTR_FLAG_ENUM.
#define RBIMPL_ATTR_FLAG_ENUM()
Wraps (or simulates) __attribute__((flag_enum)
Definition flag_enum.h:30
void rb_unexpected_object_type(VALUE obj, const char *expected)
Fails with the given object's type incompatibility to the type.
Definition error.c:1366
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Identical to rb_typeddata_is_kind_of(), except it raises exceptions instead of returning false.
Definition error.c:1449
void rb_unexpected_typeddata(const rb_data_type_t *actual, const rb_data_type_t *expected)
Fails with the given object's type incompatibility to the type.
Definition error.c:1359
Defines RBIMPL_ASSUME / RBIMPL_UNREACHABLE.
#define RBIMPL_UNREACHABLE_RETURN(_)
Wraps (or simulates) __builtin_unreachable.
Definition assume.h:48
Defines RBIMPL_ATTR_NONNULL.
#define RBIMPL_ATTR_NONNULL(list)
Wraps (or simulates) __attribute__((nonnull))
Definition nonnull.h:30
Declares rb_raise().
Defines RBIMPL_STATIC_ASSERT.
#define RBIMPL_STATIC_ASSERT
Wraps (or simulates) static_assert
#define RBIMPL_ATTR_NORETURN()
Wraps (or simulates) [[noreturn]]
Definition noreturn.h:38
Defines RBIMPL_ATTR_PURE.
#define RBIMPL_ATTR_PURE()
Wraps (or simulates) __attribute__((pure))
Definition pure.h:33
#define RBIMPL_ATTR_PURE_UNLESS_DEBUG()
Enables RBIMPL_ATTR_PURE if and only if.
Definition pure.h:38
Defines struct RBasic.
Defines struct RData.
void(* RUBY_DATA_FUNC)(void *)
This is the type of callbacks registered to RData.
Definition rdata.h:69
#define RBIMPL_ATTR_RETURNS_NONNULL()
Wraps (or simulates) __attribute__((returns_nonnull))
static bool RTYPEDDATA_P(VALUE obj)
Checks whether the passed object is RTypedData.
Definition rtypeddata.h:674
#define RTYPEDDATA_DATA(v)
Convenient getter macro.
Definition rtypeddata.h:106
static VALUE rbimpl_check_external_typeddata(VALUE obj)
This is an implementation detail of RTYPEDDATA_DATA().
Definition rtypeddata.h:756
VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *type)
This is the primitive way to wrap an existing C struct into RTypedData.
Definition gc.c:1373
VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type)
Identical to rb_data_typed_object_wrap(), except it allocates a new data region internally instead of...
Definition gc.c:1406
#define TypedData_Make_Struct0(result, klass, type, size, data_type, sval)
This is an implementation detail of TypedData_Make_Struct.
Definition rtypeddata.h:573
#define RUBY_TYPED_FREE_IMMEDIATELY
Macros to see if each corresponding flag is defined.
Definition rtypeddata.h:122
static const rb_data_type_t * RTYPEDDATA_TYPE(VALUE obj)
Queries for the type of given object.
Definition rtypeddata.h:692
#define RTYPEDDATA(obj)
Convenient casting macro.
Definition rtypeddata.h:96
static VALUE rb_data_typed_object_make(VALUE klass, const rb_data_type_t *type, void **datap, size_t size)
While we don't stop you from using this function, it seems to be an implementation detail of TypedDat...
Definition rtypeddata.h:792
C99 shim for <stdbool.h>
Ruby object's base components.
Definition rbasic.h:69
const VALUE klass
Class of an object.
Definition rbasic.h:92
Definition rdata.h:77
"Typed" user data.
Definition rtypeddata.h:393
void * data
Pointer to the actual C level struct that you want to wrap.
Definition rtypeddata.h:413
const VALUE type
This is a const rb_data_type_t *const value, with the low bits set:
Definition rtypeddata.h:410
VALUE fields_obj
Direct reference to the slots that holds instance variables, if any.
Definition rtypeddata.h:399
struct RBasic basic
The part that all ruby objects have in common.
Definition rtypeddata.h:396
This is the struct that holds necessary info for a struct.
Definition rtypeddata.h:238
size_t(* dsize)(const void *)
This function is to query the size of the underlying memory regions.
Definition rtypeddata.h:278
struct rb_data_type_struct::@64 function
Function pointers.
const rb_data_type_t * parent
Parent of this class.
Definition rtypeddata.h:333
RUBY_DATA_FUNC dfree
This function is called when the object is no longer used.
Definition rtypeddata.h:268
RUBY_DATA_FUNC dcompact
This function is called when the object is relocated.
Definition rtypeddata.h:289
void * reserved[7]
This field is reserved for future extension.
Definition rtypeddata.h:300
const char * wrap_struct_name
Name of structs of this kind.
Definition rtypeddata.h:245
RUBY_DATA_FUNC dmark
This function is called when the object is experiencing GC marks.
Definition rtypeddata.h:259
void * data
Type-specific static data.
Definition rtypeddata.h:339
VALUE flags
Type-specific behavioural characteristics.
Definition rtypeddata.h:352
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
Defines enum ruby_value_type.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition value_type.h:376
@ RUBY_T_DATA
Definition value_type.h:127