1#!/usr/local/bin/ruby
2# SimpleTupleSpace
3# Copyright (c) 1999-2000 Masatoshi SEKI
4# You can redistribute it and/or modify it under the same terms as Ruby.
5
6require 'thread'
7
8class SimpleTupleSpace
9  def initialize
10    @hash = {}
11    @waiting = {}
12    @hash.taint
13    @waiting.taint
14    self.taint
15  end
16
17  def out(key, obj)
18    Thread.critical = true
19    @hash[key] ||= []
20    @waiting[key] ||= []
21    @hash[key].push obj
22    begin
23      t = @waiting[key].shift
24      @waiting.delete(key) if @waiting[key].length == 0
25      t.wakeup if t
26    rescue ThreadError
27      retry
28    ensure
29      Thread.critical = false
30    end
31  end
32
33  def in(key)
34    Thread.critical = true
35    @hash[key] ||= []
36    @waiting[key] ||= []
37    begin
38      loop do
39        if @hash[key].length == 0
40          @waiting[key].push Thread.current
41          Thread.stop
42        else
43          return @hash[key].shift
44        end
45      end
46    ensure
47      @hash.delete(key) if @hash[key].length == 0
48      Thread.critical = false
49    end
50  end
51end
52
53if __FILE__ == $0
54  ts = SimpleTupleSpace.new
55  clients = []
56  servers = []
57
58  def server(ts)
59    Thread.start {
60      loop do
61	req = ts.in('req')
62	ac = req[0]
63	num = req[1]
64	ts.out(ac, num * num)
65      end
66    }
67  end
68
69  def client(ts, n)
70    Thread.start {
71      ac = Object.new
72      ts.out('req', [ac, n])
73      ans = ts.in(ac)
74      puts "#{n}: #{ans}"
75    }
76  end
77
78  3.times do
79    servers.push(server(ts))
80  end
81
82  (1..6).each do |n|
83    clients.push(client(ts, n))
84  end
85
86  clients.each do |t|
87    t.join
88  end
89end
90
91
92