Multicore Game Of Life Program
|
let instants = 500 // maximum number of instants fo the simulation let delay = 1000 // number of cycles run at each instant by each living cells /*****************************************************************/ let s1 = scheduler // two synchronised schedulers and s2 = scheduler // sharing the same instants /*****************************************************************/ // the type of colors; each color is a constructor without argument type color = BLUE | GREEN | YELLOW | RED | CYAN | BLACK | MAGENTA | GRAY25 /*****************************************************************/ // declaration of some interface functions (implemented in C) let get_maxx : unit -> int let get_maxy : unit -> int let start_graphics : unit -> bool // true = ok let update_display : unit -> unit let draw_rectangle : int // x * int // y * int // size * color -> bool /***********************************************/ // GRAPHICS /***********************************************/ let maxx = get_maxx () // x size of the graphical applet let maxy = get_maxy () // y size of the graphical applet /***********************************************/ // the module that initialises the display and updates it at each instant let module update () = begin if not (start_graphics ()) then begin print_string ("can't initialize display\n"); quit (1) // terminate the simulation end end; loop begin update_display (); cooperate end end /***********************************************/ // the type of areas which are images of cells type area = Area of int // x * int // y * int //size * color // drawing an area let draw_area (a) = match a with Area (x,y,s,c) -> draw_rectangle (x,y,s,c) end let draw_event = event // the event that collect areas to be drawn // at each instant, draw areas for all values of the event draw_event let module draw_processor () = loop for_all_values draw_event with a -> draw_area (a) /*****************************************************/ // MAPS /******************************************************/ // the array of cell activation events (initially, a null event) let null_event = event let event_map = ref [maxx] ref [maxy] null_event // the array of cell states (living or dead; initially dead) let state_map = ref [maxx] ref [maxy] ref false /*****************************************************************/ // CELL DISPLAY /*****************************************************************/ // function that displays a cell (BLACK when dead, color when alive) let cell_display (x,y,living,color) = if not living then generate draw_event with Area (x,y,1,BLACK) else generate draw_event with Area (x,y,1,color) /*****************************************************************/ // GOL STRATEGY /*****************************************************************/ // the Game of Life basic function that defines birth and death of cells let gol_strategy (living,neighbour) = if (not !living) && neighbour = 3 then living := true else if !living && neighbour <> 2 && neighbour <> 3 then living := false else () /*****************************************************************/ // NEIGHBOURS /*****************************************************************/ /* toric geometry (immediate as access to an array element is modulo the array size, so there is no possibility of out-of-bound error) */ let event_at (x,y) = !(!event_map [x]) [y] // list of activation events of the 8 neighbour cells let get_neighbours (x,y) = Cons_list (event_at (x,y-1), Cons_list (event_at (x+1,y-1), Cons_list (event_at (x+1,y), Cons_list (event_at (x+1,y+1), Cons_list (event_at (x,y+1), Cons_list (event_at (x-1,y+1), Cons_list (event_at (x-1,y), Cons_list (event_at (x-1,y-1),Nil_list)))))))) // activate the neighbours let awake (neighbours) = match neighbours with Nil_list -> () | Cons_list (head,tail) -> begin generate head; awake (tail) end end /*****************************************************************/ // CELLS /*****************************************************************/ // two events to synchronise the start of all cells let ready = event let starting_event = event // the module that defines the cell behaviour let module linked_cell (x,y,me,state,color,neighbours) = let count = ref 0 in let living = ref state in begin generate ready; await starting_event; loop begin cell_display (x,y,!living,color); if !living then awake (neighbours) else await me; // just wait to be activated (passive waiting) count := 0; for_all_values me with _ -> count++; // get the number of living neighbours gol_strategy (living,!count); // apply the game of life strategy repeat delay do count++ // waste some computing resource... end end /* the basic cell module; first, get the activation event of the cell, the initial state, and the neighbours; then, link to the appropriate scheduler and launch an instance of linked_cell in it. */ let module cell (k,x,y,color) = let me = !(!event_map[x])[y] in let state = !(!(!state_map[x])[y]) in let neighbours = get_neighbours (x,y) in if k=1 then link s1 do thread linked_cell (x,y,me,state,color,neighbours) else link s2 do thread linked_cell (x,y,me,state,color,neighbours) /*****************************************************/ // INITIAL SHAPE /******************************************************/ // sets as alive a cell given by its coordinates x and y let fire (x,y) = let state = !(!state_map [x]) [y] in state := true /****************************************************/ // the initial shape (called pentomino) placed at coordinates x,y let r_pentomino_shape (x,y) = begin fire (x,y); fire (x+1,y); fire (x+1,y-1); fire (x+1,y+1); fire (x+2,y-1) end /****************************************************/ // SLICES /****************************************************/ // the function that creates cells in a slice, with appropriate color let slice (n,inity,endy) = let y = ref inity in repeat endy-inity do begin let x = ref 0 in repeat maxx do begin if n = 1 then thread cell (1,!x,!y,GREEN) else thread cell (2,!x,!y,RED); x++ end; y++ end /****************************************************/ // CONTROL OF THE SIMULATION /****************************************************/ // module to trace instants and to end the simulation let module ctrl (n) = let c = ref 0 in begin await starting_event; print_string ("start simulation\n"); repeat n do begin print_int (!c); c++; print_string (" "); flush (); cooperate; end; print_string ("end simulation\n"); quit (0); end /****************************************************/ // MAP INITIALISATION /****************************************************/ // creation of the event map; a new fresh event for each cell let create_event_map () = let y = ref 0 in repeat maxy do begin let x = ref 0 in repeat maxx do begin (!event_map[!x])[!y] := event; x++; end; y++ end // creation of the state map; each cell is initially dead let create_state_map () = let y = ref 0 in repeat maxy do begin let x = ref 0 in repeat maxx do begin !(!state_map[!x])[!y] := false; x++; end; y++ end /****************************************************/ // INITIAL SYNCHRONISATION /****************************************************/ /* waits for all cells to be ready (there are maxx*maxy cells) and starts them by generating the event starting_event (events are broadcast in s1 and s2, so all cells receive it; moreover, they all receive it at the same instant) */ let module starter () = let n = maxx*maxy in let count = ref 0 in begin while !count < n do for_all_values ready with _ -> count++; generate starting_event; // go! end /****************************************************/ // MAIN /****************************************************/ // the main entry point (the initial thread) let module main () = begin create_event_map (); create_state_map (); // put the pentomino in the middle of the applet r_pentomino_shape (maxx/2,maxy/2); slice (1,0,maxy/2); // top slice of cells run by s1 slice (2,1+maxy/2,maxy); // bottom slice of cells run by s2 link s1 do begin // arbitrary choice of s1 (could be s2 as well) thread ctrl (instants); thread update (); thread draw_processor (); thread starter (); end end /****************************************************/
This Html page has been produced by
Skribe.
Last update Wed Apr 4 15:53:19 2007.