Saving the state of a Thread?

Hi,
Does anyone have any clever ideas on saving the state of a Thread?
I have a thread that runs for a couple of hours, and I need to save the
progress to disk, so that I can restart from where I left off.

Any ideas would be welcome.
-Patrick

El Viernes, 22 de Agosto de 2008, Patrick Li escribió:

Hi,
Does anyone have any clever ideas on saving the state of a Thread?
I have a thread that runs for a couple of hours, and I need to save the
progress to disk, so that I can restart from where I left off.

Not sure about what you mean. Maybe it would be useful for you the usage
of
variables in threads, for example:

this_thread = Thread.current
this_thread[:time_on] = Time.now

This stores the actual time into a variable for that thread, so you
later can
read it by doing:

this_thread[:time_on]

But not sure if you want this.

Mmm, that’s not quite it.

Here’s an example:

eg.
def start
initialize()
doSomething()
doSomethingElse() <-- Three hours into processing
doMore()
cleanup()
end

so imagine this method is called inside a Thread. And three hours into
processing, the user wants to take a break and save his progress to
disk.

Next time the program starts up, I want to be able to jump directly to
the
doSomethingElse() line. With the appropriate local variables all set and
ready.

Is this possible?
-Patrick

On Aug 22, 2008, at 9:12 AM, Patrick Li wrote:

cleanup()
ready.

Is this possible?
-Patrick

sure. do it by hand using amalgalite.

a @ http://codeforpeople.com/

El Viernes, 22 de Agosto de 2008, Patrick Li escribió:

cleanup()

Is this possible?

Using thread variables you could do:

def initialize
@thread = Thread.current
end

def doSomething()
@thread[:state] = ‘doSomething’
end

def doSomethingElse()
@thread[:state] = ‘doSomethingElse’
end

def start
initialize()
doSomething()
doSomethingElse() <-- Three hours into processing
doMore()
cleanup()
end

Patrick Li wrote:

Hi,
Does anyone have any clever ideas on saving the state of a Thread?
I have a thread that runs for a couple of hours, and I need to save the
progress to disk, so that I can restart from where I left off.

Any ideas would be welcome.
-Patrick

Maybe you should think in terms of saving the state of the objects in a
thread, instead. Thought of that way, it becomes pretty easy – you
could use
yaml, for example.

Or have I got the wrong end of the stick?

Thanks for the replies.

Alright so I have some thoughts now:

def start
status = 0
doSomething()
status = 1
doSomethingElse()
status = 2
doMore()
status = 3
cleanup()
end

So if I know the status of a thread, (ie. status = 2), and I know the
values of the local variables.
Is there way I can “jump” to that line in the method?

Amalgalite: I’m not sure if I got your point. It seems to be a SQLite
library for Ruby?

@shadowfirebird: Yes, that’s the most straightforward way of doing it.
But I’m trying to write a framework that will relieve programmers of
having to save state information manually.

ie. I’m trying to convert this:

stateVar = 124
def update
if(stateVar == 0) then doStuff(); stateVar = 1
if(stateVar == 1) then doMoreStuff(); stateVar = 2
if(stateVar == 2) then cleanup(); stateVar = 3
end

Into This:

start
doStuff()
doMoreStuff()
doEvenMore()
cleanup()
endProgram()

On 22.08.2008 18:11, Patrick Li wrote:

So if I know the status of a thread, (ie. status = 2), and I know the
values of the local variables.
Is there way I can “jump” to that line in the method?

I would not speak of the status of a thread. Instead I would model this
as status of calculation using command pattern with multiple operation
classes. Rough idea: break down the computation into multiple stages.
Each stage is handled by an instance of a single class. Every stage
knows its successor stages. When a stage is completed a central
coordinator saves the next state processor (or just the class) along
with its input via Marshalling into a file. Something along the lines
of

#!/bin/env ruby

require ‘fileutils’

class Coordinator
def initialize state_file, processor = nil
@state_file = state_file

 if File.readable? state_file
   @current_processor = load
 else
   @current_processor = processor
   save processor
 end

end

def run
loop do
next_stage = @current_processor.call

   if next_stage
     save next_stage
     @current_processor = next_stage
   else
     # done, return last processor with result
     clear
     return @current_processor
   end
 end

end

private
def save st
printf “saving %p\n”, st
File.open(@state_file + “.tmp”, “wb”) {|io| Marshal.dump(st,io)}
FileUtils.mv @state_file + “.tmp”, @state_file
end

def load
File.open(@state_file, “rb”) {|io| Marshal.load(io)}
end

def clear
FileUtils.rm_f @state_file
end
end

simple exsample

Processor = Struct.new :start, :last, :sum do
def call
limit = [start + 100, last].min
self.sum ||= 0

 for i in start .. limit
   self.sum += i
 end

 return nil if limit == last

 res = self.class.new
 res.sum = self.sum
 res.start = limit
 res.last = self.last
 res

end
end

run

pr = Processor.new 1, 1_000_000, 0
c = Coordinator.new “x.bin”, pr
puts c.run.sum

Of course I could have created two processor types, one for the initial
phase (i.e. where start + 10 < end) and one for the last chunk - but I
was lazy. At least the program works - you can break it at any step and
it will resume processing.

Kind regards

robert

Don’t forget the state of a thread may also include the set of open
file handles. What you are trying to do is called ‘checkpointing’.
See e.g. http://en.wikipedia.org/wiki/Application_checkpointing

in the general case, this is hard, though there are some packages
that support this at the application level.

A specific, application aware scheme can be simpler, because you
presumably know what state must be saved while the general case has to
assume that all things that make up state must be saved.

Ron.

Thanks Robert for the input.

Yes I agree. That’s a very clean and flexible approach. My code is
currently structured using state machines, which is similar in concept
to your operation stages.

This sort of programming is actually one of my primary motivators for
thinking about a thread-based paradigm instead.

Here’s my original idea, in it’s original un-condensed and unabbreviated
mental form. Maybe you have some ingenious ideas:

Currently, a real-time simulation loop looks something like this:

while true
scenario.update (secondsSinceLastIteration)
scenario.draw
end

And your scenario code would like something like this (ie. for a
traveling ball):

def update (timePassed)
@position += timePassed*velocity
end

You would agree that this is all very straightforward. But what if you
want the ball to travel back and forth 3 times? You’d have to do
something like this:

def update (timePassed)
if @numberOfBackAndForths == 3
return

if @travelingForward
@position += timePassedvelocity
@travelingForward = false if (reached end)
else
@position -= timePassed
velocity
if reached-end
@travelingForward = false
@numberOfBackAndForths += 1
end
end
end

So can see that @travelingForward essentially describes the state of the
system. This sort of manual state bookkeeping can get really out-of-hand
pretty quickly.

BASIC IDEA: Wouldn’t it be nice to be able to write something like this?

def start
3.times do
#TRAVEL FORWARD
update(5 seconds) do |timePassed|
@position += timePassed*velocity
end

#TRAVEL BACKWARD
update(5 seconds) do |timePassed|
  @position -= timePassed*velocity
end

end
end

Ahh… so much cleaner isn’t it? This is a shift to a thread-based
paradigm.

So far, I have everything working, EXCEPT when the simulation needs to
be saved to disk.

I can save @position, and I can save how many iterations are left. But
after I resume the simulation, how do I get the thread to start from the
appropriate line of code? I never thought I’d ask for it, but a goto
statement sounds like a blessing right now.

Thanks for all your replies.
-Patrick

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs