% ====================================================================== % ====================================================================== \chapter{Putting it all together} % ====================================================================== % ====================================================================== \section{Threads as monitors} As it was subtely alluded in section \ref{threads}, \code{threads} 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{cfacode} // 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 ); // Simualation 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} 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{cfacode} // 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 ); // Simualation 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} \section{Fibers \& Threads} As mentionned 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 uthreads in on the same system : \begin{figure} \begin{cfacode} //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}