source: EcnlProtoTool/trunk/mruby-1.2.0/mrbgems/mruby-objectspace/src/mruby_objectspace.c@ 270

Last change on this file since 270 was 270, checked in by coas-nagasima, 7 years ago

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 4.4 KB
Line 
1#include "mruby.h"
2#include "mruby/gc.h"
3#include "mruby/hash.h"
4#include "mruby/class.h"
5
6struct os_count_struct {
7 mrb_int total;
8 mrb_int freed;
9 mrb_int counts[MRB_TT_MAXDEFINE+1];
10};
11
12static void
13os_count_object_type(mrb_state *mrb, struct RBasic *obj, void *data)
14{
15 struct os_count_struct *obj_count;
16 obj_count = (struct os_count_struct*)data;
17
18 obj_count->total++;
19
20 if (mrb_object_dead_p(mrb, obj)) {
21 obj_count->freed++;
22 }
23 else {
24 obj_count->counts[obj->tt]++;
25 }
26}
27
28/*
29 * call-seq:
30 * ObjectSpace.count_objects([result_hash]) -> hash
31 *
32 * Counts objects for each type.
33 *
34 * It returns a hash, such as:
35 * {
36 * :TOTAL=>10000,
37 * :FREE=>3011,
38 * :T_OBJECT=>6,
39 * :T_CLASS=>404,
40 * # ...
41 * }
42 *
43 * If the optional argument +result_hash+ is given,
44 * it is overwritten and returned. This is intended to avoid probe effect.
45 *
46 */
47
48static mrb_value
49os_count_objects(mrb_state *mrb, mrb_value self)
50{
51 struct os_count_struct obj_count = { 0 };
52 enum mrb_vtype i;
53 mrb_value hash;
54
55 if (mrb_get_args(mrb, "|H", &hash) == 0) {
56 hash = mrb_hash_new(mrb);
57 }
58
59 if (!mrb_test(mrb_hash_empty_p(mrb, hash))) {
60 mrb_hash_clear(mrb, hash);
61 }
62
63 mrb_objspace_each_objects(mrb, os_count_object_type, &obj_count);
64
65 mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_lit(mrb, "TOTAL")), mrb_fixnum_value(obj_count.total));
66 mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_lit(mrb, "FREE")), mrb_fixnum_value(obj_count.freed));
67
68 for (i = MRB_TT_FALSE; i < MRB_TT_MAXDEFINE; i++) {
69 mrb_value type;
70 switch (i) {
71#define COUNT_TYPE(t) case (MRB_T ## t): type = mrb_symbol_value(mrb_intern_lit(mrb, #t)); break;
72 COUNT_TYPE(T_FALSE);
73 COUNT_TYPE(T_FREE);
74 COUNT_TYPE(T_TRUE);
75 COUNT_TYPE(T_FIXNUM);
76 COUNT_TYPE(T_SYMBOL);
77 COUNT_TYPE(T_UNDEF);
78 COUNT_TYPE(T_FLOAT);
79 COUNT_TYPE(T_CPTR);
80 COUNT_TYPE(T_OBJECT);
81 COUNT_TYPE(T_CLASS);
82 COUNT_TYPE(T_MODULE);
83 COUNT_TYPE(T_ICLASS);
84 COUNT_TYPE(T_SCLASS);
85 COUNT_TYPE(T_PROC);
86 COUNT_TYPE(T_ARRAY);
87 COUNT_TYPE(T_HASH);
88 COUNT_TYPE(T_STRING);
89 COUNT_TYPE(T_RANGE);
90 COUNT_TYPE(T_EXCEPTION);
91 COUNT_TYPE(T_FILE);
92 COUNT_TYPE(T_ENV);
93 COUNT_TYPE(T_DATA);
94 COUNT_TYPE(T_FIBER);
95#undef COUNT_TYPE
96 default:
97 type = mrb_fixnum_value(i); break;
98 }
99 if (obj_count.counts[i])
100 mrb_hash_set(mrb, hash, type, mrb_fixnum_value(obj_count.counts[i]));
101 }
102
103 return hash;
104}
105
106struct os_each_object_data {
107 mrb_value block;
108 struct RClass *target_module;
109 mrb_int count;
110};
111
112static void
113os_each_object_cb(mrb_state *mrb, struct RBasic *obj, void *ud)
114{
115 struct os_each_object_data *d = (struct os_each_object_data*)ud;
116
117 /* filter dead objects */
118 if (mrb_object_dead_p(mrb, obj)) {
119 return;
120 }
121
122 /* filter internal objects */
123 switch (obj->tt) {
124 case MRB_TT_ENV:
125 case MRB_TT_ICLASS:
126 return;
127 default:
128 break;
129 }
130
131 /* filter half baked (or internal) objects */
132 if (!obj->c) return;
133
134 /* filter class kind if target module defined */
135 if (d->target_module && !mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), d->target_module)) {
136 return;
137 }
138
139 mrb_yield(mrb, d->block, mrb_obj_value(obj));
140 ++d->count;
141}
142
143/*
144 * call-seq:
145 * ObjectSpace.each_object([module]) {|obj| ... } -> fixnum
146 *
147 * Calls the block once for each object in this Ruby process.
148 * Returns the number of objects found.
149 * If the optional argument +module+ is given,
150 * calls the block for only those classes or modules
151 * that match (or are a subclass of) +module+.
152 *
153 * If no block is given, ArgumentError is raised.
154 *
155 */
156
157static mrb_value
158os_each_object(mrb_state *mrb, mrb_value self)
159{
160 mrb_value cls = mrb_nil_value();
161 struct os_each_object_data d;
162 mrb_get_args(mrb, "&|C", &d.block, &cls);
163
164 if (mrb_nil_p(d.block)) {
165 mrb_raise(mrb, E_ARGUMENT_ERROR, "Expected block in ObjectSpace.each_object.");
166 }
167
168 d.target_module = mrb_nil_p(cls) ? NULL : mrb_class_ptr(cls);
169 d.count = 0;
170 mrb_objspace_each_objects(mrb, os_each_object_cb, &d);
171 return mrb_fixnum_value(d.count);
172}
173
174void
175mrb_mruby_objectspace_gem_init(mrb_state *mrb)
176{
177 struct RClass *os = mrb_define_module(mrb, "ObjectSpace");
178 mrb_define_class_method(mrb, os, "count_objects", os_count_objects, MRB_ARGS_OPT(1));
179 mrb_define_class_method(mrb, os, "each_object", os_each_object, MRB_ARGS_OPT(1));
180}
181
182void
183mrb_mruby_objectspace_gem_final(mrb_state *mrb)
184{
185}
Note: See TracBrowser for help on using the repository browser.