next up previous contents
Next: La clase Connection Up: Diseño e implantación Previous: La clase Place

   
La clase Transition

Los objetos de esta clase deben ejecutar acciones sobre los lugares de la red de Petri. Estos objetos tiene asociados un objetos NSThread, que se encargará de leer de sus lugares de entrada y arcos el número de tokens y pesos para verificar si está en posibilidades de disparar, en caso de estarlo, procederá a escribir en los lugares de salida el valor correspondiente. Esta clase utiliza una variable de clase (que hace referencia a un objeto NSLock) para evitar problemas de exclusión mútua entre los distintos hilos que se van a ejecutar en la aplicación.
@interface Transition : Figure
{
    BOOL active;
}
...
- (void)run;
- (void)execute: (id)connections;
- (NSImage *)drawFigure;
- (tGraph)typeGraph;
...
@end
La variable active indica si el usuario desea que la transición pueda ejecutarse. Con ayuda de esta variable, el usuario puede desactivar una transición desde el panel Inspector.

Los métodos se ejecutan como se describe a continuación:

run
El mensaje run se envía desde el objeto PNMatrix cuando se ponde a ejecutar una red de Petri. Este método obtiene la lista de los lugares de entrada y salida, y después crea un objeto NSThread, el cual se encargará de ejecutar la transición. Esto se muestra en el siguiente listado:
1 - (void)run {
2    if (active) {
3        [self getConnection];
4        [NSThread detachNewThreadSelector: @selector(execute:)
                                  toTarget: self
                                withObject: ioConnections];
5    }
6}
En la línea 5, se manda a ejecutar el método getConnection para obtener la lista de los lugares de entrada y salida de la transición, esta información se almacena en el objeto ioConnections (el cual, se utiliza en la siguiente línea de código). La línea 6 manda a crear y ejecutar un objeto hilo (NSThread). Este hilo ejecuta el método execute de este mismo objeto, con el argumento ioConnections.

execute
Este método lo ejecutan los hilos de cada transición, por lo que se debe tener cuidado ya que, como toda parte de código compartida, tiene secciones críticas que pueden causar problemas de exclusión mutua.

Vale la pena revisar el código para explicarlo:

1  - (void)execute: (id)connections
2  {
3    NSAutoreleasePool *localPool=[[NSAutoreleasePool alloc] init];
4    while ([superView isRunning]) {
5        while (![myLock tryLock])
6            [NSThread sleepUntilDate:
7               [NSDate dateWithTimeIntervalSinceNow:0.7]];
8        // begin critical section
9        if ([self conditionsOK]) {
10           [self setCanRunTransition:YES];
11           [self eliminateInputs];
12           [self appendOutputs];
13           [[self superview] display];
14       }
15       // end critical section
16       [myLock unlock];
17       if ([self canRunTransition]) {
18           [self setCanRunTransition:NO];
19           [NSThread sleepUntilDate:
20              [NSDate dateWithTimeIntervalSinceNow:0.9]];            
21       }
22   }
23   [localPool release];
24   [NSThread exit];
25   return;
26 }
Este método se ejecuta de la siguiente manera: primero se crea un área de memoria dedicada a almacenar objetos locales a cada hilo (línea 3). En la línea 4 inicia el ciclo que mantiene a los hilos en ejecución: mientras el objeto PNView mantenga encendida la bandera running, los hilos intentarán ejecutarse. Posteriormente, en la línea 5, se sensa el lock para entrar a la sección crítica, si el lock no está disponible, entonces el hilo debe dormirse, sin embargo los métodos de los objetos NSthread solo permiten que el hilo se duerma un determinado tiempo, se creen y ejecuten, y terminen su ejecución. Por lo que se manda a dormir un periodo de tiempo, si cuando despierte esta libre el lock, entonces podrá continuar su ejecución hacia la sección crítica. De no estar disponible el lock, el hilo se vuelve a dormir otra cantidad de tiempo. Si el hilo logra entrar a la sección crítica, en la línea 9, con el llamado al método conditionsOK se averigua si es posible ejecutar esta transición --se debe cumplir que cada lugar de entrada tenga mayor o igual número de token que el peso del arco que lo une con la transición--. Si no se puede ejecutar, termina la ejecución de la sección crítica, libera el candado e intenta ejecutarse nuevamente. Si se cumplen las condiciones para ejecutar la transición, entonces se se eliminan los tokens de los lugares de entrada y se colocan lo tokens en los lugares de salida, evidentemente considerando el peso de los arcos--. Y finalmente, se manda a actualizar la imagen de la red de Petri. Una vez terminada la ejecución de la transición, se libera el candado y la transición queda inhabilitada un pequeño lapso de tiempo para permitir a otros transiciones, la oportunidad de ejecutarse.

drawFigure
Con este método sólo se crea una figura rectangular en un cuadro donde se defiene el origen de coordenadas respectoa al superView y el tamaño de la transición.

typeGraph
Este método indica, con su valor de regreso, que el grafo es del tipo Transition.


next up previous contents
Next: La clase Connection Up: Diseño e implantación Previous: La clase Place
Amilcar Meneses
2002-11-08