Skip to content

Commit

Permalink
Add MemoryView.export and MemoryView#release (#80)
Browse files Browse the repository at this point in the history
fix #79

Users can release memory views explicitly before process exit.

Reported by xtkoba. Thanks!!!
  • Loading branch information
kou authored Jun 17, 2021
1 parent 418f381 commit 1de64b7
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 3 deletions.
42 changes: 39 additions & 3 deletions ext/fiddle/memory_view.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,25 @@ fiddle_memview_mark(void *ptr)
}

static void
fiddle_memview_free(void *ptr)
fiddle_memview_release(struct memview_data *data)
{
struct memview_data *data = ptr;
if (NIL_P(data->view.obj)) return;

rb_memory_view_release(&data->view);
if (data->members)
data->view.obj = Qnil;
data->view.byte_size = 0;
if (data->members) {
xfree(data->members);
data->members = NULL;
data->n_members = 0;
}
}

static void
fiddle_memview_free(void *ptr)
{
struct memview_data *data = ptr;
fiddle_memview_release(data);
xfree(ptr);
}

Expand All @@ -63,11 +76,32 @@ rb_fiddle_memview_s_allocate(VALUE klass)
struct memview_data *data;
VALUE obj = TypedData_Make_Struct(klass, struct memview_data, &fiddle_memview_data_type, data);
data->view.obj = Qnil;
data->view.byte_size = 0;
data->members = NULL;
data->n_members = 0;
return obj;
}

static VALUE
rb_fiddle_memview_release(VALUE obj)
{
struct memview_data *data;
TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);

if (NIL_P(data->view.obj)) return Qnil;
fiddle_memview_release(data);
return Qnil;
}

static VALUE
rb_fiddle_memview_s_export(VALUE klass, VALUE target)
{
ID id_new;
CONST_ID(id_new, "new");
VALUE memview = rb_funcall(klass, id_new, 1, target);
return rb_ensure(rb_yield, memview, rb_fiddle_memview_release, memview);
}

static VALUE
rb_fiddle_memview_initialize(VALUE obj, VALUE target)
{
Expand Down Expand Up @@ -269,7 +303,9 @@ Init_fiddle_memory_view(void)
{
rb_cMemoryView = rb_define_class_under(mFiddle, "MemoryView", rb_cObject);
rb_define_alloc_func(rb_cMemoryView, rb_fiddle_memview_s_allocate);
rb_define_singleton_method(rb_cMemoryView, "export", rb_fiddle_memview_s_export, 1);
rb_define_method(rb_cMemoryView, "initialize", rb_fiddle_memview_initialize, 1);
rb_define_method(rb_cMemoryView, "release", rb_fiddle_memview_release, 0);
rb_define_method(rb_cMemoryView, "obj", rb_fiddle_memview_get_obj, 0);
rb_define_method(rb_cMemoryView, "byte_size", rb_fiddle_memview_get_byte_size, 0);
rb_define_method(rb_cMemoryView, "readonly?", rb_fiddle_memview_get_readonly, 0);
Expand Down
16 changes: 16 additions & 0 deletions test/fiddle/test_memory_view.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,22 @@ def test_memory_view_multi_dimensional_with_multiple_members
assert_equal([-7, -8], mview[1, 3])
end

def test_export
str = "hello world"
mview_str = MemoryView.export(Pointer[str]) do |mview|
mview.to_s
end
assert_equal(str, mview_str)
end

def test_release
ptr = Pointer["hello world"]
mview = MemoryView.new(ptr)
assert_same(ptr, mview.obj)
mview.release
assert_nil(mview.obj)
end

def test_to_s
# U+3042 HIRAGANA LETTER A
data = "\u{3042}"
Expand Down

0 comments on commit 1de64b7

Please sign in to comment.