Allow `mrb_objspace_each_objects()` to break iteration; ref #3359

parent edd9fc6e
...@@ -17,7 +17,9 @@ MRB_BEGIN_DECL ...@@ -17,7 +17,9 @@ MRB_BEGIN_DECL
struct mrb_state; struct mrb_state;
typedef void (mrb_each_object_callback)(struct mrb_state *mrb, struct RBasic *obj, void *data); #define MRB_EACH_OBJ_OK 0
#define MRB_EACH_OBJ_BREAK 1
typedef int (mrb_each_object_callback)(struct mrb_state *mrb, struct RBasic *obj, void *data);
void mrb_objspace_each_objects(struct mrb_state *mrb, mrb_each_object_callback *callback, void *data); void mrb_objspace_each_objects(struct mrb_state *mrb, mrb_each_object_callback *callback, void *data);
MRB_API void mrb_free_context(struct mrb_state *mrb, struct mrb_context *c); MRB_API void mrb_free_context(struct mrb_state *mrb, struct mrb_context *c);
......
...@@ -9,7 +9,7 @@ struct os_count_struct { ...@@ -9,7 +9,7 @@ struct os_count_struct {
mrb_int counts[MRB_TT_MAXDEFINE+1]; mrb_int counts[MRB_TT_MAXDEFINE+1];
}; };
static void static int
os_count_object_type(mrb_state *mrb, struct RBasic *obj, void *data) os_count_object_type(mrb_state *mrb, struct RBasic *obj, void *data)
{ {
struct os_count_struct *obj_count; struct os_count_struct *obj_count;
...@@ -23,6 +23,7 @@ os_count_object_type(mrb_state *mrb, struct RBasic *obj, void *data) ...@@ -23,6 +23,7 @@ os_count_object_type(mrb_state *mrb, struct RBasic *obj, void *data)
else { else {
obj_count->counts[obj->tt]++; obj_count->counts[obj->tt]++;
} }
return MRB_EACH_OBJ_OK;
} }
/* /*
...@@ -109,35 +110,36 @@ struct os_each_object_data { ...@@ -109,35 +110,36 @@ struct os_each_object_data {
mrb_int count; mrb_int count;
}; };
static void static int
os_each_object_cb(mrb_state *mrb, struct RBasic *obj, void *ud) os_each_object_cb(mrb_state *mrb, struct RBasic *obj, void *ud)
{ {
struct os_each_object_data *d = (struct os_each_object_data*)ud; struct os_each_object_data *d = (struct os_each_object_data*)ud;
/* filter dead objects */ /* filter dead objects */
if (mrb_object_dead_p(mrb, obj)) { if (mrb_object_dead_p(mrb, obj)) {
return; return MRB_EACH_OBJ_OK;
} }
/* filter internal objects */ /* filter internal objects */
switch (obj->tt) { switch (obj->tt) {
case MRB_TT_ENV: case MRB_TT_ENV:
case MRB_TT_ICLASS: case MRB_TT_ICLASS:
return; return MRB_EACH_OBJ_OK;
default: default:
break; break;
} }
/* filter half baked (or internal) objects */ /* filter half baked (or internal) objects */
if (!obj->c) return; if (!obj->c) return MRB_EACH_OBJ_OK;
/* filter class kind if target module defined */ /* filter class kind if target module defined */
if (d->target_module && !mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), d->target_module)) { if (d->target_module && !mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), d->target_module)) {
return; return MRB_EACH_OBJ_OK;
} }
mrb_yield(mrb, d->block, mrb_obj_value(obj)); mrb_yield(mrb, d->block, mrb_obj_value(obj));
++d->count; ++d->count;
return MRB_EACH_OBJ_OK;
} }
/* /*
......
...@@ -1498,7 +1498,8 @@ gc_each_objects(mrb_state *mrb, mrb_gc *gc, mrb_each_object_callback *callback, ...@@ -1498,7 +1498,8 @@ gc_each_objects(mrb_state *mrb, mrb_gc *gc, mrb_each_object_callback *callback,
p = objects(page); p = objects(page);
pend = p + MRB_HEAP_PAGE_SIZE; pend = p + MRB_HEAP_PAGE_SIZE;
for (;p < pend; p++) { for (;p < pend; p++) {
(*callback)(mrb, &p->as.basic, data); if ((*callback)(mrb, &p->as.basic, data) == MRB_EACH_OBJ_BREAK)
break;
} }
page = page->next; page = page->next;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment