Skip to content

Implementation of Source/Sinks and connected blocks paradigm #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 15, 2020

Conversation

cmaglie
Copy link
Contributor

@cmaglie cmaglie commented Oct 12, 2020

This is a POC of the Blocks paradigm we discussed many times. Each thread may be seen as a "building block" with a number of "inputs" and "outputs". I didn't like to use INPUT or OUTPUT or other commonly used words in the embedded world, so to avoid confusion I opted for:

  • Source to describe a block output
  • Sink to describe a block input

Each Source may be connected to an unlimited number of Sinks, but each Sink may be connected to only one Source.
To define a Source the syntax is:

SOURCE(name, type) where name is the name of the source and type is the data type that is being transferred.

to define a Sink the syntax is:

SINK(name, type, queueSize) where name and type are the same as a Source, queueSize define the blocking behavior when the Sink is connected to a Source, more in detail:

  • queueSize == 0 is a Sink with no buffer so the reading from the sink will block until the connected source send something, and vice versa
  • queueSize > 0 is a buffered Sink with queueSize slots, so the reading will block only if there is no data in the buffer and writing (from the connected Source) will block if the buffer is full.

in general, the pace of data flow is dictated by the slowest between a Source and all his connected Sinks.

  • queueSize == -1 is a special "non-blocking size", in this case, the connection behave like a "shared" variable, so the Source will "instantly update" (without blocking) all connected Sinks and each Sink can be read (without blocking) as many times as needed.

An example is available in example/Blocks

@pnndra
Copy link
Contributor

pnndra commented Oct 15, 2020

first of all, very well done! I LOVE IT!

i have a few comments:

  1. wouldn't it be more uniform to replace send and read methods with direct assignment and read as in the shared variables? i know you don't like operator overloading but i found Martino's idea very appealing
  2. in order to avoid exposing the inject method we may use an opaque object (such for example as a void pointer) for the sink so that the public facing property has no methods (not even the connectTo which may be misleading) and it is casted to the real type within the source connectTo method. the benefit of this is that from the outside you won't be able to call inject or connectTo easily for sink properties.
  3. i think it would be beneficial to discuss the expected behaviour when connecting an output to multiple inputs with different blocking behaviours. for example you may expect all the non blocking sinks to receive an input before everything blocks due to a blocking sink with full queue. in this case we'd need to perform an insertion sort rather than a list append when adding to the list of listeners

@facchinm facchinm merged commit 8effef0 into master Oct 15, 2020
@aentinger aentinger deleted the blocks-paradigm branch November 2, 2020 06:01
aentinger added a commit that referenced this pull request Oct 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants