Giter Site home page Giter Site logo

Comments (7)

amstan avatar amstan commented on August 11, 2024

Actually, I just noticed that jack_ringbuffer_create(15) still gives me a 16 sized array. So scratch my suggestions.
So most of the time the behavior is correct, the caller gets a ringbuffer that's at least that size.

What seems to be broken here is the check for the next power of 2. If i want to store 16 items, 32 elements need to be allocated.

Though.. .size should still match whatever .write_space says when the buffer is empty.

from jack2.

x42 avatar x42 commented on August 11, 2024

Yep, this is indeed intentional. The size is always rounded up to the next power of two (2^n memory can be aligned in memory and fits in pages, the modulo operation boils down to an "and", etc etc, 2^n+1 can't)

Since the use-case for lock-free ringbuffers is cross-thread communication, requesting a specific size down to the byte for the data to transfer makes no sense. Read and write operations are not in lock-step. If you know precisely hat you can always process 16 items before 16 more items are written you must have a lock somewhere to ensure that and in that case don't need a lock-free ringbuffer in the first place.

Long story short: the buffer just needs to be large enough, exact size does not matter.

from jack2.

amstan avatar amstan commented on August 11, 2024

Long story short: the buffer just needs to be large enough, exact size does not matter.

I'm OK with the buffer being a little larger than I requested. But for powers of 2 sizes you don't actually get that size, you get size-1, which is actually smaller.

from jack2.

mgeier avatar mgeier commented on August 11, 2024

I think this is a matter of documentation.
Alexandru's arguments make sense from a user's perspective, and Robin's arguments make sense from an efficiency (memory and CPU) standpoint.

I think it would be best to mention in the documentation that the size is rounded up to the next power of two (if it's not already), but there is always one byte less available to the user (as correctly shown by jack_ringbuffer_*_space()).

I think it would be really surprising if a user requests 16 bytes but 32 bytes are actually allocated.

from jack2.

x42 avatar x42 commented on August 11, 2024

@mgeier yes, you're spot on.

from jack2.

7890 avatar 7890 commented on August 11, 2024

I just experienced the same effect. Creating a buffer of size 2^n indicates a write space of only 2^n -1 bytes, while ->size tells 2^n

To be absolutely sure to always get at least the requested size with the current ringbuffer implementation, 1 must be added to the request (in order to catch the next power of two). I.e. want size 8, will request 9, will get 15. This can be confusing, mentioning it in the docs seems reasonable.

from jack2.

7890 avatar 7890 commented on August 11, 2024

Documentation proposal for function jack_ringbuffer_t *jack_ringbuffer_create(size_t sz); in common/jack/ringbuffer.h

/**
 * Allocates a ringbuffer data structure of a specified size. The
 * caller must arrange for a call to jack_ringbuffer_free() to release
 * the memory associated with the ringbuffer.
 *
 * A caller will usually get a buffer that can hold AT LEAST the
 * requested size.
 *
 * The space available for read and write operations is the
 * smallest power of two greater or equal to sz, MINUS ONE.
 * Example: sz=5; smallest power of two greater or equal to sz: 2^3=8.
 * Usable: 2^3 - 1 = 7.
 *
 * The usable size is thus 2^n - 1 bytes.
 * The size_t size member from jack_ringbuffer_t indicates 2^n
 * (and not the space available for read and write which is one less).
 *
 * A case that needs special attention is if the buffer needs to hold
 * AT LEAST 2^n bytes:
 * The requested size sz must be > 2^n bytes to get 2^(n+1)-1 usable space.
 *
 * @param sz the ringbuffer size in bytes.
 *
 * @return a pointer to a new jack_ringbuffer_t, if successful; NULL
 * otherwise.
 */

from jack2.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.