The Multi-Threaded Game of Life Sample
Links: Up
Links: Build Script
Links: Run the sample (after building)
Links: Sample Project File for Visual Studio
This sample shows how to do advanced multi-threaded GUI (Graphical
User Interface) programming where worker threads compute the
results of an algorithm, in this case the Game of Life.
This is one of the most advanced samples, exploiting many novel features of F# not
found in other languages.
- The sample is written using the experimental #light syntax option that allows you to omit
in and other terminating tokens.
- The computation runs on a separate worker thread.
- The GUI client can control the running computation: it can halt the game (at the end of a round),
it step through rounds of the game, it can send new input to the game, even while computation is
in full-flight (turn on "User Input" in the menu and try clicking on the surface of the game - the
input will be picked up by the game at the end of a turn).
- Multiple instances of the game can be created in the one process, each with its own worker thread
- The worker (you could call it a reactive machine, automaton or object)
running on the worker thread is controlled using AutoResetEvents (see System.Threading.AutoResetEvent).
When you control the game through the GUI you are effectively sending AutoResetEvents to the
automaton.
- The transitions of the control-logic of the worker are encoded
using a set of recursive functions.
- The implementation of the GUI uses F#'s reactive 'runtime-checked' recursion in a few places
The F# code in alg.fs is the core computation of
the rules of the Game of Life on a grid. An array of cells is used for obvious
efficiency and simplicity reasons. The external interface to this component is
alg.fsi.
The F# code in worker.fs specifies the
reactive computation machine that runs on the worker thread (but not the worker thread itself).
The automata is specified as a set of recursive functions (which represent a state machine,
i.e. they block waiting for input when the machine enters the 'Paused' or 'Finished' states),
and is paramaterized by callbacks that
provide the interface to the GUI.
The GUI and thread control logic can be found in client.fs.
The specification of the GUI uses F#'s reactive 'runtime-checked' recursion.
Suggested Exercises
- Change alg.fs to add some new
rules to the game, e.g. a variation where the number
of neighbour cells that determine if a cell dies or lives
depends slightly on the coordinates of the cell.
- Change client.fs to add a menu to dump
the state of the game to the console. You will need to add
a new "dump" signal to worker.fs and
a "dump" operation to alg.fs and
alg.fsi.