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. 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 DFHack console
-------------- --------------
@ -57,10 +59,6 @@ Ruby helper functions
This is an excerpt of the functions defined in dfhack/plugins/ruby/*.rb. Check This is an excerpt of the functions defined in dfhack/plugins/ruby/*.rb. Check
the files and the comments for a complete list. 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) df.same_pos?(obj1, obj2)
Returns true if both objects are at the same game coordinates. Returns true if both objects are at the same game coordinates.
obj1 and 2 should respond to #pos and #x #y #z. obj1 and 2 should respond to #pos and #x #y #z.

@ -248,7 +248,6 @@ module DFHack
# exemple usage # exemple usage
def buildbed(pos=cursor) 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| item = world.items.all.find { |i|
@ -261,7 +260,6 @@ module DFHack
bld = building_alloc(:Bed) bld = building_alloc(:Bed)
building_position(bld, pos) building_position(bld, pos)
building_construct(bld, [item]) building_construct(bld, [item])
}
end end
end end
end end

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

@ -121,6 +121,11 @@ DFhackCExport command_result plugin_eval_ruby(const char *command)
if (!r_thread) if (!r_thread)
return CR_FAILURE; 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; command_result ret;
// ensure ruby thread is idle // ensure ruby thread is idle
@ -417,18 +422,6 @@ static VALUE rb_dfonupdateactiveset(VALUE self, VALUE val)
return Qtrue; 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) static VALUE rb_dfprint_str(VALUE self, VALUE s)
{ {
console_proxy->print("%s", rb_string_value_ptr(&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_dfonupdateactive), 0);
rb_define_singleton_method(rb_cDFHack, "onupdate_active=", RUBY_METHOD_FUNC(rb_dfonupdateactiveset), 1); 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_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_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); rb_define_singleton_method(rb_cDFHack, "get_rtti_classname", RUBY_METHOD_FUNC(rb_dfget_rtti_classname), 1);

@ -24,20 +24,6 @@ end
module DFHack module DFHack
class << self 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 # register a callback to be called every gframe or more
# ex: DFHack.onupdate_register { DFHack.world.units[0].counters.job_counter = 0 } # ex: DFHack.onupdate_register { DFHack.world.units[0].counters.job_counter = 0 }
def onupdate_register(&b) def onupdate_register(&b)

@ -17,14 +17,12 @@ end
if !material or material == 'help' or material == 'list' if !material or material == 'help' or material == 'list'
# show a list of available crop types # show a list of available crop types
cnt = Hash.new(0) cnt = Hash.new(0)
df.suspend {
df.world.items.other[:SEEDS].each { |seed| df.world.items.other[:SEEDS].each { |seed|
next if not seed.flags.in_building next if not seed.flags.in_building
next if not seed.itemrefs.find { |ref| ref._rtti_classname == :general_ref_building_holderst } 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] next if seed.grow_counter >= @raws_plant_growdur[seed.mat_index]
cnt[seed.mat_index] += 1 cnt[seed.mat_index] += 1
} }
}
cnt.sort_by { |mat, c| c }.each { |mat, c| cnt.sort_by { |mat, c| c }.each { |mat, c|
name = df.world.raws.plants.all[mat].id name = df.world.raws.plants.all[mat].id
@ -39,7 +37,6 @@ else
end end
cnt = 0 cnt = 0
df.suspend {
df.world.items.other[:SEEDS].each { |seed| df.world.items.other[:SEEDS].each { |seed|
next if seed.mat_index != wantmat next if seed.mat_index != wantmat
next if not seed.flags.in_building next if not seed.flags.in_building
@ -48,6 +45,5 @@ else
seed.grow_counter = @raws_plant_growdur[seed.mat_index] seed.grow_counter = @raws_plant_growdur[seed.mat_index]
cnt += 1 cnt += 1
} }
}
puts "Grown #{cnt} #{mat}" puts "Grown #{cnt} #{mat}"
end 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 } race_nr = df.world.raws.creatures.all.index { |cr| cr.creature_id == raw_race }
count = 0 count = 0
df.suspend { df.world.units.active.each { |u|
df.world.units.active.each { |u|
if u.race == race_nr and u.body.blood_count != 0 if u.race == race_nr and u.body.blood_count != 0
u.body.blood_count = 0 u.body.blood_count = 0
count += 1 count += 1
end end
}
} }
puts "slain #{count} #{raw_race}" puts "slain #{count} #{raw_race}"