Threadsafing a mixin module without using self.new or initialize

Threadsafing a mixin module without using self.new or initialize.

Project: Eventable - https://github.com/mikbe/eventable

Background: https://github.com/mikbe/eventable/issues/4

Problem Description:
I need to threadsafe access to an instance variable, an array. To do so
I’ve
wrapped all methods that access the array in a mutex.synchronize block.
The
problem is I’m creating the mutex in each function using
@eventable_mutex
||= Mutex.new which could cause collisions if two threads try to use a
method that creates the mutex simultaneously.

I’ve verified this could happen: https://gist.github.com/1031308

Since this is a mixin module I can’t use initialize to create the mutex
instance variable and I don’t want to use trapself.new because if the
class
uses this method itself then the instance variable will never be
created. My
aversion to using self.new to create the instance variable is this: if I
redefine a method to fix an issue it’s not unreasonable for someone else
to
do the same thing. If their doing exactly what I did breaks what I did
then
it’s a bad fix. (see https://github.com/mikbe/eventable/pull/3)

So, my current idea for a solution is to create a class level mutex for
the
inheriting class that locks on the creation of the mutex, for instance:
https://gist.github.com/1031419. This seems ugly though and I’m fairly
new
to Ruby so I’m wondering if I’ve missed, or simply don’t know about,
something that would be a better solution.

On 17.06.2011 22:46, Mike B. wrote:

||= Mutex.new which could cause collisions if two threads try to use a
method that creates the mutex simultaneously.

You do not want to be creating the mutex from different threads -
because then mutex creation itself is not thread safe.

I’ve verified this could happen: https://gist.github.com/1031308

Since this is a mixin module I can’t use initialize to create the mutex
instance variable

Why not?

module Anything
def initialize(*a,&b)
super
@lock = Mutex.new
@data = []
end
end

class Other
include Anything

def initialize
super # important!
@another_var = 15
end
end

to Ruby so I’m wondering if I’ve missed, or simply don’t know about,
something that would be a better solution.

That approach does not scale well if you have lots of instances created
concurrently. If anything fails you can add a method which creates the
mutex and which is called before the instance is used by multiple
threads - as simple as that. But I’d prefer the approach with
#initialize.

Kind regards

robert

On Fri, Jun 17, 2011 at 5:45 PM, Robert K.
[email protected]wrote:

@data = []
end

[smacks forehead] Doh! I’m still learning Ruby, didn’t even think about
that. I like the initialize method MUCH better. If they forget to
include
the super it’ll raise an exception when they go to use it so I just need
to
make sure I document and emphasize that fact really well.

That approach does not scale well if you have lots of instances created
concurrently. If anything fails you can add a method which creates the
mutex and which is called before the instance is used by multiple threads -
as simple as that. But I’d prefer the approach with #initialize.

Yeah, I thought about that and it was why I didn’t really like my
solution.
Limiting creation at the class level could be a major bottleneck. Plus
it
just felt hackey; but not in a good way.

Kind regards

   robert


remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.**com/ http://blog.rubybestpractices.com/

Thanks for the help!

Mike B. wrote in post #1006016:

On Fri, Jun 17, 2011 at 5:45 PM, Robert K.
[email protected]wrote:

@data = []
end

[smacks forehead] Doh! I’m still learning Ruby, didn’t even think about
that. I like the initialize method MUCH better. If they forget to
include
the super it’ll raise an exception when they go to use it so I just need
to
make sure I document and emphasize that fact really well.

Why would you want to bother with having to do that?

So, my current idea for a solution is to create a class level
mutex for the inheriting class that locks on the creation of the mutex,
for instance: https://gist.github.com/1031419. This seems ugly …

I guess beauty is in the eye of the beholder. I think that solution is
much more elegant: the user just has to include the module and
everything gets set up for them.

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