In my previous post I discussed about combining flow-based programming and syncrhonous dataflow both in a single visual programming language. The goal of such language would be to combine the best of both of the flow-based approaches allowing the developer to choose the paradigm that best suits to the problem in hand. Today I want to take a deeper look into this hybrid dataflow model and introduce a specific synchronous structure that, from outside the structure appears and acts like a normal asynchronous flow-based programming node but from within encloses a synchronous dataflow diagram.
Consider an image processing task of smoothing an image by replacing each pixel value with an average of rectangular 3×3 neighborhood of the original pixel. We want to implement such an algorithm in our hybrid flow-based programming application. The input and output of such diagram needs to be a stream of images. Perhaps we have a flow-based programming diagram where we read images from a folder, pass them to the smoothing algorithm that then passes them to a node saving them back to the disk.
Now let’s take a look at the implementation of the Smooth Image subdiagram in the above flow-based programming example. The Smooth Image subdiagram is illustrated in the image below that takes advantage of the proposed new synchronous structure. The synchronous structure in the subdiagram processes a stream of images, each of which is represented by a single information package (or an object in a OOP flavored language). The images arrive in an asynchronous manner from the previous Read Image step. In the examples, the asynchronous wires are represented with dotted lines and the synchronous wire with solid lines.
The synchronous structure starts executing upon startup of the subdiagram and remains executing until the input image stream is closed. The diagram waits for any incoming images (information packages) in the image stream. Each image in the example is expected to be a two dimensional array containing numeric values representing gray values for each pixel.
Every time an image arrives at the left connector of the synchronous structure, the content of the synchronous structure is executed exactly once in a synchronous dataflow manner. At the start of each execution of the content the synchronous structure, the left hand side image stream input gets the value of the received grayscale image. The image is then iterated with two for loop structures, outer for loop structure iterating each row in the image and inner for loop iterating each column in the image. Within the inner for loop, a 3×3 subarea around each pixel is averaged and the averaged value for each pixel is returned. The right hand edges of the for loops reconstruct the averaged pixels into the form of the original image and the smoothed image is passed to the right edge of the synchronous structure. The synchronous structure returns the image via its left hand side connector to the asynchronous surrounding diagram when its content has completed executing.
This hybrid dataflow approach using the synchronous structure allows easily enhancing the flow-based programming with synchronous dataflow subdiagrams. This greatly enhances the expressive power of the visual dataflow and flow-based programming languages by making them well equipped for both the complicated low-level operations requiring synchronization and high level orchestration well expressed with flow-based programming diagrams.