要約
メモリ領域を直接読み書きするための低レベルなバッファを表すクラスです。 Ruby 3.1 で導入されました。
String を経由せずにメモリ領域を扱えるため、コピーを避けた入出力 (zero-copy IO)を実現するために使われます。主に Fiber::Scheduler の実装のような、低レベルな入出力を扱う場面で利用します。
バッファは以下のいずれかの方法で確保されたメモリ領域を指します。
- 内部(internal) -- Ruby が確保したメモリ領域。IO::Buffer.new で作られます。
- 外部(external) -- String など、Ruby の他のオブジェクトが持つメモリ領域。
- マップ(mapped) -- 仮想メモリ機構(Unix の mmap など)で確保されたメモリ領域。
このクラスは実験的な機能です。利用すると「IO::Buffer is experimental and both the Ruby and C interface may change in the future!」という警告が出力されます。将来のバージョンで Ruby と C の双方のインターフェースが変更される可能性があります。
この警告は Warning[:experimental] = false を指定すると抑止できます。
buf = IO::Buffer.new(8)
p buf.size # => 8
buf.set_string("Ruby")
p buf.get_string # => "Ruby\x00\x00\x00\x00"
p buf.get_string(0, 4) # => "Ruby"
目次
- 特異メソッド
- インスタンスメソッド
- 定数
継承しているメソッド
特異メソッド
new(size = IO::Buffer::DEFAULT_SIZE, flags = 0) -> IO::BufferRuby 3.1 から[permalink][rdoc][edit]-
size バイトの、0 で埋められた新しいバッファを作成して返します。
既定では内部(internal)バッファ、すなわち Ruby が直接確保したメモリ領域になります。ただし size が OS 依存の IO::Buffer::PAGE_SIZE 以上の場合は、仮想メモリ機構(Unix では匿名 mmap、Windows では VirtualAlloc)を用いて確保されます。flags に IO::Buffer::MAPPED を指定すると、 size によらず後者の方法で確保されます。
- [PARAM]
size: - 確保するバッファのバイト数を整数で指定します。省略した場合は IO::Buffer::DEFAULT_SIZE になります。
- [PARAM]
flags: - バッファの確保方法を IO::Buffer::MAPPED などの定数で指定します。
buf = IO::Buffer.new(4) p buf.size # => 4 p buf.internal? # => true p buf.get_string # => "\x00\x00\x00\x00" - [PARAM]
インスタンスメソッド
clear(value = 0, offset = 0, length = nil) -> selfRuby 3.1 から[permalink][rdoc][edit]-
バッファを value で埋めます。
- [PARAM]
value: - 埋める値を 0 から 255 の Integer で指定します。
- [PARAM]
offset: - 埋め始める位置をバッファの先頭からのバイト数で指定します。
- [PARAM]
length: - 埋めるバイト数を指定します。省略した場合はバッファの末尾までを埋めます。
- [EXCEPTION]
IO::Buffer::AccessError: - 書き込みできないバッファに対して呼び出した場合に発生します。
buf = IO::Buffer.new(4) buf.set_string("test") buf.clear p buf.get_string # => "\x00\x00\x00\x00" # 位置と長さを指定して "A" (0x41) で埋める buf.clear(0x41, 1, 2) p buf.get_string # => "\x00AA\x00" - [PARAM]
copy(source, offset = 0, length = nil, source_offset = 0) -> IntegerRuby 3.1 から[permalink][rdoc][edit]-
別の IO::Buffer の内容を自身へコピーします。コピーしたバイト数を返します。
String の内容を書き込む場合は IO::Buffer#set_string を使用してください。
- [PARAM]
source: - コピー元を IO::Buffer で指定します。
- [PARAM]
offset: - 書き込みを開始する位置をバッファの先頭からのバイト数で指定します。
- [PARAM]
length: - コピーするバイト数を指定します。省略した場合は source 全体をコピーします。
- [PARAM]
source_offset: - source のどの位置から読み出すかをバイト数で指定します。
- [EXCEPTION]
ArgumentError: - offset と length の合計がバッファのバイト数を超える場合に発生します。
- [EXCEPTION]
IO::Buffer::AccessError: - 書き込みできないバッファに対して呼び出した場合に発生します。
buf = IO::Buffer.new(8) p buf.copy(IO::Buffer.for("test"), 2) # => 4 p buf.get_string # => "\x00\x00test\x00\x00" # 長さを指定して先頭 3 バイトだけコピーする other = IO::Buffer.new(8) p other.copy(IO::Buffer.for("abcdef"), 0, 3) # => 3 p other.get_string(0, 3) # => "abc"[SEE_ALSO] IO::Buffer#set_string, IO::Buffer#slice
- [PARAM]
empty? -> boolRuby 3.1 から[permalink][rdoc][edit]-
バッファの大きさが 0 の場合に true を返します。
大きさ 0 のバッファは、IO::Buffer.new に 0 を渡すか、空文字列から
IO::Buffer.forで作った場合などにできます。p IO::Buffer.new(0).empty? # => true p IO::Buffer.new(4).empty? # => false external? -> boolRuby 3.1 から[permalink][rdoc][edit]-
バッファが外部(external)バッファである場合に true を返します。
外部バッファは、バッファ自身が確保・マップしたのではないメモリ領域を参照します。
IO::Buffer.forで作ったバッファは、文字列のメモリを外部参照します。外部バッファは大きさを変更できません。p IO::Buffer.for("test").external? # => true p IO::Buffer.new(4).external? # => false[SEE_ALSO] IO::Buffer#internal?
free -> selfRuby 3.1 から[permalink][rdoc][edit]-
バッファが確保しているメモリ領域を解放します。
解放の内容はバッファの種類によって異なります。
- 内部(internal) -- 確保したメモリを解放します。
- 外部(external) -- 元のオブジェクトとの関連を解消します。
- マップ(mapped) -- マッピングを解除します。
解放後は、どのメモリ領域も指さない状態になります。この状態のバッファは大きさ 0 のバッファとして扱われます。
解放したバッファでも IO::Buffer#resize を呼べば、あらためてメモリ領域を確保できます。
buf = IO::Buffer.new(4) buf.set_string("Ruby") buf.free p buf.null? # => true p buf.size # => 0 # resize すれば再び使える buf.resize(4) p buf.size # => 4[SEE_ALSO] IO::Buffer#transfer, IO::Buffer#null?
get_string(offset = 0, length = nil, encoding = Encoding::BINARY) -> StringRuby 3.1 から[permalink][rdoc][edit]-
バッファの内容を String として取り出して返します。
- [PARAM]
offset: - 読み出しを開始する位置をバッファの先頭からのバイト数で指定します。
- [PARAM]
length: - 読み出すバイト数を指定します。省略した場合は offset からバッファの終端までを読み出します。
- [PARAM]
encoding: - 返す文字列のエンコーディングを指定します。省略した場合は Encoding::BINARY になります。
- [EXCEPTION]
ArgumentError: - offset と length の合計がバッファのバイト数を超える場合に発生します。
buf = IO::Buffer.new(8) buf.set_string("Ruby") p buf.get_string # => "Ruby\x00\x00\x00\x00" p buf.get_string(0, 4) # => "Ruby" p buf.get_string(1, 3) # => "uby" p buf.get_string(0, 4).encoding # => #<Encoding:BINARY (ASCII-8BIT)> p buf.get_string(0, 4, Encoding::UTF_8).encoding # => #<Encoding:UTF-8> buf.get_string(0, 99) # ~> ArgumentError[SEE_ALSO] IO::Buffer#set_string
- [PARAM]
internal? -> boolRuby 3.1 から[permalink][rdoc][edit]-
バッファが内部(internal)バッファである場合に true を返します。
内部バッファは、バッファ自身が確保したメモリ領域を参照します。文字列などの外部のメモリやファイルのマッピングとは結び付いていません。 IO::Buffer.new で作られるバッファは既定で内部バッファです。
p IO::Buffer.new(4).internal? # => true[SEE_ALSO] IO::Buffer#external?
locked? -> boolRuby 3.1 から[permalink][rdoc][edit]-
バッファがロックされている場合に true を返します。
ロックされたバッファは大きさの変更や解放ができず、さらにロックを取得することもできません。システムコールでバッファを使っている間に、そのバッファが移動しないことを保証するための仕組みです。
mapped? -> boolRuby 3.1 から[permalink][rdoc][edit]-
バッファがマップ(mapped)バッファである場合に true を返します。
マップバッファは、仮想メモリ機構でマップされたメモリ領域を参照します。 IO::Buffer.new に IO::Buffer::MAPPED を指定した場合や、大きさが IO::Buffer::PAGE_SIZE 以上の場合は匿名のマップになります。
IO::Buffer.mapで作った場合はファイルに紐づいたマップになります。 null? -> boolRuby 3.1 から[permalink][rdoc][edit]-
バッファがどのメモリ領域も指していない場合に true を返します。
IO::Buffer#free で解放したバッファ、IO::Buffer#transfer で所有権を手放したバッファ、および最初からメモリ領域を確保していないバッファがこれにあたります。
p IO::Buffer.new(0).null? # => true buf = IO::Buffer.new(4) p buf.null? # => false buf.free p buf.null? # => true[SEE_ALSO] IO::Buffer#free, IO::Buffer#transfer
private? -> boolRuby 3.3 から[permalink][rdoc][edit]-
バッファがプライベート(private)バッファである場合に true を返します。
プライベートバッファに加えた変更は、元になったファイルのマッピングには反映されません。
readonly? -> boolRuby 3.1 から[permalink][rdoc][edit]-
バッファが読み取り専用の場合に true を返します。
読み取り専用のバッファは、
IO::Buffer#set_valueや IO::Buffer#set_string、 IO::Buffer#copy などで変更できません。IO::Buffer.forにブロックを渡さずに作ったバッファは、元の文字列が freeze されているかどうかによらず、常に読み取り専用になります。内部で作った文字列の複製をバッファの元として使うためです。ブロックを渡した場合は元の文字列のメモリを直接参照するため、その文字列が freeze されている場合にだけ読み取り専用になります。読み取り専用のファイルから作ったバッファも読み取り専用です。# ブロックを渡さない場合は、元の文字列が freeze されていなくても読み取り専用 p IO::Buffer.for("test").readonly? # => true # ブロックを渡した場合は元の文字列に従う p IO::Buffer.for("test") { |buf| buf.readonly? } # => false p IO::Buffer.for("test".freeze) { |buf| buf.readonly? } # => true p IO::Buffer.new(4).readonly? # => false resize(size) -> selfRuby 3.1 から[permalink][rdoc][edit]-
バッファの大きさを size バイトに変更します。
変更前の内容は保持されます。変更後の大きさによっては、メモリ領域が別の場所に確保しなおされ、内容がそこへコピーされます。
IO::Buffer.forで作った外部バッファや、ロックされたバッファは大きさを変更できません。- [PARAM]
size: - 変更後の大きさをバイト数で指定します。
- [EXCEPTION]
IO::Buffer::AccessError: - 大きさを変更できないバッファに対して呼び出した場合に発生します。
buf = IO::Buffer.new(4) buf.set_string("test") buf.resize(8) p buf.size # => 8 p buf.get_string(0, 4) # => "test" IO::Buffer.for("abc").resize(8) # ~> IO::Buffer::AccessError - [PARAM]
set_string(string, offset = 0, length = nil, source_offset = 0) -> IntegerRuby 3.1 から[permalink][rdoc][edit]-
文字列 string の内容をバッファに書き込みます。書き込んだバイト数を返します。
- [PARAM]
string: - 書き込む内容を String で指定します。
- [PARAM]
offset: - 書き込みを開始する位置をバッファの先頭からのバイト数で指定します。
- [PARAM]
length: - 書き込むバイト数を指定します。省略した場合は string 全体を書き込みます。
- [PARAM]
source_offset: - string のどの位置から読み出すかをバイト数で指定します。
- [EXCEPTION]
ArgumentError: - offset と length の合計がバッファのバイト数を超える場合に発生します。
- [EXCEPTION]
IO::Buffer::AccessError: - 書き込みできないバッファに対して呼び出した場合に発生します。詳しくは IO::Buffer::AccessError を参照してください。
buf = IO::Buffer.new(8) p buf.set_string("Ruby") # => 4 p buf.get_string # => "Ruby\x00\x00\x00\x00" buf.set_string("XY", 6) p buf.get_string # => "Ruby\x00\x00XY" IO::Buffer.new(2).set_string("TOOLONG") # ~> ArgumentError[SEE_ALSO] IO::Buffer#get_string
- [PARAM]
shared? -> boolRuby 3.2 から[permalink][rdoc][edit]-
バッファが共有(shared)バッファである場合に true を返します。
共有バッファは、他のプロセスと共有できるメモリ領域を参照します。そのため、このプロセスで変更しなくても内容が変わることがあります。
size -> IntegerRuby 3.1 から[permalink][rdoc][edit]-
バッファのバイト数を返します。
p IO::Buffer.new(8).size # => 8 slice(offset = 0, length = nil) -> IO::BufferRuby 3.1 から[permalink][rdoc][edit]-
バッファの一部を指す新しい IO::Buffer を返します。
メモリのコピーは行わず、返されるバッファは元のバッファと同じメモリ領域を参照します。そのため、一方への書き込みはもう一方からも見えます。元のバッファが文字列やファイルに由来する場合、その関連も引き継がれます。
- [PARAM]
offset: - 参照を開始する位置をバッファの先頭からのバイト数で指定します。省略した場合は 0 になります。
- [PARAM]
length: - 参照するバイト数を指定します。省略した場合はバッファの末尾までになります。
- [EXCEPTION]
ArgumentError: - offset や length が負の場合、または offset と length の合計がバッファのバイト数を超える場合に発生します。
buf = IO::Buffer.new(8) buf.set_string("Ruby") part = buf.slice(0, 4) p part.get_string # => "Ruby" # 同じメモリ領域を参照しているので、変更は元のバッファにも反映される part.set_string("Xy") p buf.get_string # => "Xyby\x00\x00\x00\x00"[SEE_ALSO] IO::Buffer#copy
- [PARAM]
transfer -> IO::BufferRuby 3.1 から[permalink][rdoc][edit]-
メモリ領域の所有権を新しい IO::Buffer へ移し、その新しいバッファを返します。
所有権を手放した自身は、どのメモリ領域も指さない状態になります。この状態は IO::Buffer#null? で調べられます。
buf = IO::Buffer.new(4) buf.set_string("Ruby") other = buf.transfer p other.get_string # => "Ruby" p buf.null? # => true p buf.size # => 0[SEE_ALSO] IO::Buffer#free, IO::Buffer#null?
valid? -> boolRuby 3.1 から[permalink][rdoc][edit]-
バッファがアクセス可能な場合に true を返します。
別のバッファや文字列の一部を参照している(IO::Buffer#slice で作った)バッファは、参照元が解放されたり別のアドレスに再確保されたりすると、アクセスできなくなります。
定数
LITTLE_ENDIAN -> IntegerRuby 3.1 から[permalink][rdoc][edit]BIG_ENDIAN -> IntegerHOST_ENDIAN -> IntegerNETWORK_ENDIAN -> Integer-
バイトオーダー(エンディアン)を表す定数です。
HOST_ENDIAN は実行中の環境のバイトオーダーで、LITTLE_ENDIAN か BIG_ENDIAN のいずれかと同じ値になります。NETWORK_ENDIAN はネットワークバイトオーダーで、 BIG_ENDIAN と同じ値です。
p IO::Buffer::NETWORK_ENDIAN == IO::Buffer::BIG_ENDIAN # => true # リトルエンディアンの環境の場合 p IO::Buffer::HOST_ENDIAN == IO::Buffer::LITTLE_ENDIAN # => true DEFAULT_SIZE -> IntegerRuby 3.1 から[permalink][rdoc][edit]-
IO::Buffer.new で size を省略した場合に使われる既定のバイト数です。
値は環境依存です。
EXTERNAL -> IntegerRuby 3.1 から[permalink][rdoc][edit]-
バッファが外部(external)のメモリ領域、すなわち String など他のオブジェクトが所有するメモリ領域を指していることを表すフラグです。
INTERNAL -> IntegerRuby 3.1 から[permalink][rdoc][edit]-
バッファが内部(internal)のメモリ領域、すなわち Ruby が直接確保したメモリ領域を指していることを表すフラグです。
LOCKED -> IntegerRuby 3.1 から[permalink][rdoc][edit]-
バッファがロックされていることを表すフラグです。
ロックされている間はバッファの解放やリサイズができません。バッファがロックされているかどうかは IO::Buffer#locked? で調べられます。
MAPPED -> IntegerRuby 3.1 から[permalink][rdoc][edit]-
バッファを仮想メモリ機構(Unix では匿名 mmap、Windows では VirtualAlloc)で確保することを表すフラグです。IO::Buffer.new の flags に指定します。
PAGE_SIZE -> IntegerRuby 3.1 から[permalink][rdoc][edit]-
OS のページサイズをバイト数で表した値です。
IO::Buffer.new は、size がこの値より大きい場合に仮想メモリ機構を用いてバッファを確保します。
値は環境依存です。
PRIVATE -> IntegerRuby 3.1 から[permalink][rdoc][edit]-
バッファがコピーオンライトで確保されていることを表すフラグです。
このバッファへの変更は元のメモリ領域には反映されません。
READONLY -> IntegerRuby 3.1 から[permalink][rdoc][edit]-
バッファが読み込み専用であることを表すフラグです。
このフラグが立っているバッファに書き込もうとすると IO::Buffer::AccessError が発生します。
SHARED -> IntegerRuby 3.2 から[permalink][rdoc][edit]-
バッファが他のプロセスと共有されるメモリ領域を指していることを表すフラグです。