Re: Associating data with a function

From: Joel VanderWerf [mailto:[email protected]]

Joel VanderWerf wrote:

Use closures and class scopes:

class Foo
tmp1 = ExpensiveObject.new
tmp2 = ExpensiveObject.new

Assuming you want to share the tmp1 and tmp2 among all instances of the
class, which probably you don’t want. Sorry.

No, I very much do - each object is only needed as a ‘scratch’ pad for
performing calculations within the method; before and after the method I
don’t care about the value. Your idea has interesting merit. I hadn’t
thought of closing and re-opening the class to ‘reset’ the closure
scope. Or (for that matter) of using define_method to create a method as
a closure as both you and David suggested.

Thanks, interesting ideas!

Gavin K. wrote:

No, I very much do - each object is only needed as a ‘scratch’ pad for performing calculations within the method; before and after the method I don’t care about the value. Your idea has interesting merit. I hadn’t thought of closing and re-opening the class to ‘reset’ the closure scope. Or (for that matter) of using define_method to create a method as a closure as both you and David suggested.
Watch out for threads, then. If your program can have multiple threads
running these calculations, a mutex will keep them from fighting over
the expensive objects.

On 10/5/06, Joel VanderWerf [email protected] wrote:

Watch out for threads, then. If your program can have multiple threads
running these calculations, a mutex will keep them from fighting over
the expensive objects.

This got me thinking about the idea of thread local instance variables.

Thread#[] and Thread#[]= give you ‘global’ thread locals, here’s an
UNTESTED ‘SKETCH’ of a class which would let you do something like:

class Foo

def meth1
@tliv1 = ThreadLocalInstanceVariable.new
{ExpensiveVariable1.new}
@tiiv2 = ThreadLocalInstanceVariable.new
{ExpensiveVariable2.new}
… do something with those expensive variables
end

end

rick@frodo:/public/rubyscripts$ cat thread_local.rb
require ‘delegator’
class ThreadLocalInstanceVariable < Delegator

def initialize(&init_block)
super
@init_block = init_block
end

def get_obj
# thread local instance variable proxies are kept in a hash
# which is itself a thread local variable
iv_hash = Thread.current[:tl_iv_hash] || = Hash.new
local_iv = iv_hash[self.object_id]
unless local_iv
# store using object_id to avoid direct reference
my_id = self.object_id
# clean out when local iv gets GC’d, e.g. when the instance
holding
# it dies
ObjectSpace.define_finalizer(self, lambda {iv_hash.delete(my_id)})
local_iv = iv_hash[self.object_id] = init_block.call
end
local_iv
end

end


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/