咳といいます。
dRubyをつかって なんちゃってLindaもどき を書いてみました。
いまマシンが一台しかないので並列処理の実験まではできないので
ほんとにうまく並列処理できるか自信がないのですが
もしよろしければ見てやって下さい。
Lindaの様にリクエストをtuple spaceに投入するのではなく、
手の空いたサービスをプールしておいて、リクエストが投入されると
その中から一つ取り出して処理をお願いするものです。
#すみません。正しい用語がよくわかりません。
三つのファイルからなります。
・rinda.rb ---- Rindaのライブラリ。単体で実行するとサービスのプールとなる。
・rincha.rb --- Rindaサンプル・サービス。またもchasenをしてくれます。
・rinchac.rb -- Rindaサンプル・クライアント。
Rinda は、実処理(サービス)を行うオブジェクトをプールするクラスです。
RindaEntry は、サービスをRindaに登録したり、Rindaからサービスを起動させたり
するクラスです。
--- rinda.rb ---
#!/usr/local/bin/ruby
=begin
Tiny Ruby Linda
Copyright (c) 1999 Masatoshi SEKI
$Id: rinda.rb,v 1.2 1999/12/27 14:37:52 mas Exp $
=end
=begin
How to play
Terminal 1. -- rinda tuple space
% ruby rinda.rb
druby://yourhost:7640
Terminal 2. -- rinda chasen service.
% ruby rincha.rb 7950 druby://yourhost:7640
Terminal 3. -- more rinda chasen service.
% ruby rincha.rb 7951 druby://yourhost:7640
Terminal 4. -- rinda chasen client.
% ruby rinchac.rb 8470 druby://yourhost:7640
....
Terminal 5. -- more rinda chasen client.
% ruby rinchac.rb 8471 druby://yourhost:7640
....
=end
require 'drb'
require 'thread'
class Rinda
include DRbUndumped
def initialize
@q = Queue.new
end
def invoke(*arg)
entry, id = @q.pop
entry.invoke(id, *arg)
end
def push(entry, id)
@q.push([entry, id])
end
end
class RindaEntry
include DRbUndumped
def initialize(factory, rinda)
@factory = factory
@rinda = rinda
@count = 0
@room = Hash.new
end
def entry
@count += 1
curr = @count
service = @factory.new
@room[curr] = service
@rinda.push(self, curr)
end
def invoke(id, *arg)
begin
service = @room.fetch(id, nil)
raise 'invalid id' unless service
service.do_service(*arg)
ensure
@room.delete(id)
self.entry
end
end
end
if __FILE__ == $0
here = "druby://#{`hostname`.chomp}:7640"
puts here
DRb.start_service(here, Rinda.new)
DRb.thread.join
end
--- rincha.rb ---
#!/usr/local/bin/ruby
=begin
Tiny distributed Ruby --- rinda Sample Server
Copyright (c) 1999 Masatoshi SEKI
$Id: rincha.rb,v 1.2 1999/12/27 14:37:52 mas Exp $
=end
require 'drb'
require 'rinda'
require 'chasen'
class Rincha
def do_service(str, *arg)
p str
Chasen.getopt(*arg)
Chasen.sparse(str)
end
end
if __FILE__ == $0
port = ARGV.shift
there = ARGV.shift
unless there
$stderr.puts("usage: #{$0} <port> <server_uri>")
exit 1
end
here = "druby://#{`hostname`.chomp}:#{port}"
ro = DRbObject.new(nil, there)
re = RindaEntry.new(Rincha, ro)
DRb.start_service(here, re)
re.entry
DRb.thread.join
end
--- rinchac.rb ---
#!/usr/local/bin/ruby
=begin
Tiny distributed Ruby --- rinda Sample Client -- chasen client
Copyright (c) 1999 Masatoshi SEKI
$Id: rinchac.rb,v 1.2 1999/12/27 14:37:52 mas Exp $
=end
require 'drb.rb'
if __FILE__ == $0
port = ARGV.shift
there = ARGV.shift
unless there
$stderr.puts("usage: #{$0} <server_uri>")
exit 1
end
here = "druby://#{`hostname`.chomp}:#{port}"
DRb.start_service(here)
chasen = DRbObject.new(nil, there)
str = `man man | nkf -e | head -20`
t = []
10.times do
th = Thread.new {
print chasen.invoke(str, "-F", '(%BB %m %M)\n', "-j")
print chasen.invoke(str, "-F", '(%m %M)\n')
}
t.push(th)
end
t.each do |th| th.join end
end