i see that a number of modules are declared 'thread safe?'
what does this mean as it applies to ruby?
i see that a number of modules are declared 'thread safe?'
what does this mean as it applies to ruby?
The methods inside them can be called concurrently from multiple
threads.
Note that this is not the same as reentrant, where the same method can
be safely executing simultaneously in two threads.
Thread safety can be implemented easily by adding the appropriate
mutexes. Making a module reentrant requires more care.
tony summerfelt (snowzone5@hotmail.com) wrote:
i see that a number of modules are declared 'thread safe?'
what does this mean as it applies to ruby?
--
Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04
I'd like to call a particular inherited method rather than the one in my immediate ancestor. For instance
class Parent
def to_s
super.to_s + " Parent-specific stuff here."
end
end
class Child < Parent
def to_s
# I want to call Object.to_s here ...
end
end
I can't figure out the right syntax. Any hints? For what it's worth I'm using Ruby 1.8.1.
Normally I wouldn't want to skip an ancestor method for fear of violating the Liskov Substitution Principle. For to_s, though, it seems reasonable enough to me.
--
Adam Wildavsky Extreme Programmer Tameware, LLC
adam@tameware.com http://www.tameware.com
Adam Wildavsky wrote:
I'd like to call a particular inherited method rather than the one in my immediate ancestor. For instance
class Parent
alias object__to_s to_s
def to_s
super.to_s + " Parent-specific stuff here."
end
endclass Child < Parent
def to_s
# I want to call Object.to_s here ...
object__to_s
end
endI can't figure out the right syntax. Any hints? For what it's worth I'm using Ruby 1.8.1.
Regards,
Michael
The methods inside them can be called concurrently from multiple
threads.
Note that this is not the same as reentrant, where the same method can
be safely executing simultaneously in two threads.
when i first read this i thought ok, that answers my question...but
after over thinking it, i'm not sure i see the difference.
i would think the same method running in two different threads is
either safely executing or it isn't.
Thread safety can be implemented easily by adding the appropriate
mutexes. Making a module reentrant requires more care.
i've gone to considerably length to make sure methods in my module are
thread safe as they access the same resource. i've leaned on them
pretty heavily, with threaded code and the resource never gets
corrupted..
just wanted to make sure i was on the right track...
On Wed, 21 Jul 2004 01:20:56 +0900, you wrote:
Adam Wildavsky schrieb:
I'd like to call a particular inherited method rather than the one in my immediate ancestor. For instance
class Parent
def to_s
super.to_s + " Parent-specific stuff here."
end
endclass Child < Parent
def to_s
# I want to call Object.to_s here ...
Object.instance_method( :to_s ).bind( self ).call
end
endI can't figure out the right syntax. Any hints? For what it's worth I'm using Ruby 1.8.1.
Normally I wouldn't want to skip an ancestor method for fear of violating the Liskov Substitution Principle. For to_s, though, it seems reasonable enough to me.
Regards,
Pit
Pit Capitain wrote:
Adam Wildavsky schrieb:
I'd like to call a particular inherited method rather than the one in my immediate ancestor. For instance
Object.instance_method( :to_s ).bind( self ).call
For the fun of it I've taken this to the extreme and called it superjump: (It 'jumps' over one or more method in the inheritance chain)
# Like super this calls methods from the inheritance chain which this
# method is replacing. However this version jumps over one or more
# methods in the inheritance chain. It is used like this:
#
# class X
# def it; p "X#it"; end
# end
#
# class Y < X
# def it; p "Y#it"; end
# end
#
# class Z < Y
# def it
# p "Z#it"
# superjump
# end
# end
#
# Z.new.it # outputs "X#it", "Z#it"
#
# Be careful. This method can't automatically pass the arguments of the
# caller like super does. You'll have to manually supply them.
def superjump(gap, *args)
method_name = caller[0][/in `(.*?)'/, 1].intern
klass = self.class.ancestors[1 + gap]
klass.instance_method(method_name).bind(self).call(*args)
end
Regards,
Florian Gross
"tony summerfelt" <snowzone5@hotmail.com> schrieb im Newsbeitrag
news:cajqf0trmr26t845682he50t20gep9dhlu@4ax.com...
>The methods inside them can be called concurrently from multiple
>threads.>Note that this is not the same as reentrant, where the same method can
>be safely executing simultaneously in two threads.when i first read this i thought ok, that answers my question...but
after over thinking it, i'm not sure i see the difference.i would think the same method running in two different threads is
either safely executing or it isn't.>Thread safety can be implemented easily by adding the appropriate
>mutexes. Making a module reentrant requires more care.i've gone to considerably length to make sure methods in my module are
thread safe as they access the same resource.i've leaned on them
pretty heavily, with threaded code and the resource never gets
corrupted..
That's not a proof - at best it's an indication. ![]()
just wanted to make sure i was on the right track...
There are several ways to achieve thread safety. Making methods reentrant
is one of them. Consider
class Foo
def bar(x,y)
# this method is thread safe because it does
# not access any instance state
( x + y ) * 2
end
end
You can invoke this method arbitrarily often from multiple threads.
Synchronizing with mutexes is another way to make method thread safe.
Thread confinement is another: you make sure that an instance is just
accessible from a single thread, like in:
10.times do |i|
Thread.new(i) do |limit|
storage =
# accesses to storage need not be synchronized because
# there is one per thread and the reference is not leaked
# to other threads
limit.times { storage << "x" }
puts storage.join
end
end
You can as well consider not to put synchronization / mutexes in a class at
all but instead rely on external synchronization. In some cases this is
even necessary:
storage = {}
lock = Mutex.new
10.times do |i|
Thread.new( "Thread-#{i}" ) do |name|
key = rand 10
lock.synchronize do
if not storage.has_key? key
storage[key] =
end
storage[key] << name
end
sleep( rand(5) )
end
end
This is typically the case if you have to do multiple accesses to a resource
that depend on each other. In this case the hash insertion depends on the
check for key presence.
Regards
robert
On Wed, 21 Jul 2004 01:20:56 +0900, you wrote:
>The methods inside them can be called concurrently from multiple
>threads.>Note that this is not the same as reentrant, where the same method can
>be safely executing simultaneously in two threads.when i first read this i thought ok, that answers my question...but
after over thinking it, i'm not sure i see the difference.i would think the same method running in two different threads is
either safely executing or it isn't.
I didn't explain it very well, and my definition may be a little off
(its rather subtle, but there). When you have a thread-safe method, it
can be called multiple times concurrently, but you may have only one
thread executing in the method, while the others are blocked waiting.
(Of course, you may have more than one critical section, or a critical
section only around a small part of the method. Only one thread can be
executing inside a critical section.)
When you have a reentrant method, there are no critical sections, so N
threads can safely execute in the method at the same time.
In case that's not clear, here's an even better description:
http://weblogs.asp.net/oldnewthing/archive/2004/06/29/168719.aspx
>Thread safety can be implemented easily by adding the appropriate
>mutexes. Making a module reentrant requires more care.i've gone to considerably length to make sure methods in my module are
thread safe as they access the same resource. i've leaned on them
pretty heavily, with threaded code and the resource never gets
corrupted..just wanted to make sure i was on the right track...
Yep!
tony summerfelt (snowzone5@hotmail.com) wrote:
On Wed, 21 Jul 2004 01:20:56 +0900, you wrote:
--
Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04
Adam Wildavsky schrieb:
I'd like to call a particular inherited method rather than the one in my immediate ancestor.
...
Object.instance_method( :to_s ).bind( self ).call
That did the trick -- thanks!
Thanks also to everyone else who replied.
At 2:26 AM +0900 7/21/04, Pit Capitain wrote:
--
Adam Wildavsky Extreme Programmer Tameware, LLC
adam@tameware.com http://www.tameware.com
Should this take a block, for completeness?
H
Florian Gross <flgr@ccan.de> wrote in message news:<2m576aFj3oedU1@uni-berlin.de>...
For the fun of it I've taken this to the extreme and called it
superjump: (It 'jumps' over one or more method in the inheritance chain)# Like super this calls methods from the inheritance chain which this
# method is replacing. However this version jumps over one or more
# methods in the inheritance chain. It is used like this:
#
# class X
# def it; p "X#it"; end
# end
#
# class Y < X
# def it; p "Y#it"; end
# end
#
# class Z < Y
# def it
# p "Z#it"
# superjump
# end
# end
#
# Z.new.it # outputs "X#it", "Z#it"
#
# Be careful. This method can't automatically pass the arguments of the
# caller like super does. You'll have to manually supply them.
def superjump(gap, *args)
method_name = caller[0][/in `(.*?)'/, 1].intern
klass = self.class.ancestors[1 + gap]
klass.instance_method(method_name).bind(self).call(*args)
endRegards,
Florian Gross
Should this take a block, for completeness?
H
Florian Gross <flgr@ccan.de> wrote in message news:<2m576aFj3oedU1@uni-berlin.de>...
For the fun of it I've taken this to the extreme and called it
superjump: (It 'jumps' over one or more method in the inheritance chain)# Like super this calls methods from the inheritance chain which this
# method is replacing. However this version jumps over one or more
# methods in the inheritance chain. It is used like this:
#
# class X
# def it; p "X#it"; end
# end
#
# class Y < X
# def it; p "Y#it"; end
# end
#
# class Z < Y
# def it
# p "Z#it"
# superjump
# end
# end
#
# Z.new.it # outputs "X#it", "Z#it"
#
# Be careful. This method can't automatically pass the arguments of the
# caller like super does. You'll have to manually supply them.
def superjump(gap, *args)
method_name = caller[0][/in `(.*?)'/, 1].intern
klass = self.class.ancestors[1 + gap]
klass.instance_method(method_name).bind(self).call(*args)
endRegards,
Florian Gross
pretty heavily, with threaded code and the resource never gets
corrupted..
That's not a proof - at best it's an indication.
well if it gets corrupted, there will e be a problem with the mutex
synchronization method. the resource is only accessed in a synchronize
block...
Synchronizing with mutexes is another way to make method thread safe.
that's what i'm doing. it seems to be working well, no matter what i
throw at it...
of course, when i eventually release it and if it gets wider spread
use, that will be the real test.
http://home.cogeco.ca/~tsummerfelt1
On Wed, 21 Jul 2004 05:17:05 +0900, you wrote:
When you have a thread-safe method, it
can be called multiple times concurrently, but you may have only one
thread executing in the method, while the others are blocked waiting.
with what i have now, the method can be called multiple times in
different threads, and the resource is under control of a a mutex. all
the threads get access to the resource with the expected results.
section only around a small part of the method. Only one thread can be
executing inside a critical section.)
do i assume that a mutex will handle that? in my testing it seems to
work ok (ie. i get what i expect)
http://home.cogeco.ca/~tsummerfelt1
On Wed, 21 Jul 2004 05:26:36 +0900, you wrote:
Hunter Kelly wrote:
Should this take a block, for completeness?
Good idea. I've changed it:
# Like super this calls methods from the inheritance chain which this
# method is replacing. However this version jumps over one or more
# methods in the inheritance chain. It is used like this:
#
# class X
# def it; p "X#it"; end
# end
#
# class Y < X
# def it; p "Y#it"; end
# end
#
# class Z < Y
# def it
# p "Z#it"
# superjump
# end
# end
#
# Z.new.it # outputs "X#it", "Z#it"
#
# Be careful. This method can't automatically pass the arguments of the
# caller like super does. You'll have to manually supply them.
def superjump(gap, *args, &block)
method_name = caller[0][/in `(.*?)'/, 1].intern
klass = self.class.ancestors[1 + gap]
klass.instance_method(method_name).bind(self).call(*args, &block)
end
Regards,
Florian Gross
You should. That's what a mutex is for. I believe Robert meant that no
matter how many threads access your code if it doesn't get corrupted,
that doesn't prove it won't fail. In order to assert that you need
some sort of math proof.
Check out this presentation
For a formal treatment on the subject, take a look at "On a Method of
Multi-Programming" by W.H.J. Feijen, A.J.M. van Gasteren [Springer,
1999.]
Regards.
Ed
On Thu, 22 Jul 2004 03:09:08 +0900, tony summerfelt <snowzone5@hotmail.com> wrote:
>section only around a small part of the method. Only one thread can be
>executing inside a critical section.)do i assume that a mutex will handle that? in my testing it seems to
work ok (ie. i get what i expect)