mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	 b4489ae953
			
		
	
	
		b4489ae953
		
	
	
	
	
		
			
			https://github.com/ruby/ruby/pull/364 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42086 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			214 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			214 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| #!/usr/local/bin/ruby
 | |
| # TupleSpace
 | |
| # Copyright (c) 1999-2000 Masatoshi SEKI
 | |
| # You can redistribute it and/or modify it under the same terms as Ruby.
 | |
| 
 | |
| require 'thread'
 | |
| 
 | |
| class TupleSpace
 | |
|   class Template
 | |
|     def initialize(list)
 | |
|       @list = list
 | |
|       @check_idx = []
 | |
|       @list.each_with_index do |x, i|
 | |
|         @check_idx.push i if x
 | |
|       end
 | |
|       @size = @list.size
 | |
|     end
 | |
| 
 | |
|     attr :size
 | |
|     alias length size
 | |
| 
 | |
|     def match(tuple)
 | |
|       return nil if tuple.size != self.size
 | |
|       @check_idx.each do |i|
 | |
|         unless @list[i] === tuple[i]
 | |
|           return false
 | |
|         end
 | |
|       end
 | |
|       return true
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def initialize
 | |
|     @que = {}
 | |
|     @waiting = {}
 | |
|     @que.taint		# enable tainted comunication
 | |
|     @waiting.taint
 | |
|     self.taint
 | |
|   end
 | |
| 
 | |
|   def wakeup_waiting(tuple)
 | |
|     sz = tuple.length
 | |
|     return nil unless @waiting[sz]
 | |
| 
 | |
|     x = nil
 | |
|     i = -1
 | |
|     found = false
 | |
|     @waiting[sz] = @waiting[sz].find_all { |x|
 | |
|       if x[0].match(tuple)
 | |
|         begin
 | |
|           x[1].wakeup
 | |
|         rescue ThreadError
 | |
|         end
 | |
|         false
 | |
|       else
 | |
|         true
 | |
|       end
 | |
|     }
 | |
|   end
 | |
| 
 | |
|   def put_waiting(template, thread)
 | |
|     sz = template.length
 | |
|     @waiting[sz] = [] unless @waiting[sz]
 | |
|     @waiting[sz].push([Template.new(template), thread])
 | |
|   end
 | |
|   private :wakeup_waiting
 | |
|   private :put_waiting
 | |
| 
 | |
|   def get_que(template)
 | |
|     sz = template.length
 | |
|     return nil unless @que[sz]
 | |
| 
 | |
|     template = Template.new(template)
 | |
| 
 | |
|     x = nil
 | |
|     i = -1
 | |
|     found = false
 | |
|     @que[sz].each_with_index do |x, i|
 | |
|       if template.match(x)
 | |
|         found = true
 | |
|         break
 | |
|       end
 | |
|     end
 | |
|     return nil unless found
 | |
| 
 | |
|     @que[sz].delete_at(i)
 | |
| 
 | |
|     return x
 | |
|   end
 | |
| 
 | |
|   def put_que(tuple)
 | |
|     sz = tuple.length
 | |
|     @que[sz] = [] unless @que[sz]
 | |
|     @que[sz].push tuple
 | |
|   end
 | |
|   private :get_que
 | |
|   private :put_que
 | |
| 
 | |
|   def out(*tuples)
 | |
|     tuples.each do |tuple|
 | |
|       Thread.critical = true
 | |
|       put_que(tuple)
 | |
|       wakeup_waiting(tuple)
 | |
|       Thread.critical = false
 | |
|     end
 | |
|   end
 | |
|   alias put out
 | |
|   alias write out
 | |
| 
 | |
|   def in(template, non_block=false)
 | |
|     begin
 | |
|       loop do
 | |
|         Thread.critical = true
 | |
|         tuple = get_que(template)
 | |
|         unless tuple
 | |
|           if non_block
 | |
|             raise ThreadError, "queue empty"
 | |
|           end
 | |
|           put_waiting(template, Thread.current)
 | |
|           Thread.stop
 | |
|         else
 | |
|           return tuple
 | |
|         end
 | |
|       end
 | |
|     ensure
 | |
|       Thread.critical = false
 | |
|     end
 | |
|   end
 | |
|   alias get in
 | |
|   alias take in
 | |
| 
 | |
|   def rd(template, non_block=false)
 | |
|     tuple = self.in(template, non_block)
 | |
|     out(tuple)
 | |
|     tuple
 | |
|   end
 | |
|   alias read rd
 | |
| 
 | |
|   def mv(dest, template, non_block=false)
 | |
|     tuple = self.in(template, non_block)
 | |
|     begin
 | |
|       dest.out(tuple)
 | |
|     rescue
 | |
|       self.out(tuple)
 | |
|     end
 | |
|   end
 | |
|   alias move mv
 | |
| end
 | |
| 
 | |
| if __FILE__ == $0
 | |
|   ts = TupleSpace.new
 | |
|   clients = []
 | |
|   servers = []
 | |
| 
 | |
|   def server(ts, id)
 | |
|     Thread.start {
 | |
|       loop do
 | |
|         req = ts.in(['req', nil, nil])
 | |
|         ac = req[1]
 | |
|         num = req[2]
 | |
|         sleep id
 | |
|         ts.out([ac, id, num, num * num])
 | |
|       end
 | |
|     }
 | |
|   end
 | |
| 
 | |
|   def client(ts, n)
 | |
|     Thread.start {
 | |
|       ac = Object.new
 | |
|       tuples = (1..10).collect { |i|
 | |
|         ['req', ac, i * 10 + n]
 | |
|       }
 | |
|       ts.out(*tuples)
 | |
|       ts.out(tuples[0])
 | |
|       puts "out: #{n}"
 | |
|       11.times do |i|
 | |
|         ans = ts.in([ac, nil, nil, nil])
 | |
|         puts "client(#{n}) server(#{ans[1]}) #{ans[2]} #{ans[3]}"
 | |
|       end
 | |
|     }
 | |
|   end
 | |
| 
 | |
|   def watcher(ts)
 | |
|     Thread.start {
 | |
|       loop do
 | |
|         begin
 | |
|           sleep 1
 | |
|           p ts.rd(['req', nil, nil], true)
 | |
|         rescue ThreadError
 | |
|           puts "'req' not found."
 | |
|         end
 | |
|       end
 | |
|     }
 | |
|   end
 | |
| 
 | |
|   (0..3).each do |n|
 | |
|     servers.push(server(ts, n))
 | |
|   end
 | |
| 
 | |
|   (1..6).each do |n|
 | |
|     clients.push(client(ts, n))
 | |
|   end
 | |
| 
 | |
|   (1..3).each do
 | |
|     watcher(ts)
 | |
|   end
 | |
| 
 | |
|   clients.each do |t|
 | |
|     t.join
 | |
|   end
 | |
| end
 | |
| 
 | |
| 
 | |
| 
 |