From: ptkwt@...1.aracnet.com (Phil Tomson) Date: 2002-05-20T09:28:51+09:00 Subject: complicated callcc question (long) I'm trying to create processes that can wait for certain events to occur before continuing on. I'm using continuations (callcc) to do this, but it seems like the continuation is carrying a lot more context around than I would like it to. Here's the code (and there's a bit of it): class WaitException < Exception end class T_Process def initialize(callable= nil,sensitivityList=nil) @sensitivity_list= sensitivityList @callableObj = callable @savedCallableObj = @callableObj @contin = nil @wait_cond = proc{true} #nop proc @wait_pending = false end def call if @wait_pending if @wait_cond.call @contin.call @callableObj = @savedCallableObj if @wait_cond.call @wait_pending = false else call_with_rescue(@callableObj) end else call_with_rescue(@callableObj) end end def wait(cond) @wait_cond = cond @wait_pending = true @callableObj = proc{} #insert a NOP callcc{|@contin| puts "Start Wait..." raise WaitException } end private def call_with_rescue(p) begin p.call rescue WaitException puts "Got a WaitException" end end end $time = 0 class Design def initialize @process = nil end def define_behavior(&b) puts "define the behavior" @behavior = b end def process(&p) unless @process puts "define the process" @process = T_Process.new(p) else @process.call end end def step @behavior.call sleep .2 $time+=1 end def wait(&cond) @process.wait(cond) end end #now try it out: class MyDesign < Design def initialize define_behavior { process { puts "first" puts "second" wait { $time == 8 } puts "back in define_behavior..." puts "time is: #{$time}" } } end end i=0 md = MyDesign.new 12.times do |i| puts ">>>>>iteration: #{i}" md.step end #########################end of code###################### Here's the output: ruby Process.rb define the behavior >>>>>iteration: 0 define the process >>>>>iteration: 1 first second Start Wait... Got a WaitException >>>>>iteration: 2 >>>>>iteration: 3 >>>>>iteration: 4 >>>>>iteration: 5 >>>>>iteration: 6 >>>>>iteration: 7 >>>>>iteration: 8 back in define_behavior... time is: 8 >>>>>iteration: 2 >>>>>iteration: 3 >>>>>iteration: 4 >>>>>iteration: 5 >>>>>iteration: 6 >>>>>iteration: 7 >>>>>iteration: 8 >>>>>iteration: 9 >>>>>iteration: 10 >>>>>iteration: 11 The main idea here is that in the constructor for MyDesign I define a behavior (basically a proc) that has a process in it (again basically a proc) which contains a wait (yet again, basically a proc). The idea is that the process defined in define_behavior will get called each time the step method is called. What I want to happen is that the process executes until the wait statement which then says in effect 'wait until the global time is 8'. With each call to md.step the global time variable is incremented. After $time == 8 the rest of the process should be executed (in this case it'll do puts "back in define_behavior" and then print the current value of $time). It's working pretty close to how I intend it to work, except that after the wait condition has been satisfied and the continuation is called (to run the rest of the process) the iteration variable (i) that exists at the toplevel scope also is returned to the value it had just as the continuation was created (in the wait method of T_Process class) which means that although it was 8 before the continuation was called, it's returned to 2 and it starts all over from that point until it has run 12 times (for a total of something like 20 iterations instead of 12.times as indicated). So it seems that the call to the continuation not only continued execution at the statement after the wait, but it also restored variables at the toplevel scope to their values at that time. How can I avoid this so I get an output that looks like: define the behavior >>>>>iteration: 0 define the process >>>>>iteration: 1 first second Start Wait... Got a WaitException >>>>>iteration: 2 >>>>>iteration: 3 >>>>>iteration: 4 >>>>>iteration: 5 >>>>>iteration: 6 >>>>>iteration: 7 >>>>>iteration: 8 back in define_behavior... time is: 8 >>>>>iteration: 9 #<=continue from 8 instead of reseting to 2 >>>>>iteration: 10 >>>>>iteration: 11 Phil