咳といいます。

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