thread safe?

T

tony summerfelt

i see that a number of modules are declared 'thread safe?'

what does this mean as it applies to ruby?
 
E

Eric Hodel

--bgLLobvf7eP6VP5c
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
i see that a number of modules are declared 'thread safe?'
=20
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.

--=20
Eric Hodel - (e-mail address removed) - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04


--bgLLobvf7eP6VP5c
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (FreeBSD)

iD8DBQFA/UZlMypVHHlsnwQRAtb9AKCKLFdIKoIfJabeCcI6LlvDewdQ9QCeOQWm
8ZUAdm4TFitYqoZzPlEUR/g=
=U1eb
-----END PGP SIGNATURE-----

--bgLLobvf7eP6VP5c--
 
A

Adam Wildavsky

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.
 
M

Michael Neumann

Adam said:
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
end

class Child < Parent
def to_s
# I want to call Object.to_s here ...
object__to_s

end
end

I can't figure out the right syntax. Any hints? For what it's worth I'm
using Ruby 1.8.1.

Regards,

Michael
 
T

tony summerfelt

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...
 
P

Pit Capitain

Adam said:
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 ...

Object.instance_method( :to_s ).bind( self ).call
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.

Regards,
Pit
 
F

Florian Gross

Pit said:
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
 
R

Robert Klemme

tony summerfelt said:
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'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
 
E

Eric Hodel

--Wfe1KbQWcwuymTys
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
On Wed, 21 Jul 2004 01:20:56 +0900, you wrote:
=20
=20
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.
=20
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
=20
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..
=20
just wanted to make sure i was on the right track...

Yep! =20

--=20
Eric Hodel - (e-mail address removed) - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04


--Wfe1KbQWcwuymTys
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (FreeBSD)

iD8DBQFA/X/6MypVHHlsnwQRAnUgAKDVRa9dCqaiKhUfjzwi9MR/6A3n+ACfS3P0
0tE17IJCc8zXB7vgF4JVV6A=
=MTtt
-----END PGP SIGNATURE-----

--Wfe1KbQWcwuymTys--
 
F

Florian Gross

Hunter said:
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
 
T

tony summerfelt

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
 
T

tony summerfelt

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
 
E

Edgardo Hames

do i assume that a mutex will handle that? in my testing it seems to
work ok (ie. i get what i expect)

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
http://www-sop.inria.fr/lemme/verificard/2002/slides/prensa.pdf

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,431
Messages
2,571,679
Members
48,796
Latest member
Greg L.

Latest Threads

Top