Advertisement
LiTTleDRAgo

[RGSS/2] Drago - Replicated Fiber

Oct 3rd, 2013
168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 6.16 KB | None | 0 0
  1. #==============================================================================
  2. # ** Drago - Replicated Fiber
  3. # Version : 1.01
  4. # Author : LiTTleDRAgo
  5. #==============================================================================
  6.  
  7. ($imported ||= {})[:drg_replicated_fiber] = 1.01
  8. #==============================================================================
  9. # ** Fiber
  10. #------------------------------------------------------------------------------
  11. #  
  12. #==============================================================================
  13. unless defined?(Fiber)
  14.   class Fiber
  15.     #-------------------------------------------------------------------------
  16.     # * New method: initialize
  17.     #-------------------------------------------------------------------------
  18.     def initialize
  19.       block_given? || raise(ArgumentError,'new Fiber requires a block')
  20.       @yield  = Queue.new
  21.       @resume = Queue.new
  22.       @thread = Thread.new { @yield.push [yield(*@resume.pop)] }
  23.       @thread.abort_on_exception = true
  24.       @thread[:fiber] = self
  25.     end
  26.     #-------------------------------------------------------------------------
  27.     # * New method: self.current
  28.     #-------------------------------------------------------------------------
  29.     def self.current
  30.       Thread.current[:fiber] || raise(FiberError,'not inside a fiber',caller(1))
  31.     end
  32.     #-------------------------------------------------------------------------
  33.     # * New method: self.yield
  34.     #-------------------------------------------------------------------------
  35.     def self.yield(*args)
  36.       (fiber = Thread.current[:fiber]) || (raise "can't yield from root fiber")
  37.       fiber.yield(*args)
  38.     end
  39.     #-------------------------------------------------------------------------
  40.     # * New method: inspect
  41.     #-------------------------------------------------------------------------
  42.     def inspect
  43.       "#<#{self.class}:0x#{self.object_id.to_s(16)}>"
  44.     end
  45.     #-------------------------------------------------------------------------
  46.     # * New method: resume
  47.     #-------------------------------------------------------------------------
  48.     def resume(*args)
  49.       alive? || raise(FiberError,'dead fiber called',caller(1))
  50.       @resume.push(args)
  51.       result = @yield.pop
  52.       result.size > 1 ? result : result.first
  53.     end
  54.     #-------------------------------------------------------------------------
  55.     # * New method: alive?
  56.     #-------------------------------------------------------------------------
  57.     def alive?
  58.       @thread.alive?
  59.     end
  60.     #-------------------------------------------------------------------------
  61.     # * New method: yield
  62.     #-------------------------------------------------------------------------
  63.     def yield(*args)
  64.       @yield.push(args)
  65.       result = @resume.pop
  66.       result.size > 1 ? result : result.first
  67.     end
  68.   end
  69. end
  70.  
  71. #==============================================================================
  72. # ** Queue
  73. #------------------------------------------------------------------------------
  74. #  
  75. #==============================================================================
  76. unless defined?(Queue)
  77.   class Queue
  78.     #-------------------------------------------------------------------------
  79.     # * New method: initialize
  80.     #-------------------------------------------------------------------------
  81.     def initialize
  82.       (@que     ||= []).taint
  83.       (@waiting ||= []).taint # enable tainted comunication
  84.       self.taint
  85.     end
  86.     #-------------------------------------------------------------------------
  87.     # * New method: clear
  88.     #-------------------------------------------------------------------------
  89.     def clear
  90.       @que.clear
  91.     end
  92.     #-------------------------------------------------------------------------
  93.     # * New method: empty?
  94.     #-------------------------------------------------------------------------
  95.     def empty?
  96.       @que.empty?
  97.     end
  98.     #-------------------------------------------------------------------------
  99.     # * New method: length
  100.     #-------------------------------------------------------------------------
  101.     def length
  102.       @que.length
  103.     end
  104.     #-------------------------------------------------------------------------
  105.     # * New method: num_waiting
  106.     #-------------------------------------------------------------------------
  107.     def num_waiting
  108.       @waiting.size
  109.     end
  110.     #-------------------------------------------------------------------------
  111.     # * New method: pop
  112.     #-------------------------------------------------------------------------
  113.     def pop(non_block=false)
  114.       while (Thread.critical = true; @que.empty?)
  115.         non_block && raise(ThreadError,"queue empty",caller(1))
  116.         @waiting.push(Thread.current)
  117.         Thread.stop
  118.       end
  119.       @que.shift
  120.     ensure
  121.       Thread.critical = false
  122.     end
  123.     #-------------------------------------------------------------------------
  124.     # * New method: push
  125.     #-------------------------------------------------------------------------
  126.     def push(obj)
  127.       Thread.critical = true
  128.       @que.push obj
  129.       begin
  130.         t = @waiting.shift
  131.         t && t.wakeup
  132.       rescue ThreadError
  133.         retry
  134.       ensure
  135.         Thread.critical = false
  136.       end
  137.       begin
  138.         t && t.run
  139.       rescue ThreadError
  140.       end
  141.     end
  142.     #-------------------------------------------------------------------------
  143.     # * Alias Listing
  144.     #-------------------------------------------------------------------------
  145.     method_defined?(:size)  || (alias_method :size,  :length)
  146.     method_defined?(:shift) || (alias_method :shift, :pop)
  147.     method_defined?(:deq)   || (alias_method :deq,   :pop)
  148.     method_defined?(:"<<")  || (alias_method :"<<",  :push)
  149.     method_defined?(:enq)   || (alias_method :enq,   :push)
  150.   end
  151. end
  152.  
  153. #==============================================================================
  154. # ** FiberError
  155. #------------------------------------------------------------------------------
  156. #  
  157. #==============================================================================
  158. defined?(FiberError) || (class FiberError < StandardError ; end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement