diff options
author | Kenta Murata <mrkn@users.noreply.github.com> | 2020-09-25 20:32:02 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-25 20:32:02 +0900 |
commit | 890bc2cdde4097390f3b71dfeaa36dd92ee0afe2 (patch) | |
tree | b06641556aa22c6d4aa37200c00ffaf23f6838b7 /include | |
parent | 6eeacbbc3603bcd63a53e43a2002ca0872945e9f (diff) |
Buffer protocol proposal (#3261)
* Add buffer protocol
* Modify for some review comments
* Per-object buffer availability
* Rename to MemoryView from Buffer and make compilable
* Support integral repeat count in memory view format
* Support 'x' for padding bytes
* Add rb_memory_view_parse_item_format
* Check type in rb_memory_view_register
* Update dependencies in common.mk
* Add test of MemoryView
* Add test of rb_memory_view_init_as_byte_array
* Add native size format test
* Add MemoryView test utilities
* Add test of rb_memory_view_fill_contiguous_strides
* Skip spaces in format string
* Support endianness specifiers
* Update documentation
* Support alignment
* Use RUBY_ALIGNOF
* Fix format parser to follow the pack format
* Support the _ modifier
* Parse count specifiers in get_format_size function.
* Use STRUCT_ALIGNOF
* Fix test
* Fix test
* Fix total size for the case with tail padding
* Fix rb_memory_view_get_item_pointer
* Fix rb_memory_view_parse_item_format again
Notes
Notes:
Merged-By: mrkn <mrkn@ruby-lang.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/ruby/memory_view.h | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/include/ruby/memory_view.h b/include/ruby/memory_view.h new file mode 100644 index 0000000000..dc6c971593 --- /dev/null +++ b/include/ruby/memory_view.h @@ -0,0 +1,136 @@ +#ifndef RUBY_MEMORY_VIEW_H +#define RUBY_MEMORY_VIEW_H 1 +/** + * @file + * @author Ruby developers <ruby-core@ruby-lang.org> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @brief Memory View. + */ + +#include "ruby/internal/dllexport.h" +#include "ruby/internal/stdbool.h" +#include "ruby/internal/value.h" +#include "ruby/intern.h" + +enum ruby_memory_view_flags { + RUBY_MEMORY_VIEW_SIMPLE = 0, + RUBY_MEMORY_VIEW_WRITABLE = (1<<0), + RUBY_MEMORY_VIEW_FORMAT = (1<<1), + RUBY_MEMORY_VIEW_MULTI_DIMENSIONAL = (1<<2), + RUBY_MEMORY_VIEW_STRIDES = (1<<3) | RUBY_MEMORY_VIEW_MULTI_DIMENSIONAL, + RUBY_MEMORY_VIEW_ROW_MAJOR = (1<<4) | RUBY_MEMORY_VIEW_STRIDES, + RUBY_MEMORY_VIEW_COLUMN_MAJOR = (1<<5) | RUBY_MEMORY_VIEW_STRIDES, + RUBY_MEMORY_VIEW_ANY_CONTIGUOUS = RUBY_MEMORY_VIEW_ROW_MAJOR | RUBY_MEMORY_VIEW_COLUMN_MAJOR, + RUBY_MEMORY_VIEW_INDIRECT = (1<<6) | RUBY_MEMORY_VIEW_STRIDES, +}; + +typedef struct { + char format; + unsigned native_size_p: 1; + unsigned little_endian_p: 1; + size_t offset; + size_t size; + size_t repeat; +} rb_memory_view_item_component_t; + +typedef struct { + /* The original object that have the memory exported via this memory view. + * The consumer of this memory view has the responsibility to call rb_gc_mark + * for preventing this obj collected by GC. */ + VALUE obj; + + /* The pointer to the exported memory. */ + void *data; + + /* The number of bytes in data. */ + ssize_t len; + + /* 1 for readonly memory, 0 for writable memory. */ + int readonly; + + /* A string to describe the format of an element, or NULL for unsigned byte. + * The format string is a sequence the following pack-template specifiers: + * + * c, C, s, s!, S, S!, n, v, i, i!, I, I!, l, l!, + * L, L!, N, V, f, e, g, d, E, G, j, J, x + * + * For example, "dd" for an element that consists of two double values, + * and "CCC" for an element that consists of three bytes, such as + * a RGB color triplet. + * + * Also, the value endianness can be explicitly specified by '<' or '>' + * following a value type specifier. + */ + const char *format; + + /* The number of bytes in each element. + * item_size should equal to rb_memory_view_item_size_from_format(format). */ + ssize_t item_size; + + struct { + /* The array of rb_memory_view_item_component_t that describes the + * item structure. */ + rb_memory_view_item_component_t *components; + + /* The number of components in an item. */ + ssize_t length; + } item_desc; + + /* The number of dimension. */ + int ndim; + + /* ndim size array indicating the number of elements in each dimension. + * This can be NULL when ndim == 1. */ + ssize_t *shape; + + /* ndim size array indicating the number of bytes to skip to go to the + * next element in each dimension. */ + ssize_t *strides; + + /* The offset in each dimension when this memory view exposes a nested array. + * Or, NULL when this memory view exposes a flat array. */ + ssize_t *sub_offsets; + + /* the private data for managing this exported memory */ + void *const private; +} rb_memory_view_t; + +typedef int (* rb_memory_view_get_func_t)(VALUE obj, rb_memory_view_t *view, int flags); +typedef int (* rb_memory_view_release_func_t)(VALUE obj, rb_memory_view_t *view); +typedef int (* rb_memory_view_available_p_func_t)(VALUE obj); + +typedef struct { + rb_memory_view_get_func_t get_func; + rb_memory_view_release_func_t release_func; + rb_memory_view_available_p_func_t available_p_func; +} rb_memory_view_entry_t; + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* memory_view.c */ +bool rb_memory_view_register(VALUE klass, const rb_memory_view_entry_t *entry); + +#define rb_memory_view_is_contiguous(view) ( \ + rb_memory_view_is_row_major_contiguous(view) \ + || rb_memory_view_is_column_major_contiguous(view)) + +int rb_memory_view_is_row_major_contiguous(const rb_memory_view_t *view); +int rb_memory_view_is_column_major_contiguous(const rb_memory_view_t *view); +void rb_memory_view_fill_contiguous_strides(const int ndim, const int item_size, const ssize_t *const shape, const int row_major_p, ssize_t *const strides); +int rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data, const ssize_t len, const int readonly); +ssize_t rb_memory_view_parse_item_format(const char *format, + rb_memory_view_item_component_t **members, + ssize_t *n_members, const char **err); +ssize_t rb_memory_view_item_size_from_format(const char *format, const char **err); +void *rb_memory_view_get_item_pointer(rb_memory_view_t *view, const ssize_t *indices); + +int rb_memory_view_available_p(VALUE obj); +int rb_memory_view_get(VALUE obj, rb_memory_view_t* memory_view, int flags); +int rb_memory_view_release(rb_memory_view_t* memory_view); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RUBY_BUFFER_H */ |