26 "MultiChunk must be large enough to reinterpret as a MultiPacket.");
29 static const char* LBL_MBUFF =
"MBUFF";
32 unsigned max_peek = min_unsigned(SATCAT5_MBUFF_CHUNK,
m_length);
56 m_read_chunk = packet->m_chunks.head();
70 if (nbytes > m_read_rem)
return false;
74 unsigned chunk = SATCAT5_MBUFF_CHUNK - m_read_pos;
75 unsigned nread = min_unsigned(nbytes, chunk);
76 if (dst8) memcpy(dst8, m_read_chunk->m_data + m_read_pos, nread);
78 if (nread == chunk) m_read_chunk = m_read_pkt->m_chunks.next(m_read_chunk);
79 m_read_pos = modulo_add_uns(m_read_pos + nread, SATCAT5_MBUFF_CHUNK);
81 if (dst8) dst8 += nread;
89 return read_bytes(nbytes, 0);
93 read_reset(m_read_pkt);
99 u8 temp = m_read_chunk->m_data[m_read_pos];
101 if (++m_read_pos >= SATCAT5_MBUFF_CHUNK) {
102 m_read_chunk = m_read_pkt->m_chunks.next(m_read_chunk);
112 , m_write_chunk(pkt->m_chunks.head())
123 if (nbytes > m_write_rem)
return;
127 unsigned chunk = SATCAT5_MBUFF_CHUNK - m_write_pos;
128 unsigned ncopy = min_unsigned(nbytes, chunk);
129 memcpy(m_write_chunk->m_data + m_write_pos, src8, ncopy);
131 if (ncopy == chunk) m_write_chunk = ListCore::next(m_write_chunk);
132 m_write_pos = modulo_add_uns(m_write_pos + ncopy, SATCAT5_MBUFF_CHUNK);
136 m_write_rem -= ncopy;
137 m_write_tot += ncopy;
143 --m_write_rem; ++m_write_tot;
144 m_write_chunk->m_data[m_write_pos] = data;
146 if (++m_write_pos >= SATCAT5_MBUFF_CHUNK) {
147 m_write_chunk = ListCore::next(m_write_chunk);
162 m_free_chunks.
add(temp);
163 m_free_bytes += SATCAT5_MBUFF_CHUNK;
171 if (m_free_chunks.
has_loop())
return false;
172 unsigned free_count = m_free_chunks.
len() * SATCAT5_MBUFF_CHUNK;
173 return free_count == m_free_bytes;
202 unsigned result =
deliver(pkt);
204 if (result > 1) pkt->m_refct = result;
214 if (ptr->
accept(packet)) ++count;
215 ptr = m_read_ports.
next(ptr);
224 if (tmp) m_free_bytes -= SATCAT5_MBUFF_CHUNK;
245 unsigned count = 1 + packet->m_chunks.
len();
248 m_free_bytes += count * SATCAT5_MBUFF_CHUNK;
249 m_free_chunks.
add_list(packet->m_chunks);
257 , m_port_enable(true)
258 , m_read_timeout(SATCAT5_MBUFF_TIMEOUT)
264 #if SATCAT5_ALLOW_DELETION
265 MultiReader::~MultiReader() {
329 #if SATCAT5_ALLOW_DELETION
330 MultiReaderSimple::~MultiReaderSimple() {
366 #if SATCAT5_ALLOW_DELETION
367 MultiReaderPriority::~MultiReaderPriority() {
380 if (pa < pl || pa < pr)
return false;
395 unsigned parent = (idx - 1) / 2;
413 unsigned ll = 2*idx + 1;
414 unsigned rr = 2*idx + 2;
418 if ((pi > pl) && (pi > pr))
break;
431 return 65536 * pri + age + 1;
448 , m_write_maxlen(SATCAT5_MBUFF_PKTLEN)
449 , m_write_timeout(SATCAT5_MBUFF_TIMEOUT)
454 #if SATCAT5_ALLOW_DELETION
455 MultiWriter::~MultiWriter() {
469 unsigned alloc =
m_dst->m_free_bytes;
471 return min_unsigned(pkrem, alloc);
480 const u8* src8 = (
const u8*)src;
486 unsigned nwrite = min_unsigned(nbytes, chunk);
525 bool rcvd = pkt && dst->
accept(pkt);
610 :
MultiWriter(buf), m_dst(dst), m_priority(priority)
Ephemeral Readable interface for a simple array.
A multi-source, multi-sink packet buffer.
void free_packet(satcat5::io::MultiPacket *packet)
Immediately free memory associated with this packet.
satcat5::io::MultiPacket * new_packet()
Memory allocation.
u16 get_pcount()
Current value of the packet counter.
satcat5::io::MultiChunk * new_chunk()
Memory allocation.
bool consistency() const
Internal consistency self-test (Optional).
MultiBuffer(u8 *buff, unsigned nbytes)
Configure this object and link to the working buffer.
void poll_demand() override
Deferred event handler, called after request().
virtual unsigned deliver(satcat5::io::MultiPacket *packet)
Deliver a complete packet to any number of output port(s).
satcat5::io::MultiPacket * dequeue()
Event handler for deferred packet delivery.
bool enqueue(satcat5::io::MultiPacket *packet)
Queue an incoming packet for deferred processing.
void write_next(u8 data) override
Write the next byte to the underlying buffer or device.
void write_bytes(unsigned nbytes, const void *src) override
Write 0 or more bytes from a buffer.
Overwriter(satcat5::io::MultiPacket *pkt)
Create a new Writer object.
unsigned get_write_space() const override
How many bytes can be written without blocking?
Barebones class for reading data from a MultiPacket.
unsigned get_read_ready() const override
How many bytes can be read without blocking?
bool read_consume(unsigned nbytes) override
Read and discard 0 or more bytes.
Reader(const satcat5::io::MultiPacket *pkt=0)
Create a new Reader object.
u8 read_next() override
Read the next byte from the underlying buffer or device.
bool read_bytes(unsigned nbytes, void *dst) override
Read 0 or more bytes into a buffer.
void read_reset(const satcat5::io::MultiPacket *pkt)
Reset read state for the designated packet.
satcat5::io::MultiPacket * get_packet() const
Get a pointer to the current packet, if active.
void read_finalize() override
Consume any remaining bytes in this frame, if applicable.
A port for reading from a MultiBuffer object.
virtual bool accept(satcat5::io::MultiPacket *packet)
Accept a packet from the source buffer? Default accepts all packets unless this port is disabled or f...
bool m_port_enable
Internal state.
void timer_event() override
Timeouts help prevent resource-hogging.
unsigned m_read_timeout
Internal state.
void read_finalize() override
Consume any remaining bytes in this frame, if applicable.
satcat5::io::MultiBuffer *const m_src
Pointer to the source buffer.
void flush()
Discard all queued packets.
MultiReader(satcat5::io::MultiBuffer *src)
Constructor and destructor are only accessible to children.
void pkt_init(satcat5::io::MultiPacket *packet)
Helper function for starting a new packet, or NULL to stop.
virtual satcat5::io::MultiPacket * pkt_pop()=0
Choose the next packet to start reading, or NULL to stop.
void pkt_free(satcat5::io::MultiPacket *packet)
Decrement reference count, free when it reaches zero.
virtual bool pkt_push(satcat5::io::MultiPacket *packet)=0
Push a packet onto the end of a queue or similar data structure.
A variant of MultiReader that follows priority ordering.
unsigned m_heap_count
Binary heap sorted by increasing priority.
satcat5::io::MultiPacket * pkt_pop() override
Implement the push() and pop() methods.
satcat5::io::MultiPacket * m_heap[SATCAT5_MBUFF_RXPKT]
Binary heap sorted by increasing priority.
bool consistency() const
Internal consistency self-test (Optional).
bool pkt_push(satcat5::io::MultiPacket *pkt) override
Implement the push() and pop() methods.
u32 offset_priority(unsigned idx) const
Return modified priority, with tie-breaker using packet count.
unsigned swap_index(unsigned prev, unsigned next)
Swap two elements and return the new index.
MultiReaderPriority(satcat5::io::MultiBuffer *src)
Create this port and link it to the source buffer.
A variant of MultiReader with a simple first-in, first-out queue.
satcat5::io::MultiPacket * pkt_pop() override
Implement the push() and pop() methods.
unsigned m_queue_rdidx
Queue based on a circular buffer.
satcat5::io::MultiPacket * m_queue[SATCAT5_MBUFF_RXPKT]
Queue based on a circular buffer.
bool pkt_push(satcat5::io::MultiPacket *pkt) override
Implement the push() and pop() methods.
unsigned m_queue_count
Queue based on a circular buffer.
MultiReaderSimple(satcat5::io::MultiBuffer *src)
Create this port and link it to the source buffer.
MultiWriter adapter for bypass mode.
bool write_finalize() override
Override redirects to write_bypass().
MultiWriterBypass(satcat5::io::MultiBuffer *buf, satcat5::io::MultiReader *dst, u16 priority=0)
Link this object to a buffer and a destination.
A port for writing to a MultiBuffer object.
void write_bytes(unsigned nbytes, const void *src) override
Write 0 or more bytes from a buffer.
void set_priority(u16 priority)
Set priority of the current packet.
bool write_finalize() override
Mark end of frame and release temporary working data.
MultiWriter(satcat5::io::MultiBuffer *dst)
Create this port and link it to the destination buffer.
unsigned m_write_pos
Current write state.
satcat5::io::MultiBuffer *const m_dst
Pointer to the destination buffer.
satcat5::io::MultiChunk * m_write_tail
Current write state.
void timer_event() override
Timeouts help prevent resource-hogging.
unsigned get_write_space() const override
How many bytes can be written without blocking?
void write_overflow() override
Optional error handling for write overflow.
bool write_bypass(satcat5::io::MultiReader *dst)
Deliver data directly to the designated MultiReader.
unsigned m_write_maxlen
Current write state.
satcat5::io::MultiPacket * m_write_pkt
Current write state.
unsigned m_write_timeout
Current write state.
unsigned write_prep()
Open a new packet or allocate additional buffers.
unsigned m_write_len
Current write state.
void write_next(u8 data) override
Write the next byte to the underlying buffer or device.
satcat5::io::MultiPacket * prepare_pkt()
Prepare packet for delivery and reset internal state.
void write_abort() override
If possible, abort the current partially-written packet.
bool copy_and_finalize(satcat5::io::Writeable *dst, satcat5::io::CopyMode mode=CopyMode::PACKET)
Copy data to a Writeable object, then finalize.
Abstract API for writing byte-streams and packets.
void request_poll()
Call this method to request polling at a later time.
void timer_stop()
Stop all future notifications.
void timer_once(unsigned msec)
Configure a one-time notification after X milliseconds.
Helper functions for manipulating singly-linked lists.
unsigned len() const
Traverse the linked list to count its length.
void add_list(satcat5::util::List< T > &other)
Add each item from "list2" onto "list1", destroying "list2".
T * next(const T *item) const
Fetch pointer to the next item.
void push_back(T *item)
Add a new item at the tail of the list.
void reset(T *item=0)
Discard list contents and reset to empty or a single item.
bool has_loop() const
Check if the linked list loops back on itself, using the two-pointer "tortoise and hare" algorithm.
void insert_after(T *where, T *item)
Insert a new item just after the designated position.
void add(T *item)
Add new item to front or back, whichever is simpler.
T * pop_front()
Remove the item at the head of the list.
void remove(T *item)
Remove the designated item from the list.
Multi-source, multi-sink packet buffer.
Platform-agnostic API for interrupt management.
Data-structure representing a single fine-grained memory block.
A packet is a linked-list of memory blocks, plus metadata.
unsigned m_length
Packet length in bytes.
u16 m_priority
Packet priority.
u16 m_pcount
Packet counter.
u32 m_user[SATCAT5_MBUFF_USER]
Packet metadata.
bool copy_to(satcat5::io::Writeable *wr) const
Copy the packet contents to the specified destination.
unsigned m_refct
Reference counter.
Miscellaneous mathematical utility functions.
constexpr unsigned min_unsigned(unsigned a, unsigned b)
Min and max functions.
constexpr unsigned modulo_add_uns(unsigned sum, unsigned m)
Modulo addition function.