mbed I/F binding for mruby
Dependents: mruby_mbed_web mirb_mbed
mruby_objectspace.c
00001 #include "mruby.h" 00002 #include "mruby/gc.h" 00003 #include "mruby/hash.h" 00004 #include "mruby/class.h" 00005 00006 struct os_count_struct { 00007 mrb_int total; 00008 mrb_int freed; 00009 mrb_int counts[MRB_TT_MAXDEFINE+1]; 00010 }; 00011 00012 static void 00013 os_count_object_type(mrb_state *mrb, struct RBasic *obj, void *data) 00014 { 00015 struct os_count_struct *obj_count; 00016 obj_count = (struct os_count_struct*)data; 00017 00018 obj_count->total++; 00019 00020 if (is_dead(mrb, obj)) { 00021 obj_count->freed++; 00022 } 00023 else { 00024 obj_count->counts[obj->tt]++; 00025 } 00026 } 00027 00028 /* 00029 * call-seq: 00030 * ObjectSpace.count_objects([result_hash]) -> hash 00031 * 00032 * Counts objects for each type. 00033 * 00034 * It returns a hash, such as: 00035 * { 00036 * :TOTAL=>10000, 00037 * :FREE=>3011, 00038 * :T_OBJECT=>6, 00039 * :T_CLASS=>404, 00040 * # ... 00041 * } 00042 * 00043 * If the optional argument +result_hash+ is given, 00044 * it is overwritten and returned. This is intended to avoid probe effect. 00045 * 00046 */ 00047 00048 static mrb_value 00049 os_count_objects(mrb_state *mrb, mrb_value self) 00050 { 00051 struct os_count_struct obj_count = { 0 }; 00052 enum mrb_vtype i; 00053 mrb_value hash; 00054 00055 if (mrb_get_args(mrb, "|H", &hash) == 0) { 00056 hash = mrb_hash_new(mrb); 00057 } 00058 00059 if (!mrb_test(mrb_hash_empty_p(mrb, hash))) { 00060 mrb_hash_clear(mrb, hash); 00061 } 00062 00063 mrb_objspace_each_objects(mrb, os_count_object_type, &obj_count); 00064 00065 mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_lit(mrb, "TOTAL")), mrb_fixnum_value(obj_count.total)); 00066 mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_lit(mrb, "FREE")), mrb_fixnum_value(obj_count.freed)); 00067 00068 for (i = MRB_TT_FALSE; i < MRB_TT_MAXDEFINE; i++) { 00069 mrb_value type; 00070 switch (i) { 00071 #define COUNT_TYPE(t) case (MRB_T ## t): type = mrb_symbol_value(mrb_intern_lit(mrb, #t)); break; 00072 COUNT_TYPE(T_FALSE); 00073 COUNT_TYPE(T_FREE); 00074 COUNT_TYPE(T_TRUE); 00075 COUNT_TYPE(T_FIXNUM); 00076 COUNT_TYPE(T_SYMBOL); 00077 COUNT_TYPE(T_UNDEF); 00078 COUNT_TYPE(T_FLOAT); 00079 COUNT_TYPE(T_CPTR); 00080 COUNT_TYPE(T_OBJECT); 00081 COUNT_TYPE(T_CLASS); 00082 COUNT_TYPE(T_MODULE); 00083 COUNT_TYPE(T_ICLASS); 00084 COUNT_TYPE(T_SCLASS); 00085 COUNT_TYPE(T_PROC); 00086 COUNT_TYPE(T_ARRAY); 00087 COUNT_TYPE(T_HASH); 00088 COUNT_TYPE(T_STRING); 00089 COUNT_TYPE(T_RANGE); 00090 COUNT_TYPE(T_EXCEPTION); 00091 COUNT_TYPE(T_FILE); 00092 COUNT_TYPE(T_ENV); 00093 COUNT_TYPE(T_DATA); 00094 COUNT_TYPE(T_FIBER); 00095 #undef COUNT_TYPE 00096 default: 00097 type = mrb_fixnum_value(i); break; 00098 } 00099 if (obj_count.counts[i]) 00100 mrb_hash_set(mrb, hash, type, mrb_fixnum_value(obj_count.counts[i])); 00101 } 00102 00103 return hash; 00104 } 00105 00106 struct os_each_object_data { 00107 mrb_value block; 00108 struct RClass *target_module; 00109 mrb_int count; 00110 }; 00111 00112 static void 00113 os_each_object_cb(mrb_state *mrb, struct RBasic *obj, void *ud) 00114 { 00115 struct os_each_object_data *d = (struct os_each_object_data*)ud; 00116 00117 /* filter dead objects */ 00118 if (is_dead(mrb, obj)) { 00119 return; 00120 } 00121 00122 /* filter internal objects */ 00123 switch (obj->tt) { 00124 case MRB_TT_ENV: 00125 case MRB_TT_ICLASS: 00126 return; 00127 default: 00128 break; 00129 } 00130 00131 /* filter half baked (or internal) objects */ 00132 if (!obj->c) return; 00133 00134 /* filter class kind if target module defined */ 00135 if (d->target_module && !mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), d->target_module)) { 00136 return; 00137 } 00138 00139 mrb_yield(mrb, d->block, mrb_obj_value(obj)); 00140 ++d->count; 00141 } 00142 00143 /* 00144 * call-seq: 00145 * ObjectSpace.each_object([module]) {|obj| ... } -> fixnum 00146 * 00147 * Calls the block once for each object in this Ruby process. 00148 * Returns the number of objects found. 00149 * If the optional argument +module+ is given, 00150 * calls the block for only those classes or modules 00151 * that match (or are a subclass of) +module+. 00152 * 00153 * If no block is given, ArgumentError is raised. 00154 * 00155 */ 00156 00157 static mrb_value 00158 os_each_object(mrb_state *mrb, mrb_value self) 00159 { 00160 mrb_value cls = mrb_nil_value(); 00161 struct os_each_object_data d; 00162 mrb_get_args(mrb, "&|C", &d.block, &cls); 00163 00164 if (mrb_nil_p(d.block)) { 00165 mrb_raise(mrb, E_ARGUMENT_ERROR, "Expected block in ObjectSpace.each_object."); 00166 } 00167 00168 d.target_module = mrb_nil_p(cls) ? NULL : mrb_class_ptr(cls); 00169 d.count = 0; 00170 mrb_objspace_each_objects(mrb, os_each_object_cb, &d); 00171 return mrb_fixnum_value(d.count); 00172 } 00173 00174 void 00175 mrb_mruby_objectspace_gem_init(mrb_state *mrb) 00176 { 00177 struct RClass *os = mrb_define_module(mrb, "ObjectSpace"); 00178 mrb_define_class_method(mrb, os, "count_objects", os_count_objects, MRB_ARGS_OPT(1)); 00179 mrb_define_class_method(mrb, os, "each_object", os_each_object, MRB_ARGS_OPT(1)); 00180 } 00181 00182 void 00183 mrb_mruby_objectspace_gem_final(mrb_state *mrb) 00184 { 00185 } 00186
Generated on Tue Jul 12 2022 18:00:34 by 1.7.2