Skip to content

Commit a465d00

Browse files
authored
Merge pull request #3305 from Watson1978/io-buffer-state-queries
IO::Buffer: 状態問い合わせの 10 メソッドを追加
2 parents 3e0b9a1 + bc8fbae commit a465d00

1 file changed

Lines changed: 137 additions & 4 deletions

File tree

manual/api/_builtin/IO__Buffer.md

Lines changed: 137 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ include:
1010
Ruby 3.1 で導入されました。
1111

1212
[c:String] を経由せずにメモリ領域を扱えるため、コピーを避けた入出力
13-
(zero-copy IO)を実現するために使われます。主に [c:Fiber::Scheduler]
13+
(zero-copy IO)を実現するために使われます。主に
14+
[Fiber::Scheduler](https://docs.ruby-lang.org/en/4.0/Fiber/Scheduler.html)
1415
実装のような、低レベルな入出力を扱う場面で利用します。
1516

1617
バッファは以下のいずれかの方法で確保されたメモリ領域を指します。
@@ -78,7 +79,8 @@ OS のページサイズをバイト数で表した値です。
7879
バッファがロックされていることを表すフラグです。
7980

8081
ロックされている間はバッファの解放やリサイズができません。
81-
[m:IO::Buffer#locked] を参照してください。
82+
バッファがロックされているかどうかは [m:IO::Buffer#locked?] で調べられます。
83+
#@# locked を収録したら、ブロックの間ロックする IO::Buffer#locked への言及も足す
8284

8385
### const PRIVATE -> Integer
8486

@@ -118,7 +120,7 @@ p IO::Buffer::HOST_ENDIAN == IO::Buffer::LITTLE_ENDIAN # => true
118120
size バイトの、0 で埋められた新しいバッファを作成して返します。
119121

120122
既定では内部(internal)バッファ、すなわち Ruby が直接確保したメモリ領域に
121-
なります。ただし size が OS 依存の [m:IO::Buffer::PAGE_SIZE] より大きい場合は
123+
なります。ただし size が OS 依存の [m:IO::Buffer::PAGE_SIZE] 以上の場合は
122124
仮想メモリ機構(Unix では匿名 mmap、Windows では VirtualAlloc)を用いて
123125
確保されます。flags に [m:IO::Buffer::MAPPED] を指定すると、
124126
size によらず後者の方法で確保されます。
@@ -299,7 +301,8 @@ p buf.get_string # => "\x00AA\x00"
299301
変更後の大きさによっては、メモリ領域が別の場所に確保しなおされ、
300302
内容がそこへコピーされます。
301303

302-
[m:IO::Buffer.for] で作った外部バッファや、ロックされたバッファは大きさを変更できません。
304+
#@# for を収録したらリンクに戻す
305+
`IO::Buffer.for` で作った外部バッファや、ロックされたバッファは大きさを変更できません。
303306

304307
- **param** `size` -- 変更後の大きさをバイト数で指定します。
305308
- **raise** `IO::Buffer::AccessError` -- 大きさを変更できないバッファに対して呼び出した場合に発生します。
@@ -369,3 +372,133 @@ p buf.size # => 4
369372
```
370373

371374
- **SEE** [m:IO::Buffer#transfer], [m:IO::Buffer#null?]
375+
376+
### def empty? -> bool
377+
378+
バッファの大きさが 0 の場合に true を返します。
379+
380+
#@# for を収録したらリンクに戻す
381+
大きさ 0 のバッファは、[m:IO::Buffer.new] に 0 を渡すか、
382+
空文字列から `IO::Buffer.for` で作った場合などにできます。
383+
384+
```ruby
385+
p IO::Buffer.new(0).empty? # => true
386+
p IO::Buffer.new(4).empty? # => false
387+
```
388+
389+
### def null? -> bool
390+
391+
バッファがどのメモリ領域も指していない場合に true を返します。
392+
393+
[m:IO::Buffer#free] で解放したバッファ、[m:IO::Buffer#transfer] で所有権を手放した
394+
バッファ、および最初からメモリ領域を確保していないバッファがこれにあたります。
395+
396+
```ruby
397+
p IO::Buffer.new(0).null? # => true
398+
399+
buf = IO::Buffer.new(4)
400+
p buf.null? # => false
401+
buf.free
402+
p buf.null? # => true
403+
```
404+
405+
- **SEE** [m:IO::Buffer#free], [m:IO::Buffer#transfer]
406+
407+
### def valid? -> bool
408+
409+
バッファがアクセス可能な場合に true を返します。
410+
411+
別のバッファや文字列の一部を参照している([m:IO::Buffer#slice] で作った)バッファは、
412+
参照元が解放されたり別のアドレスに再確保されたりすると、アクセスできなくなります。
413+
414+
### def internal? -> bool
415+
416+
バッファが内部(internal)バッファである場合に true を返します。
417+
418+
内部バッファは、バッファ自身が確保したメモリ領域を参照します。
419+
文字列などの外部のメモリやファイルのマッピングとは結び付いていません。
420+
[m:IO::Buffer.new] で作られるバッファは既定で内部バッファです。
421+
422+
```ruby
423+
p IO::Buffer.new(4).internal? # => true
424+
```
425+
426+
- **SEE** [m:IO::Buffer#external?]
427+
428+
### def external? -> bool
429+
430+
バッファが外部(external)バッファである場合に true を返します。
431+
432+
外部バッファは、バッファ自身が確保・マップしたのではないメモリ領域を参照します。
433+
#@# for を収録したらリンクに戻す
434+
`IO::Buffer.for` で作ったバッファは、文字列のメモリを外部参照します。
435+
外部バッファは大きさを変更できません。
436+
437+
```ruby
438+
p IO::Buffer.for("test").external? # => true
439+
p IO::Buffer.new(4).external? # => false
440+
```
441+
442+
- **SEE** [m:IO::Buffer#internal?]
443+
444+
### def readonly? -> bool
445+
446+
バッファが読み取り専用の場合に true を返します。
447+
448+
#@# set_value / for を収録したらリンクに戻す
449+
読み取り専用のバッファは、`IO::Buffer#set_value`[m:IO::Buffer#set_string]
450+
[m:IO::Buffer#copy] などで変更できません。
451+
452+
`IO::Buffer.for` にブロックを渡さずに作ったバッファは、元の文字列が freeze
453+
されているかどうかによらず、常に読み取り専用になります。内部で作った文字列の
454+
複製をバッファの元として使うためです。
455+
ブロックを渡した場合は元の文字列のメモリを直接参照するため、
456+
その文字列が freeze されている場合にだけ読み取り専用になります。
457+
読み取り専用のファイルから作ったバッファも読み取り専用です。
458+
459+
```ruby
460+
# ブロックを渡さない場合は、元の文字列が freeze されていなくても読み取り専用
461+
p IO::Buffer.for("test").readonly? # => true
462+
463+
# ブロックを渡した場合は元の文字列に従う
464+
p IO::Buffer.for("test") { |buf| buf.readonly? } # => false
465+
p IO::Buffer.for("test".freeze) { |buf| buf.readonly? } # => true
466+
467+
p IO::Buffer.new(4).readonly? # => false
468+
```
469+
470+
### def mapped? -> bool
471+
472+
バッファがマップ(mapped)バッファである場合に true を返します。
473+
474+
マップバッファは、仮想メモリ機構でマップされたメモリ領域を参照します。
475+
[m:IO::Buffer.new][m:IO::Buffer::MAPPED] を指定した場合や、
476+
大きさが [m:IO::Buffer::PAGE_SIZE] 以上の場合は匿名のマップになります。
477+
#@# map を収録したらリンクに戻す
478+
`IO::Buffer.map` で作った場合はファイルに紐づいたマップになります。
479+
480+
### def locked? -> bool
481+
482+
バッファがロックされている場合に true を返します。
483+
484+
ロックされたバッファは大きさの変更や解放ができず、
485+
さらにロックを取得することもできません。
486+
システムコールでバッファを使っている間に、そのバッファが移動しないことを
487+
保証するための仕組みです。
488+
489+
#@since 3.2
490+
### def shared? -> bool
491+
492+
バッファが共有(shared)バッファである場合に true を返します。
493+
494+
共有バッファは、他のプロセスと共有できるメモリ領域を参照します。
495+
そのため、このプロセスで変更しなくても内容が変わることがあります。
496+
#@end
497+
498+
#@since 3.3
499+
### def private? -> bool
500+
501+
バッファがプライベート(private)バッファである場合に true を返します。
502+
503+
プライベートバッファに加えた変更は、元になったファイルのマッピングには反映されません。
504+
#@end

0 commit comments

Comments
 (0)