[ragel-users] Ragel Ruby generated code uses singleton class so it's not thread safe

Iñaki Baz Castillo ibc at aliax.net
Wed Feb 4 14:49:03 UTC 2009


Hi, i'm using Ragel parser generating Ruby code. The generated code
uses a Class instead of an instance, and that class has lots of
attributes and methods. Something like:

--------------
class MyParser

   class << self
       attr_accessor :_machine_trans_keys
       private :_machine_trans_keys, :_machine_trans_keys=
   end

 self._machine_trans_keys = [
       0, 0, 9, 34, 10, 10,
       9, 32, 9, 34, -64,
       126, -128, -65, -128, -65,
       -128, -65, -128, -65, -128, -65,
       10, 10, 9, 32, 13,
       13, 10, 10, 0, 127,
       0, 0, 0
   ]

 ...
 ...

 def self.run_machine(data)
     ...
 end

end
-------------


So I wonder how could I use this class into a threaded program. A Ruby
singleton class is the Class itself, so if a running thread modifies
some Class attribute then all the other threads will see that change (error!!!).

As an ilustration, please run the following Ruby code:

-----------------------
#!/usr/bin/env ruby

class Test

	class << self
		attr_accessor :my_string
	end

	self.my_string = "initial value"

end

t1 = Thread.new(Test) do |test|
	puts "--- I'm thread 1:"
	puts "---   Writting: my_string = 'new value'"
	test.my_string = "new value"
	puts "---   Reading:  my_string = #{test.my_string}"
end

sleep 0.5

t2 = Thread.new(Test) do |test|
	puts "--- I'm thread 2:"
	puts "---   Reading:  my_string = #{test.my_string}"
end

t1.join
t2.join
-----------------------


This will generate the following output:
--------------------
--- I'm thread 1:
---   Writting: my_string = 'new value'
---   Reading:  my_string = new value
--- I'm thread 2:
---   Reading:  my_string = new value
-------------------

As you can see, when thread2 gets the value of "my_string" it is "new
value", the value set previously by thread1.
AFAIK there is no way to avoid this problem since "Test" is a class,
not an instance (we are using the Singleton mode).


Now imagine that instead of Test we use MyParser with Ragel code
generated (Singleton class again). We would have the same problem.


Why does the Ruby generated code make use of Singleton class instead
of creating instance methods and attributes?
Thanks a lot.

-- 
Iñaki Baz Castillo
<ibc at aliax.net>




More information about the ragel-users mailing list