Los objetos compartidos y las colecciones compartidas son objetos específicos y colecciones cuyos contenidos se comparten entre procesos. A diferencia de , los objetos compartidos y las colecciones compartidas tienen la ventaja de ser compatibles con Procesos 4D apropiativos: se pueden pasar por referencia como parámetros a comandos como New process o CALL WORKER.
Los objetos compartidos y las colecciones compartidas se pueden almacenar en las variables declaradas con los comandos estándar C_OBJECT y C_COLLECTION, pero se deben crear instancias utilizando comandos específicos:
para crear un objeto compartido, utilice el comando New shared object o OB Copy con la opción ck shared.
Nota: los objetos compartidos y las colecciones compartidas se pueden definir como propiedades de objetos o colecciones estándar (no compartidos).
Para modificar un objeto/colección compartido, debe llamarse la estructura Use...End use. Leer un valor de objeto/colección compartido no requiere Use...End use.
Un único catálogo global devuelto por el comando Storage siempre está disponible en toda la base y sus componentes y se puede usar para almacenar todos los objetos y colecciones compartidos.
Una vez instanciado con los comandosNew shared object o New shared collection, los atributos objeto/colección compartidos y elementos se pueden modificar o leer desde cualquier proceso.
Las modificaciones se pueden aplicar a objetos compartidos y colecciones compartidas:
agregar o eliminar propiedades de objetos,
agregar o editar valores (siempre que sean soportados en objetos compartidos), incluyendo otros objetos o colecciones compartidos (que crea un grupo compartido, ver más adelante).
Sin embargo, todas las instrucciones de modificación en un objeto compartido o colección deben estar rodeadas por las palabras claves Use...End use, de lo contrario, se generará un error.
$s_obj:=New shared object("prop1";"alpha") Use($s_obj) $s_obj.prop1:="omega" End Use
Un objeto/colección compartido solo puede ser modificado por un proceso a la vez. Use bloquea el objeto/colección compartido de otros hilos, mientras que End use desbloquea todos los objetos/colecciones compartidos (si el contador de bloqueo está en 0, ver abajo). Tratar de modificar un objeto/colección compartido sin al menos Use...End use genera un error. Cuando un proceso llama a Use...End use en un objeto/colección compartido que ya está siendo utilizado por otro proceso, simplemente se pone en espera hasta que un End use lo desbloquee (no se genera ningún error). Por lo tanto, las instrucciones en estructuras Use...End use deben ejecutarse rápidamente y desbloquear los elementos tan pronto como sea posible. Por lo tanto, se recomienda encarecidamente evitar la modificación de un objeto o colección compartido directamente desde la interfaz, por ejemplo, a través de un cuadro de diálogo.
La asignación de objetos/colecciones compartidas a propiedades o elementos de otros objetos compartidos / colecciones está permitida y crea grupos compartidos. Un grupo compartido se crea automáticamente cuando un objeto compartido/colección se establece en un valor de propiedad o un objeto compartido. Los grupos compartidos permiten anidar objetos y colecciones compartidos pero se deben seguir reglas adicionales:
La llamada a Use con un objeto/colección compartido que pertenece a un grupo provocará el bloqueo de las propiedades/elementos de todos los objetos/colecciones del grupo e incrementa el contador de bloqueo. Llamar End use disminuye el contador de bloqueo del grupo y cuando el contador está en 0, se desbloquean todos los objetos/colecciones compartidos vinculados.
Un objeto o una colección compartida(o) solo puede pertenecer a un grupo compartido. Se devuelve un error si desea asignar un objeto/colección compartido ya agrupados a un grupo diferente.
Los objetos/colecciones agrupados no se pueden desagrupar. Una vez incluido en un grupo compartido, un objeto o una colección compartida se une definitivamente al grupo durante todas la duración de la sesión. Incluso si todas las referencias del objeto/la colección se eliminen de los objetos/colecciones padre, permanecerán vinculados.
Consulte el ejemplo 2 para ver una ilustración de las reglas de grupo compartidas.
Nota: los grupos compartidos se administran a través de una propiedad interna llamada locking identifier. Para obtener información detallada sobre este valor, consulte la sección avanzada Identificador de bloqueo a continuación.
La lectura de propiedades o elementos de un objeto/colección compartido está permitida sin tener que llamar a la estructura Use...End use, incluso si el objeto/colección compartido está siendo utilizado por otro proceso.
Sin embargo, es necesario leer un objeto/colección compartido dentro de Use...End use cuando varios valores se vinculan entre sí y se deben leer a la vez, por razones de coherencia.
De manera predeterminada, llame a OB Copy/collection.copy( ) con un objeto/colección compartido (o que contiene objetos/colecciones compartidas) devolverá un objeto/colección clásico (no compartido) incluidos sus objetos contenidos (si los hay).
Sin embargo, puede utilizar el parámetro opcionck shared con estos comandos para producir una copia compartida del objeto/colección fuente.
Storage es un objeto compartido único, disponible automáticamente en cada aplicación y máquina.Este objeto compartido es devuelto por el comandoStorage. Está diseñado para referenciar los objetos/colecciones compartidos definidos durante la sesión que quiere que sean accesibles a todos los procesos, apropiativos o estándar.
Tenga en cuenta que, a diferencia de los objetos compartidos estándar, el objeto Storage no crea un grupo compartido cuando los objetos/colección son agregados como sus propiedades.Esta excepción permite que el objeto Storage se use sin bloquear todos los objetos compartidos conectados.
Para más información, consulte la descripción del comandoStorage.
Desea iniciar varios procesos que realizan una tarea de inventario en diferentes productos y actualizar el mismo objeto compartido.El proceso principal ejemplifica un objeto compartido vacío y luego, inicia los otros procesos, pasando el objeto compartido y los productos para contar como parámetros:
ARRAY TEXT($_items;0)
... //fill the array with items to count $nbItems:=Size of array($_items) C_OBJECT($inventory) $inventory:=New shared object Use($inventory) $inventory.nbItems:=$nbItems End use
//Crear procesos For($i;1;$nbItems) $ps:=New process("HowMany";0;"HowMany_"+$_items{$i};$_items{$i};$inventory) //$inventory object sent by reference End for
En el método "HowMany", se hizo el inventario y el objeto compartido $inventory se actualiza tan pronto como es posible:
C_TEXT($1) C_TEXT($what) C_OBJECT($2) C_OBJECT($inventory) $what:=$1//para mayor lecturabilidad $inventory:=$2
$count:=CountMethod($what) //método para contar productos Use($inventory) //utilizar objeto compartido $inventory[$what]:=$count //guardar los resultados para este elemento End use
Nota: esta sección ofrece información adicional sobre mecanismos internos específicos y puede ser útil en casos específicos únicamente.
Todos los objetos/colecciones conectados:
El valor del identificador de bloqueo de un objeto/colección compartido "único" es negativo;
El valor del identificador de bloqueo de un objeto/colección compartido "múltiple" es positivo.
Cada nuevo objeto/colección compartido se crea con un identificador de bloqueo único (un valor entero largo). El valor inicial del identificador de bloqueo es siempre negativo, lo que significa que el objeto/colección compartido es "single". Cuando un objeto/colección compartido con un estado "único" se establece como una propiedad o elemento de otro objeto/colección compartido, todos los objetos/colecciones conectados se convierten en "múltiples". Comparten el mismo identificador de bloqueo (propiedades/elementos agregados heredan el identificador de bloqueo del objeto/colección padre), y el valor del identificador de bloqueo se vuelve positivo.
Cuando se elimina un objeto/colección compartido de su objeto/colección padre:
aún se consideran como "múltiples"
mantienen el mismo identificador de bloqueo.
Las reglas se aplican al establecer objetos/colecciones compartidos como propiedades o elementos a otros objetos/colecciones compartidos:
un objeto/colección "único" se puede unir a otro objeto/colección "único" o "múltiple",
un objeto/colección "múltiple" se puede unir a otro objeto/ colección "múltiple" que tiene el mismo identificador de bloqueo,
se produce un error si intenta adjuntar un objeto/colección "múltiple" a otro objeto/colección "único" o "múltiple" que no tiene el mismo identificador de bloqueo.
Estas reglas se ilustran en los siguientes gráficos:
Los objetos compartidos y las colecciones compartidas (A, B, C, D) se crean con un "identificador de bloqueo" interno y único (1, 2, 3, 4).
Cuando se hace referencia a un único objeto (A) dentro de otro objeto único (B), ambos se vuelven múltiples y comparten el mismo identificador de bloqueo. Se pueden agregar objetos individuales adicionales a (A) ya sea al costado o dentro de (B). Todos los objetos se consideran múltiples y comparten el mismo identificador de bloqueo.
Cuando un objeto múltiple (B) se elimina (desreferencia) de otro objeto múltiple (A), ambos permanecen múltiples y continúan conservando y compartiendo el mismo identificador de bloqueo
Los objetos múltiples (A, B) no se pueden usar como propiedades de un solo objeto (D), mientras que los objetos individuales (C) se pueden usar.
Se pueden usar varios objetos (A, B) como propiedades del objeto (D) si comparten el mismo identificador de bloqueo. Los objetos individuales (C) también se pueden usar.
El identificador de bloqueo de objetos y colecciones compartidos se muestra en el depurador como la propiedad privada __LockerID. Puede mostrar el tipo de "Objeto compartido" en el depurador seleccionando Mostrar tipos en el menú contextual del depurador:
Tenga en cuenta que los objetos compartidos y las colecciones se pueden ingresar en el depurador, siempre que no se "usen" en ningún otro lugar, en cuyo caso no se pueden modificar.