前田です。

keiju / bc.mbn.or.jp (石塚圭樹 ) wrote:

|前田さんがいなくて淋しかったです(^^;;;

どうもです:-)

|># Synchronizer呼んでるだけですし(^^;
|
|でも, 面白いですね.
|
|SynchronizableはSynchronizerを利用して(デレゲートタイプの利用ですね)実
|現しているのに対して, 逆に, SyncはSync_mをインクルードして実現していま
|す. 結局同じことを実現するのに反対のやりかたをしています.

まさかSyncがこうなるとは思っていなかったもので(^^;

extend_objectをオーバーライドして初期化処理をしてるんですね。
このワザいただきます:-)
でもincludeした時はやはりinitializeでsyns_extendedしないといけないのか...。
これはincludeをClassで再定義しちゃうしかないのかな。

class Class
   def include(*modules)
      result = super
      modules.each do |mixin|
	 if mixin.respond_to? :__extend_class
	    mixin.__extend_class(self)
	 end
      end
      result
   end
end

module Sync_m
   def Sync_m.__extend_class(klass)
      klass.eval %q{
	 def klass.new(*args)
	    obj = super
	    begin
	       eval "class << obj; @sync_locked; end"
	       obj.extend(For_primitive_object)
	    rescue TypeError
	       obj.extend(For_general_object)
	    end
	    obj
	 end
      }
   end

   module For_primitive_object
      def For_primitive_object.__extend_class(klass)
	 klass.eval %q{
	    def klass.new(*args)
	       obj = super
	       obj.sync_extended
	       Finalizer.add(obj, For_primitive_object, :sync_finalize)
	       obj
	    end
	 }
      end
   end
   
   module For_general_object
      def For_general_object.__extend_class(klass)
	 klass.eval %q{
	    def klass.new(*args)
	       obj = super
	       obj.sync_extended
	       obj
	    end
	 }
      end
   end
end

newを再定義するとまずそうな気がしたのですが、

class Spokesperson < String
   include Sync_m::For_primitive_object
   
   def msg=(msg)
      self[0..-1] = msg
   end
   
   def say
      print self, "\n"
   end
end

p tom = Spokesperson.new("This is message.")
t = Thread.new {
   3.times {
      tom.synchronize {
	 p tom.msg = "This is thread1."
	 sleep(0.3)
	 tom.say
      }
   }
}
3.times {
   tom.synchronize {
      p tom.msg = "This is thread2."
      sleep(0.3)
      tom.say
   }
}
Thread.join t

なんてのも動いてしまいました。
newの引数が違うとちゃんとArgumentErrorになりますね。

-- 
前田 修吾