Skip to content

Commit 10e26cf

Browse files
kounobu
authored andcommitted
[ruby/fiddle] Add MemoryView.export and MemoryView#release (ruby/fiddle#80)
fix ruby/fiddle#79 Users can release memory views explicitly before process exit. Reported by xtkoba. Thanks!!! ruby/fiddle@1de64b7e76
1 parent 9988f6a commit 10e26cf

File tree

2 files changed

+55
-3
lines changed

2 files changed

+55
-3
lines changed

ext/fiddle/memory_view.c

+39-3
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,25 @@ fiddle_memview_mark(void *ptr)
3636
}
3737

3838
static void
39-
fiddle_memview_free(void *ptr)
39+
fiddle_memview_release(struct memview_data *data)
4040
{
41-
struct memview_data *data = ptr;
41+
if (NIL_P(data->view.obj)) return;
42+
4243
rb_memory_view_release(&data->view);
43-
if (data->members)
44+
data->view.obj = Qnil;
45+
data->view.byte_size = 0;
46+
if (data->members) {
4447
xfree(data->members);
48+
data->members = NULL;
49+
data->n_members = 0;
50+
}
51+
}
52+
53+
static void
54+
fiddle_memview_free(void *ptr)
55+
{
56+
struct memview_data *data = ptr;
57+
fiddle_memview_release(data);
4558
xfree(ptr);
4659
}
4760

@@ -63,11 +76,32 @@ rb_fiddle_memview_s_allocate(VALUE klass)
6376
struct memview_data *data;
6477
VALUE obj = TypedData_Make_Struct(klass, struct memview_data, &fiddle_memview_data_type, data);
6578
data->view.obj = Qnil;
79+
data->view.byte_size = 0;
6680
data->members = NULL;
6781
data->n_members = 0;
6882
return obj;
6983
}
7084

85+
static VALUE
86+
rb_fiddle_memview_release(VALUE obj)
87+
{
88+
struct memview_data *data;
89+
TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
90+
91+
if (NIL_P(data->view.obj)) return Qnil;
92+
fiddle_memview_release(data);
93+
return Qnil;
94+
}
95+
96+
static VALUE
97+
rb_fiddle_memview_s_export(VALUE klass, VALUE target)
98+
{
99+
ID id_new;
100+
CONST_ID(id_new, "new");
101+
VALUE memview = rb_funcall(klass, id_new, 1, target);
102+
return rb_ensure(rb_yield, memview, rb_fiddle_memview_release, memview);
103+
}
104+
71105
static VALUE
72106
rb_fiddle_memview_initialize(VALUE obj, VALUE target)
73107
{
@@ -269,7 +303,9 @@ Init_fiddle_memory_view(void)
269303
{
270304
rb_cMemoryView = rb_define_class_under(mFiddle, "MemoryView", rb_cObject);
271305
rb_define_alloc_func(rb_cMemoryView, rb_fiddle_memview_s_allocate);
306+
rb_define_singleton_method(rb_cMemoryView, "export", rb_fiddle_memview_s_export, 1);
272307
rb_define_method(rb_cMemoryView, "initialize", rb_fiddle_memview_initialize, 1);
308+
rb_define_method(rb_cMemoryView, "release", rb_fiddle_memview_release, 0);
273309
rb_define_method(rb_cMemoryView, "obj", rb_fiddle_memview_get_obj, 0);
274310
rb_define_method(rb_cMemoryView, "byte_size", rb_fiddle_memview_get_byte_size, 0);
275311
rb_define_method(rb_cMemoryView, "readonly?", rb_fiddle_memview_get_readonly, 0);

test/fiddle/test_memory_view.rb

+16
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,22 @@ def test_memory_view_multi_dimensional_with_multiple_members
114114
assert_equal([-7, -8], mview[1, 3])
115115
end
116116

117+
def test_export
118+
str = "hello world"
119+
mview_str = MemoryView.export(Pointer[str]) do |mview|
120+
mview.to_s
121+
end
122+
assert_equal(str, mview_str)
123+
end
124+
125+
def test_release
126+
ptr = Pointer["hello world"]
127+
mview = MemoryView.new(ptr)
128+
assert_same(ptr, mview.obj)
129+
mview.release
130+
assert_nil(mview.obj)
131+
end
132+
117133
def test_to_s
118134
# U+3042 HIRAGANA LETTER A
119135
data = "\u{3042}"

0 commit comments

Comments
 (0)