ruby: move all ruby invocations inside a CoreSuspend lock, remove ruby suspend method

develop
jj 2012-06-25 17:06:37 +02:00
parent 8fb139a2f4
commit 17d06b969b
7 changed files with 38 additions and 79 deletions

@ -17,6 +17,8 @@ DFHack structures are renamed in CamelCase in the ruby namespace.
For a list of the structures and their methods, grep the ruby-autogen.rb file.
All ruby code runs while the main DF process and other plugins are suspended.
DFHack console
--------------
@ -57,10 +59,6 @@ Ruby helper functions
This is an excerpt of the functions defined in dfhack/plugins/ruby/*.rb. Check
the files and the comments for a complete list.
df.suspend { }
Ensures that the main game thread is paused while exec'ing the content of the
block. Similar to df.suspend() ; <run_block> ; df.resume().
df.same_pos?(obj1, obj2)
Returns true if both objects are at the same game coordinates.
obj1 and 2 should respond to #pos and #x #y #z.

@ -248,20 +248,18 @@ module DFHack
# exemple usage
def buildbed(pos=cursor)
suspend {
raise 'where to ?' if pos.x < 0
raise 'where to ?' if pos.x < 0
item = world.items.all.find { |i|
i.kind_of?(ItemBedst) and
i.itemrefs.empty? and
!i.flags.in_job
}
raise 'no free bed, build more !' if not item
bld = building_alloc(:Bed)
building_position(bld, pos)
building_construct(bld, [item])
item = world.items.all.find { |i|
i.kind_of?(ItemBedst) and
i.itemrefs.empty? and
!i.flags.in_job
}
raise 'no free bed, build more !' if not item
bld = building_alloc(:Bed)
building_position(bld, pos)
building_construct(bld, [item])
end
end
end

@ -55,21 +55,18 @@ module DFHack
if !material
# list trees
cnt = Hash.new(0)
suspend {
each_tree { |plant|
each_tree { |plant|
next if plant.grow_counter < SaplingToTreeAge
next if map_designation_at(plant).hidden
cnt[plant.material] += 1
}
}
cnt.sort_by { |mat, c| c }.each { |mat, c|
name = @raws_tree_name[mat]
puts " #{name} #{c}"
}
else
cnt = 0
suspend {
each_tree(material) { |plant|
each_tree(material) { |plant|
next if plant.grow_counter < SaplingToTreeAge
b = map_block_at(plant)
d = b.designation[plant.pos.x%16][plant.pos.y%16]
@ -81,7 +78,6 @@ module DFHack
break if cnt == count_max
end
}
}
puts "Updated #{cnt} plant designations"
end
end
@ -90,28 +86,24 @@ module DFHack
if !material
# list plants
cnt = Hash.new(0)
suspend {
each_tree { |plant|
each_tree { |plant|
next if plant.grow_counter >= SaplingToTreeAge
next if map_designation_at(plant).hidden
cnt[plant.material] += 1
}
}
cnt.sort_by { |mat, c| c }.each { |mat, c|
name = @raws_tree_name[mat]
puts " #{name} #{c}"
}
else
cnt = 0
suspend {
each_tree(material) { |plant|
each_tree(material) { |plant|
next if plant.grow_counter >= SaplingToTreeAge
next if map_designation_at(plant).hidden
plant.grow_counter = SaplingToTreeAge
cnt += 1
break if cnt == count_max
}
}
puts "Grown #{cnt} saplings"
end
end

@ -121,6 +121,11 @@ DFhackCExport command_result plugin_eval_ruby(const char *command)
if (!r_thread)
return CR_FAILURE;
// wrap all ruby code inside a suspend block
// if we dont do that and rely on ruby code doing it, we'll deadlock in
// onupdate
CoreSuspender suspend;
command_result ret;
// ensure ruby thread is idle
@ -417,18 +422,6 @@ static VALUE rb_dfonupdateactiveset(VALUE self, VALUE val)
return Qtrue;
}
static VALUE rb_dfresume(VALUE self)
{
Core::getInstance().Resume();
return Qtrue;
}
static VALUE rb_dfsuspend(VALUE self)
{
Core::getInstance().Suspend();
return Qtrue;
}
static VALUE rb_dfprint_str(VALUE self, VALUE s)
{
console_proxy->print("%s", rb_string_value_ptr(&s));
@ -769,8 +762,6 @@ static void ruby_bind_dfhack(void) {
rb_define_singleton_method(rb_cDFHack, "onupdate_active", RUBY_METHOD_FUNC(rb_dfonupdateactive), 0);
rb_define_singleton_method(rb_cDFHack, "onupdate_active=", RUBY_METHOD_FUNC(rb_dfonupdateactiveset), 1);
rb_define_singleton_method(rb_cDFHack, "resume", RUBY_METHOD_FUNC(rb_dfresume), 0);
rb_define_singleton_method(rb_cDFHack, "do_suspend", RUBY_METHOD_FUNC(rb_dfsuspend), 0);
rb_define_singleton_method(rb_cDFHack, "get_global_address", RUBY_METHOD_FUNC(rb_dfget_global_address), 1);
rb_define_singleton_method(rb_cDFHack, "get_vtable", RUBY_METHOD_FUNC(rb_dfget_vtable), 1);
rb_define_singleton_method(rb_cDFHack, "get_rtti_classname", RUBY_METHOD_FUNC(rb_dfget_rtti_classname), 1);

@ -24,20 +24,6 @@ end
module DFHack
class << self
# update the ruby.cpp version to accept a block
def suspend
if block_given?
begin
do_suspend
yield
ensure
resume
end
else
do_suspend
end
end
# register a callback to be called every gframe or more
# ex: DFHack.onupdate_register { DFHack.world.units[0].counters.job_counter = 0 }
def onupdate_register(&b)

@ -17,13 +17,11 @@ end
if !material or material == 'help' or material == 'list'
# show a list of available crop types
cnt = Hash.new(0)
df.suspend {
df.world.items.other[:SEEDS].each { |seed|
next if not seed.flags.in_building
next if not seed.itemrefs.find { |ref| ref._rtti_classname == :general_ref_building_holderst }
next if seed.grow_counter >= @raws_plant_growdur[seed.mat_index]
cnt[seed.mat_index] += 1
}
df.world.items.other[:SEEDS].each { |seed|
next if not seed.flags.in_building
next if not seed.itemrefs.find { |ref| ref._rtti_classname == :general_ref_building_holderst }
next if seed.grow_counter >= @raws_plant_growdur[seed.mat_index]
cnt[seed.mat_index] += 1
}
cnt.sort_by { |mat, c| c }.each { |mat, c|
@ -39,15 +37,13 @@ else
end
cnt = 0
df.suspend {
df.world.items.other[:SEEDS].each { |seed|
next if seed.mat_index != wantmat
next if not seed.flags.in_building
next if not seed.itemrefs.find { |ref| ref._rtti_classname == :general_ref_building_holderst }
next if seed.grow_counter >= @raws_plant_growdur[seed.mat_index]
seed.grow_counter = @raws_plant_growdur[seed.mat_index]
cnt += 1
}
df.world.items.other[:SEEDS].each { |seed|
next if seed.mat_index != wantmat
next if not seed.flags.in_building
next if not seed.itemrefs.find { |ref| ref._rtti_classname == :general_ref_building_holderst }
next if seed.grow_counter >= @raws_plant_growdur[seed.mat_index]
seed.grow_counter = @raws_plant_growdur[seed.mat_index]
cnt += 1
}
puts "Grown #{cnt} #{mat}"
end

@ -9,13 +9,11 @@ raise 'invalid race' if not raw_race
race_nr = df.world.raws.creatures.all.index { |cr| cr.creature_id == raw_race }
count = 0
df.suspend {
df.world.units.active.each { |u|
if u.race == race_nr and u.body.blood_count != 0
u.body.blood_count = 0
count += 1
end
}
df.world.units.active.each { |u|
if u.race == race_nr and u.body.blood_count != 0
u.body.blood_count = 0
count += 1
end
}
puts "slain #{count} #{raw_race}"