skypjack / uvw

Header-only, event based, tiny and easy to use libuv wrapper in modern C++ - now available as also shared/static library!
MIT License
1.82k stars 207 forks source link

I need the way to set buffer when I read from stream #267

Closed hihig2001 closed 1 year ago

hihig2001 commented 2 years ago

In stream like things, I need to collect several data events to make full packet. but it seems there are lack of interface I can give my buffer data(aka. char[]) when I read from stream.

Because uvw stands for thin wrapper of libuv, I think it should be possible.

Current implementation allocates by uvw in Handle::allocCallback

It seems when I write I have controls of buffer but when I read it seems not.

If i can set this kind of call back to streams I could control it. auto alloc_callback(Handle<T, U>& handle, std::size_t suggested) -> char*

I don't want allocation happens in every read operation.

skypjack commented 2 years ago

Why not setting the allocation functions using the same utilities of libuv? Is there any problem with it?

hihig2001 commented 2 years ago

oh am I misunderstood something?

below codes are something I tracked.

template<typename T, typename U>
class StreamHandle: public Handle<T, U> {
    void read() {
        this->invoke(&uv_read_start, this->template get<uv_stream_t>(), &this->allocCallback, &readCallback);
    }
}
template<typename T, typename U>
class Handle: public Resource<T, U> {
    static void allocCallback(uv_handle_t *, std::size_t suggested, uv_buf_t *buf) {
        auto size = static_cast<unsigned int>(suggested);
        *buf = uv_buf_init(new char[size], size);
    }
}

I thought that problem rise this line of code

*buf = uv_buf_init(new char[size], size);

I'd like to pass pre-allocated buffer that I'm gonna re-use over and over. In that way I understand that there should be a way that I can pass my pre-allocated buffer to uv_buf.base.

Is there are something that I misunderstood or miss some of functionality in libuv or uvw?

skypjack commented 2 years ago

Hi, sorry for the late reply, I'm on vacation and also trying to have a real break from my dev life. 😅 I see what you mean. Consider that we're about to merge branch v3 that is a HUGE change to the library, both in terms of performance and compilation time. Can we consider this as a feature request to add allocator support to that version? It seems to me the only viable solution. Any other idea?

0EVSG commented 2 years ago

+1 for the ability to inject a custom buffer allocation callback.

First of all new is a lot of overhead compared to reusing buffers from an allocation pool. Also it looks like your current implementation effectively prevents recvmmsg() for UDP, which is the use case I'm evaluating now. The suggested buffer size is given as max UDP datagram size, but libuv requires a multiple of that for recvmmsg(). Rather crude implementation from libuv side too, but that's what it is now.

skypjack commented 1 year ago

Closing this as a duplicate of #289