@interface Transition : Figure { BOOL active; } ... - (void)run; - (void)execute: (id)connections; - (NSImage *)drawFigure; - (tGraph)typeGraph; ... @endLa 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:
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.
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.