aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rw-r--r--gc.c58
-rw-r--r--include/ruby/ruby.h30
3 files changed, 103 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index ac2c7c021a..bf8c371997 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+Wed Jun 17 06:19:06 2009 Koichi Sasada <ko1@atdot.net>
+
+ * include/ruby/ruby.h: New structure RTypedData, added.
+ This structure incldues more explicit type information for
+ T_DATA objects. If RData(obj)->dfree is immediate value `1' on
+ T_DATA object obj, obj is needed to be accessed with RTYPEDDATA(obj)
+ instead of RDATA(obj). A RTypedData structure points the structure
+ rb_typed_data_t. rb_typed_data_t includes information such as the
+ type name of this data, mark and free function what RData includes,
+ and memsize function show how data consuming the memory size.
+ Note that you do not need any change existing T_DATA objects.
+ If you use RDataType instead of RData on T_DATA object,
+ you can specify explicit type information.
+
+ * gc.c (rb_data_typed_object_alloc, rb_objspace_data_type_memsize,
+ rb_objspace_data_type_name): added.
+
Wed Jun 17 06:14:23 2009 Koichi Sasada <ko1@atdot.net>
* gc.c: fix indent.
diff --git a/gc.c b/gc.c
index 76b4053806..bb19fa38da 100644
--- a/gc.c
+++ b/gc.c
@@ -264,6 +264,7 @@ typedef struct RVALUE {
struct RRegexp regexp;
struct RHash hash;
struct RData data;
+ struct RTypedData typeddata;
struct RStruct rstruct;
struct RBignum bignum;
struct RFile file;
@@ -1177,6 +1178,44 @@ rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_F
return (VALUE)data;
}
+VALUE
+rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *type)
+{
+ NEWOBJ(data, struct RTypedData);
+
+ if (klass) Check_Type(klass, T_CLASS);
+
+ OBJSETUP(data, klass, T_DATA);
+
+ data->data = datap;
+ data->typed_flag = 1;
+ data->type = type;
+
+ return (VALUE)data;
+}
+
+size_t
+rb_objspace_data_type_memsize(VALUE obj)
+{
+ if (RTYPEDDATA_P(obj)) {
+ return RTYPEDDATA_TYPE(obj)->dsize(RTYPEDDATA_DATA(obj));
+ }
+ else {
+ return 0;
+ }
+}
+
+const char *
+rb_objspace_data_type_name(VALUE obj)
+{
+ if (RTYPEDDATA_P(obj)) {
+ return RTYPEDDATA_TYPE(obj)->name;
+ }
+ else {
+ return 0;
+ }
+}
+
#ifdef __ia64
#define SET_STACK_END (SET_MACHINE_STACK_END(&th->machine_stack_end), th->machine_register_stack_end = rb_ia64_bsp())
#else
@@ -1695,7 +1734,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
break;
case T_DATA:
+ if (RTYPEDDATA_P(obj)) {
+ if (obj->as.typeddata.type->dmark) (*obj->as.typeddata.type->dmark)(DATA_PTR(obj));
+ }
+ else {
if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj));
+ }
break;
case T_OBJECT:
@@ -2058,6 +2102,9 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
break;
case T_DATA:
if (DATA_PTR(obj)) {
+ if (RTYPEDDATA_P(obj)) {
+ RDATA(obj)->dfree = RANY(obj)->as.typeddata.type->dfree;
+ }
if ((long)RANY(obj)->as.data.dfree == -1) {
xfree(DATA_PTR(obj));
}
@@ -2652,12 +2699,19 @@ run_final(rb_objspace_t *objspace, VALUE obj)
long i;
int status;
VALUE args[3], table, objid;
+ RUBY_DATA_FUNC free_func = 0;
objid = rb_obj_id(obj); /* make obj into id */
RBASIC(obj)->klass = 0;
- if (RDATA(obj)->dfree) {
- (*RDATA(obj)->dfree)(DATA_PTR(obj));
+ if (RTYPEDDATA_P(obj)) {
+ free_func = RTYPEDDATA_TYPE(obj)->dfree;
+ }
+ else {
+ free_func = RDATA(obj)->dfree;
+ }
+ if (free_func) {
+ (*free_func)(DATA_PTR(obj));
}
if (finalizer_table &&
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 7da0b9e908..9da3f5b9fd 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -735,14 +735,34 @@ struct RData {
void *data;
};
+typedef struct rb_data_type_struct {
+ const char *name;
+ void (*dmark)(void*);
+ void (*dfree)(void*);
+ size_t (*dsize)(void *);
+ void *ary[4]; /* for extension */
+} rb_data_type_t;
+
+struct RTypedData {
+ struct RBasic basic;
+ const rb_data_type_t *type;
+ VALUE typed_flag; /* 1 or not */
+ void *data;
+};
+
#define DATA_PTR(dta) (RDATA(dta)->data)
+#define RTYPEDDATA_P(v) (RTYPEDDATA(v)->typed_flag == 1)
+#define RTYPEDDATA_TYPE(v) (RTYPEDDATA(v)->type)
+#define RTYPEDDATA_DATA(v) (RTYPEDDATA(v)->data)
+
/*
#define RUBY_DATA_FUNC(func) ((void (*)(void*))func)
*/
typedef void (*RUBY_DATA_FUNC)(void*);
VALUE rb_data_object_alloc(VALUE,void*,RUBY_DATA_FUNC,RUBY_DATA_FUNC);
+VALUE rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *);
#define Data_Wrap_Struct(klass,mark,free,sval)\
rb_data_object_alloc(klass,sval,(RUBY_DATA_FUNC)mark,(RUBY_DATA_FUNC)free)
@@ -753,6 +773,15 @@ VALUE rb_data_object_alloc(VALUE,void*,RUBY_DATA_FUNC,RUBY_DATA_FUNC);
Data_Wrap_Struct(klass,mark,free,sval)\
)
+#define Data_Wrap_TypedStruct(klass,data_type,sval)\
+ rb_data_typed_object_alloc(klass,sval,data_type)
+
+#define Data_Make_TypedStruct(klass, type, data_type, sval) (\
+ sval = ALLOC(type),\
+ memset(sval, 0, sizeof(type)),\
+ Data_Wrap_TypedStruct(klass,data_type,sval)\
+)
+
#define Data_Get_Struct(obj,type,sval) do {\
Check_Type(obj, T_DATA); \
sval = (type*)DATA_PTR(obj);\
@@ -826,6 +855,7 @@ struct RBignum {
#define RARRAY(obj) (R_CAST(RArray)(obj))
#define RHASH(obj) (R_CAST(RHash)(obj))
#define RDATA(obj) (R_CAST(RData)(obj))
+#define RTYPEDDATA(obj) (R_CAST(RTypedData)(obj))
#define RSTRUCT(obj) (R_CAST(RStruct)(obj))
#define RBIGNUM(obj) (R_CAST(RBignum)(obj))
#define RFILE(obj) (R_CAST(RFile)(obj))