diff --git a/include/ruby/io/buffer.h b/include/ruby/io/buffer.h index 0ee0a005e8..d5f646cd49 100644 --- a/include/ruby/io/buffer.h +++ b/include/ruby/io/buffer.h @@ -27,20 +27,24 @@ RUBY_EXTERN size_t RUBY_IO_BUFFER_DEFAULT_SIZE; enum rb_io_buffer_flags { // The memory in the buffer is owned by someone else. - RB_IO_BUFFER_EXTERNAL = 0, + // More specifically, it means that someone else owns the buffer and we shouldn't try to resize it. + RB_IO_BUFFER_EXTERNAL = 1, // The memory in the buffer is allocated internally. - RB_IO_BUFFER_INTERNAL = 1, + RB_IO_BUFFER_INTERNAL = 2, // The memory in the buffer is mapped. - RB_IO_BUFFER_MAPPED = 2, + // A non-private mapping is marked as external. + RB_IO_BUFFER_MAPPED = 4, // The buffer is locked and cannot be resized. - RB_IO_BUFFER_LOCKED = 16, + // More specifically, it means we can't change the base address or size. + // A buffer is typically locked before a system call that uses the data. + RB_IO_BUFFER_LOCKED = 32, // The buffer mapping is private and will not impact other processes or the underlying file. - RB_IO_BUFFER_PRIVATE = 32, + RB_IO_BUFFER_PRIVATE = 64, // The buffer is read-only and cannot be modified. - RB_IO_BUFFER_IMMUTABLE = 64 + RB_IO_BUFFER_IMMUTABLE = 128 }; enum rb_io_buffer_endian { diff --git a/io_buffer.c b/io_buffer.c index 63f5bd2c24..d87575bfdd 100644 --- a/io_buffer.c +++ b/io_buffer.c @@ -83,6 +83,9 @@ io_buffer_map_file(struct rb_io_buffer *data, int descriptor, size_t size, off_t if (flags & RB_IO_BUFFER_PRIVATE) { access |= FILE_MAP_COPY; data->flags |= RB_IO_BUFFER_PRIVATE; + } else { + // This buffer refers to external data. + data->flags |= RB_IO_BUFFER_EXTERNAL; } void *base = MapViewOfFile(mapping, access, (DWORD)(offset >> 32), (DWORD)(offset & 0xFFFFFFFF), size); @@ -107,6 +110,8 @@ io_buffer_map_file(struct rb_io_buffer *data, int descriptor, size_t size, off_t data->flags |= RB_IO_BUFFER_PRIVATE; } else { + // This buffer refers to external data. + data->flags |= RB_IO_BUFFER_EXTERNAL; access |= MAP_SHARED; } @@ -572,7 +577,7 @@ rb_io_buffer_external_p(VALUE self) struct rb_io_buffer *data = NULL; TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, data); - return data->flags & (RB_IO_BUFFER_INTERNAL | RB_IO_BUFFER_MAPPED) ? Qfalse : Qtrue; + return data->flags & RB_IO_BUFFER_EXTERNAL ? Qtrue : Qfalse; } static VALUE @@ -611,12 +616,6 @@ rb_io_buffer_immutable_p(VALUE self) return data->flags & RB_IO_BUFFER_IMMUTABLE ? Qtrue : Qfalse; } -static int -io_buffer_external_p(enum rb_io_buffer_flags flags) -{ - return !(flags & (RB_IO_BUFFER_INTERNAL | RB_IO_BUFFER_MAPPED)); -} - VALUE rb_io_buffer_lock(VALUE self) { @@ -858,7 +857,7 @@ rb_io_buffer_resize(VALUE self, size_t size) return; } - if (io_buffer_external_p(data->flags)) { + if (data->flags & RB_IO_BUFFER_EXTERNAL) { rb_raise(rb_eIOBufferMutationError, "Cannot resize external buffer!"); } diff --git a/test/ruby/test_io_buffer.rb b/test/ruby/test_io_buffer.rb index f2b9ca45e1..2b371f873d 100644 --- a/test/ruby/test_io_buffer.rb +++ b/test/ruby/test_io_buffer.rb @@ -18,14 +18,14 @@ class TestIOBuffer < Test::Unit::TestCase end def test_flags - assert_equal 0, IO::Buffer::EXTERNAL - assert_equal 1, IO::Buffer::INTERNAL - assert_equal 2, IO::Buffer::MAPPED + assert_equal 1, IO::Buffer::EXTERNAL + assert_equal 2, IO::Buffer::INTERNAL + assert_equal 4, IO::Buffer::MAPPED - assert_equal 16, IO::Buffer::LOCKED - assert_equal 32, IO::Buffer::PRIVATE + assert_equal 32, IO::Buffer::LOCKED + assert_equal 64, IO::Buffer::PRIVATE - assert_equal 64, IO::Buffer::IMMUTABLE + assert_equal 128, IO::Buffer::IMMUTABLE end def test_endian