[前][次][番号順一覧][スレッド一覧]

ruby-changes:69714

From: Samuel <ko1@a...>
Date: Fri, 12 Nov 2021 12:46:23 +0900 (JST)
Subject: [ruby-changes:69714] c833ece5f7 (master): Rework implementation of `IO::Buffer.for(string)` to use string locking.

https://git.ruby-lang.org/ruby.git/commit/?id=c833ece5f7

From c833ece5f78b8c2e43263e08ccbd3ce1628bf610 Mon Sep 17 00:00:00 2001
From: Samuel Williams <samuel.williams@o...>
Date: Fri, 22 Oct 2021 15:05:00 +1300
Subject: Rework implementation of `IO::Buffer.for(string)` to use string
 locking.

---
 io_buffer.c                 | 20 ++++++++++++++++++++
 test/ruby/test_io_buffer.rb | 19 +++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/io_buffer.c b/io_buffer.c
index 1acc942987f..9b8f85ed4cc 100644
--- a/io_buffer.c
+++ b/io_buffer.c
@@ -182,6 +182,10 @@ io_buffer_free(struct rb_io_buffer *data) https://github.com/ruby/ruby/blob/trunk/io_buffer.c#L182
             io_buffer_unmap(data->base, data->size);
         }
 
+        if (RB_TYPE_P(data->source, T_STRING)) {
+            rb_str_unlocktmp(data->source);
+        }
+
         data->base = NULL;
 
 #if defined(_WIN32)
@@ -252,6 +256,21 @@ rb_io_buffer_type_allocate(VALUE self) https://github.com/ruby/ruby/blob/trunk/io_buffer.c#L256
     return instance;
 }
 
+VALUE
+rb_io_buffer_type_for(VALUE klass, VALUE string)
+{
+    VALUE instance = rb_io_buffer_type_allocate(klass);
+
+    struct rb_io_buffer *data = NULL;
+    TypedData_Get_Struct(instance, struct rb_io_buffer, &rb_io_buffer_type, data);
+
+    rb_str_locktmp(string);
+
+    io_buffer_initialize(data, RSTRING_PTR(string), RSTRING_LEN(string), RB_IO_BUFFER_EXTERNAL, string);
+
+    return instance;
+}
+
 VALUE
 rb_io_buffer_new(void *base, size_t size, enum rb_io_buffer_flags flags)
 {
@@ -1029,6 +1048,7 @@ Init_IO_Buffer(void) https://github.com/ruby/ruby/blob/trunk/io_buffer.c#L1048
     rb_cIOBuffer = rb_define_class_under(rb_cIO, "Buffer", rb_cObject);
 
     rb_define_alloc_func(rb_cIOBuffer, rb_io_buffer_type_allocate);
+    rb_define_singleton_method(rb_cIOBuffer, "for", rb_io_buffer_type_for, 1);
 
 #ifdef _WIN32
     SYSTEM_INFO info;
diff --git a/test/ruby/test_io_buffer.rb b/test/ruby/test_io_buffer.rb
index 1bd839e1632..12937729f4e 100644
--- a/test/ruby/test_io_buffer.rb
+++ b/test/ruby/test_io_buffer.rb
@@ -62,6 +62,25 @@ class TestIOBuffer < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_io_buffer.rb#L62
     assert_include buffer.to_str, "Hello World"
   end
 
+  def test_string_mapped
+    string = "Hello World"
+    buffer = IO::Buffer.for(string)
+
+    # Cannot modify string as it's locked by the buffer:
+    assert_raise RuntimeError do
+      string[0] = "h"
+    end
+
+    buffer.set(:U8, 0, "h".ord)
+
+    # Buffer releases it's ownership of the string:
+    buffer.free
+
+    assert_equal "hello World", string
+    string[0] = "H"
+    assert_equal "Hello World", string
+  end
+
   def test_resize
     buffer = IO::Buffer.new(1024, IO::Buffer::MAPPED)
     buffer.resize(2048, 0)
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]