ioplus 0.0.1.PROTOTYPE
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/LICENSE.md +35 -0
 - data/README.ja.md +20 -0
 - data/README.md +24 -0
 - data/Rakefile +143 -0
 - data/examples/aio_read.rb +28 -0
 - data/ext/extconf.rb +38 -0
 - data/ext/extio.c +865 -0
 - data/gemstub.rb +18 -0
 - data/lib/ioplus.rb +47 -0
 - metadata +90 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA1:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 6242bf07dabdee5e581a67b3fe6139deb291b924
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 569d32580f365d037f8e4bb7342b1b1a1963b13c
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: e655c0bea9f742c59c432982470e89618c0fd2a81128c3d72617d473c47681fd96b7e8fadea0995e12267004ce6dafb731a520ae6f1fd223a00fdf63eb5b8376
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 145738e030b55c8838b2a7ba460e3ffa04f4e8d5df9c5c38fb14dc9ea3a931428bc6cce2ccaea43b1e3e48be3e48091c2bdd3271ff237e4f591867d8633184a9
         
     | 
    
        data/LICENSE.md
    ADDED
    
    | 
         @@ -0,0 +1,35 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # ioplus License (2-clause BSD License)
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            ----
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Copyright (c) 2015, dearblue
         
     | 
| 
      
 6 
     | 
    
         
            +
            All rights reserved.
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            Redistribution and use in source and binary forms, with or without
         
     | 
| 
      
 9 
     | 
    
         
            +
            modification, are permitted provided that the following conditions are met:
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            1.  Redistributions of source code must retain the above copyright notice,
         
     | 
| 
      
 12 
     | 
    
         
            +
                this list of conditions and the following disclaimer.
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            2.  Redistributions in binary form must reproduce the above copyright
         
     | 
| 
      
 15 
     | 
    
         
            +
                notice, this list of conditions and the following disclaimer in the
         
     | 
| 
      
 16 
     | 
    
         
            +
                documentation and/or other materials provided with the distribution.
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
         
     | 
| 
      
 19 
     | 
    
         
            +
            AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
         
     | 
| 
      
 20 
     | 
    
         
            +
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
         
     | 
| 
      
 21 
     | 
    
         
            +
            ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
         
     | 
| 
      
 22 
     | 
    
         
            +
            LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
         
     | 
| 
      
 23 
     | 
    
         
            +
            OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
         
     | 
| 
      
 24 
     | 
    
         
            +
            SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
         
     | 
| 
      
 25 
     | 
    
         
            +
            INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
         
     | 
| 
      
 26 
     | 
    
         
            +
            CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
         
     | 
| 
      
 27 
     | 
    
         
            +
            ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
         
     | 
| 
      
 28 
     | 
    
         
            +
            POSSIBILITY OF SUCH DAMAGE.
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            ----
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            In Japanese.
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            日本語訳については次のページが参考になるでしょう:
         
     | 
| 
      
 35 
     | 
    
         
            +
            http://www.freebsd.org/ja/copyright/freebsd-license.html
         
     | 
    
        data/README.ja.md
    ADDED
    
    | 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # ioplus - IO 拡張モジュール
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            このライブラリは IO クラスを拡張させるモジュールが含まれています。
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            *   非同期読み込みメソッド - ``IO#aio_read`` / ``IO#aread`` <- ``IOPlus::IO#aio_read``
         
     | 
| 
      
 6 
     | 
    
         
            +
            *   非同期書き込みメソッド - ``IO#aio_write`` / ``IO#awrite`` <- ``IOPlus::IO#aio_write``
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            これらのメソッドは ``aio_read(2)`` と ``aio_write(2)`` に似た機能を提供します。
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            ***このライブラリはセーフレベルを考慮しないため、セキュリティリスクがあります。信頼できない外部データを取り扱う環境では、このライブラリを読み込まないで下さい。***
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            ## 注意点
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            *   FreeBSD 上では ``aio.ko`` がカーネルに読み込まれている必要があります。
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                ``/boot/loader.conf`` に ``aio_load="YES"`` を追加するか、実行前に ``kldload aio`` を行って下さい。
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            *   ``IO#read`` / ``IO#write`` を経由するメソッドとの使用は不可解な動作の原因となります。
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                必要であれば ``IO#sysread`` / ``IO#syswrite`` などのメソッドを用いて下さい。
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # ioplus - IO 拡張モジュール
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            This library is included a module for IO class extension.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            These methods are provide similar functions as ``pread(2)``, ``pwrite(2)``, ``aio_read(2)`` and ``aio_write(2)``.
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            ***This library has a security risk, because it is not consideration for the safe-level.***
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            ## Required kernel object on FreeBSD
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            ``aio.ko`` is required for asynchronouse I/O operation on FreeBSD.
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            Execute ruby script before try following:
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            ```shell:shell
         
     | 
| 
      
 16 
     | 
    
         
            +
            # echo 'aio_load="YES"' >> /boot/loader.conf
         
     | 
| 
      
 17 
     | 
    
         
            +
            # shutdown -r now
         
     | 
| 
      
 18 
     | 
    
         
            +
            ```
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            OR
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            ```shell:shell
         
     | 
| 
      
 23 
     | 
    
         
            +
            # kldload aio
         
     | 
| 
      
 24 
     | 
    
         
            +
            ```
         
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,143 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            require "rake/clean"
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            DOC = FileList["{README,LICENSE,CHANGELOG,Changelog,HISTORY}{,.ja}{,.txt,.rd,.rdoc,.md,.markdown}"] +
         
     | 
| 
      
 5 
     | 
    
         
            +
                  FileList["ext/**/{README,LICENSE,CHANGELOG,Changelog,HISTORY}{,.ja}{,.txt,.rd,.rdoc,.md,.markdown}"]
         
     | 
| 
      
 6 
     | 
    
         
            +
            #EXT = FileList["ext/**/*.{h,hh,c,cc,cpp,cxx}"] +
         
     | 
| 
      
 7 
     | 
    
         
            +
            #      FileList["ext/externals/**/*"]
         
     | 
| 
      
 8 
     | 
    
         
            +
            EXT = FileList["ext/**/*"]
         
     | 
| 
      
 9 
     | 
    
         
            +
            BIN = FileList["bin/*"]
         
     | 
| 
      
 10 
     | 
    
         
            +
            LIB = FileList["lib/**/*.rb"]
         
     | 
| 
      
 11 
     | 
    
         
            +
            SPEC = FileList["spec/**/*"]
         
     | 
| 
      
 12 
     | 
    
         
            +
            EXAMPLE = FileList["examples/**/*"]
         
     | 
| 
      
 13 
     | 
    
         
            +
            RAKEFILE = [File.basename(__FILE__), "gemstub.rb"]
         
     | 
| 
      
 14 
     | 
    
         
            +
            EXTRA = []
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            load "gemstub.rb"
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            EXTCONF = FileList["ext/extconf.rb"]
         
     | 
| 
      
 19 
     | 
    
         
            +
            EXTCONF.reject! { |n| !File.file?(n) }
         
     | 
| 
      
 20 
     | 
    
         
            +
            GEMSTUB.extensions += EXTCONF
         
     | 
| 
      
 21 
     | 
    
         
            +
            GEMSTUB.executables += FileList["bin/*"].map { |n| File.basename n }
         
     | 
| 
      
 22 
     | 
    
         
            +
            GEMSTUB.executables.sort!
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            GEMFILE = "#{GEMSTUB.name}-#{GEMSTUB.version}.gem"
         
     | 
| 
      
 25 
     | 
    
         
            +
            GEMSPEC = "#{GEMSTUB.name}.gemspec"
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            GEMSTUB.files += DOC + EXT + EXTCONF + BIN + LIB + SPEC + EXAMPLE + RAKEFILE + EXTRA
         
     | 
| 
      
 28 
     | 
    
         
            +
            GEMSTUB.files.sort!
         
     | 
| 
      
 29 
     | 
    
         
            +
            GEMSTUB.rdoc_options ||= %w(--charset UTF-8)
         
     | 
| 
      
 30 
     | 
    
         
            +
            GEMSTUB.extra_rdoc_files += DOC + LIB + EXT.reject { |n| n.include?("/externals/") || !%w(.h .hh .c .cc .cpp .cxx).include?(File.extname(n)) }
         
     | 
| 
      
 31 
     | 
    
         
            +
            GEMSTUB.extra_rdoc_files.sort!
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            CLEAN << GEMSPEC
         
     | 
| 
      
 34 
     | 
    
         
            +
            CLOBBER << GEMFILE
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            task :default => :all
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            unless EXTCONF.empty?
         
     | 
| 
      
 40 
     | 
    
         
            +
              RUBYSET ||= (ENV["RUBYSET"] || "").split(",")
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              if RUBYSET.nil? || RUBYSET.empty?
         
     | 
| 
      
 43 
     | 
    
         
            +
                $stderr.puts <<-EOS
         
     | 
| 
      
 44 
     | 
    
         
            +
            #{__FILE__}:
         
     | 
| 
      
 45 
     | 
    
         
            +
            |
         
     | 
| 
      
 46 
     | 
    
         
            +
            | If you want binary gem package, launch rake with ``RUBYSET`` enviroment
         
     | 
| 
      
 47 
     | 
    
         
            +
            | variable for set ruby interpreters by comma separated.
         
     | 
| 
      
 48 
     | 
    
         
            +
            |
         
     | 
| 
      
 49 
     | 
    
         
            +
            |   e.g.) $ rake RUBYSET=ruby
         
     | 
| 
      
 50 
     | 
    
         
            +
            |     or) $ rake RUBYSET=ruby20,ruby21,ruby22
         
     | 
| 
      
 51 
     | 
    
         
            +
            |
         
     | 
| 
      
 52 
     | 
    
         
            +
                EOS
         
     | 
| 
      
 53 
     | 
    
         
            +
              else
         
     | 
| 
      
 54 
     | 
    
         
            +
                platforms = RUBYSET.map { |ruby| `#{ruby} --disable gems -rrbconfig -e "puts RbConfig::CONFIG['arch']"`.chomp }
         
     | 
| 
      
 55 
     | 
    
         
            +
                platforms1 = platforms.uniq
         
     | 
| 
      
 56 
     | 
    
         
            +
                unless platforms1.size == 1 && !platforms1[0].empty?
         
     | 
| 
      
 57 
     | 
    
         
            +
                  raise "different platforms (#{Hash[*RUBYSET.zip(platforms).flatten].inspect})"
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
                PLATFORM = platforms1[0]
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                RUBY_VERSIONS = RUBYSET.map do |ruby|
         
     | 
| 
      
 62 
     | 
    
         
            +
                  ver = `#{ruby} --disable gem -rrbconfig -e "puts RbConfig::CONFIG['ruby_version']"`.slice(/\d+\.\d+/)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  raise "failed ruby checking - ``#{ruby}''" unless $?.success?
         
     | 
| 
      
 64 
     | 
    
         
            +
                  [ver, ruby]
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
                SOFILES_SET = RUBY_VERSIONS.map { |(ver, ruby)| ["lib/#{ver}/#{GEMSTUB.name}.so", ruby] }
         
     | 
| 
      
 67 
     | 
    
         
            +
                SOFILES = SOFILES_SET.map { |(lib, ruby)| lib }
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                GEMSTUB_NATIVE = GEMSTUB.dup
         
     | 
| 
      
 70 
     | 
    
         
            +
                GEMSTUB_NATIVE.files += SOFILES
         
     | 
| 
      
 71 
     | 
    
         
            +
                GEMSTUB_NATIVE.platform = Gem::Platform.new(PLATFORM).to_s
         
     | 
| 
      
 72 
     | 
    
         
            +
                GEMSTUB_NATIVE.extensions.clear
         
     | 
| 
      
 73 
     | 
    
         
            +
                GEMFILE_NATIVE = "#{GEMSTUB_NATIVE.name}-#{GEMSTUB_NATIVE.version}-#{GEMSTUB_NATIVE.platform}.gem"
         
     | 
| 
      
 74 
     | 
    
         
            +
                GEMSPEC_NATIVE = "#{GEMSTUB_NATIVE.name}-#{GEMSTUB_NATIVE.platform}.gemspec"
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                task :all => ["native-gem", GEMFILE]
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                desc "build binary gem package"
         
     | 
| 
      
 79 
     | 
    
         
            +
                task "native-gem" => GEMFILE_NATIVE
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                desc "generate binary gemspec"
         
     | 
| 
      
 82 
     | 
    
         
            +
                task "native-gemspec" => GEMSPEC_NATIVE
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                file GEMFILE_NATIVE => DOC + EXT + EXTCONF + BIN + LIB + SPEC + EXAMPLE + SOFILES + RAKEFILE + [GEMSPEC_NATIVE] do
         
     | 
| 
      
 85 
     | 
    
         
            +
                  sh "gem build #{GEMSPEC_NATIVE}"
         
     | 
| 
      
 86 
     | 
    
         
            +
                end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                file GEMSPEC_NATIVE => __FILE__ do
         
     | 
| 
      
 89 
     | 
    
         
            +
                  File.write(GEMSPEC_NATIVE, GEMSTUB_NATIVE.to_ruby, mode: "wb")
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                SOFILES_SET.each do |(soname, ruby)|
         
     | 
| 
      
 93 
     | 
    
         
            +
                  sodir = File.dirname(soname)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  makefile = File.join(sodir, "Makefile")
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                  CLEAN << GEMSPEC_NATIVE << sodir
         
     | 
| 
      
 97 
     | 
    
         
            +
                  CLOBBER << GEMFILE_NATIVE
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                  directory sodir
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                  desc "generate Makefile for binary extension library"
         
     | 
| 
      
 102 
     | 
    
         
            +
                  file makefile => [sodir] + EXTCONF do
         
     | 
| 
      
 103 
     | 
    
         
            +
                    cd sodir do
         
     | 
| 
      
 104 
     | 
    
         
            +
                      sh "#{ruby} ../../#{EXTCONF[0]} \"--ruby=#{ruby}\""
         
     | 
| 
      
 105 
     | 
    
         
            +
                    end
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                  desc "build binary extension library"
         
     | 
| 
      
 109 
     | 
    
         
            +
                  file soname => [makefile] + EXT do
         
     | 
| 
      
 110 
     | 
    
         
            +
                    cd sodir do
         
     | 
| 
      
 111 
     | 
    
         
            +
                      sh "make"
         
     | 
| 
      
 112 
     | 
    
         
            +
                    end
         
     | 
| 
      
 113 
     | 
    
         
            +
                  end
         
     | 
| 
      
 114 
     | 
    
         
            +
                end
         
     | 
| 
      
 115 
     | 
    
         
            +
              end
         
     | 
| 
      
 116 
     | 
    
         
            +
            end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
            task :all => GEMFILE
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
            desc "generate local rdoc"
         
     | 
| 
      
 122 
     | 
    
         
            +
            task :rdoc => DOC + EXT + LIB do
         
     | 
| 
      
 123 
     | 
    
         
            +
              sh *(%w(rdoc) + GEMSTUB.rdoc_options + DOC + EXT + LIB)
         
     | 
| 
      
 124 
     | 
    
         
            +
            end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
            desc "launch rspec"
         
     | 
| 
      
 127 
     | 
    
         
            +
            task rspec: :all do
         
     | 
| 
      
 128 
     | 
    
         
            +
              sh "rspec"
         
     | 
| 
      
 129 
     | 
    
         
            +
            end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
            desc "build gem package"
         
     | 
| 
      
 132 
     | 
    
         
            +
            task gem: GEMFILE
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
            desc "generate gemspec"
         
     | 
| 
      
 135 
     | 
    
         
            +
            task gemspec: GEMSPEC
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
            file GEMFILE => DOC + EXT + EXTCONF + BIN + LIB + SPEC + EXAMPLE + RAKEFILE + [GEMSPEC] do
         
     | 
| 
      
 138 
     | 
    
         
            +
              sh "gem build #{GEMSPEC}"
         
     | 
| 
      
 139 
     | 
    
         
            +
            end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
            file GEMSPEC => RAKEFILE do
         
     | 
| 
      
 142 
     | 
    
         
            +
              File.write(GEMSPEC, GEMSTUB.to_ruby, mode: "wb")
         
     | 
| 
      
 143 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,28 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            #vim: set fileencoding:utf-8
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require "pp"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "ioplus"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            file = ARGV[0] || "/usr/bin/cc"
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            puts "read file: #{file}"
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            File.open(file, "rb") do |f|
         
     | 
| 
      
 12 
     | 
    
         
            +
              aio = []
         
     | 
| 
      
 13 
     | 
    
         
            +
              aio << f.aio_read(0, 500, b = "".b) { |x| puts "<aio done! offset #{x.offset} +#{x.status}>\n" }
         
     | 
| 
      
 14 
     | 
    
         
            +
              aio << f.aio_read(rand(1000000), 1000) { |x| puts "<aio done! offset #{x.offset} +#{x.status}>\n" }
         
     | 
| 
      
 15 
     | 
    
         
            +
              aio << f.aio_read(rand(1000000), 100) { |x| puts "<aio done! offset #{x.offset} +#{x.status}>\n" }
         
     | 
| 
      
 16 
     | 
    
         
            +
              aio << f.aio_read(rand(1000000), 200) { |x| puts "<aio done! offset #{x.offset} +#{x.status}>\n" }
         
     | 
| 
      
 17 
     | 
    
         
            +
              aio << f.aio_read(0, 300, "a".b) { |x| puts "<aio done! offset #{x.offset} +#{x.status}>\n" }
         
     | 
| 
      
 18 
     | 
    
         
            +
              p aio[1].cancel rescue nil
         
     | 
| 
      
 19 
     | 
    
         
            +
              pp aio
         
     | 
| 
      
 20 
     | 
    
         
            +
              IO.aio_suspend(*aio)
         
     | 
| 
      
 21 
     | 
    
         
            +
              p b
         
     | 
| 
      
 22 
     | 
    
         
            +
              pp aio
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            GC.start
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            puts "<finished main thread and 1 sec sleeping>\n"
         
     | 
| 
      
 28 
     | 
    
         
            +
            sleep 1
         
     | 
    
        data/ext/extconf.rb
    ADDED
    
    | 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            #vim: set fileencoding:utf-8
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require "mkmf"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            srcdirpat = File.dirname(__FILE__).gsub(/[\[\{\},]/, "[\\0]")
         
     | 
| 
      
 7 
     | 
    
         
            +
            $srcs = Dir.glob(File.join(srcdirpat, "*.{c,cc}"))
         
     | 
| 
      
 8 
     | 
    
         
            +
            vpath = []
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            case
         
     | 
| 
      
 11 
     | 
    
         
            +
            when have_header("aio.h")
         
     | 
| 
      
 12 
     | 
    
         
            +
              if have_func("kevent", %w(sys/types.h sys/event.h sys/time.h))
         
     | 
| 
      
 13 
     | 
    
         
            +
                $defs << " -DEXTIO_HAVE_KEVENT=1"
         
     | 
| 
      
 14 
     | 
    
         
            +
              else
         
     | 
| 
      
 15 
     | 
    
         
            +
                $stderr.puts <<EOS
         
     | 
| 
      
 16 
     | 
    
         
            +
            |
         
     | 
| 
      
 17 
     | 
    
         
            +
            | #{__FILE__}:#{__LINE__}: NOT SUPPORTED PLATFORM.
         
     | 
| 
      
 18 
     | 
    
         
            +
            |
         
     | 
| 
      
 19 
     | 
    
         
            +
            EOS
         
     | 
| 
      
 20 
     | 
    
         
            +
                exit 1
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
              $srcs += Dir.glob(File.join(srcdirpat, "posix/*.c"))
         
     | 
| 
      
 23 
     | 
    
         
            +
              vpath << "$(srcdir)/posix"
         
     | 
| 
      
 24 
     | 
    
         
            +
              $defs << " -DEXTIO_WITH_POSIX=1"
         
     | 
| 
      
 25 
     | 
    
         
            +
            #when have_header("windows.h")
         
     | 
| 
      
 26 
     | 
    
         
            +
            #  $srcs += Dir.glob(File.join(srcdirpat, "win32/*.c"))
         
     | 
| 
      
 27 
     | 
    
         
            +
            #  vpath << "$(srcdir)/win32"
         
     | 
| 
      
 28 
     | 
    
         
            +
            #  $defs << " -DEXTIO_WITH_WIN32=1"
         
     | 
| 
      
 29 
     | 
    
         
            +
            else
         
     | 
| 
      
 30 
     | 
    
         
            +
              $stderr.puts <<EOS
         
     | 
| 
      
 31 
     | 
    
         
            +
            |
         
     | 
| 
      
 32 
     | 
    
         
            +
            | #{__FILE__}:#{__LINE__}: NOT SUPPORTED PLATFORM.
         
     | 
| 
      
 33 
     | 
    
         
            +
            |
         
     | 
| 
      
 34 
     | 
    
         
            +
            EOS
         
     | 
| 
      
 35 
     | 
    
         
            +
              exit 1
         
     | 
| 
      
 36 
     | 
    
         
            +
            end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            create_makefile "ioplus" or exit 1
         
     | 
    
        data/ext/extio.c
    ADDED
    
    | 
         @@ -0,0 +1,865 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #include <ruby.h>
         
     | 
| 
      
 2 
     | 
    
         
            +
            #include <ruby/io.h>
         
     | 
| 
      
 3 
     | 
    
         
            +
            #include <ruby/thread.h>
         
     | 
| 
      
 4 
     | 
    
         
            +
            #include <errno.h>
         
     | 
| 
      
 5 
     | 
    
         
            +
            #include <pthread.h>
         
     | 
| 
      
 6 
     | 
    
         
            +
            #include <fcntl.h>
         
     | 
| 
      
 7 
     | 
    
         
            +
            #include <sys/stat.h>
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            #if EXTIO_WITH_WIN32
         
     | 
| 
      
 10 
     | 
    
         
            +
            #   include <windows.h>
         
     | 
| 
      
 11 
     | 
    
         
            +
            #elif EXTIO_WITH_POSIX
         
     | 
| 
      
 12 
     | 
    
         
            +
            #   include <aio.h>
         
     | 
| 
      
 13 
     | 
    
         
            +
            #   if EXTIO_HAVE_KEVENT
         
     | 
| 
      
 14 
     | 
    
         
            +
            #       include <sys/types.h>
         
     | 
| 
      
 15 
     | 
    
         
            +
            #       include <sys/event.h>
         
     | 
| 
      
 16 
     | 
    
         
            +
            #       include <sys/time.h>
         
     | 
| 
      
 17 
     | 
    
         
            +
            #   endif
         
     | 
| 
      
 18 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            enum {
         
     | 
| 
      
 21 
     | 
    
         
            +
                EXTAIO_READ = 0x00,
         
     | 
| 
      
 22 
     | 
    
         
            +
                EXTAIO_WRITE = 0x01,
         
     | 
| 
      
 23 
     | 
    
         
            +
            };
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            struct extaio
         
     | 
| 
      
 26 
     | 
    
         
            +
            {
         
     | 
| 
      
 27 
     | 
    
         
            +
                aiocb_t aio;
         
     | 
| 
      
 28 
     | 
    
         
            +
                VALUE self;
         
     | 
| 
      
 29 
     | 
    
         
            +
                VALUE notify_block;
         
     | 
| 
      
 30 
     | 
    
         
            +
                VALUE file;
         
     | 
| 
      
 31 
     | 
    
         
            +
                VALUE buffer;
         
     | 
| 
      
 32 
     | 
    
         
            +
                VALUE status; /* converted value of aio_return */
         
     | 
| 
      
 33 
     | 
    
         
            +
                uint64_t offset;
         
     | 
| 
      
 34 
     | 
    
         
            +
                int operation; /* EXTAIO_READ, EXTAIO_WRITE */
         
     | 
| 
      
 35 
     | 
    
         
            +
            #if EXTIO_HAVE_KEVENT
         
     | 
| 
      
 36 
     | 
    
         
            +
                struct kevent kev;
         
     | 
| 
      
 37 
     | 
    
         
            +
            #else
         
     | 
| 
      
 38 
     | 
    
         
            +
                struct extaio *next;
         
     | 
| 
      
 39 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 40 
     | 
    
         
            +
            };
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            static pthread_mutex_t extaio_mutex = PTHREAD_MUTEX_INITIALIZER;
         
     | 
| 
      
 43 
     | 
    
         
            +
            static pthread_cond_t extaio_cond = PTHREAD_COND_INITIALIZER;
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
            #if EXTIO_HAVE_KEVENT
         
     | 
| 
      
 46 
     | 
    
         
            +
            static int extaio_kqueue;
         
     | 
| 
      
 47 
     | 
    
         
            +
            #else
         
     | 
| 
      
 48 
     | 
    
         
            +
            static struct extaio *extaio_queue, *extaio_queue_tail;
         
     | 
| 
      
 49 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            static VALUE mIOPlus, mIO, mIOClass, cAIO;
         
     | 
| 
      
 52 
     | 
    
         
            +
            static VALUE extio_lives;
         
     | 
| 
      
 53 
     | 
    
         
            +
            static ID IDto_time;
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            static inline struct timespec
         
     | 
| 
      
 56 
     | 
    
         
            +
            aux_conv_to_timespec(VALUE time)
         
     | 
| 
      
 57 
     | 
    
         
            +
            {
         
     | 
| 
      
 58 
     | 
    
         
            +
                struct timespec ts = { 0, 0 };
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                switch (TYPE(time)) {
         
     | 
| 
      
 61 
     | 
    
         
            +
                case RUBY_T_FIXNUM:
         
     | 
| 
      
 62 
     | 
    
         
            +
                case RUBY_T_BIGNUM:
         
     | 
| 
      
 63 
     | 
    
         
            +
                    ts.tv_sec = NUM2LL(time);
         
     | 
| 
      
 64 
     | 
    
         
            +
                    return ts;
         
     | 
| 
      
 65 
     | 
    
         
            +
                case RUBY_T_FLOAT:
         
     | 
| 
      
 66 
     | 
    
         
            +
                    ts.tv_sec = NUM2LL(time);
         
     | 
| 
      
 67 
     | 
    
         
            +
                    ts.tv_nsec = (int64_t)(NUM2DBL(time) * 1000000000) % 1000000000;
         
     | 
| 
      
 68 
     | 
    
         
            +
                    return ts;
         
     | 
| 
      
 69 
     | 
    
         
            +
                default:
         
     | 
| 
      
 70 
     | 
    
         
            +
                    if (rb_obj_is_kind_of(time, rb_cTime)) {
         
     | 
| 
      
 71 
     | 
    
         
            +
                        return rb_time_timespec(time);
         
     | 
| 
      
 72 
     | 
    
         
            +
                    } else if (rb_respond_to(time, IDto_time)) {
         
     | 
| 
      
 73 
     | 
    
         
            +
                        time = rb_funcall(time, IDto_time, 0);
         
     | 
| 
      
 74 
     | 
    
         
            +
                        if (rb_obj_is_kind_of(time, rb_cTime)) {
         
     | 
| 
      
 75 
     | 
    
         
            +
                            return rb_time_timespec(time);
         
     | 
| 
      
 76 
     | 
    
         
            +
                        } else {
         
     | 
| 
      
 77 
     | 
    
         
            +
                            rb_raise(rb_eTypeError,
         
     | 
| 
      
 78 
     | 
    
         
            +
                                     "not convert to time object by ``to_time''");
         
     | 
| 
      
 79 
     | 
    
         
            +
                        }
         
     | 
| 
      
 80 
     | 
    
         
            +
                    } else {
         
     | 
| 
      
 81 
     | 
    
         
            +
                        time = rb_Float(time);
         
     | 
| 
      
 82 
     | 
    
         
            +
                        ts.tv_sec = NUM2LL(time);
         
     | 
| 
      
 83 
     | 
    
         
            +
                        ts.tv_nsec = (int64_t)(NUM2DBL(time) * 1000000000) % 1000000000;
         
     | 
| 
      
 84 
     | 
    
         
            +
                        return ts;
         
     | 
| 
      
 85 
     | 
    
         
            +
                    }
         
     | 
| 
      
 86 
     | 
    
         
            +
                }
         
     | 
| 
      
 87 
     | 
    
         
            +
            }
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
            static inline int
         
     | 
| 
      
 90 
     | 
    
         
            +
            ext_io_getfd(VALUE file)
         
     | 
| 
      
 91 
     | 
    
         
            +
            {
         
     | 
| 
      
 92 
     | 
    
         
            +
                struct rb_io_t *fp;
         
     | 
| 
      
 93 
     | 
    
         
            +
                GetOpenFile(file, fp);
         
     | 
| 
      
 94 
     | 
    
         
            +
                return fp->fd;
         
     | 
| 
      
 95 
     | 
    
         
            +
            }
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
            static inline ssize_t
         
     | 
| 
      
 98 
     | 
    
         
            +
            ext_getiosize(int d)
         
     | 
| 
      
 99 
     | 
    
         
            +
            {
         
     | 
| 
      
 100 
     | 
    
         
            +
                struct stat s;
         
     | 
| 
      
 101 
     | 
    
         
            +
                if (fstat(d, &s) == 0) {
         
     | 
| 
      
 102 
     | 
    
         
            +
                    return s.st_size;
         
     | 
| 
      
 103 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 104 
     | 
    
         
            +
                    return -1;
         
     | 
| 
      
 105 
     | 
    
         
            +
                }
         
     | 
| 
      
 106 
     | 
    
         
            +
            }
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
            static inline struct extaio *
         
     | 
| 
      
 109 
     | 
    
         
            +
            extaio_refp(VALUE aio)
         
     | 
| 
      
 110 
     | 
    
         
            +
            {
         
     | 
| 
      
 111 
     | 
    
         
            +
                struct extaio *p;
         
     | 
| 
      
 112 
     | 
    
         
            +
                Data_Get_Struct(aio, struct extaio, p);
         
     | 
| 
      
 113 
     | 
    
         
            +
                return p;
         
     | 
| 
      
 114 
     | 
    
         
            +
            }
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
            static inline struct extaio *
         
     | 
| 
      
 117 
     | 
    
         
            +
            extaio_ref(VALUE aio)
         
     | 
| 
      
 118 
     | 
    
         
            +
            {
         
     | 
| 
      
 119 
     | 
    
         
            +
                struct extaio *p = extaio_refp(aio);
         
     | 
| 
      
 120 
     | 
    
         
            +
                if (!p) {
         
     | 
| 
      
 121 
     | 
    
         
            +
                    VALUE v = rb_inspect(aio);
         
     | 
| 
      
 122 
     | 
    
         
            +
                    rb_raise(rb_eRuntimeError,
         
     | 
| 
      
 123 
     | 
    
         
            +
                             "invalid reference - %s",
         
     | 
| 
      
 124 
     | 
    
         
            +
                             StringValueCStr(v));
         
     | 
| 
      
 125 
     | 
    
         
            +
                }
         
     | 
| 
      
 126 
     | 
    
         
            +
                return p;
         
     | 
| 
      
 127 
     | 
    
         
            +
            }
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
            #if !EXTIO_HAVE_KEVENT
         
     | 
| 
      
 130 
     | 
    
         
            +
            static void
         
     | 
| 
      
 131 
     | 
    
         
            +
            extaio_read_notify(union sigval sv)
         
     | 
| 
      
 132 
     | 
    
         
            +
            {
         
     | 
| 
      
 133 
     | 
    
         
            +
                /* NOT RUBY MANAGED THREAD! */
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                struct extaio *p = sv.sival_ptr;
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                pthread_mutex_lock(&extaio_mutex);
         
     | 
| 
      
 138 
     | 
    
         
            +
                if (extaio_queue) {
         
     | 
| 
      
 139 
     | 
    
         
            +
                    extaio_queue_tail = extaio_queue_tail->next = p;
         
     | 
| 
      
 140 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 141 
     | 
    
         
            +
                    extaio_queue_tail = extaio_queue = p;
         
     | 
| 
      
 142 
     | 
    
         
            +
                }
         
     | 
| 
      
 143 
     | 
    
         
            +
                pthread_cond_signal(&extaio_cond);
         
     | 
| 
      
 144 
     | 
    
         
            +
                pthread_mutex_unlock(&extaio_mutex);
         
     | 
| 
      
 145 
     | 
    
         
            +
            }
         
     | 
| 
      
 146 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
            static void
         
     | 
| 
      
 149 
     | 
    
         
            +
            extaio_gcmark(struct extaio *p)
         
     | 
| 
      
 150 
     | 
    
         
            +
            {
         
     | 
| 
      
 151 
     | 
    
         
            +
                if (p) {
         
     | 
| 
      
 152 
     | 
    
         
            +
                    rb_gc_mark(p->self);
         
     | 
| 
      
 153 
     | 
    
         
            +
                    rb_gc_mark(p->notify_block);
         
     | 
| 
      
 154 
     | 
    
         
            +
                    rb_gc_mark(p->file);
         
     | 
| 
      
 155 
     | 
    
         
            +
                    rb_gc_mark(p->buffer);
         
     | 
| 
      
 156 
     | 
    
         
            +
                    rb_gc_mark(p->status);
         
     | 
| 
      
 157 
     | 
    
         
            +
                }
         
     | 
| 
      
 158 
     | 
    
         
            +
            }
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
            static void
         
     | 
| 
      
 161 
     | 
    
         
            +
            extaio_free(struct extaio *p)
         
     | 
| 
      
 162 
     | 
    
         
            +
            {
         
     | 
| 
      
 163 
     | 
    
         
            +
                if (p) {
         
     | 
| 
      
 164 
     | 
    
         
            +
                    aio_cancel(ext_io_getfd(p->file), &p->aio);
         
     | 
| 
      
 165 
     | 
    
         
            +
                    const struct aiocb *pp = &p->aio;
         
     | 
| 
      
 166 
     | 
    
         
            +
                    aio_suspend(&pp, 1, NULL); /* FIXME: GC 中に無限待機の可能性あり? */
         
     | 
| 
      
 167 
     | 
    
         
            +
                    free(p);
         
     | 
| 
      
 168 
     | 
    
         
            +
                }
         
     | 
| 
      
 169 
     | 
    
         
            +
            }
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
            static inline struct extaio *
         
     | 
| 
      
 172 
     | 
    
         
            +
            extaio_new(int operation, VALUE file, rb_io_t *fp, uint64_t offset, VALUE buf, uint64_t size)
         
     | 
| 
      
 173 
     | 
    
         
            +
            {
         
     | 
| 
      
 174 
     | 
    
         
            +
                struct extaio *p;
         
     | 
| 
      
 175 
     | 
    
         
            +
                VALUE objaio = Data_Make_Struct(cAIO, struct extaio, extaio_gcmark, extaio_free, p);
         
     | 
| 
      
 176 
     | 
    
         
            +
                rb_str_locktmp(buf);
         
     | 
| 
      
 177 
     | 
    
         
            +
                p->aio.aio_offset   = offset;
         
     | 
| 
      
 178 
     | 
    
         
            +
                p->aio.aio_buf      = RSTRING_PTR(buf);
         
     | 
| 
      
 179 
     | 
    
         
            +
                p->aio.aio_nbytes   = size;
         
     | 
| 
      
 180 
     | 
    
         
            +
                p->aio.aio_reqprio  = 0;
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
            #if EXTIO_HAVE_KEVENT
         
     | 
| 
      
 183 
     | 
    
         
            +
                p->aio.aio_sigevent.sigev_notify            = SIGEV_KEVENT;
         
     | 
| 
      
 184 
     | 
    
         
            +
                p->aio.aio_sigevent.sigev_notify_kqueue     = extaio_kqueue;
         
     | 
| 
      
 185 
     | 
    
         
            +
                p->aio.aio_sigevent.sigev_notify_kevent_flags = EV_ONESHOT;
         
     | 
| 
      
 186 
     | 
    
         
            +
            #else
         
     | 
| 
      
 187 
     | 
    
         
            +
                p->aio.aio_sigevent.sigev_notify            = SIGEV_THREAD;
         
     | 
| 
      
 188 
     | 
    
         
            +
                p->aio.aio_sigevent.sigev_notify_function   = extaio_read_notify;
         
     | 
| 
      
 189 
     | 
    
         
            +
                p->aio.aio_sigevent.sigev_notify_attributes = NULL;
         
     | 
| 
      
 190 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 191 
     | 
    
         
            +
             
     | 
| 
      
 192 
     | 
    
         
            +
                p->aio.aio_fildes = fp->fd;
         
     | 
| 
      
 193 
     | 
    
         
            +
                p->aio.aio_sigevent.sigev_value.sival_ptr = p;
         
     | 
| 
      
 194 
     | 
    
         
            +
             
     | 
| 
      
 195 
     | 
    
         
            +
                p->notify_block = rb_block_given_p() ? rb_block_proc() : Qnil;
         
     | 
| 
      
 196 
     | 
    
         
            +
                p->operation = operation;
         
     | 
| 
      
 197 
     | 
    
         
            +
                p->self = objaio;
         
     | 
| 
      
 198 
     | 
    
         
            +
                p->file = file;
         
     | 
| 
      
 199 
     | 
    
         
            +
                p->buffer = buf;
         
     | 
| 
      
 200 
     | 
    
         
            +
                p->status = Qnil;
         
     | 
| 
      
 201 
     | 
    
         
            +
                p->offset = offset;
         
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
      
 203 
     | 
    
         
            +
            #if EXTIO_HAVE_KEVENT
         
     | 
| 
      
 204 
     | 
    
         
            +
                //EV_SET(&p->kev, fp->fd, EVFILT_AIO, EV_ADD, 0, 0, NULL);
         
     | 
| 
      
 205 
     | 
    
         
            +
                //kevent(extaio_kqueue, &p->kev, 1, NULL, 0, NULL);
         
     | 
| 
      
 206 
     | 
    
         
            +
            #else
         
     | 
| 
      
 207 
     | 
    
         
            +
            #   error IMPLEMENT ME!
         
     | 
| 
      
 208 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
      
 210 
     | 
    
         
            +
                return p;
         
     | 
| 
      
 211 
     | 
    
         
            +
            }
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
            static void
         
     | 
| 
      
 214 
     | 
    
         
            +
            extio_aio_read_scanargs(int argc, VALUE argv[], int d, off_t *offset, size_t *size, VALUE *buf)
         
     | 
| 
      
 215 
     | 
    
         
            +
            {
         
     | 
| 
      
 216 
     | 
    
         
            +
                switch (argc) {
         
     | 
| 
      
 217 
     | 
    
         
            +
                case 1:
         
     | 
| 
      
 218 
     | 
    
         
            +
                    *offset = NUM2OFFT(argv[0]);
         
     | 
| 
      
 219 
     | 
    
         
            +
                    // TODO: エラーの場合 (size_t)-1 が返ってくるけれど、メモリ要求でパンクする
         
     | 
| 
      
 220 
     | 
    
         
            +
                    // TODO: これではエラーメッセージがわかりにくいからどうにかする
         
     | 
| 
      
 221 
     | 
    
         
            +
                    *size = ext_getiosize(d);
         
     | 
| 
      
 222 
     | 
    
         
            +
                    *buf = rb_str_buf_new(*size);
         
     | 
| 
      
 223 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 224 
     | 
    
         
            +
                case 2:
         
     | 
| 
      
 225 
     | 
    
         
            +
                    *offset = NUM2OFFT(argv[0]);
         
     | 
| 
      
 226 
     | 
    
         
            +
                    *size = NUM2SIZET(argv[1]);
         
     | 
| 
      
 227 
     | 
    
         
            +
                    *buf = rb_str_buf_new(*size);
         
     | 
| 
      
 228 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 229 
     | 
    
         
            +
                case 3:
         
     | 
| 
      
 230 
     | 
    
         
            +
                    *offset = NUM2OFFT(argv[0]);
         
     | 
| 
      
 231 
     | 
    
         
            +
                    *size = NUM2SIZET(argv[1]);
         
     | 
| 
      
 232 
     | 
    
         
            +
                    *buf = argv[2];
         
     | 
| 
      
 233 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 234 
     | 
    
         
            +
                default:
         
     | 
| 
      
 235 
     | 
    
         
            +
                    rb_error_arity(argc, 1, 3);
         
     | 
| 
      
 236 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 237 
     | 
    
         
            +
                }
         
     | 
| 
      
 238 
     | 
    
         
            +
             
     | 
| 
      
 239 
     | 
    
         
            +
                rb_check_type(*buf, RUBY_T_STRING);
         
     | 
| 
      
 240 
     | 
    
         
            +
                if (OBJ_FROZEN(*buf)) {
         
     | 
| 
      
 241 
     | 
    
         
            +
                    rb_raise(rb_eTypeError, 
         
     | 
| 
      
 242 
     | 
    
         
            +
                             "wrong immutable object for ``buffer''");
         
     | 
| 
      
 243 
     | 
    
         
            +
                }
         
     | 
| 
      
 244 
     | 
    
         
            +
                rb_str_resize(*buf, *size);
         
     | 
| 
      
 245 
     | 
    
         
            +
                rb_str_set_len(*buf, 0);
         
     | 
| 
      
 246 
     | 
    
         
            +
            }
         
     | 
| 
      
 247 
     | 
    
         
            +
             
     | 
| 
      
 248 
     | 
    
         
            +
            /*
         
     | 
| 
      
 249 
     | 
    
         
            +
             * call-seq:
         
     | 
| 
      
 250 
     | 
    
         
            +
             *  aio_read(offset) -> aio_object
         
     | 
| 
      
 251 
     | 
    
         
            +
             *  aio_read(offset) { |aio_obj| ... } -> aio_object
         
     | 
| 
      
 252 
     | 
    
         
            +
             *  aio_read(offset, size, buf = nil) -> aio_object
         
     | 
| 
      
 253 
     | 
    
         
            +
             *  aio_read(offset, size, buf = nil) { |aio_obj| ... } -> aio_object
         
     | 
| 
      
 254 
     | 
    
         
            +
             *
         
     | 
| 
      
 255 
     | 
    
         
            +
             * I/O オブジェクトに対して非同期読み込みを行います。
         
     | 
| 
      
 256 
     | 
    
         
            +
             *
         
     | 
| 
      
 257 
     | 
    
         
            +
             * システムに対して読み込み要求を出すだけなので、すぐに制御が戻ります。
         
     | 
| 
      
 258 
     | 
    
         
            +
             *
         
     | 
| 
      
 259 
     | 
    
         
            +
             * この時の戻り値は、読み込み要求の状態を保持するオブジェクトです。
         
     | 
| 
      
 260 
     | 
    
         
            +
             *
         
     | 
| 
      
 261 
     | 
    
         
            +
             * このオブジェクトを用いて待機する、処理の完了状態を取得するなどを行うことが出来ます。
         
     | 
| 
      
 262 
     | 
    
         
            +
             *
         
     | 
| 
      
 263 
     | 
    
         
            +
             * ブロックを指定した場合、読み込みが完了した時に評価されます。
         
     | 
| 
      
 264 
     | 
    
         
            +
             *
         
     | 
| 
      
 265 
     | 
    
         
            +
             * ブロック引数と戻り値は同じオブジェクトです。
         
     | 
| 
      
 266 
     | 
    
         
            +
             *
         
     | 
| 
      
 267 
     | 
    
         
            +
             * ioplus ライブラリの実装上の問題として aio_read(2) システムコールよりも大きな遅延があります。
         
     | 
| 
      
 268 
     | 
    
         
            +
             *
         
     | 
| 
      
 269 
     | 
    
         
            +
             * 数ミリ秒単位の遅延すら許容できないアプリケーションでは使い物にならないことに注意して下さい。
         
     | 
| 
      
 270 
     | 
    
         
            +
             *
         
     | 
| 
      
 271 
     | 
    
         
            +
             * また、aio_read を呼んだスレッドとは異なるスレッドがブロックを評価します。
         
     | 
| 
      
 272 
     | 
    
         
            +
             *
         
     | 
| 
      
 273 
     | 
    
         
            +
             * [RETURN]
         
     | 
| 
      
 274 
     | 
    
         
            +
             *  IOPlus::AIO インスタンスです。
         
     | 
| 
      
 275 
     | 
    
         
            +
             *
         
     | 
| 
      
 276 
     | 
    
         
            +
             * [YIELD aio_obj]
         
     | 
| 
      
 277 
     | 
    
         
            +
             *  IOPlus::AIO インスタンスです。
         
     | 
| 
      
 278 
     | 
    
         
            +
             */
         
     | 
| 
      
 279 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 280 
     | 
    
         
            +
            extio_aio_read(int argc, VALUE argv[], VALUE file)
         
     | 
| 
      
 281 
     | 
    
         
            +
            {
         
     | 
| 
      
 282 
     | 
    
         
            +
                rb_check_type(file, RUBY_T_FILE);
         
     | 
| 
      
 283 
     | 
    
         
            +
                struct rb_io_t *fp;
         
     | 
| 
      
 284 
     | 
    
         
            +
                GetOpenFile(file, fp);
         
     | 
| 
      
 285 
     | 
    
         
            +
             
     | 
| 
      
 286 
     | 
    
         
            +
                off_t offset;
         
     | 
| 
      
 287 
     | 
    
         
            +
                size_t size;
         
     | 
| 
      
 288 
     | 
    
         
            +
                VALUE buf;
         
     | 
| 
      
 289 
     | 
    
         
            +
                extio_aio_read_scanargs(argc, argv, fp->fd, &offset, &size, &buf);
         
     | 
| 
      
 290 
     | 
    
         
            +
             
     | 
| 
      
 291 
     | 
    
         
            +
                struct extaio *p = extaio_new(EXTAIO_READ, file, fp, offset, buf, size);
         
     | 
| 
      
 292 
     | 
    
         
            +
             
     | 
| 
      
 293 
     | 
    
         
            +
                if (aio_read(&p->aio) != 0) {
         
     | 
| 
      
 294 
     | 
    
         
            +
                    DATA_PTR(p->self) = NULL;
         
     | 
| 
      
 295 
     | 
    
         
            +
                    free(p);
         
     | 
| 
      
 296 
     | 
    
         
            +
                    VALUE v = rb_inspect(file);
         
     | 
| 
      
 297 
     | 
    
         
            +
                    rb_sys_fail_str(v);
         
     | 
| 
      
 298 
     | 
    
         
            +
                }
         
     | 
| 
      
 299 
     | 
    
         
            +
             
     | 
| 
      
 300 
     | 
    
         
            +
                rb_ary_push(extio_lives, p->self);
         
     | 
| 
      
 301 
     | 
    
         
            +
             
     | 
| 
      
 302 
     | 
    
         
            +
                return p->self;
         
     | 
| 
      
 303 
     | 
    
         
            +
            }
         
     | 
| 
      
 304 
     | 
    
         
            +
             
     | 
| 
      
 305 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 306 
     | 
    
         
            +
            extio_aio_write(VALUE file, VALUE off, VALUE buf)
         
     | 
| 
      
 307 
     | 
    
         
            +
            {
         
     | 
| 
      
 308 
     | 
    
         
            +
                rb_check_type(file, RUBY_T_FILE);
         
     | 
| 
      
 309 
     | 
    
         
            +
                struct rb_io_t *fp;
         
     | 
| 
      
 310 
     | 
    
         
            +
                GetOpenFile(file, fp);
         
     | 
| 
      
 311 
     | 
    
         
            +
             
     | 
| 
      
 312 
     | 
    
         
            +
                off_t offset = NUM2OFFT(off);
         
     | 
| 
      
 313 
     | 
    
         
            +
                rb_check_type(buf, RUBY_T_STRING);
         
     | 
| 
      
 314 
     | 
    
         
            +
                size_t size = RSTRING_LEN(buf);
         
     | 
| 
      
 315 
     | 
    
         
            +
             
     | 
| 
      
 316 
     | 
    
         
            +
                struct extaio *p = extaio_new(EXTAIO_WRITE, file, fp, offset, buf, size);
         
     | 
| 
      
 317 
     | 
    
         
            +
             
     | 
| 
      
 318 
     | 
    
         
            +
                if (aio_write(&p->aio) != 0) {
         
     | 
| 
      
 319 
     | 
    
         
            +
                    DATA_PTR(p->self) = NULL;
         
     | 
| 
      
 320 
     | 
    
         
            +
                    free(p);
         
     | 
| 
      
 321 
     | 
    
         
            +
                    VALUE v = rb_inspect(file);
         
     | 
| 
      
 322 
     | 
    
         
            +
                    rb_sys_fail_str(v);
         
     | 
| 
      
 323 
     | 
    
         
            +
                }
         
     | 
| 
      
 324 
     | 
    
         
            +
             
     | 
| 
      
 325 
     | 
    
         
            +
                rb_ary_push(extio_lives, p->self);
         
     | 
| 
      
 326 
     | 
    
         
            +
             
     | 
| 
      
 327 
     | 
    
         
            +
                return p->self;
         
     | 
| 
      
 328 
     | 
    
         
            +
            }
         
     | 
| 
      
 329 
     | 
    
         
            +
             
     | 
| 
      
 330 
     | 
    
         
            +
            /*
         
     | 
| 
      
 331 
     | 
    
         
            +
             * このファイルに関するすべての非同期処理の取り消しをシステムに要求します。
         
     | 
| 
      
 332 
     | 
    
         
            +
             *
         
     | 
| 
      
 333 
     | 
    
         
            +
             * 常に取り消されるわけではないことに注意してください。
         
     | 
| 
      
 334 
     | 
    
         
            +
             */
         
     | 
| 
      
 335 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 336 
     | 
    
         
            +
            extio_aio_cancel(VALUE file)
         
     | 
| 
      
 337 
     | 
    
         
            +
            {
         
     | 
| 
      
 338 
     | 
    
         
            +
                int fd = ext_io_getfd(file);
         
     | 
| 
      
 339 
     | 
    
         
            +
                int status = aio_cancel(fd, NULL);
         
     | 
| 
      
 340 
     | 
    
         
            +
                switch (status) {
         
     | 
| 
      
 341 
     | 
    
         
            +
                case AIO_CANCELED:
         
     | 
| 
      
 342 
     | 
    
         
            +
                    return ID2SYM(rb_intern("canceled"));
         
     | 
| 
      
 343 
     | 
    
         
            +
                case AIO_NOTCANCELED:
         
     | 
| 
      
 344 
     | 
    
         
            +
                    return ID2SYM(rb_intern("notcanceled"));
         
     | 
| 
      
 345 
     | 
    
         
            +
                case AIO_ALLDONE:
         
     | 
| 
      
 346 
     | 
    
         
            +
                    return ID2SYM(rb_intern("alldone"));
         
     | 
| 
      
 347 
     | 
    
         
            +
                case -1:
         
     | 
| 
      
 348 
     | 
    
         
            +
                    rb_sys_fail_str(rb_inspect(file));
         
     | 
| 
      
 349 
     | 
    
         
            +
                default:
         
     | 
| 
      
 350 
     | 
    
         
            +
                    return rb_sprintf("unknown-status:0x%02x", status);
         
     | 
| 
      
 351 
     | 
    
         
            +
                }
         
     | 
| 
      
 352 
     | 
    
         
            +
            }
         
     | 
| 
      
 353 
     | 
    
         
            +
             
     | 
| 
      
 354 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 355 
     | 
    
         
            +
            extaio_validate(VALUE aio)
         
     | 
| 
      
 356 
     | 
    
         
            +
            {
         
     | 
| 
      
 357 
     | 
    
         
            +
                if (extaio_refp(aio)) {
         
     | 
| 
      
 358 
     | 
    
         
            +
                    return aio;
         
     | 
| 
      
 359 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 360 
     | 
    
         
            +
                    return Qnil;
         
     | 
| 
      
 361 
     | 
    
         
            +
                }
         
     | 
| 
      
 362 
     | 
    
         
            +
            }
         
     | 
| 
      
 363 
     | 
    
         
            +
             
     | 
| 
      
 364 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 365 
     | 
    
         
            +
            extaio_file(VALUE aio)
         
     | 
| 
      
 366 
     | 
    
         
            +
            {
         
     | 
| 
      
 367 
     | 
    
         
            +
                return extaio_ref(aio)->file;
         
     | 
| 
      
 368 
     | 
    
         
            +
            }
         
     | 
| 
      
 369 
     | 
    
         
            +
             
     | 
| 
      
 370 
     | 
    
         
            +
            static inline VALUE
         
     | 
| 
      
 371 
     | 
    
         
            +
            ext_aio_operation_inspect(struct extaio *p)
         
     | 
| 
      
 372 
     | 
    
         
            +
            {
         
     | 
| 
      
 373 
     | 
    
         
            +
                int operation = p->operation;
         
     | 
| 
      
 374 
     | 
    
         
            +
                switch (operation) {
         
     | 
| 
      
 375 
     | 
    
         
            +
                case EXTAIO_READ:
         
     | 
| 
      
 376 
     | 
    
         
            +
                    return ID2SYM(rb_intern("read"));
         
     | 
| 
      
 377 
     | 
    
         
            +
                case EXTAIO_WRITE:
         
     | 
| 
      
 378 
     | 
    
         
            +
                    return ID2SYM(rb_intern("write"));
         
     | 
| 
      
 379 
     | 
    
         
            +
                default:
         
     | 
| 
      
 380 
     | 
    
         
            +
                    return rb_sprintf("unknown:0x%02x", operation);
         
     | 
| 
      
 381 
     | 
    
         
            +
                }
         
     | 
| 
      
 382 
     | 
    
         
            +
            }
         
     | 
| 
      
 383 
     | 
    
         
            +
             
     | 
| 
      
 384 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 385 
     | 
    
         
            +
            extaio_operation(VALUE aio)
         
     | 
| 
      
 386 
     | 
    
         
            +
            {
         
     | 
| 
      
 387 
     | 
    
         
            +
                return ext_aio_operation_inspect(extaio_ref(aio));
         
     | 
| 
      
 388 
     | 
    
         
            +
            }
         
     | 
| 
      
 389 
     | 
    
         
            +
             
     | 
| 
      
 390 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 391 
     | 
    
         
            +
            extaio_buffer(VALUE aio)
         
     | 
| 
      
 392 
     | 
    
         
            +
            {
         
     | 
| 
      
 393 
     | 
    
         
            +
                return extaio_ref(aio)->buffer;
         
     | 
| 
      
 394 
     | 
    
         
            +
            }
         
     | 
| 
      
 395 
     | 
    
         
            +
             
     | 
| 
      
 396 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 397 
     | 
    
         
            +
            extaio_offset(VALUE aio)
         
     | 
| 
      
 398 
     | 
    
         
            +
            {
         
     | 
| 
      
 399 
     | 
    
         
            +
                return ULL2NUM(extaio_ref(aio)->offset);
         
     | 
| 
      
 400 
     | 
    
         
            +
            }
         
     | 
| 
      
 401 
     | 
    
         
            +
             
     | 
| 
      
 402 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 403 
     | 
    
         
            +
            extaio_to_s(VALUE aio)
         
     | 
| 
      
 404 
     | 
    
         
            +
            {
         
     | 
| 
      
 405 
     | 
    
         
            +
                return rb_sprintf("%s:%p", rb_obj_classname(aio), (void *)aio);
         
     | 
| 
      
 406 
     | 
    
         
            +
            }
         
     | 
| 
      
 407 
     | 
    
         
            +
             
     | 
| 
      
 408 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 409 
     | 
    
         
            +
            extaio_inspect(VALUE aio)
         
     | 
| 
      
 410 
     | 
    
         
            +
            {
         
     | 
| 
      
 411 
     | 
    
         
            +
                struct extaio *p = extaio_refp(aio);
         
     | 
| 
      
 412 
     | 
    
         
            +
                if (!p) {
         
     | 
| 
      
 413 
     | 
    
         
            +
                    return rb_sprintf("#<%s:%p **INVALID-REFERENCE**>",
         
     | 
| 
      
 414 
     | 
    
         
            +
                                      rb_obj_classname(aio), (void *)aio);
         
     | 
| 
      
 415 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 416 
     | 
    
         
            +
                    VALUE ioobj = rb_inspect(p->file);
         
     | 
| 
      
 417 
     | 
    
         
            +
                    int bufsize = RSTRING_LEN(p->buffer);
         
     | 
| 
      
 418 
     | 
    
         
            +
                    VALUE retval = rb_inspect(p->status);
         
     | 
| 
      
 419 
     | 
    
         
            +
                    VALUE operation = rb_String(ext_aio_operation_inspect(p));
         
     | 
| 
      
 420 
     | 
    
         
            +
                    return rb_sprintf("#<%s:%p %s %s offset=%d buffer.bytesize=%d return=%s>",
         
     | 
| 
      
 421 
     | 
    
         
            +
                                      rb_obj_classname(aio), (void *)aio,
         
     | 
| 
      
 422 
     | 
    
         
            +
                                      StringValueCStr(operation), StringValueCStr(ioobj),
         
     | 
| 
      
 423 
     | 
    
         
            +
                                      (int)p->offset, bufsize, StringValueCStr(retval));
         
     | 
| 
      
 424 
     | 
    
         
            +
                }
         
     | 
| 
      
 425 
     | 
    
         
            +
            }
         
     | 
| 
      
 426 
     | 
    
         
            +
             
     | 
| 
      
 427 
     | 
    
         
            +
            struct extaio_suspend_wait_args
         
     | 
| 
      
 428 
     | 
    
         
            +
            {
         
     | 
| 
      
 429 
     | 
    
         
            +
                struct extaio *aio;
         
     | 
| 
      
 430 
     | 
    
         
            +
                int64_t timeout;
         
     | 
| 
      
 431 
     | 
    
         
            +
            };
         
     | 
| 
      
 432 
     | 
    
         
            +
             
     | 
| 
      
 433 
     | 
    
         
            +
            enum {
         
     | 
| 
      
 434 
     | 
    
         
            +
                EXTAIO_POLLING_INTERVAL_NSEC = 100 * 1000 * 1000,
         
     | 
| 
      
 435 
     | 
    
         
            +
                EXTAIO_POLLING_INTERVAL_INFINITY = -1ll,
         
     | 
| 
      
 436 
     | 
    
         
            +
                EXTAIO_DONE = 0,
         
     | 
| 
      
 437 
     | 
    
         
            +
                EXTAIO_TIMEDOUT = 1,
         
     | 
| 
      
 438 
     | 
    
         
            +
                EXTAIO_ERROR = -1,
         
     | 
| 
      
 439 
     | 
    
         
            +
            };
         
     | 
| 
      
 440 
     | 
    
         
            +
             
     | 
| 
      
 441 
     | 
    
         
            +
            enum {
         
     | 
| 
      
 442 
     | 
    
         
            +
                EXT_1SEC_TO_NSEC = 1 * 1000 * 1000 * 1000,
         
     | 
| 
      
 443 
     | 
    
         
            +
            };
         
     | 
| 
      
 444 
     | 
    
         
            +
             
     | 
| 
      
 445 
     | 
    
         
            +
            static int
         
     | 
| 
      
 446 
     | 
    
         
            +
            extaio_suspend_wait_ungvl(struct extaio_suspend_wait_args *args)
         
     | 
| 
      
 447 
     | 
    
         
            +
            {
         
     | 
| 
      
 448 
     | 
    
         
            +
                /*
         
     | 
| 
      
 449 
     | 
    
         
            +
                 * aio_suspend を中断するにはシグナルを必要とするが、ruby と
         
     | 
| 
      
 450 
     | 
    
         
            +
                 * 適合するかどうかわからないためポーリング処理する。
         
     | 
| 
      
 451 
     | 
    
         
            +
                 * このため、指定された timeout よりも大きな待機時間となる。
         
     | 
| 
      
 452 
     | 
    
         
            +
                 * 現時点では 100 ms 単位で行う。
         
     | 
| 
      
 453 
     | 
    
         
            +
                 */
         
     | 
| 
      
 454 
     | 
    
         
            +
                struct timespec timeout = { 0, EXTAIO_POLLING_INTERVAL_NSEC };
         
     | 
| 
      
 455 
     | 
    
         
            +
                int64_t timerest = args->timeout;
         
     | 
| 
      
 456 
     | 
    
         
            +
                VALUE thcur = rb_thread_current();
         
     | 
| 
      
 457 
     | 
    
         
            +
             
     | 
| 
      
 458 
     | 
    
         
            +
                for (;;) {
         
     | 
| 
      
 459 
     | 
    
         
            +
                    if (timerest >= 0 && timerest < EXTAIO_POLLING_INTERVAL_NSEC) {
         
     | 
| 
      
 460 
     | 
    
         
            +
                        timeout.tv_sec = 0;
         
     | 
| 
      
 461 
     | 
    
         
            +
                        timeout.tv_nsec = timerest;
         
     | 
| 
      
 462 
     | 
    
         
            +
                    }
         
     | 
| 
      
 463 
     | 
    
         
            +
                    int state = aio_suspend((const struct aiocb *const *)&args->aio->aio, 1, &timeout);
         
     | 
| 
      
 464 
     | 
    
         
            +
                    if (rb_thread_interrupted(thcur)) { return EXTAIO_ERROR; }
         
     | 
| 
      
 465 
     | 
    
         
            +
                    if (state == 0) { break; }
         
     | 
| 
      
 466 
     | 
    
         
            +
                    if (state == -1) {
         
     | 
| 
      
 467 
     | 
    
         
            +
                        switch (errno) {
         
     | 
| 
      
 468 
     | 
    
         
            +
                        case EAGAIN:
         
     | 
| 
      
 469 
     | 
    
         
            +
                            if (timerest >= 0 && timerest <= EXTAIO_POLLING_INTERVAL_NSEC) {
         
     | 
| 
      
 470 
     | 
    
         
            +
                                return EXTAIO_TIMEDOUT;
         
     | 
| 
      
 471 
     | 
    
         
            +
                            } else {
         
     | 
| 
      
 472 
     | 
    
         
            +
                                timerest -= EXTAIO_POLLING_INTERVAL_NSEC;
         
     | 
| 
      
 473 
     | 
    
         
            +
                                continue;
         
     | 
| 
      
 474 
     | 
    
         
            +
                            }
         
     | 
| 
      
 475 
     | 
    
         
            +
                        //case EINVAL:
         
     | 
| 
      
 476 
     | 
    
         
            +
                        //case EINTR:
         
     | 
| 
      
 477 
     | 
    
         
            +
                        //case ENOSYS:
         
     | 
| 
      
 478 
     | 
    
         
            +
                        default:
         
     | 
| 
      
 479 
     | 
    
         
            +
                            return EXTAIO_ERROR;
         
     | 
| 
      
 480 
     | 
    
         
            +
                        }
         
     | 
| 
      
 481 
     | 
    
         
            +
                    }
         
     | 
| 
      
 482 
     | 
    
         
            +
                }
         
     | 
| 
      
 483 
     | 
    
         
            +
             
     | 
| 
      
 484 
     | 
    
         
            +
                /*
         
     | 
| 
      
 485 
     | 
    
         
            +
                 * 非同期 I/O 要求が正常完了して aio_suspend から戻ってきたが、
         
     | 
| 
      
 486 
     | 
    
         
            +
                 * ruby 側の処理が完了していないかもしれないため待機する。
         
     | 
| 
      
 487 
     | 
    
         
            +
                 */
         
     | 
| 
      
 488 
     | 
    
         
            +
             
     | 
| 
      
 489 
     | 
    
         
            +
                int status = EXTAIO_DONE;
         
     | 
| 
      
 490 
     | 
    
         
            +
             
     | 
| 
      
 491 
     | 
    
         
            +
                timeout.tv_sec = 0;
         
     | 
| 
      
 492 
     | 
    
         
            +
                timeout.tv_nsec = EXTAIO_POLLING_INTERVAL_NSEC;
         
     | 
| 
      
 493 
     | 
    
         
            +
             
     | 
| 
      
 494 
     | 
    
         
            +
                if (pthread_mutex_lock(&extaio_mutex) == 0) {
         
     | 
| 
      
 495 
     | 
    
         
            +
                    while (NIL_P(args->aio->status)) {
         
     | 
| 
      
 496 
     | 
    
         
            +
                        if (timerest >= 0 && timerest <= EXTAIO_POLLING_INTERVAL_NSEC) {
         
     | 
| 
      
 497 
     | 
    
         
            +
                            timeout.tv_nsec = timerest;
         
     | 
| 
      
 498 
     | 
    
         
            +
                        }
         
     | 
| 
      
 499 
     | 
    
         
            +
             
     | 
| 
      
 500 
     | 
    
         
            +
                        if (rb_thread_interrupted(thcur)) {
         
     | 
| 
      
 501 
     | 
    
         
            +
                            status = EXTAIO_ERROR;
         
     | 
| 
      
 502 
     | 
    
         
            +
                            break;
         
     | 
| 
      
 503 
     | 
    
         
            +
                        }
         
     | 
| 
      
 504 
     | 
    
         
            +
                        int s = pthread_cond_timedwait(&extaio_cond, &extaio_mutex, &timeout);
         
     | 
| 
      
 505 
     | 
    
         
            +
                        if (s == 0) {
         
     | 
| 
      
 506 
     | 
    
         
            +
                            break;
         
     | 
| 
      
 507 
     | 
    
         
            +
                        } else if (s == ETIMEDOUT) {
         
     | 
| 
      
 508 
     | 
    
         
            +
                            if (timerest <= EXTAIO_POLLING_INTERVAL_NSEC) {
         
     | 
| 
      
 509 
     | 
    
         
            +
                                status = EXTAIO_TIMEDOUT;
         
     | 
| 
      
 510 
     | 
    
         
            +
                                break;
         
     | 
| 
      
 511 
     | 
    
         
            +
                            }
         
     | 
| 
      
 512 
     | 
    
         
            +
                            timerest -= EXTAIO_POLLING_INTERVAL_NSEC;
         
     | 
| 
      
 513 
     | 
    
         
            +
                        } else if (s == EINTR) {
         
     | 
| 
      
 514 
     | 
    
         
            +
                            status = EXTAIO_ERROR;
         
     | 
| 
      
 515 
     | 
    
         
            +
                            errno = s;
         
     | 
| 
      
 516 
     | 
    
         
            +
                            break;
         
     | 
| 
      
 517 
     | 
    
         
            +
                        } else {
         
     | 
| 
      
 518 
     | 
    
         
            +
                            /* TODO: 仕様の上ではなさそうだけれども、どうするべきか考えておこう */
         
     | 
| 
      
 519 
     | 
    
         
            +
                            status = EXTAIO_ERROR;
         
     | 
| 
      
 520 
     | 
    
         
            +
                            break;
         
     | 
| 
      
 521 
     | 
    
         
            +
                        }
         
     | 
| 
      
 522 
     | 
    
         
            +
                    }
         
     | 
| 
      
 523 
     | 
    
         
            +
                    pthread_mutex_unlock(&extaio_mutex);
         
     | 
| 
      
 524 
     | 
    
         
            +
                }
         
     | 
| 
      
 525 
     | 
    
         
            +
             
     | 
| 
      
 526 
     | 
    
         
            +
                return status;
         
     | 
| 
      
 527 
     | 
    
         
            +
            }
         
     | 
| 
      
 528 
     | 
    
         
            +
             
     | 
| 
      
 529 
     | 
    
         
            +
            static inline VALUE
         
     | 
| 
      
 530 
     | 
    
         
            +
            extaio_suspend_wait(struct extaio *aio, int64_t timeout_nsec)
         
     | 
| 
      
 531 
     | 
    
         
            +
            {
         
     | 
| 
      
 532 
     | 
    
         
            +
                if (!NIL_P(aio->status)) {
         
     | 
| 
      
 533 
     | 
    
         
            +
                    // すでに完了しているため待機の必要はない
         
     | 
| 
      
 534 
     | 
    
         
            +
                    return aio->self;
         
     | 
| 
      
 535 
     | 
    
         
            +
                }
         
     | 
| 
      
 536 
     | 
    
         
            +
             
     | 
| 
      
 537 
     | 
    
         
            +
                struct extaio_suspend_wait_args args = {
         
     | 
| 
      
 538 
     | 
    
         
            +
                    .aio = aio,
         
     | 
| 
      
 539 
     | 
    
         
            +
                    .timeout = timeout_nsec,
         
     | 
| 
      
 540 
     | 
    
         
            +
                };
         
     | 
| 
      
 541 
     | 
    
         
            +
                int s = (int)rb_thread_call_without_gvl((void *(*)(void *))extaio_suspend_wait_ungvl,
         
     | 
| 
      
 542 
     | 
    
         
            +
                                                        &args, RUBY_UBF_PROCESS, NULL);
         
     | 
| 
      
 543 
     | 
    
         
            +
             
     | 
| 
      
 544 
     | 
    
         
            +
                if (s == 0) {
         
     | 
| 
      
 545 
     | 
    
         
            +
                    return aio->self;
         
     | 
| 
      
 546 
     | 
    
         
            +
                } else if (s == EXTAIO_TIMEDOUT) {
         
     | 
| 
      
 547 
     | 
    
         
            +
                    return Qnil;
         
     | 
| 
      
 548 
     | 
    
         
            +
                } else if (s == EXTAIO_ERROR) {
         
     | 
| 
      
 549 
     | 
    
         
            +
                    VALUE v = rb_inspect(aio->self);
         
     | 
| 
      
 550 
     | 
    
         
            +
                    rb_sys_fail_str(v);
         
     | 
| 
      
 551 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 552 
     | 
    
         
            +
                    rb_bug("%s:%d:%s: extaio_suspend_wait_ungvl returned not handled code (0x%04x)",
         
     | 
| 
      
 553 
     | 
    
         
            +
                           __FILE__, __LINE__, __func__, s);
         
     | 
| 
      
 554 
     | 
    
         
            +
                }
         
     | 
| 
      
 555 
     | 
    
         
            +
            }
         
     | 
| 
      
 556 
     | 
    
         
            +
             
     | 
| 
      
 557 
     | 
    
         
            +
            /*
         
     | 
| 
      
 558 
     | 
    
         
            +
             * call-seq:
         
     | 
| 
      
 559 
     | 
    
         
            +
             *  suspend(timeout = nil) -> self or nil
         
     | 
| 
      
 560 
     | 
    
         
            +
             */
         
     | 
| 
      
 561 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 562 
     | 
    
         
            +
            extaio_suspend(int argc, VALUE argv[], VALUE aio)
         
     | 
| 
      
 563 
     | 
    
         
            +
            {
         
     | 
| 
      
 564 
     | 
    
         
            +
                VALUE timeout;
         
     | 
| 
      
 565 
     | 
    
         
            +
                switch (argc) {
         
     | 
| 
      
 566 
     | 
    
         
            +
                case 0:
         
     | 
| 
      
 567 
     | 
    
         
            +
                    timeout = Qnil;
         
     | 
| 
      
 568 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 569 
     | 
    
         
            +
                case 1:
         
     | 
| 
      
 570 
     | 
    
         
            +
                    timeout = argv[0];
         
     | 
| 
      
 571 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 572 
     | 
    
         
            +
                default:
         
     | 
| 
      
 573 
     | 
    
         
            +
                    rb_error_arity(argc, 0, 1);
         
     | 
| 
      
 574 
     | 
    
         
            +
                    timeout = Qnil; /* clear warnings for compiler */
         
     | 
| 
      
 575 
     | 
    
         
            +
                }
         
     | 
| 
      
 576 
     | 
    
         
            +
             
     | 
| 
      
 577 
     | 
    
         
            +
                if (NIL_P(timeout)) {
         
     | 
| 
      
 578 
     | 
    
         
            +
                    return extaio_suspend_wait(extaio_ref(aio), EXTAIO_POLLING_INTERVAL_INFINITY);
         
     | 
| 
      
 579 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 580 
     | 
    
         
            +
                    struct timespec time = aux_conv_to_timespec(timeout);
         
     | 
| 
      
 581 
     | 
    
         
            +
                    int64_t t = time.tv_sec * EXT_1SEC_TO_NSEC + time.tv_nsec;
         
     | 
| 
      
 582 
     | 
    
         
            +
                    if (t / EXT_1SEC_TO_NSEC != time.tv_sec) {
         
     | 
| 
      
 583 
     | 
    
         
            +
                        t = EXTAIO_POLLING_INTERVAL_INFINITY;
         
     | 
| 
      
 584 
     | 
    
         
            +
                    }
         
     | 
| 
      
 585 
     | 
    
         
            +
                    return extaio_suspend_wait(extaio_ref(aio), t);
         
     | 
| 
      
 586 
     | 
    
         
            +
                }
         
     | 
| 
      
 587 
     | 
    
         
            +
            }
         
     | 
| 
      
 588 
     | 
    
         
            +
             
     | 
| 
      
 589 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 590 
     | 
    
         
            +
            extaio_fsync(VALUE aio)
         
     | 
| 
      
 591 
     | 
    
         
            +
            {
         
     | 
| 
      
 592 
     | 
    
         
            +
                struct extaio *p = extaio_ref(aio);
         
     | 
| 
      
 593 
     | 
    
         
            +
                if (aio_fsync(O_SYNC, &p->aio) != 0) {
         
     | 
| 
      
 594 
     | 
    
         
            +
                    VALUE v = rb_inspect(p->file);
         
     | 
| 
      
 595 
     | 
    
         
            +
                    rb_sys_fail_str(v);
         
     | 
| 
      
 596 
     | 
    
         
            +
                }
         
     | 
| 
      
 597 
     | 
    
         
            +
             
     | 
| 
      
 598 
     | 
    
         
            +
                return aio;
         
     | 
| 
      
 599 
     | 
    
         
            +
            }
         
     | 
| 
      
 600 
     | 
    
         
            +
             
     | 
| 
      
 601 
     | 
    
         
            +
            #if 0
         
     | 
| 
      
 602 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 603 
     | 
    
         
            +
            extaio_fdatasync(VALUE aio)
         
     | 
| 
      
 604 
     | 
    
         
            +
            {
         
     | 
| 
      
 605 
     | 
    
         
            +
                struct extaio *p = extaio_ref(aio);
         
     | 
| 
      
 606 
     | 
    
         
            +
                if (aio_fsync(O_DSYNC, p->aio) != 0) {
         
     | 
| 
      
 607 
     | 
    
         
            +
                    VALUE v = rb_inspect(p->file);
         
     | 
| 
      
 608 
     | 
    
         
            +
                    rb_sys_fail_str(v);
         
     | 
| 
      
 609 
     | 
    
         
            +
                }
         
     | 
| 
      
 610 
     | 
    
         
            +
             
     | 
| 
      
 611 
     | 
    
         
            +
                return aio;
         
     | 
| 
      
 612 
     | 
    
         
            +
            }
         
     | 
| 
      
 613 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 614 
     | 
    
         
            +
             
     | 
| 
      
 615 
     | 
    
         
            +
            /*
         
     | 
| 
      
 616 
     | 
    
         
            +
             * call-seq:
         
     | 
| 
      
 617 
     | 
    
         
            +
             *  status -> object
         
     | 
| 
      
 618 
     | 
    
         
            +
             *
         
     | 
| 
      
 619 
     | 
    
         
            +
             * <tt>aio_return</tt> の戻り値です。
         
     | 
| 
      
 620 
     | 
    
         
            +
             *
         
     | 
| 
      
 621 
     | 
    
         
            +
             * 正常完了時は読み込みまたは書き込みデータサイズを返します。
         
     | 
| 
      
 622 
     | 
    
         
            +
             *
         
     | 
| 
      
 623 
     | 
    
         
            +
             * 処理中であれば nil を返します。
         
     | 
| 
      
 624 
     | 
    
         
            +
             *
         
     | 
| 
      
 625 
     | 
    
         
            +
             * 異常完了の場合は errno に対する Errno::EXXX クラスを返します。
         
     | 
| 
      
 626 
     | 
    
         
            +
             */
         
     | 
| 
      
 627 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 628 
     | 
    
         
            +
            extaio_status(VALUE aio)
         
     | 
| 
      
 629 
     | 
    
         
            +
            {
         
     | 
| 
      
 630 
     | 
    
         
            +
                return extaio_ref(aio)->status;
         
     | 
| 
      
 631 
     | 
    
         
            +
            }
         
     | 
| 
      
 632 
     | 
    
         
            +
             
     | 
| 
      
 633 
     | 
    
         
            +
            /*
         
     | 
| 
      
 634 
     | 
    
         
            +
             * 非同期処理の取り消しをシステムに要求します。
         
     | 
| 
      
 635 
     | 
    
         
            +
             *
         
     | 
| 
      
 636 
     | 
    
         
            +
             * 常に取り消されるわけではないことに注意してください。
         
     | 
| 
      
 637 
     | 
    
         
            +
             */
         
     | 
| 
      
 638 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 639 
     | 
    
         
            +
            extaio_cancel(VALUE aio)
         
     | 
| 
      
 640 
     | 
    
         
            +
            {
         
     | 
| 
      
 641 
     | 
    
         
            +
                struct extaio *p = extaio_ref(aio);
         
     | 
| 
      
 642 
     | 
    
         
            +
                int fd = ext_io_getfd(p->file);
         
     | 
| 
      
 643 
     | 
    
         
            +
                int status = aio_cancel(fd, &p->aio);
         
     | 
| 
      
 644 
     | 
    
         
            +
                switch (status) {
         
     | 
| 
      
 645 
     | 
    
         
            +
                case AIO_CANCELED:
         
     | 
| 
      
 646 
     | 
    
         
            +
                    return ID2SYM(rb_intern("canceled"));
         
     | 
| 
      
 647 
     | 
    
         
            +
                case AIO_NOTCANCELED:
         
     | 
| 
      
 648 
     | 
    
         
            +
                    return ID2SYM(rb_intern("notcanceled"));
         
     | 
| 
      
 649 
     | 
    
         
            +
                case AIO_ALLDONE:
         
     | 
| 
      
 650 
     | 
    
         
            +
                    return ID2SYM(rb_intern("alldone"));
         
     | 
| 
      
 651 
     | 
    
         
            +
                case -1:
         
     | 
| 
      
 652 
     | 
    
         
            +
                    rb_sys_fail_str(rb_inspect(p->file));
         
     | 
| 
      
 653 
     | 
    
         
            +
                default:
         
     | 
| 
      
 654 
     | 
    
         
            +
                    return rb_sprintf("unknown-status:0x%02x", status);
         
     | 
| 
      
 655 
     | 
    
         
            +
                }
         
     | 
| 
      
 656 
     | 
    
         
            +
            }
         
     | 
| 
      
 657 
     | 
    
         
            +
             
     | 
| 
      
 658 
     | 
    
         
            +
            /*
         
     | 
| 
      
 659 
     | 
    
         
            +
             * 正常値であれば自身を返す。
         
     | 
| 
      
 660 
     | 
    
         
            +
             *
         
     | 
| 
      
 661 
     | 
    
         
            +
             * 非同期処理中であれば nil を返す。
         
     | 
| 
      
 662 
     | 
    
         
            +
             *
         
     | 
| 
      
 663 
     | 
    
         
            +
             * エラーがあった場合は errno の例外を発生させる。
         
     | 
| 
      
 664 
     | 
    
         
            +
             */
         
     | 
| 
      
 665 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 666 
     | 
    
         
            +
            extaio_error(VALUE aio)
         
     | 
| 
      
 667 
     | 
    
         
            +
            {
         
     | 
| 
      
 668 
     | 
    
         
            +
                struct extaio *p = extaio_ref(aio);
         
     | 
| 
      
 669 
     | 
    
         
            +
                int err = aio_error(&p->aio);
         
     | 
| 
      
 670 
     | 
    
         
            +
                switch (err) {
         
     | 
| 
      
 671 
     | 
    
         
            +
                case 0:
         
     | 
| 
      
 672 
     | 
    
         
            +
                    return p->file;
         
     | 
| 
      
 673 
     | 
    
         
            +
                case EINPROGRESS:
         
     | 
| 
      
 674 
     | 
    
         
            +
                    return Qnil;
         
     | 
| 
      
 675 
     | 
    
         
            +
                case -1:
         
     | 
| 
      
 676 
     | 
    
         
            +
                    {
         
     | 
| 
      
 677 
     | 
    
         
            +
                        VALUE v = rb_inspect(p->file);
         
     | 
| 
      
 678 
     | 
    
         
            +
                        rb_sys_fail_str(v);
         
     | 
| 
      
 679 
     | 
    
         
            +
                    }
         
     | 
| 
      
 680 
     | 
    
         
            +
                    /* fall through */
         
     | 
| 
      
 681 
     | 
    
         
            +
                default:
         
     | 
| 
      
 682 
     | 
    
         
            +
                    {
         
     | 
| 
      
 683 
     | 
    
         
            +
                        errno = err;
         
     | 
| 
      
 684 
     | 
    
         
            +
                        VALUE v = rb_inspect(p->file);
         
     | 
| 
      
 685 
     | 
    
         
            +
                        rb_sys_fail_str(v);
         
     | 
| 
      
 686 
     | 
    
         
            +
                    }
         
     | 
| 
      
 687 
     | 
    
         
            +
                    //return LL2NUM(err);
         
     | 
| 
      
 688 
     | 
    
         
            +
                }
         
     | 
| 
      
 689 
     | 
    
         
            +
            }
         
     | 
| 
      
 690 
     | 
    
         
            +
             
     | 
| 
      
 691 
     | 
    
         
            +
            struct extaio_notify_dequeue_args
         
     | 
| 
      
 692 
     | 
    
         
            +
            {
         
     | 
| 
      
 693 
     | 
    
         
            +
                struct kevent kevent;
         
     | 
| 
      
 694 
     | 
    
         
            +
                const struct timespec *timeout;
         
     | 
| 
      
 695 
     | 
    
         
            +
                //int status;
         
     | 
| 
      
 696 
     | 
    
         
            +
            };
         
     | 
| 
      
 697 
     | 
    
         
            +
             
     | 
| 
      
 698 
     | 
    
         
            +
            static int
         
     | 
| 
      
 699 
     | 
    
         
            +
            extaio_notify_dequeue_ungvl(struct extaio_notify_dequeue_args *args)
         
     | 
| 
      
 700 
     | 
    
         
            +
            {
         
     | 
| 
      
 701 
     | 
    
         
            +
                return kevent(extaio_kqueue, NULL, 0, &args->kevent, 1, args->timeout);
         
     | 
| 
      
 702 
     | 
    
         
            +
            }
         
     | 
| 
      
 703 
     | 
    
         
            +
             
     | 
| 
      
 704 
     | 
    
         
            +
            static inline struct extaio *
         
     | 
| 
      
 705 
     | 
    
         
            +
            extaio_notify_dequeue(const struct timespec *timeout)
         
     | 
| 
      
 706 
     | 
    
         
            +
            {
         
     | 
| 
      
 707 
     | 
    
         
            +
                struct extaio_notify_dequeue_args args = {
         
     | 
| 
      
 708 
     | 
    
         
            +
                    .timeout = timeout,
         
     | 
| 
      
 709 
     | 
    
         
            +
                };
         
     | 
| 
      
 710 
     | 
    
         
            +
                int s = (int)rb_thread_call_without_gvl((void *(*)(void *))extaio_notify_dequeue_ungvl,
         
     | 
| 
      
 711 
     | 
    
         
            +
                                                        &args, RUBY_UBF_PROCESS, NULL);
         
     | 
| 
      
 712 
     | 
    
         
            +
                if (s == 0) {
         
     | 
| 
      
 713 
     | 
    
         
            +
                    return NULL;
         
     | 
| 
      
 714 
     | 
    
         
            +
                } else if (s > 0) {
         
     | 
| 
      
 715 
     | 
    
         
            +
                    return (struct extaio *)args.kevent.ident;
         
     | 
| 
      
 716 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 717 
     | 
    
         
            +
                    rb_sys_fail("kevent failed (signaled event)");
         
     | 
| 
      
 718 
     | 
    
         
            +
                }
         
     | 
| 
      
 719 
     | 
    
         
            +
            }
         
     | 
| 
      
 720 
     | 
    
         
            +
             
     | 
| 
      
 721 
     | 
    
         
            +
            static void *
         
     | 
| 
      
 722 
     | 
    
         
            +
            extaio_notify_cond_broadcast_ungvl(void *unused__)
         
     | 
| 
      
 723 
     | 
    
         
            +
            {
         
     | 
| 
      
 724 
     | 
    
         
            +
                (void)unused__;
         
     | 
| 
      
 725 
     | 
    
         
            +
             
     | 
| 
      
 726 
     | 
    
         
            +
                if (pthread_mutex_lock(&extaio_mutex) == 0) {
         
     | 
| 
      
 727 
     | 
    
         
            +
                    pthread_cond_broadcast(&extaio_cond);
         
     | 
| 
      
 728 
     | 
    
         
            +
                    pthread_mutex_unlock(&extaio_mutex);
         
     | 
| 
      
 729 
     | 
    
         
            +
                }
         
     | 
| 
      
 730 
     | 
    
         
            +
             
     | 
| 
      
 731 
     | 
    
         
            +
                return NULL;
         
     | 
| 
      
 732 
     | 
    
         
            +
            }
         
     | 
| 
      
 733 
     | 
    
         
            +
             
     | 
| 
      
 734 
     | 
    
         
            +
            static inline void
         
     | 
| 
      
 735 
     | 
    
         
            +
            extaio_notify_cond_broadcast(void)
         
     | 
| 
      
 736 
     | 
    
         
            +
            {
         
     | 
| 
      
 737 
     | 
    
         
            +
                rb_thread_call_without_gvl(extaio_notify_cond_broadcast_ungvl,
         
     | 
| 
      
 738 
     | 
    
         
            +
                                           NULL, RUBY_UBF_PROCESS, NULL);
         
     | 
| 
      
 739 
     | 
    
         
            +
            }
         
     | 
| 
      
 740 
     | 
    
         
            +
             
     | 
| 
      
 741 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 742 
     | 
    
         
            +
            extaio_notify_main(VALUE unused__)
         
     | 
| 
      
 743 
     | 
    
         
            +
            {
         
     | 
| 
      
 744 
     | 
    
         
            +
                (void)unused__;
         
     | 
| 
      
 745 
     | 
    
         
            +
             
     | 
| 
      
 746 
     | 
    
         
            +
                struct timespec timeout = { 1, 0 };
         
     | 
| 
      
 747 
     | 
    
         
            +
                struct extaio *aiop = extaio_notify_dequeue(&timeout);
         
     | 
| 
      
 748 
     | 
    
         
            +
             
     | 
| 
      
 749 
     | 
    
         
            +
                if (aiop) {
         
     | 
| 
      
 750 
     | 
    
         
            +
                    VALUE aio = aiop->self;
         
     | 
| 
      
 751 
     | 
    
         
            +
                    rb_str_unlocktmp(aiop->buffer);
         
     | 
| 
      
 752 
     | 
    
         
            +
                    rb_ary_delete(extio_lives, aio);
         
     | 
| 
      
 753 
     | 
    
         
            +
             
     | 
| 
      
 754 
     | 
    
         
            +
                    int s = aio_return(&aiop->aio);
         
     | 
| 
      
 755 
     | 
    
         
            +
                    if (s < 0) {
         
     | 
| 
      
 756 
     | 
    
         
            +
                        aiop->status = rb_obj_class(rb_syserr_new_str(errno, Qnil));
         
     | 
| 
      
 757 
     | 
    
         
            +
                        if (aiop->operation == EXTAIO_READ) {
         
     | 
| 
      
 758 
     | 
    
         
            +
                            rb_str_set_len(aiop->buffer, 0);
         
     | 
| 
      
 759 
     | 
    
         
            +
                        }
         
     | 
| 
      
 760 
     | 
    
         
            +
                    } else {
         
     | 
| 
      
 761 
     | 
    
         
            +
                        aiop->status = INT2FIX(s);
         
     | 
| 
      
 762 
     | 
    
         
            +
                        if (aiop->operation == EXTAIO_READ) {
         
     | 
| 
      
 763 
     | 
    
         
            +
                            rb_str_set_len(aiop->buffer, s);
         
     | 
| 
      
 764 
     | 
    
         
            +
                        }
         
     | 
| 
      
 765 
     | 
    
         
            +
                    }
         
     | 
| 
      
 766 
     | 
    
         
            +
             
     | 
| 
      
 767 
     | 
    
         
            +
                    VALUE notify_block = aiop->notify_block;
         
     | 
| 
      
 768 
     | 
    
         
            +
                    if (!NIL_P(notify_block)) {
         
     | 
| 
      
 769 
     | 
    
         
            +
                        // rb_proc_call は array オブジェクトを生成する必要があるため
         
     | 
| 
      
 770 
     | 
    
         
            +
                        // rb_proc_call_with_block に置き換えている
         
     | 
| 
      
 771 
     | 
    
         
            +
                        rb_proc_call_with_block(notify_block, 1, &aio, Qnil);
         
     | 
| 
      
 772 
     | 
    
         
            +
                    }
         
     | 
| 
      
 773 
     | 
    
         
            +
             
     | 
| 
      
 774 
     | 
    
         
            +
                    extaio_notify_cond_broadcast();
         
     | 
| 
      
 775 
     | 
    
         
            +
                }
         
     | 
| 
      
 776 
     | 
    
         
            +
             
     | 
| 
      
 777 
     | 
    
         
            +
                return 0;
         
     | 
| 
      
 778 
     | 
    
         
            +
            }
         
     | 
| 
      
 779 
     | 
    
         
            +
             
     | 
| 
      
 780 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 781 
     | 
    
         
            +
            extaio_notify(VALUE unused__)
         
     | 
| 
      
 782 
     | 
    
         
            +
            {
         
     | 
| 
      
 783 
     | 
    
         
            +
                (void)unused__;
         
     | 
| 
      
 784 
     | 
    
         
            +
             
     | 
| 
      
 785 
     | 
    
         
            +
                int state;
         
     | 
| 
      
 786 
     | 
    
         
            +
                for (;;) {
         
     | 
| 
      
 787 
     | 
    
         
            +
                    rb_set_errinfo(Qnil);
         
     | 
| 
      
 788 
     | 
    
         
            +
                    rb_protect(extaio_notify_main, 0, &state);
         
     | 
| 
      
 789 
     | 
    
         
            +
                    if (state != 0) {
         
     | 
| 
      
 790 
     | 
    
         
            +
                        //fprintf(stderr, "%s:%d:%s: rb_protect was returned state=%d (0x%08x)\n",
         
     | 
| 
      
 791 
     | 
    
         
            +
                        //        __FILE__, __LINE__, __func__, state, state);
         
     | 
| 
      
 792 
     | 
    
         
            +
                        VALUE e = rb_errinfo();
         
     | 
| 
      
 793 
     | 
    
         
            +
                        if (!NIL_P(e)) {
         
     | 
| 
      
 794 
     | 
    
         
            +
                            if (TYPE(e) == RUBY_T_FIXNUM) {
         
     | 
| 
      
 795 
     | 
    
         
            +
                                rb_jump_tag(state);
         
     | 
| 
      
 796 
     | 
    
         
            +
                            }
         
     | 
| 
      
 797 
     | 
    
         
            +
                            VALUE v = rb_inspect(e);
         
     | 
| 
      
 798 
     | 
    
         
            +
                            //fprintf(stderr, "%s:%d:%s: %s\n",
         
     | 
| 
      
 799 
     | 
    
         
            +
                            //        __FILE__, __LINE__, __func__, StringValueCStr(v));
         
     | 
| 
      
 800 
     | 
    
         
            +
                            rb_funcall(rb_thread_main(), rb_intern("raise"), 1, e);
         
     | 
| 
      
 801 
     | 
    
         
            +
                            rb_set_errinfo(Qnil);
         
     | 
| 
      
 802 
     | 
    
         
            +
                        }
         
     | 
| 
      
 803 
     | 
    
         
            +
                        //rb_jump_tag(state);
         
     | 
| 
      
 804 
     | 
    
         
            +
                    }
         
     | 
| 
      
 805 
     | 
    
         
            +
                }
         
     | 
| 
      
 806 
     | 
    
         
            +
            }
         
     | 
| 
      
 807 
     | 
    
         
            +
             
     | 
| 
      
 808 
     | 
    
         
            +
            void
         
     | 
| 
      
 809 
     | 
    
         
            +
            Init_ioplus(void)
         
     | 
| 
      
 810 
     | 
    
         
            +
            {
         
     | 
| 
      
 811 
     | 
    
         
            +
            #if EXTIO_HAVE_KEVENT
         
     | 
| 
      
 812 
     | 
    
         
            +
                extaio_kqueue = kqueue();
         
     | 
| 
      
 813 
     | 
    
         
            +
            #else
         
     | 
| 
      
 814 
     | 
    
         
            +
            #   error NOT IMPLEMENTED WITHOUT EXTIO_HAVE_KEVENT
         
     | 
| 
      
 815 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 816 
     | 
    
         
            +
             
     | 
| 
      
 817 
     | 
    
         
            +
                IDto_time = rb_intern_const("to_time");
         
     | 
| 
      
 818 
     | 
    
         
            +
             
     | 
| 
      
 819 
     | 
    
         
            +
                mIOPlus = rb_define_module("IOPlus");
         
     | 
| 
      
 820 
     | 
    
         
            +
             
     | 
| 
      
 821 
     | 
    
         
            +
                extio_lives = rb_ary_new();
         
     | 
| 
      
 822 
     | 
    
         
            +
                rb_gc_register_address(&extio_lives);
         
     | 
| 
      
 823 
     | 
    
         
            +
             
     | 
| 
      
 824 
     | 
    
         
            +
                VALUE notify_thread = rb_thread_create(extaio_notify, 0);
         
     | 
| 
      
 825 
     | 
    
         
            +
             
     | 
| 
      
 826 
     | 
    
         
            +
                /*
         
     | 
| 
      
 827 
     | 
    
         
            +
                 * This is extension module for IO.
         
     | 
| 
      
 828 
     | 
    
         
            +
                 */
         
     | 
| 
      
 829 
     | 
    
         
            +
                mIO = rb_define_module_under(mIOPlus, "IO");
         
     | 
| 
      
 830 
     | 
    
         
            +
                rb_include_module(rb_cIO, mIO);
         
     | 
| 
      
 831 
     | 
    
         
            +
                rb_define_method(mIO, "aio_cancel", RUBY_METHOD_FUNC(extio_aio_cancel), 0);
         
     | 
| 
      
 832 
     | 
    
         
            +
                rb_define_method(mIO, "aio_read", RUBY_METHOD_FUNC(extio_aio_read), -1);
         
     | 
| 
      
 833 
     | 
    
         
            +
                rb_define_method(mIO, "aio_write", RUBY_METHOD_FUNC(extio_aio_write), 2);
         
     | 
| 
      
 834 
     | 
    
         
            +
                rb_define_alias(mIO, "aread", "aio_read");
         
     | 
| 
      
 835 
     | 
    
         
            +
                rb_define_alias(mIO, "awrite", "aio_write");
         
     | 
| 
      
 836 
     | 
    
         
            +
             
     | 
| 
      
 837 
     | 
    
         
            +
                /*
         
     | 
| 
      
 838 
     | 
    
         
            +
                 * This is extension module for IO class.
         
     | 
| 
      
 839 
     | 
    
         
            +
                 */
         
     | 
| 
      
 840 
     | 
    
         
            +
                mIOClass = rb_define_module_under(mIOPlus, "IOClass");
         
     | 
| 
      
 841 
     | 
    
         
            +
                rb_extend_object(rb_cIO, mIOClass);
         
     | 
| 
      
 842 
     | 
    
         
            +
             
     | 
| 
      
 843 
     | 
    
         
            +
                /*
         
     | 
| 
      
 844 
     | 
    
         
            +
                 * This is the request context of asynchronous I/O for <tt>IO#aio_read</tt> and <tt>IO#aio_write</tt>.
         
     | 
| 
      
 845 
     | 
    
         
            +
                 *
         
     | 
| 
      
 846 
     | 
    
         
            +
                 * The instance of this class can not directly created by <tt>IOPlus::AIO.new</tt>.
         
     | 
| 
      
 847 
     | 
    
         
            +
                 */
         
     | 
| 
      
 848 
     | 
    
         
            +
                cAIO = rb_define_class_under(mIOPlus, "AIO", rb_cObject);
         
     | 
| 
      
 849 
     | 
    
         
            +
                rb_undef_alloc_func(cAIO);
         
     | 
| 
      
 850 
     | 
    
         
            +
                rb_define_method(cAIO, "to_s", RUBY_METHOD_FUNC(extaio_to_s), 0);
         
     | 
| 
      
 851 
     | 
    
         
            +
                rb_define_method(cAIO, "inspect", RUBY_METHOD_FUNC(extaio_inspect), 0);
         
     | 
| 
      
 852 
     | 
    
         
            +
                rb_define_method(cAIO, "validate", RUBY_METHOD_FUNC(extaio_validate), 0);
         
     | 
| 
      
 853 
     | 
    
         
            +
                rb_define_method(cAIO, "file", RUBY_METHOD_FUNC(extaio_file), 0);
         
     | 
| 
      
 854 
     | 
    
         
            +
                rb_define_method(cAIO, "operation", RUBY_METHOD_FUNC(extaio_operation), 0);
         
     | 
| 
      
 855 
     | 
    
         
            +
                rb_define_method(cAIO, "buffer", RUBY_METHOD_FUNC(extaio_buffer), 0);
         
     | 
| 
      
 856 
     | 
    
         
            +
                rb_define_method(cAIO, "offset", RUBY_METHOD_FUNC(extaio_offset), 0);
         
     | 
| 
      
 857 
     | 
    
         
            +
                rb_define_method(cAIO, "suspend", RUBY_METHOD_FUNC(extaio_suspend), -1);
         
     | 
| 
      
 858 
     | 
    
         
            +
                rb_define_method(cAIO, "fsync", RUBY_METHOD_FUNC(extaio_fsync), 0);
         
     | 
| 
      
 859 
     | 
    
         
            +
            #if 0
         
     | 
| 
      
 860 
     | 
    
         
            +
                rb_define_method(cAIO, "fdatasync", RUBY_METHOD_FUNC(extaio_fdatasync), 0);
         
     | 
| 
      
 861 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 862 
     | 
    
         
            +
                rb_define_method(cAIO, "status", RUBY_METHOD_FUNC(extaio_status), 0);
         
     | 
| 
      
 863 
     | 
    
         
            +
                rb_define_method(cAIO, "cancel", RUBY_METHOD_FUNC(extaio_cancel), 0);
         
     | 
| 
      
 864 
     | 
    
         
            +
                rb_define_method(cAIO, "error", RUBY_METHOD_FUNC(extaio_error), 0);
         
     | 
| 
      
 865 
     | 
    
         
            +
            }
         
     | 
    
        data/gemstub.rb
    ADDED
    
    | 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            GEMSTUB = Gem::Specification.new do |s|
         
     | 
| 
      
 2 
     | 
    
         
            +
              s.name = "ioplus"
         
     | 
| 
      
 3 
     | 
    
         
            +
              s.version = "0.0.1.PROTOTYPE"
         
     | 
| 
      
 4 
     | 
    
         
            +
              s.summary = "Append IO#aio_read/aio_write methods. These provide similar functionality to aio_read(2)/aio_write(2)."
         
     | 
| 
      
 5 
     | 
    
         
            +
              s.description = <<EOS
         
     | 
| 
      
 6 
     | 
    
         
            +
            "ioplus" is appended IO#aio_read/aio_write methods. These provide similar functionality to aio_read(2)/aio_write(2).
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            This library need posix aio(4) and kqueue(2). Tested on FreeBSD 10.1 only.
         
     | 
| 
      
 9 
     | 
    
         
            +
            EOS
         
     | 
| 
      
 10 
     | 
    
         
            +
              s.license = "2-clause BSD License"
         
     | 
| 
      
 11 
     | 
    
         
            +
              s.author = "dearblue"
         
     | 
| 
      
 12 
     | 
    
         
            +
              s.email = "dearblue@users.sourceforge.jp"
         
     | 
| 
      
 13 
     | 
    
         
            +
              s.homepage = "http://sourceforge.jp/projects/rutsubo/"
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              s.required_ruby_version = ">= 2.0"
         
     | 
| 
      
 16 
     | 
    
         
            +
              s.add_development_dependency "rspec", "~> 2.14"
         
     | 
| 
      
 17 
     | 
    
         
            +
              s.add_development_dependency "rake", "~> 10.0"
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/ioplus.rb
    ADDED
    
    | 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            require "rbconfig"
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            ver = RbConfig::CONFIG["ruby_version"]
         
     | 
| 
      
 5 
     | 
    
         
            +
            soname = File.basename(__FILE__, ".rb") << ".so"
         
     | 
| 
      
 6 
     | 
    
         
            +
            lib = File.join(File.dirname(__FILE__), ver, soname)
         
     | 
| 
      
 7 
     | 
    
         
            +
            if File.file?(lib)
         
     | 
| 
      
 8 
     | 
    
         
            +
              require_relative File.join(ver, soname)
         
     | 
| 
      
 9 
     | 
    
         
            +
            else
         
     | 
| 
      
 10 
     | 
    
         
            +
              require_relative soname
         
     | 
| 
      
 11 
     | 
    
         
            +
            end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            module IOPlus
         
     | 
| 
      
 14 
     | 
    
         
            +
              module IOClass
         
     | 
| 
      
 15 
     | 
    
         
            +
                def aio_suspend(*aio, timeout: nil)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  aio.each { |x| x.suspend(timeout) }
         
     | 
| 
      
 17 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              class AIO
         
     | 
| 
      
 22 
     | 
    
         
            +
                def pretty_print(q)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  return q.text("#<#{to_s} **INVALID-REFERENCE**>") unless validate
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  q.group(2, "#<#{to_s}") do
         
     | 
| 
      
 26 
     | 
    
         
            +
                    q.breakable " "
         
     | 
| 
      
 27 
     | 
    
         
            +
                    q.text "operation=#{operation},"
         
     | 
| 
      
 28 
     | 
    
         
            +
                    q.breakable " "
         
     | 
| 
      
 29 
     | 
    
         
            +
                    q.text "file="
         
     | 
| 
      
 30 
     | 
    
         
            +
                    q.pp file
         
     | 
| 
      
 31 
     | 
    
         
            +
                    q.text ","
         
     | 
| 
      
 32 
     | 
    
         
            +
                    q.breakable " "
         
     | 
| 
      
 33 
     | 
    
         
            +
                    q.text "offset="
         
     | 
| 
      
 34 
     | 
    
         
            +
                    q.pp offset
         
     | 
| 
      
 35 
     | 
    
         
            +
                    q.text ","
         
     | 
| 
      
 36 
     | 
    
         
            +
                    q.breakable " "
         
     | 
| 
      
 37 
     | 
    
         
            +
                    q.text "buffer.bytesize="
         
     | 
| 
      
 38 
     | 
    
         
            +
                    q.pp buffer.bytesize
         
     | 
| 
      
 39 
     | 
    
         
            +
                    q.text ","
         
     | 
| 
      
 40 
     | 
    
         
            +
                    q.breakable " "
         
     | 
| 
      
 41 
     | 
    
         
            +
                    q.text "status="
         
     | 
| 
      
 42 
     | 
    
         
            +
                    q.pp status
         
     | 
| 
      
 43 
     | 
    
         
            +
                    q.text ">"
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,90 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: ioplus
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.1.PROTOTYPE
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - dearblue
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2015-02-08 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              name: rspec
         
     | 
| 
      
 15 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 16 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 17 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 19 
     | 
    
         
            +
                    version: '2.14'
         
     | 
| 
      
 20 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 21 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 23 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 25 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 26 
     | 
    
         
            +
                    version: '2.14'
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: rake
         
     | 
| 
      
 29 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 30 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: '10.0'
         
     | 
| 
      
 34 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 35 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 36 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 37 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 38 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 39 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 40 
     | 
    
         
            +
                    version: '10.0'
         
     | 
| 
      
 41 
     | 
    
         
            +
            description: |
         
     | 
| 
      
 42 
     | 
    
         
            +
              "ioplus" is appended IO#aio_read/aio_write methods. These provide similar functionality to aio_read(2)/aio_write(2).
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              This library need posix aio(4) and kqueue(2). Tested on FreeBSD 10.1 only.
         
     | 
| 
      
 45 
     | 
    
         
            +
            email: dearblue@users.sourceforge.jp
         
     | 
| 
      
 46 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 47 
     | 
    
         
            +
            extensions:
         
     | 
| 
      
 48 
     | 
    
         
            +
            - ext/extconf.rb
         
     | 
| 
      
 49 
     | 
    
         
            +
            extra_rdoc_files:
         
     | 
| 
      
 50 
     | 
    
         
            +
            - LICENSE.md
         
     | 
| 
      
 51 
     | 
    
         
            +
            - README.ja.md
         
     | 
| 
      
 52 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 53 
     | 
    
         
            +
            - ext/extio.c
         
     | 
| 
      
 54 
     | 
    
         
            +
            - lib/ioplus.rb
         
     | 
| 
      
 55 
     | 
    
         
            +
            files:
         
     | 
| 
      
 56 
     | 
    
         
            +
            - LICENSE.md
         
     | 
| 
      
 57 
     | 
    
         
            +
            - README.ja.md
         
     | 
| 
      
 58 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 59 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 60 
     | 
    
         
            +
            - examples/aio_read.rb
         
     | 
| 
      
 61 
     | 
    
         
            +
            - ext/extconf.rb
         
     | 
| 
      
 62 
     | 
    
         
            +
            - ext/extio.c
         
     | 
| 
      
 63 
     | 
    
         
            +
            - gemstub.rb
         
     | 
| 
      
 64 
     | 
    
         
            +
            - lib/ioplus.rb
         
     | 
| 
      
 65 
     | 
    
         
            +
            homepage: http://sourceforge.jp/projects/rutsubo/
         
     | 
| 
      
 66 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 67 
     | 
    
         
            +
            - 2-clause BSD License
         
     | 
| 
      
 68 
     | 
    
         
            +
            metadata: {}
         
     | 
| 
      
 69 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 70 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 71 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 72 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 73 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 74 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 75 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 76 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 77 
     | 
    
         
            +
                  version: '2.0'
         
     | 
| 
      
 78 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 79 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 80 
     | 
    
         
            +
              - - ">"
         
     | 
| 
      
 81 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 82 
     | 
    
         
            +
                  version: 1.3.1
         
     | 
| 
      
 83 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 84 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 85 
     | 
    
         
            +
            rubygems_version: 2.4.5
         
     | 
| 
      
 86 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 87 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 88 
     | 
    
         
            +
            summary: Append IO#aio_read/aio_write methods. These provide similar functionality
         
     | 
| 
      
 89 
     | 
    
         
            +
              to aio_read(2)/aio_write(2).
         
     | 
| 
      
 90 
     | 
    
         
            +
            test_files: []
         
     |