@m_seki の

I like ruby tooから引っ越し

n月刊ラムダノートに寄稿しました。

n月刊ラムダノートにdRubyの記事を書きました。

すごく早いうちにお誘いいただいたのに、vol.2からの参加となりました。 自分の記事とは思えないほどの読みやすくなっているし、図もすばらしいのでみんなも買って読んで驚いてほしい。

内容ですが、去年の初めにやったdRubyワークショップのテキストを土台に、流行りの環境で使う話やユーザー数2のSSE向けライブラリを使う話を追加した感じです。

n月刊ラムダノート Vol.2, No.1(2020)(紙書籍+PDF版) – 技術書出版と販売のラムダノート

スタンダードレギュレーションで使えるトレーナーとか(2020/02版)

スタンダードで使えるトレーナーと特殊エネルギー

ポケモンカードのスタンダードレギュ、再録多くてわかりにくいのでリスト作ってみました。あってるかなあ。 *1

なお、前回は画像認識を使って調べたのだった。→ ポケカのカードブロックが変更になるとのこと - @m_seki の

  • グッズ
    • あとだしハンマー
    • いれかえフロート
    • おとりよせパッド
    • きずぐすり
    • しんかのおこう
    • すごいきずぐすり
    • たっぷりバケツ
    • ともだちてちょう
    • なぞの化石
    • なんでもなおし
    • びっくりボックス
    • ふしぎなアメ
    • ふっかつそう
    • ふつうのつりざお
    • ぼうけんのカバン
    • やみのいし
    • ウルトラボール
    • エネポーター
    • エネルギーつけかえ
    • エネルギースピナー
    • エネルギー回収
    • エネルギー循環装置
    • エネルギー転送
    • エレキチャージャー
    • エレキパワー
    • カスタムキャッチャー
    • ギリギリポーション
    • クイックボール
    • クラッシュハンマー
    • グレートキャッチャー
    • グレートポーション
    • ザクザクピッケル
    • ジャッジマンホイッスル
    • スイレンのつりざお
    • スタジアムナビ
    • スーパーボール
    • タッグコール
    • タッグスイッチ
    • ダートじてんしゃ
    • デンジャラスドリル
    • ネットボール
    • ハンサムホイッスル
    • ビーストリング
    • フレンドボール
    • プレシャスボール
    • ポケギア3.0
    • ポケナビ
    • ポケモンいれかえ
    • ポケモンキャッチャー
    • ポケモン通信
    • ミステリートレジャー
    • ミックスハーブ
    • ミッシングクローバー
    • メタルソーサー
    • モンスターボール
    • モーモーミルク
    • リセットスタンプ
    • リターンラベル
    • リーリエのピッピ人形
    • ルアーボール
    • レインボーブラシ
    • ロストミキサー
    • ロトムじてんしゃ
    • 勝利の証
    • 化石発掘マップ
    • 火打石
    • 炎の結晶
    • 退化スプレーZ
    • 電磁レーダー
  • サポート
    • Nの覚悟
    • TVレポーター
    • あばれる君
    • おじょうさま
    • かいじゅうマニア
    • かんこうきゃく
    • きとうし
    • ぼんぐり職人
    • むしとりしょうねん
    • アカギ◇
    • アカネ
    • アローラの仲間たち
    • アンズ
    • イツキ
    • ウツギ博士のレクチャー
    • ウルトラフォレストのかみつかい
    • ウルトラ調査隊
    • エリカ
    • エリカのおもてなし
    • エーテル財団職員
    • エール団のしたっぱ
    • オーキド博士のセッティング
    • カスミ&カンナ
    • カスミのおねがい
    • カスミのやる気
    • カスミの水さばき
    • カツラのクイズショー
    • カツラの一発勝負
    • カヒリ
    • カルネ
    • キョウの罠
    • ギーマ
    • クチナシ
    • グズマ&ハラ
    • グリーンの戦略
    • コーチトレーナー
    • サカキの追放
    • ザオボー
    • シロナ
    • シロナ&カトレア
    • ジャッジマン
    • ジュジュベ&ハチクマン
    • ソニア
    • タケシのガッツ
    • タケシのトレーニン
    • ダイゴの決断
    • デンジ
    • ナタネ
    • ナツメの暗示
    • ナリヤ・オーキド
    • ノボリとクダリ
    • ハプウ
    • ハンサム
    • ヒガナ
    • ビート
    • フウとラン
    • フウロ
    • フラダリ◇
    • ブルーの探索
    • ホップ
    • ホミカ
    • ポケモンごっこ
    • ポケモンだいすきクラブ
    • ポケモンセンターのお姉さん
    • マオ&スイレン
    • マキシ
    • マサキのメンテナンス
    • マサキの解析
    • マチスの作戦
    • マツバ
    • マツリカ
    • マリィ
    • マーズ
    • マーレイン
    • ミカン
    • ムサシとコジロウ
    • メイ
    • モノマネむすめ
    • ヤロー
    • ヤーコン
    • ユリーカ
    • ヨシダ警部補
    • ラジュルネ
    • ラニュイ
    • リーリエの全力
    • ルザミーネ
    • ルスワール
    • ルチア
    • ルミタン
    • レッド&グリーン
    • レッドの挑戦
    • ローラースケーター
    • ワタル◇
    • 博士の研究(マグノリア博士)
    • 地底探険隊
    • 溶接工
    • 釣り人
  • スタジアム
    • そらのはしら
    • まどろみの森
    • ウルトラスペース
    • カスミのハナダシティジム
    • サンダーマウンテン◇
    • シオンタウン
    • タケシのニビシティジム
    • ターフスタジアム
    • ダストアイランド
    • チャンピオンズフェスティバル
    • テンガン山
    • トキワの森
    • レーニングコート
    • ナイトシティ
    • ヒートファクトリー◇
    • フラダリラボ
    • ブラックマーケット◇
    • リザードタウン
    • プレイヤーズセレモニー
    • ポケモンけんきゅうじょ
    • ライフフォレスト◇
    • ワンダーラビリンス◇
    • ヴェラ火山公園
    • 巨大なカマド
    • 戒めの祠
    • 格闘道場
    • 混沌のうねり
    • 無人発電所
  • ポケモンのどうぐ
    • Uターンボード
    • くろおび
    • げんきのハチマキ
    • こだわりメット
    • しあわせタマゴ
    • しまめぐりのあかし
    • にじいろのはな
    • のろいのおふだ
    • ふうせん
    • みみなりベル
    • ウォーターメモリ
    • エスケープボード
    • オボンのみ
    • カウンターゲイン
    • グラスメモリ
    • ジャイアントボム
    • ドラゴンZ ドラゴンクロー
    • ノーマルZ たいあたり
    • ハッスルベルト
    • ヒコウZ エアスラッシュ
    • ビーストナイト
    • ビーストブリンガー
    • フェアリーチャーム UB
    • フェアリーチャーム 特性
    • フェアリーチャーム 雷
    • フェアリーチャームドラゴン
    • フェアリーチャーム草
    • フェアリーチャーム超
    • フェアリーチャーム闘
    • ムキムキパッド
    • メタルコアバリア
    • メタルゴーグル
    • ラムのみ
    • 大きなおまもり
    • 燃えるスカーフ
    • 竜の鉤爪
    • 鋼鉄のフライパン
    • 隠密フード
  • 特殊エネルギー
    • ウィークガードエネルギー
    • オーロラエネルギー
    • ツインエネルギー
    • トリプル加速エネルギー
    • ドローエネルギー
    • ビーストエネルギー◇
    • モリーエネルギー
    • ユニットエネルギー草炎水
    • ユニットエネルギー闘悪フェアリー
    • ユニットエネルギー雷超鋼
    • リサイクルエネルギー
    • 超ブーストエネルギー◇

*1:Safariの開発ツールの練習を兼ねて作ってみた。

forkしたら回収されるオブジェクトが欲しい

forkしたあと、DRbのコネクションプールが残ってる(つながったまま)のは嫌そう

execしてくれれば閉じられるけど...

いただいたPRは次のdRubyのメソッド呼び出しをトリガーにしてpidを見てcloseするものでした。dRubyRMIしないとずっと残ったままなので、それは多分ダメ。

fork後のThreadの仕様

たしかサブスレッド(forkしたスレッド以外?)はすべて終了する。これを使えば、fork時に回収されるようになりそう。

アクターがマイブームのころにスレッドをオブジェクト風にする素振りをしていたけど、まさか実用品として復活することになるとは!
今回は即座に(同期して)メソッドの結果が欲しいので、そのような同期メカニズムを書いて、その中にスレッドを作るようにした。
(つまり今回は並行性ではなく、forkのタイミングで消えてもらう情報を管理するためにスレッドを使う)

class ThreadObject
    include MonitorMixin

    def initialize(&blk)
      super()
      @wait_ev = new_cond
      @req_ev = new_cond
      @res_ev = new_cond
      @status = :wait
      @req = nil
      @res = nil
      @thread = Thread.new(self, &blk)
    end

    def alive?
      @thread.alive?
    end

    def method_missing(msg, *arg, &blk)
      synchronize do
        @wait_ev.wait_until { @status == :wait }
        @req = [msg] + arg
        @status = :req
        @req_ev.broadcast
        @res_ev.wait_until { @status == :res }
        value = @res
        @req = @res = nil
        @status = :wait
        @wait_ev.broadcast
        return value
      end
    end

    def _execute()
      synchronize do
        @req_ev.wait_until { @status == :req }
        @res = yield(@req)
        @status = :res
        @res_ev.signal
      end   
    end
  end

サーバーに相当する処理をブロックで渡す。method_missingの情報が渡るので、それっぽっく処理する。
スレッドにHashを管理してもらって、そこにFileオブジェクトを預ける。forkするとGCのタイミングでcloseされるようになる。

  proxy = ThreadObject.new do |queue|
    dict = {}
    while true
      queue._execute do |message|
        case(message[0])
        when :[]= then
          dict[message[1]] = message[2]
        when :[] then
          dict[message[1]]
        when :size
          dict.size
        else
          nil
        end
      end
    end
  end

  20.times do |n|
    Thread.new(n) do |x|
      proxy[x] = File.open("rdv.rb")
    end
  end

  sleep 0.01
  p proxy.size

  system("lsof -p #{$$} | wc -l")

  fork {
    system("lsof -p #{$$} | wc -l")
    GC.start # ここでcloseされて減る
    system("lsof -p #{$$} | wc -l")
  }

  sleep 10

drb.rb中のプールの管理はこんな感じ。take(uri)とstore(conn)の二つのメソッドを提供する。fork後にはGCされる。

    def self.make_pool
      ThreadObject.new do |queue|
        pool = []
        while true
          queue._execute do |message|
            case(message[0])
            when :take then
              remote_uri = message[1]
              conn = nil
              new_pool = []
              pool.each do |c|
                if conn.nil? and c.uri == remote_uri
                  conn = c if c.alive?
                else
                  new_pool.push c
                end
              end
              pool = new_pool
              conn
            when :store then
              conn = message[1]
              pool.unshift(conn)
              pool.pop.close while pool.size > POOL_SIZE
              conn
            else
              nil
            end
          end
        end
      end
    end
    @pool_proxy = make_pool

fork後にFDがどれくらい残るか確かめるgist

ThreadObjectを入れる前後でFDの増減の様子を調べたときのスクリプト。今日もらったPRはdRubyRMIするタイミングでcloseできるようになった。ThreadObject版はRMIしない場合でもGCが起こればcloseされるようになったので、ちょっとまし。

gist.github.com