summaryrefslogtreecommitdiff
path: root/sample/drb/simpletuple.rb
blob: 4bb4b1cff914757375a05285dd1d4c2e13bd372b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#!/usr/local/bin/ruby
# SimpleTupleSpace
# Copyright (c) 1999-2000 Masatoshi SEKI
# You can redistribute it and/or modify it under the same terms as Ruby.

class SimpleTupleSpace
  def initialize
    @hash = {}
    @waiting = {}
    @hash.taint
    @waiting.taint
    self.taint
  end

  def out(key, obj)
    Thread.critical = true
    @hash[key] ||= []
    @waiting[key] ||= []
    @hash[key].push obj
    begin
      t = @waiting[key].shift
      @waiting.delete(key) if @waiting[key].length == 0
      t.wakeup if t
    rescue ThreadError
      retry
    ensure
      Thread.critical = false
    end
  end

  def in(key)
    Thread.critical = true
    @hash[key] ||= []
    @waiting[key] ||= []
    begin
      loop do
        if @hash[key].length == 0
          @waiting[key].push Thread.current
          Thread.stop
        else
          return @hash[key].shift
        end
      end
    ensure
      @hash.delete(key) if @hash[key].length == 0
      Thread.critical = false
    end
  end
end

if __FILE__ == $0
  ts = SimpleTupleSpace.new
  clients = []
  servers = []

  def server(ts)
    Thread.start {
      loop do
        req = ts.in('req')
        ac = req[0]
        num = req[1]
        ts.out(ac, num * num)
      end
    }
  end

  def client(ts, n)
    Thread.start {
      ac = Object.new
      ts.out('req', [ac, n])
      ans = ts.in(ac)
      puts "#{n}: #{ans}"
    }
  end

  3.times do
    servers.push(server(ts))
  end

  (1..6).each do |n|
    clients.push(client(ts, n))
  end

  clients.each do |t|
    t.join
  end
end