Class: Computable
- Inherits:
-
Object
- Object
- Computable
- Defined in:
- lib/computable.rb,
lib/computable/version.rb
Defined Under Namespace
Classes: Error, InvalidFormat, RecursionDetected, UndefinedValue, Variable
Constant Summary collapse
- Unknown =
This is a special value to mark a variable to be computed.
Object.new
- VERSION =
"1.1.2"
Class Method Summary collapse
- .calc_value(name, format = nil, freeze: true, &block) ⇒ Object
- .input_value(name, format = nil, **kwargs) ⇒ Object
- .verify_format(name, value, format) ⇒ Object
Instance Method Summary collapse
- #computable_debug ⇒ Object
- #computable_debug=(v) ⇒ Object
- #computable_display_dot(**kwargs) ⇒ Object
- #computable_max_threads ⇒ Object
- #computable_max_threads=(v) ⇒ Object
- #computable_to_dot(rankdir: "TB", multiline: true) ⇒ Object
-
#initialize ⇒ Computable
constructor
A new instance of Computable.
Constructor Details
#initialize ⇒ Computable
Returns a new instance of Computable.
262 263 264 265 266 267 268 |
# File 'lib/computable.rb', line 262 def initialize @computable_debug = false @computable_max_threads = 0 @computable_variables = {} @computable_caller = nil @computable_mutex = Mutex.new end |
Class Method Details
.calc_value(name, format = nil, freeze: true, &block) ⇒ Object
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
# File 'lib/computable.rb', line 290 def self.calc_value name, format=nil, freeze: true, &block calc_method_id = "calc_#{name}".intern define_method(calc_method_id, &block) calc_method2_id = "calc_#{name}_with_tracking".intern define_method(calc_method2_id) do |v| old_caller = Thread.current.thread_variable_get("Computable #{object_id}") Thread.current.thread_variable_set("Computable #{self.object_id}", v) begin puts "do calc #{v.inspect}" if @computable_debug begin res = send(calc_method_id) rescue Exception => err improve_backtrace(err, block, name) end Computable.verify_format(name, res, format) res.freeze if freeze res ensure Thread.current.thread_variable_set("Computable #{self.object_id}", old_caller) end end define_method("#{name}=") do |value| Computable.verify_format(name, value, format) @computable_mutex.synchronize do v = @computable_variables[name] puts "set #{name}: #{value.inspect} #{v.inspect}" if @computable_debug v = @computable_variables[name] = Variable.new(name, method(calc_method2_id), self, @computable_mutex) unless v value.freeze if freeze v.assign_value(value) end end define_method(name) do @computable_mutex.synchronize do v = @computable_variables[name] puts "called #{name} #{v.inspect}" if @computable_debug v = @computable_variables[name] = Variable.new(name, method(calc_method2_id), self, @computable_mutex) unless v kaller = Thread.current.thread_variable_get("Computable #{object_id}") v.query_value(kaller) end end end |
.input_value(name, format = nil, **kwargs) ⇒ Object
337 338 339 340 341 |
# File 'lib/computable.rb', line 337 def self.input_value name, format=nil, **kwargs calc_value name, format, **kwargs do raise UndefinedValue, "input variable '#{name}' is not assigned" end end |
.verify_format(name, value, format) ⇒ Object
271 272 273 274 275 |
# File 'lib/computable.rb', line 271 def self.verify_format(name, value, format) if format && !(Unknown==value) && !(format === value) raise InvalidFormat, "variable '#{name}': value #{value.inspect} is not in format #{format.inspect}" end end |
Instance Method Details
#computable_debug ⇒ Object
223 224 225 |
# File 'lib/computable.rb', line 223 def computable_debug @computable_debug end |
#computable_debug=(v) ⇒ Object
220 221 222 |
# File 'lib/computable.rb', line 220 def computable_debug=(v) @computable_debug = v end |
#computable_display_dot(**kwargs) ⇒ Object
234 235 236 237 238 |
# File 'lib/computable.rb', line 234 def computable_display_dot(**kwargs) IO.popen("dot -Tpng | display -", "w") do |fd| fd.puts computable_to_dot(**kwargs) end end |
#computable_max_threads ⇒ Object
230 231 232 |
# File 'lib/computable.rb', line 230 def computable_max_threads @computable_max_threads end |
#computable_max_threads=(v) ⇒ Object
227 228 229 |
# File 'lib/computable.rb', line 227 def computable_max_threads=(v) @computable_max_threads = v end |
#computable_to_dot(rankdir: "TB", multiline: true) ⇒ Object
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/computable.rb', line 240 def computable_to_dot(rankdir: "TB", multiline: true) dot = "digraph #{self.class.name.inspect} {\n" dot << "graph [ dpi = 45, rankdir=#{rankdir} ];\n" @computable_variables.each do |name, v| col = case when !v.value_calced then "color = red," when !v.used_for.empty? then "color = green," else "color = blue," end label = if multiline "#{name.to_s.gsub("_","\n")}\n(#{v.count})" else "#{name.to_s} (#{v.count})" end dot << "#{name.to_s.inspect} [#{col} label=#{label.inspect}];\n" v.used_for.each do |name2, v2| dot << "#{name.to_s.inspect} -> #{name2.to_s.inspect};\n" end end dot << "}\n" end |