This is the legacy 4D documentation web site. Documentations are progressively being moved to developer.4d.com

Home

 
4D v20.6
Shared objects and shared collections

Shared objects and shared collections  


 

Shared objects and shared collections are specific objects and collections whose contents are shared between processes. In contrast to interprocess variables, shared objects and shared collections have the advantage of being compatible with Preemptive 4D processes: they can be passed by reference as parameters to commands such as New process or CALL WORKER.

Shared objects and shared collections can be stored in variables declared with standard C_OBJECT and C_COLLECTION commands, howeverr they must be instantiated using specific commands:

Note: Shared objects and collections can be set as properties of standard (not shared) objects or collections.

In order to modify a shared object/collection, the Use...End use structure must be called. Reading a shared object/collection value does not require Use...End use.

A unique, global catalog returned by the Storage command is always available throughout the database and its components, and can be used to store all shared objects and collections.

Once instantiated with the New shared object or New shared collection commands, shared object/collection properties and elements can be modified or read from any process.

The following modifications can be applied to shared objects and shared collections:

  • adding or removing object properties,
  • adding or editing values (provided they are supported in shared objects), including other shared objects or collections (which creates a shared group, see below).

However, all modification instructions in a shared object or collection must be surrounded by the Use...End use keywords, otherwise an error is generated.

 $s_obj:=New shared object("prop1";"alpha")
 Use($s_obj)
    $s_obj.prop1:="omega"
 End Use

A shared object/collection can only be modified by one process at a time. Use locks the shared object/collection from other threads, while End use unlocks the shared object/collection (if the locking counter is at 0, see below). Trying to modify a shared object/collection without at least one Use...End use generates an error. When a process calls Use...End use on a shared object/collection that is already in use by another process, it is simply put on hold until a End use unlocks it (no error is generated). Consequently, instructions within Use...End use structures should execute quickly and unlock the elements as soon as possible. Thus, it is strongly advised to avoid modifying a shared object or collection directly from the interface, e.g. through a dialog box.

Assigning shared objects/collections to properties or elements of other shared objects/collections is allowed and creates shared groups. A shared group is automatically created when a shared object/collection is set as property value or element of another shared object/collection. Shared groups allow nesting shared objects and collections but enforce additional rules:

  • Calling Use on a shared object/collection belonging to a group locks properties/elements of all shared objects/collections of the group and increments its locking counter. Calling End use decrements the locking counter of the group and when the counter is at 0, all the linked shared objects/collections are unlocked.
  • A shared object/collection can only belong to one shared group. An error is returned if you try to set an already grouped shared object/collection to a different group.
  • Grouped shared objects/collections cannot be ungrouped. Once included in a shared group, a shared object/collection is permanently linked to that group during the entire session. Even if all references of an object/collection are removed from the parent object/collection, they will remain linked.

Please refer to example 2 for an illustration of shared group rules.

Note: Shared groups are managed through an internal property named locking identifier. For detailed information on this value, please refer to About the locking identifier (how shared groups work) advanced section below.

 

Read  

Reading properties or elements of a shared object/collection is allowed without having to call the Use...End use structure, even if the shared object/collection is in use by another process.

However, it is necessary to read a shared object/collection within Use...End use when several values are linked together and must be read at once, for consistency reasons.

By default, calling OB Copy/collection.copy( ) with a shared object/collection (or containing shared objects/collections) will return a regular (not shared) object/collection including its contained objects (if any). 

However, you can use the ck shared option parameter with these commands to produce a shared copy of the source object/collection. 

Storage  

Storage is a unique shared object, automatically available on each application and machine. This shared object is returned by the Storage command. You can use this object to reference all shared objects/collections defined during the session that you want to be available from any preemptive or standard processes.

Note that, unlike standard shared objects, the storage object does not create a shared group when shared objects/collections are added as its properties. This exception allows the Storage object to be used without locking all connected shared objects or collections.

For more information, refer to the Storage command description.

You want to launch several processes that perform an inventory task on different products and update the same shared object. The main process instantiates an empty shared object and then, launches the other processes, passing the shared object and the products to count as parameters:

 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
 
  //Create processes
 For($i;1;$nbItems)
    $ps:=New process("HowMany";0;"HowMany_"+$_items{$i};$_items{$i};$inventory)
  //$inventory object sent by reference
 End for

In the "HowMany" method, inventory is done and the $inventory shared object is updated as soon as possible:

 C_TEXT($1)
 C_TEXT($what)
 C_OBJECT($2)
 C_OBJECT($inventory)
 $what:=$1 //for better readability
 $inventory:=$2
 
 $count:=CountMethod($what//method to count products
 Use($inventory//use shared object
    $inventory[$what]:=$count  //save the results for this item
 End use

The following examples highlight specific rules when handling shared groups:

 $ob1:=New shared object
 $ob2:=New shared object
 Use($ob1)
    $ob1.a:=$ob2  //group 1 is created
 End use
 
 $ob3:=New shared object
 $ob4:=New shared object
 Use($ob3)
    $ob3.a:=$ob4  //group 2 is created
 End use
 
 Use($ob1//use an object from group 1
    $ob1.b:=$ob4  //ERROR
  //$ob4 already belongs to another group
  //assignment is not allowed
 End use
 
 Use($ob3)
    $ob3.a:=Null //remove any reference to $ob4 from group 2
 End use
 
 Use($ob1//use an object from group 1
    $ob1.b:=$ob4  //ERROR
  //$ob4 still belongs to group 2
  //assignment is not allowed
 End use

Note: This section provides additional information about internal mechanisms and may be useful in specific cases only.

Every new shared object/collection is created with a unique locking identifier (a longint value). The initial value of the locking identifier is always negative, which means that the shared object/collection is "single". When a "single" shared object/collection is set as a property or element of another shared object/collection, both become "multiple" and a shared group is created. They share the same locking identifier (added properties/element inherit from the locking identifier of the parent object/collection), and the value of the locking identifier becomes positive.

When a shared object/collection is removed from its parent object/collection:

  • they are still considered as "multiple"
  • they keep the same locking identifier.

Rules are applied when setting shared objects/collections as properties or elements to other shared objects/collections:

  • a "single" object/collection can be attached to another "single" or "multiple" object/collection,
  • a "multiple" object/collection can be attached to another "multiple" object/collection which has the same locking identifier,
  • an error occurs if you try to attach a "multiple" object/collection to another "single" or "multiple" object/collection that does not have the same locking identifier.

These rules are illustrated in the following graphics:

  1. Shared objects and shared collections (A, B, C, D) are created with a negative, unique "locking identifier" (in green).
  2. When a single object (B) is referenced inside another single object (A), they both become multiple and share the same positive locking identifier (in red). Additional single objects can be added to (A) either alongside or within (B). All objects are considered multiple and share the same locking identifier.
  3. When a multiple object (B) is removed (dereferenced) from another multiple object (A), they both remain multiple and continue to keep and share the same locking identifier
  4. Multiple objects (A, B) cannot be used as properties of a single object (D), while single objects (C) can be used.
  5. Multiple objects (A, B) can be used as properties of object (D) if they share the same locking identifier. Single objects (C) can also be used.

The locking identifier of shared objects and collections is displayed in the debugger as the __LockerID private property. You can display the "Shared Object" type in the debugger by selecting Show Types in the debugger's contextual menu:

Note that shared objects and collections are enterable in the debugger as long as they are not "used" anywhere else, in which case they cannot be modified.  



See also 

New shared collection
New shared object
OB Copy
Storage

 
PROPERTIES 

Product: 4D
Theme: Objects (Language)

 
PAGE CONTENTS 
 
HISTORY 

Created: 4D v16 R6

 
ARTICLE USAGE

4D Language Reference ( 4D v20)
4D Language Reference ( 4D v20.1)
4D Language Reference ( 4D v20.2)
4D Language Reference ( 4D v20.3)
4D Language Reference ( 4D v20.4)
4D Language Reference ( 4D v20.5)
4D Language Reference ( 4D v20.6)