This article is a code example that is changed from serial to parallel.
In the book "patterns for parallel programming" by Timothy G. Mattson, Beverly A. Sanders and Berna L. Massingill.
They have broken the pattern language structure into 4 design spaces.
The first design space is: "finding concurrency". In the next code ( that
show a plane that can shooting ) exists a "concurrency block" when each
shoot is moving. But this code is serial.
The serial code
#include <stdio.h>
#include <conio.h>
#include <windows.h>
/*
@autor jose jesus ambriz meza
@fecha 23/en/2010
@descrip programa en "simbolo de sistema" que muestra un avion
lanzando tiros ( máximo 10 ) no validado todavía la
eliminación de los tiros que llegan a la máxima columna.
this airplane can shooting 10 shot. It has a
concurrent code when the shots are moving.
*/
#define SIMBOLO_ASTERISCO '*'
#define CHARACTER_SALIDA 'x'
#define SIMBOLO_ARRIBA 'e'
#define SIMBOLO_ABAJO 'c'
#define SIMBOLO_DISPARO ' '
#define CANTIDAD_MAXIMA_DISPAROS 5
#define SIMBOLO_GUION '-'
#define TIEMPO_ESPERA_ENTRE_DISPAROS 30
#define COLUMNA_MAXIMA 40
void mostrarAvion( int c, int r, char simbolo );
void mostrarSimbolo( int c, int r, char simbolo );
void agregarDisparo( int c, int r, int colDisparos[],int renDisparos[], int *cantDisparos );
void main()
{
int colAsterisco=3, renAsterisco=10; //posicion del avion
char letra; //letra recibida
int colDisparos[ CANTIDAD_MAXIMA_DISPAROS ]; //columna de cada disparo
int renDisparos[ CANTIDAD_MAXIMA_DISPAROS ]; //renglón de cada disparo
int cantDisparos= 0; //cantidad de disparos
int disparoActual= 0;
clrscr(); //limpiar pantalla
mostrarAvion( colAsterisco, renAsterisco, SIMBOLO_ASTERISCO ); //mostrar avion por primera vez
while ( (letra=getch())!= CHARACTER_SALIDA ) //tomar lectura de teclado
{
mostrarAvion( colAsterisco, renAsterisco, SIMBOLO_DISPARO ); //borrar avion en cada movimiento
switch ( letra )
{
case SIMBOLO_ARRIBA: //avion hacia arriba
if ( renAsterisco>2 ) //si se puede hacer hacia arriba
{
renAsterisco-=1;
}
break;
case SIMBOLO_ABAJO: //avion hacia abajo
if ( renAsterisco<79 ) //si se puede hacer hacia abajo
{
renAsterisco+=1;
}
break;
case SIMBOLO_DISPARO:
if ( cantDisparos< CANTIDAD_MAXIMA_DISPAROS ) //hay disparos disponibles
{
agregarDisparo( colAsterisco, renAsterisco, colDisparos,renDisparos, &cantDisparos );
}
break;
}
mostrarAvion( colAsterisco, renAsterisco, SIMBOLO_ASTERISCO ); //mostrar avion en cada movimiento
/*
Begins concurrency block
*/
while ( !kbhit() )
{
if ( cantDisparos>0 ) //si hay disparos
{
mostrarSimbolo( //borrar el disparo
colDisparos[ disparoActual ],
renDisparos[ disparoActual ],
SIMBOLO_DISPARO );
colDisparos[ disparoActual ]+=1;
mostrarSimbolo( //mostrar el disparo
colDisparos[ disparoActual ],
renDisparos[ disparoActual ],
SIMBOLO_GUION );
Sleep( TIEMPO_ESPERA_ENTRE_DISPAROS );
//si el disparo realizado se salió de los límites de la pantalla
if ( colDisparos[ disparoActual ] >= COLUMNA_MAXIMA )
{
mostrarSimbolo( //borrar el disparo
colDisparos[ disparoActual ],
renDisparos[ disparoActual ],
SIMBOLO_DISPARO );
//si quedan más disparos por hacer
if ( disparoActual<(cantDisparos-1) )
{
//el último disparo remplaza al disparo actual
colDisparos[ disparoActual ]= colDisparos[ cantDisparos -1 ];
renDisparos[ disparoActual ]= renDisparos[ cantDisparos -1 ];
//se vuelve al anterior disparo para el siguiente
//IF repita el disparo de la posición actual
disparoActual -=1 ;
}
cantDisparos -= 1; //se elimina el último disparo porque este cambio de lugar por el disparo eliminado
}
//si NO se recorrieron todos los disparos
if ( disparoActual< (cantDisparos-1) )
disparoActual += 1; //seguir con el siguiente disparo
else
disparoActual= 0; //volver al primer disparo
}
}
/*
Ends concurrency block
*/
}
}
/*
@descrip muestra el avion en una posición determinada
@param c columna de las alas del avión
@param r renglón del centro del avión
@param simbolo character con el cual se escribirá el avion, puede
mostrarse o borrarse el avión con la misma subrutina.
*/
void mostrarAvion( int c, int r, char simbolo )
{
gotoxy(c,r);printf("%c", simbolo );
gotoxy(c,r-1);printf("%c", simbolo );
gotoxy(c,r+1);printf("%c", simbolo );
gotoxy(c+1,r);printf("%c", simbolo );
}
/*
@descrip muestra un símbolo en una posición determinada
@param c columna del símbolo
@param r renglón del símbolo
@param simbolo character que se muestra
*/
void mostrarSimbolo( int c, int r, char simbolo )
{
gotoxy(c,r);
printf("%c", simbolo );
}
/*
@descrip agrega un disparo al arreglo de disparos
@param c columna del avión del cual sale el disparo
@param r renglón del avión del cual sale el disparo
@param renDisparos arreglo que contiene los renglones de cada disparo
@param colDisparos arreglo que contiene las columnas de cada disparo
@param *cantDisparos cantidad de disparos, se cambiará al final
*/
void agregarDisparo( int c, int r, int colDisparos[],int renDisparos[], int *cantDisparos )
{
colDisparos[ *cantDisparos ]= c + 2;
renDisparos[ *cantDisparos ]= r;
(*cantDisparos) += 1;
}
The next step is "Algorithm structure". One decision is made a thread for
the plane and another for all the shoots; but you can made a thread for the plane y one thread for each shoot.
Which are the best choice?
to be continued in the next article...
References
[1] Timothy G. Mattson, Beverly A. Sanders and Berna L. Massingill.
Patterns for Parallel Programming. 2005. Addison Wesley