% ====================================================================== % ====================================================================== \chapter{Putting It All Together} % ====================================================================== % ====================================================================== \section{Threads As Monitors} As it was subtly alluded in section \ref{threads}, \code{thread}s in \CFA are in fact monitors, which means that all monitor features are available when using threads. For example, here is a very simple two thread pipeline that could be used for a simulator of a game engine: \begin{figure}[H] \begin{cfacode}[caption={Toy simulator using \code{thread}s and \code{monitor}s.},label={lst:engine-v1}] // Visualization declaration thread Renderer {} renderer; Frame * simulate( Simulator & this ); // Simulation declaration thread Simulator{} simulator; void render( Renderer & this ); // Blocking call used as communication void draw( Renderer & mutex this, Frame * frame ); // Simulation loop void main( Simulator & this ) { while( true ) { Frame * frame = simulate( this ); draw( renderer, frame ); } } // Rendering loop void main( Renderer & this ) { while( true ) { waitfor( draw, this ); render( this ); } } \end{cfacode} \end{figure} One of the obvious complaints of the previous code snippet (other than its toy-like simplicity) is that it does not handle exit conditions and just goes on forever. Luckily, the monitor semantics can also be used to clearly enforce a shutdown order in a concise manner: \begin{figure}[H] \begin{cfacode}[caption={Same toy simulator with proper termination condition.},label={lst:engine-v2}] // Visualization declaration thread Renderer {} renderer; Frame * simulate( Simulator & this ); // Simulation declaration thread Simulator{} simulator; void render( Renderer & this ); // Blocking call used as communication void draw( Renderer & mutex this, Frame * frame ); // Simulation loop void main( Simulator & this ) { while( true ) { Frame * frame = simulate( this ); draw( renderer, frame ); // Exit main loop after the last frame if( frame->is_last ) break; } } // Rendering loop void main( Renderer & this ) { while( true ) { waitfor( draw, this ); or waitfor( ^?{}, this ) { // Add an exit condition break; } render( this ); } } // Call destructor for simulator once simulator finishes // Call destructor for renderer to signify shutdown \end{cfacode} \end{figure} \section{Fibers \& Threads} As mentioned in section \ref{preemption}, \CFA uses preemptive threads by default but can use fibers on demand. Currently, using fibers is done by adding the following line of code to the program~: \begin{cfacode} unsigned int default_preemption() { return 0; } \end{cfacode} This function is called by the kernel to fetch the default preemption rate, where 0 signifies an infinite time-slice, i.e., no preemption. However, once clusters are fully implemented, it will be possible to create fibers and \glspl{uthread} in the same system, as in listing \ref{lst:fiber-uthread} \begin{figure} \begin{cfacode}[caption={Using fibers and \glspl{uthread} side-by-side in \CFA},label={lst:fiber-uthread}] //Cluster forward declaration struct cluster; //Processor forward declaration struct processor; //Construct clusters with a preemption rate void ?{}(cluster& this, unsigned int rate); //Construct processor and add it to cluster void ?{}(processor& this, cluster& cluster); //Construct thread and schedule it on cluster void ?{}(thread& this, cluster& cluster); //Declare two clusters cluster thread_cluster = { 10`ms }; //Preempt every 10 ms cluster fibers_cluster = { 0 }; //Never preempt //Construct 4 processors processor processors[4] = { //2 for the thread cluster thread_cluster; thread_cluster; //2 for the fibers cluster fibers_cluster; fibers_cluster; }; //Declares thread thread UThread {}; void ?{}(UThread& this) { //Construct underlying thread to automatically //be scheduled on the thread cluster (this){ thread_cluster } } void main(UThread & this); //Declares fibers thread Fiber {}; void ?{}(Fiber& this) { //Construct underlying thread to automatically //be scheduled on the fiber cluster (this.__thread){ fibers_cluster } } void main(Fiber & this); \end{cfacode} \end{figure}