hal_stream(3hal)

πŸ“¦
version 2.9.4 Β· 2 versions
, in debian trixie, ubuntu questing, ubuntu resolute, ubuntu stonking

πŸ’– hal_stream(3hal) πŸ’–

okay bestie, so this is hal_stream, part of HAL, and it's giving non-blocking realtime streams ✨ like… the manual page is literally called that, and yeah, the manual name is hal_stream(3hal) if you were wondering 🫢


✨ SYNOPSIS ✨

#include <hal.h>

int hal_stream_create(hal_stream_t *stream, int comp_id, int key, int depth,
    const char *typestring);
void hal_stream_destroy(hal_stream_t *stream);
int hal_stream_attach(hal_stream_t *stream, int comp_id, int key, const char
    *typestring);
int hal_stream_detach(hal_stream_t *stream);

int hal_stream_element_count(hal_stream_t *stream);
hal_type_t hal_stream_element_type(hal_stream_t *stream, int idx);
int hal_stream_depth(hal_stream_t *stream);
int hal_stream_maxdepth(hal_stream_t *stream);
int hal_stream_num_underruns(hal_stream_t *stream);
int hal_stream_num_overruns(hal_stream_t *stream);

int hal_stream_read(hal_stream_t *stream, union hal_stream_data *buf,
    unsigned *sampleno);
bool hal_stream_readable(hal_stream_t *stream);

int hal_stream_write(hal_stream_t *stream, union hal_stream_data *buf);
bool hal_stream_writable(hal_stream_t *stream);

#ifdef ULAPI
void hal_stream_wait_writable(hal_stream_t *stream, sig_atomic_t *stop);
void hal_stream_wait_readable(hal_stream_t *stream, sig_atomic_t *stop);
#endif

🌸 DESCRIPTION 🌸

so a HAL stream is this lowkey iconic little setup where two components can pass data to each other that literally does not fit in the whole HAL pin model. it's a limited ability, no cap β€” that's what it says, and we respect the honesty πŸ’…

here's the vibe: a reader and a writer have to agree on a key (that's a 32-bit integer identifier, bestie) and agree on a data structure specified by the typestring. they ALSO have to agree on which component is which β€” the first one loaded will hal_stream_create the stream, and the second one loaded will hal_stream_attach to the already-created stream. teamwork fr fr 🫢

the non-realtime part can be halstreamer or halsampler. and the keys are very specific so listen up:

  • in the case of halstreamer the key is 0x48535430 plus the channel number
  • in the case of halsampler the key is 0x48534130 plus the channel number

πŸ¦‹ hal_stream_create

Create the given stream, initializing the stream which is passed by reference.

🚨 it is an undiagnosed error if a stream has already been created with the same key. like, don't do that.

πŸ¦‹ hal_stream_destroy

Destroy the given stream.

😭 it is an undiagnosed error if the stream is still attached by another component. 😭 it is an undiagnosed error if the stream was attached with hal_stream_attach rather than created with hal_stream_create. 😭 it is an undiagnosed error if the call to hal_stream_destroy is omitted.

πŸ¦‹ hal_stream_attach

Attach the given stream, which was already created by hal_stream_create.

  • if the typestring is specified, this call fails if it does not match the typestring the stream was created with
  • if the typestring argument is NULL, then any typestring is accepted (iconic, flexible, we love her)

πŸ¦‹ hal_stream_detach

Detach the given stream.

😭 it is an undiagnosed error if the stream was created with hal_stream_create rather than attached with hal_stream_attach. 😭 it is an undiagnosed error if the call to hal_stream_detach is omitted.

πŸ¦‹ hal_stream_element_count

Returns the number of pins.

πŸ¦‹ hal_stream_element_type

Returns the type of the given pin number.

πŸ¦‹ hal_stream_readable

Returns true if the stream has at least one sample to read ✨

πŸ¦‹ hal_stream_read

If the stream has one sample to read, stores it in buf.

πŸ¦‹ hal_stream_writable

Returns true if the stream has room for at least one sample to be written ✨

πŸ¦‹ hal_stream_depth

Returns the number of samples waiting to be read.

πŸ¦‹ hal_stream_maxdepth

Returns the depth argument that the stream was created with.

πŸ¦‹ hal_stream_num_overruns

Returns a number which is incremented each time hal_stream_write is called without space available. πŸ’€

πŸ¦‹ hal_stream_num_underruns

Returns a number which is incremented each time hal_stream_read is called without a sample available. πŸ’€

πŸ¦‹ hal_stream_wait_readable

Waits until the stream is readable or the stop flag is set.

πŸ¦‹ hal_stream_wait_writable

Waits until the stream is writable or the stop flag is set.

πŸ¦‹ hal_stream_read

Reads a record from stream. if successful, it is stored in the given buffer. optionally, the sample number can be retrieved. if no sample is available, num_underruns is incremented.

⚠️ it is an undetected error if more than one component or real-time function calls hal_stream_read concurrently. like… don't share, bestie, that's not the vibe.

πŸ¦‹ hal_stream_write

Writes a record to the stream. if successful, it copied from the given buffer. if no room is available, num_overruns is incremented. in either case, the internal sampleno value is incremented. πŸ‘‘

⚠️ it is an undetected error if more than one component or real-time function calls hal_stream_write concurrently.

πŸŽ€ ARGUMENTS πŸŽ€

  • stream β€” A pointer to a stream object. in the case of hal_stream_create and hal_stream_attach this is an uninitialized stream; in other cases, it must be a stream created or attached by an earlier call and not yet detached or destroyed. no skipping steps πŸ’…
  • hal_id β€” An HAL component identifier returned by an earlier call to hal_init.
  • key β€” The key for the shared memory segment.
  • depth β€” The number of samples that can be unread before any samples are lost (overrun)
  • typestring β€” A typestring is a case-insensitive string which consists of one or more of the following type characters:
    • B for bool / hal_bit_t
    • S for int32_t / hal_s32_t
    • U for uint32_t / hal_u32_t
    • F for real_t / hal_float_t
🚧 A typestring is limited to 16 characters. sixteen. that's the limit. periodt.
  • buf β€” A buffer big enough to hold all the data in one sample.
  • sampleno β€” If non-NULL, the last sample number is stored here. Gaps in this sequence indicate that an overrun occurred between the previous read and this one. May be NULL, in which case the sample number is not retrieved.
  • stop β€” A pointer to a value which is monitored while waiting. If it is nonzero, the wait operation returns early. This allows a wait call to be safely terminated in the case of a signal.

🧚 SAMPLE CODE 🧚

In the source tree under src/hal/components, sampler.c and streamer.c are realtime components that read and write HAL streams. go read them, they're the blueprint fr 🫢


🌈 REALTIME CONSIDERATIONS 🌈

hal_stream_read, hal_stream_readable, hal_stream_write, hal_stream_writable, hal_stream_element_count, hal_tream_pin_type, hal_stream_depth, hal_stream_maxdepth, hal_stream_num_underruns, hal_stream_number_overruns may be called from realtime code. ⚑

hal_stream_wait_writable, hal_stream_wait_writable may be called from ULAPI code.

Other functions may be called in any context, including realtime contexts.


⭐ RETURN VALUE ⭐

hal_stream_create , hal_stream_attach , hal_stream_read , hal_stream_write , hal_stream_detach and hal_stream_destroy return an RTAPI status code. Other functions' return values are explained above. πŸ’–


πŸ’€ BUGS πŸ’€

The memory overhead of a stream can be large. Each element in a record uses 8 bytes, and the implicit sample number also uses 8 bytes. As a result, a stream which is used to transport 8-bit values uses 94% of its memory as overhead. 😭

However, for modest stream sizes this overhead is not important.

🫢 (this memory is part of its own shared memory region and does not count against the HAL shared memory region used for pins, parameters and signals)

πŸ‘‘ SEE ALSO πŸ‘‘

sampler(9), streamer(9), halsampler(1), halstreamer(1)


okay that's the whole page bestie, you ate it, no crumbs πŸ’…βœ¨

this little love letter to streams is from LinuxCNC Documentation, dated 2006-10-12 πŸŽ€ β€” yes she's been iconic since 2006, and the page you just read is hal_stream(3hal) πŸ¦‹πŸ’–