On Thu, 11 Aug 2016 10:39:27 -0300 Gustavo Sverzut Barbieri
<barbi...@gmail.com> said:

> On Thu, Aug 11, 2016 at 3:29 AM, Carsten Haitzler <ras...@rasterman.com>
> wrote:
> > On Tue, 9 Aug 2016 18:31:37 -0300 Gustavo Sverzut Barbieri
> > <barbi...@gmail.com> said:
> >
> > i think we should re-use binbuf/strbuf here and add whatever is missing to
> > them...
> >
> > in fact at a raw level they have everything needed even to point to mmaped
> > memory and use multiple binbufs to point to slices of it without any
> > memcpy's etc.
> >
> > we have a lot of api in efl. let's not add more if we don't NEED it. it's
> > complex enough to learn! :)
> 
> Well, the purpose of Slice can indeed be satisfied with Eina_Binbuf,
> but I'd still keep the slice for the following reasons:
> 
>  - super-lightweight: no need to alloc, we can pass value, not
> pointer. (see my examples in the original email)
> 
>  - type independent: if we have a string or a strbuf and we expect
> binbuf, we'd need to convert to them (which results in an alloc/free).
> With slice we can have "_slice_get()" methods in most functions that
> used to return memory+size, like binbuf/strbuf (string_get() +
> length_get()), or stringshare (it's the memory and offers
> eina_stringshare_strlen()).
> 
>  - easily usable in tokenization/parsers, like how to split "a:b:c" at
> ":" without alloc? you can create a slice for "a:b:c" and then on each
> loop fill the proper segment.
> 
>  - clear purpose that memory is pre-defined in content and length. Say
> the "Efl.Io.Reader.read()" method, if we give a slice, it's clear that
> will read up to slice.len. If you receive 'Eina_Binbuf', do I need to
> pre-allocate its size (no binbuf_resize(), would need to add)? If it
> will grow dynamically, how do I limit that amount? By using
> yet-another parameter?
> 
> With slices one can easily use the stack buffers as Tasn mentioned or
> binbuf. We can still add binbuf_resize()/grow() so we can later use a
> slice from within that new memory and read straight into it, like:
> 
>     size_t oldlen = eina_binbuf_length_get(buf);
>     eina_binbuf_grow(buf, 4096); // you control how much you want to
> grow at once
>     Eina_Rw_Slice rw_slice = eina_binbuf_rw_slice_get(buf);
>     rw_slice.mem = (uint8_t *)rw_slice.mem + oldlen; // these 2 lines
> can be an eina_rw_slice static inline helper
>     rw_slice.len -= oldlen;
>     size_t used;
>     Eina_Error error = efl_io_reader_read(obj, rw_slice, &used); //
> reads straight into buffer, no copies
>     eina_binbuf_length_set(buf, oldlen + used);
> 
> Or in more common code:
> 
>     char buf[4096];
>     Eina_Rw_Slice rw_slice = {.mem = buf, .len = sizeof(buf) - 1}; //
> these 2 lines can be made easier with a macro
>     size_t used;
>     Eina_Error error = efl_io_reader_read(obj, rw_slice, &used);
>     buf[used] = '\0';
>     printf("got: %s\n", buf);
> 
> RDONLY slices used for Write are even easier:
> 
> 
>     size_t used;
>     Eina_Error error = efl_io_writer_write(obj,
> eina_slice_from_str("hello world"), &used);
> 
> 
> You could do these with Eina_Binbuf by using the managed version and
> setting "ro" flag, but you always need to allocate the binbuf and free
> it, even for a simple operation like the one above.
> 
> Did you change your mind or should I go with solely Eina_Binbuf?

i'm still not that happy. first slice should not be void *. it needs a proper
type. unsigned char *, char * - at least bindings can expose a useful type,
though seriously - some languages just are broken (js for example only has a
number type... it has no concept of a blob of binary data unless you want to do
something silly like an array of numbers... where you strictly use the value
ranges 0 to 255 per number thus using 64bits per 8byt value effectively...
ugh :( ... but that's what we have, so unsigned char or char arrays... (or
pointers) not void *.

technically if you REALLY want zero copy, then any read or write buffers MUST
be allocated by efl.net - this slice interface will have t EXPOSE a region of a
buffer to write to or read from. the allocation of that buffer is managed by
efl.net - it grants access to the slice.

also just like binbuf you are going to have to ALLOCATE a slice every time you
get one... just the same. what you do in your example above it illegal in c and
c++. you're returning stack stuff that has been popped. to return something
that will survive it has to allocate.. and this would be the same in any
language that's the same.

one way or another i don't think you can avoid allocating some object that
represents a blob of data. if its a slice, or a binbuf - it doesn't matter. my
point here is - create a binbuf and PASS It IN as a whole. it's immutable once
passed to efl.net or when efl.net passes it back to the caller in events. the
binbuf size is as large as is needed to transport that piece of data.

all your slice is is a binbuf under another name here. once you fix it and do
it right and allocate/free when done.


-- 
------------- Codito, ergo sum - "I code, therefore I am" --------------
The Rasterman (Carsten Haitzler)    ras...@rasterman.com


------------------------------------------------------------------------------
What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic
patterns at an interface-level. Reveals which users, apps, and protocols are 
consuming the most bandwidth. Provides multi-vendor support for NetFlow, 
J-Flow, sFlow and other flows. Make informed decisions using capacity 
planning reports. http://sdm.link/zohodev2dev
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to