Map the guests to a ruby hash to avoid creating new ruby objects on each call of Guest.each or Guest[].

This commit is contained in:
Tobias Brunner
2010-10-12 15:04:38 +02:00
parent 9b0847dd9a
commit d679266fe1
+35 -41
View File
@@ -120,79 +120,73 @@ static void dumm_init()
/** /**
* Guest bindings * Guest bindings
*/ */
static VALUE guest_find(VALUE class, VALUE key) static VALUE guest_hash_create(VALUE class)
{ {
enumerator_t *enumerator; enumerator_t *enumerator;
guest_t *guest, *found = NULL; guest_t *guest;
VALUE hash = rb_hash_new();
if (TYPE(key) == T_SYMBOL)
{
key = rb_convert_type(key, T_STRING, "String", "to_s");
}
enumerator = dumm->create_guest_enumerator(dumm); enumerator = dumm->create_guest_enumerator(dumm);
while (enumerator->enumerate(enumerator, &guest)) while (enumerator->enumerate(enumerator, &guest))
{ {
if (streq(guest->get_name(guest), StringValuePtr(key))) rb_hash_aset(hash, rb_str_new2(guest->get_name(guest)),
{ Data_Wrap_Struct(class, NULL, NULL, guest));
found = guest;
break;
}
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
if (!found) return hash;
}
static VALUE guest_hash(VALUE class)
{
ID id = rb_intern("@@guests");
if (!rb_cvar_defined(class, id))
{ {
return Qnil; VALUE hash = guest_hash_create(class);
rb_cvar_set(class, id, hash, 0);
return hash;
} }
return Data_Wrap_Struct(class, NULL, NULL, found); return rb_cvar_get(class, id);
}
static VALUE guest_find(VALUE class, VALUE key)
{
if (TYPE(key) != T_STRING)
{
key = rb_convert_type(key, T_STRING, "String", "to_s");
}
return rb_hash_aref(guest_hash(class), key);
} }
static VALUE guest_get(VALUE class, VALUE key) static VALUE guest_get(VALUE class, VALUE key)
{ {
VALUE guest = guest_find(class, key); return guest_find(class, key);
if (NIL_P(guest))
{
rb_raise(rb_eRuntimeError, "guest not found");
}
return guest;
} }
static VALUE guest_each(int argc, VALUE *argv, VALUE class) static VALUE guest_each(int argc, VALUE *argv, VALUE class)
{ {
linked_list_t *list;
enumerator_t *enumerator;
guest_t *guest;
if (!rb_block_given_p()) if (!rb_block_given_p())
{ {
rb_raise(rb_eArgError, "must be called with a block"); rb_raise(rb_eArgError, "must be called with a block");
} }
list = linked_list_create(); rb_block_call(guest_hash(class), rb_intern("each_value"), 0, 0,
enumerator = dumm->create_guest_enumerator(dumm); rb_yield, 0);
while (enumerator->enumerate(enumerator, &guest))
{
list->insert_last(list, guest);
}
enumerator->destroy(enumerator);
while (list->remove_first(list, (void**)&guest) == SUCCESS)
{
rb_yield(Data_Wrap_Struct(class, NULL, NULL, guest));
}
list->destroy(list);
return class; return class;
} }
static VALUE guest_new(VALUE class, VALUE name, VALUE kernel, static VALUE guest_new(VALUE class, VALUE name, VALUE kernel,
VALUE master, VALUE args) VALUE master, VALUE args)
{ {
VALUE self;
guest_t *guest; guest_t *guest;
guest = dumm->create_guest(dumm, StringValuePtr(name),
guest = dumm->create_guest(dumm, StringValuePtr(name), StringValuePtr(kernel), StringValuePtr(kernel), StringValuePtr(master),
StringValuePtr(master), StringValuePtr(args)); StringValuePtr(args));
if (!guest) if (!guest)
{ {
rb_raise(rb_eRuntimeError, "creating guest failed"); rb_raise(rb_eRuntimeError, "creating guest failed");
} }
return Data_Wrap_Struct(class, NULL, NULL, guest); self = Data_Wrap_Struct(class, NULL, NULL, guest);
rb_hash_aset(guest_hash(class), name, self);
return self;
} }
static VALUE guest_to_s(VALUE self) static VALUE guest_to_s(VALUE self)