Skip to content

Non-atomic version of bip_buffer_spsc_atomic ? #1294

Description

@serges147

Hello!

So far I successfully used etl::bip_buffer_spsc_atomic for BIP buffer behavior but my environment is completely single threaded (plain old super loop), single CPU core, and there is no even ISR involved. So, it would be nice to have an alternative - a bit more lighter variant of the buffer (with exactly the same public API) but without atomics inside (and so not dependent on ETL_HAS_ATOMIC).

My question (probably for maintainers):

  • Should it be a new bip_buffer_spsc class/file (essentially almost full copy/paste of the atomic version but with plain size_type index fields (read, write & last)?
  • OR, some efforts should be invested into trying to extract common functionality (which is a lot!) into some base class for both cases?
    Please share Your thoughts on that.

Thanks!

P.S. Maybe it's not applicable analogy, but just in case, if we look at etl::queue_spsc_xxx variants then it seems that the former approach is taken, namely copy/paste one.

Activity

  1. serges147 commented on Feb 10, 2026

    @serges147
    CollaboratorAuthor

    @jwellbelove John, could you please take a look? Thank You!

  2. jwellbelove commented on Feb 14, 2026

    @jwellbelove
    Contributor

    I'll try to look at this as soon as I can (but it may take a while)

  3. wsciaroni commented on Feb 27, 2026

    @wsciaroni
    Contributor

    @serges147 Would an etl::circular_buffer meet your needs?

  4. serges147 commented on Feb 27, 2026

    @serges147
    CollaboratorAuthor

    @wsciaroni No, it wouldn't. I need access to a range of items at once (see BIP buffer reserve/commit API), not like one by one (push & pop). More importantly these ranges of items (in my case uint8_t of raw bytes) have to be in continuous memory - this is exactly where BIP buffer shines!

  5. jwellbelove commented on Jul 26, 2026

    @jwellbelove
    Contributor

    I'm wondering whether an extra default template parameter could select between atomic and non-atomic indexes, and move the indexes to a separate class.

    Something along the lines of:-

      template <typename TSize, bool Is_Atomic>
      class bip_indexes;
    
      // Non-atomic
      template <typename TSize>
      class bip_indexes<TSize, false>
      {
      public:
    
        void clear()
        {
          read  = 0;
          write = 0;
          last  = 0;
        }
    
        TSize read_load() const
        {
          return read;
        }
    
        void read_store(TSize value)
        {
          read = value;
        }
    
        TSize write_load() const
        {
          return write;
        }
    
        void write_store(TSize value)
        {
          write = value;
        }
        TSize last_load() const
        {
          return last;
        }
    
        void last_store(TSize value)
        {
          last = value;
        }
    
      private:
    
        TSize read;
        TSize write;
        TSize last;
      };
    
      // Atomic
      template <typename TSize>
      class bip_indexes<TSize, true>
      {
      public:
    
        void clear()
        {
          read.store(0, etl::memory_order_release);
          write.store(0, etl::memory_order_release);
          last.store(0, etl::memory_order_release);
        }
    
        TSize read_load() const
        {
          return read.load(etl::memory_order_acquire);
        }
    
        void read_store(TSize value)
        {
          read.store(value, etl::memory_order_release);
        }
    
        TSize write_load() const
        {
          return write.load(etl::memory_order_acquire);
        }
    
        void write_store(TSize value)
        {
          write.store(value, etl::memory_order_release);
        }
        TSize last_load() const
        {
          return last.load(etl::memory_order_acquire);
        }
    
        void last_store(TSize value)
        {
          last.store(value, etl::memory_order_release);
        }
    
      private:
    
        etl::atomic<TSize> read;
        etl::atomic<TSize> write;
        etl::atomic<TSize> last;
      };
    
  6. jwellbelove commented on Jul 27, 2026

    @jwellbelove
    Contributor

    The downside of course is that a bit_buffer_spsc_atomic may not actually be atomic is some circumstances.

  7. jwellbelove commented on Jul 30, 2026

    @jwellbelove
    Contributor

    Another option is to use the above solution, deprecate bit_buffer_spsc_atomic and call the new class bit_buffer_spsc (with a default to it being atomic?)

  8. serges147 commented on Jul 30, 2026

    @serges147
    CollaboratorAuthor

    deprecate bit_buffer_spsc_atomic

    1. bit -> bip
    2. there are also ibip_buffer_spsc_atomic "interface" and bip_buffer_spsc_atomic_base "base" in the picture.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions