Este es el sitio web histórico de la documentación de 4D. La documentación se está trasladando progresivamente a developer.4d.com

Inicio

 
4D v20.6
Semáforos y señales

Semáforos y señales  


 

Los semáforos y las señales son herramientas suministradas por el lenguaje 4D para gestionar las interacciones y evitar conflictos entre procesos en una aplicación multiproceso. Satisfacen diferentes necesidades:

  • un semáforo le permite asegurarse de que dos o más procesos no modifiquen el mismo recurso al mismo tiempo. Solo el proceso que define el semáforo puede eliminarlo.
  • una señal le permite asegurarse de que uno o más procesos esperarán a que se complete una tarea específica antes de continuar con su ejecución. Cualquier proceso puede esperar y/o liberar una señal.

En un programa de ordenador, un semáforo es una herramienta que se utiliza para protegerse de las acciones que deben ser realizadas por un único proceso o usuario a la vez.

En 4D, la necesidad convencional de uso de un semáforo es para modificar un array interproceso: si un proceso está modificando los valores del array, otro proceso no debe poder hacer lo mismo al mismo tiempo. El desarrollador utiliza un semáforo para indicar a un proceso que sólo puede realizar su secuencia de operaciones si ningún otro proceso está llevando a cabo las mismas tareas. Cuando un proceso se encuentra con un semáforo, hay tres posibilidades:

  • Obtiene inmediatamente el derecho a pasar
  • Espera su turno hasta que obtiene el derecho a pasar
  • Continúa su camino, abandonando la idea de realizar las tareas.
Por lo tanto, el semáforo protege partes del código. Se permite pasar sólo un proceso a la vez y bloquea el acceso hasta que el proceso que tiene actualmente el derecho de uso renuncia a este derecho liberando el semáforo.

En 4D, se establece un semáforo llamando a la función Semaphore. Para liberar un semáforo, se llama al comando CLEAR SEMAPHORE.

La función Semaphore tiene un comportamiento muy especial ya que realiza potencialmente dos acciones a la vez:

  • Si el semáforo ya está asignado, la función devuelve True
  • Si no se asigna el semáforo, la función lo asigna al proceso y devuelve False al mismo tiempo.

Esta doble acción realizada por el mismo comando asegura que ninguna operación externa se puede insertar entre la prueba del semáforo y su asignación.

Puede utilizar el comando Test semaphore para saber si un semáforo ya está asignado o no. Este comando se utiliza principalmente como parte de las operaciones largas, tales como el cierre anual de las cuentas, en donde Test semaphore le permite controlar la interfaz para evitar el acceso a ciertas operaciones tales como la adición de los datos contables.

Los semáforos deben utilizarse respetando los siguientes principios:

  • un semáforo se debe definir y lanzar en el mismo método,
  • la ejecución de código protegido por el semáforo debe ser lo más corta posible,
  • el código debe ser temporizado por medio del parámetro contTics de la función Semaphore para esperar la liberación del semáforo.

Este es el código típico para el uso de un semáforo:

 While(Semaphore("MySemaphore";300))
    IDLE
 End while
  // ubicar aquí el código protegido por el semáforo
 CLEAR SEMAPHORE("MySemaphore")

Un semáforo que no se libera puede bloquear parte de la base. Configurar y liberar el semáforo en el mismo método ayuda a eliminar este riesgo.

Minimizar el código protegido por el semáforo aumenta la fluidez de la aplicación y evita que el semáforo sea un cuello de botella.

Por último, utilizando el parámetro opcional contTics del comando Semaphore es esencial para optimizar la espera del semáforo a liberar. Utilizando este parámetro, los comandos funcionan de la siguiente manera:

  • El proceso espera un máximo del número especificado de tics (300 en el ejemplo) para que el semáforo esté disponible, sin la ejecución de código pasa a la siguiente línea,
  • Si se libera el semáforo antes del final de este límite, se le asigna inmediatamente al proceso (Semaphore devuelve False) y se reanuda la ejecución de código,
  • Si el semáforo no se libera antes del final de este límite y se reanuda la ejecución del código.

El comando también da prioridad a las peticiones estableciendo una cola. De esta manera, el primer proceso que solicita un semáforo será el primero en obtener uno.

Tenga en cuenta que el tiempo de espera se establece en función de las características específicas de la aplicación.

Hay dos tipos de semáforos en 4D: semáforos locales y semáforos globales.

  • Un semáforo local es visible para todos los procesos de un mismo puesto  y sólo en el puesto. Un semáforo local puede ser creado al añadir un prefijo al nombre del semáforo un signo de dólar ($). Se utiliza semáforos locales para supervisar las operaciones entre los diferentes procesos que se ejecutan en el misma equipo. Por ejemplo, un semáforo local se puede utilizar para controlar el acceso a un array interproceso compartido por todos los procesos de una base de datos mono usuario o de un equipo cliente.
  • Un semáforo global es accesible a todos los usuarios y todos sus procesos. Los semáforos globales se utilizan para controlar las operaciones entre los usuarios de una base de datos multiusuario.

Los semáforos globales y locales son idénticos en su lógica. La diferencia reside en su alcance.

En el modo cliente-servidor, los semáforos globales se comparten entre todos los procesos que se ejecutan en todos los clientes y servidores. Un semáforo local solamente se comparte entre los procesos que se ejecutan en la máquina donde se ha creado.

En 4D, los semáforos globales o locales tienen el mismo alcance, ya que usted es el único usuario. Sin embargo, si su base se está utilizando en ambas configuraciones, asegúrese de usar semáforos globales o locales, dependiendo de lo que quiere hacer.

Nota: se recomienda el uso de semáforos locales cuando se necesita un semáforo para gestionar un aspecto local para un cliente de la aplicación, tales como la interfaz o un conjunto de variables interproceso. Si se utiliza un semáforo global en este caso, no sólo haría intercambios de red innecesarios, sino también podría afectar a otros equipos cliente innecesariamente. El uso de un semáforo local evitaría estos indeseables efectos secundarios.

Una señal es un objeto compartido que contiene dos métodos integrados, signal.wait( ) y signal.trigger( ), y debe pasarse como un parámetro a los comandos que llaman o crean workers o procesos.

Todo worker/proceso que llame al método signal.wait( ) de la señal suspenderá su ejecución hasta que la propiedad signal.signaled sea true. Mientras se espera una señal, el proceso de llamada no utiliza ninguna CPU, lo que es muy interesante para el rendimiento en aplicaciones multiproceso. La propiedad signal.signaled se vuelve true cuando cualquier worker/proceso llama al método signal.trigger( ) de la señal.

Tenga en cuenta que para evitar situaciones de bloqueo, signal.wait( ) también puede regresar después de que se haya alcanzado un tiempo de espera definido.

El siguiente diagrama ilustra cómo se puede utilizar un objeto señal:

En 4D, crea un nuevo objeto señal llamando a la funcióne New signal. Una vez creada, esta señal se debe pasar como un parámetro a los comandos New process o CALL WORKER para que puedan modificarla cuando hayan finalizado la tarea que desea esperar.

La señal es un objeto compartido que contiene dos métodos integrados, signal.wait( ) y signal.trigger( ) y dos propiedades, signal.signaled (solo lectura, false cuando se crea la señal) y signal.description, escribible).

  • signal.wait( ) debe llamarse desde el worker/proceso que necesita otro worker/proceso para finalizar una tarea para continuar.
  • signal.trigger( ) debe llamarse desde el worker/proceso que terminó su ejecución para liberar todos los demás

Una vez que se ha liberado una señal utilizando una llamada signal.trigger( ) (la propiedad signal.signaled es true), no se puede reutilizar nuevamente. Si desea establecer otra señal, debe volver a llamar a la función New signal.

Como un objeto señal es un objeto compartido (ver Objetos y colecciones compartidos), puede utilizarlo para devolver resultados de workers/procesos, llamados, siempre que no olvide escribir valores dentro de una estructura Use...End use (ver ejemplo).

Un proceso apropiativo necesita obtener un valor de usuario (desde un diálogo, por ejemplo). Como no está permitido mostrar un diálogo desde un proceso apropiativo, llama a un proceso cooperativo y espera el valor de retorno:

 C_OBJECT($signal)
 
  // Creación de una señal
 $signal:=New signal
 
  // llamar al proceso principal y ejecutar el método OpenForm
 CALL WORKER(1;"OpenForm";$signal)
  // hacer otro cálculo
 ...
  // Esperando el final del proceso
 $signaled:=$signal.wait()
 
  // Procesamiento de los resultados
 $calc:=$signal.result+...

Método OpenForm:

 C_OBJECT($1;$signal;$form)
 $signal:=$1
 $form:=New object("value";0)
 
  // Abrir el formulario
 $win:=Open form window("Information";Movable form dialog box)
 DIALOG("Information";$form)
 CLOSE WINDOW($win)
 
  // Agrega un nuevo atributo a su objeto compartido $signal para pasar su resultado al otro proceso:
 Use($signal)
    $signal.result:=$form.value
 End use
 
  // Activar la señal al proceso de espera.
 $signal.trigger()



Ver también 

CLEAR SEMAPHORE
Espèce de sémaphore ! (Blog O. Deschanels)
Semaphore
Sobre workers

 
PROPIEDADES 

Producto: 4D
Tema: Procesos (Comunicación)

 
CONTENIDO DE LA PÁGINA 
 
HISTORIA 

Modificado: 4D v17 R4

 
ARTICLE USAGE

Manual de lenguaje 4D ( 4D v20)
Manual de lenguaje 4D ( 4D v20.1)
Manual de lenguaje 4D ( 4D v20.2)
Manual de lenguaje 4D ( 4D v20.3)
Manual de lenguaje 4D ( 4D v20.4)
Manual de lenguaje 4D ( 4D v20.5)
Manual de lenguaje 4D ( 4D v20.6)