gtpa2m1wApplication Programming

Cursors

A cursor is a nonpersistent internal structure associated with a collection that is used to reference an element in the collection. Cursors are used for the following:

For more information about cursor APIs, see the TPF C/C++ Language Support User's Guide.

Cursors can be used with any collection. If you use the cursor APIs to add or remove elements, cursor positioning remains valid unless an error occurs. If you use the collection (noncursor) APIs on collections that have a cursor associated with them to add or remove elements, cursor positioning might not be valid. One of the following conditions occurs:

Positioning might not be valid because a cursor points to a particular element position within a collection, not to an element itself. If collection APIs are used to add or remove elements in a collection that has a cursor pointing to a specific element, the elements in the collection may shift position and the cursor may no longer be pointing to same element. For example, if the cursor last pointed at the fifth position and an element was inserted after the first position, the cursor would be pointing at the same position when positioning is checked again. However, this position would now be referencing what was originally the fourth element.

When the cursor is used again, the positioning is checked and, if the cursor no longer points to an element or to an element that matches the current positioning information of the cursor, the cursor is marked as not valid and a request to reposition the cursor to a specific element is required before it can be used again. Note that elements in collections that allow multiples do not have a uniqueness among themselves. As a result, it is possible for the current positioning information of the cursor to match an element that is not the original element to which the cursor was pointing.

Initializing a Cursor

When a cursor is created, the cursor does not have a default position. A positioning-type operation (such as TO2_first or TO2_locate) is required before the cursor can be used to access the target collection. Whenever an error code indicating that the cursor is not valid (TO2_ERROR_CURSOR) is returned, it signifies that the cursor function has lost position either because the collection has been changed by the current user, some other user (only for dirty-reads), or because of a TPFCS problem. When you see this error code, try to reposition the cursor with a positioning-type operation on the cursor.

TPFCS provides the following functions to construct a cursor for a given collection:

If the position of the element changes, TPFCS attempts to reposition the cursor to point to the subject element. If TPFCS is unable to do so, the cursor is not valid. This occurs because the cursor refers only to the position of the element and not to the element itself.

If you add or remove elements from a collection while you are iterating over a collection (except by using the cursor doing the iteration), all elements may not be visited once.

Using Cursors for Locating, Accessing, and Removing Elements

Cursors provide a basic mechanism for accessing elements of collections. For each collection, you can define one or more cursors and you can use these cursors to access elements. Collection functions such as TO2_locate, TO2_setPositionIndex, and TO2_setPositionValue use cursors to locate and access specific elements. You can then access the actual element by using cursor functions such as TO2_atCursor, TO2_atCursorPut, or TO2_remove (see Removing Elements for more information).

Note:
Cursor functions specify the PID of the cursor, not the PID of the collection.

Using Cursors with Alternate Key Paths

A key path is used to determine the order in which some collections are traversed. There are two types of key paths: primary and alternate. When a collection is first created, the primary key path of the collection is used by default for searching and accessing data. You can use alternate key paths only with cursors.

You can use the TO2_setKeyPath function to override the default setting or any previous TO2_setKeyPath calls to specify an alternate key path. A maximum of 16 alternate key paths (in addition to the primary) can be defined for each collection. When the TO2_setKeyPath function is issued, the position of the cursor must be reestablished by using one of the positioning functions such as TO2_first. See Key Path Support for more information.

Cursor Positioning

The first and last elements in a collection are based on what type of collection it is. The following sections describe what the first and last elements are according to the type of collection.

First Element in a Collection

The first element in a collection is based on the type of collection:

Last Element in a Collection

The last element in a collection is based on the type of collection:

Determining the End of the Collection

The end of the collection is defined as the position after the last existing element in the collection. For collections without an explicit ordering, this position is determined by the implementation (that is, randomly). In the following example, x points to the first element, y points to the last element, and z points to the end of the collection.

Figure 16. Collection with N Elements


Table 16 relates to Figure 16 and provides a summary of cursor returns for the TO2_first, TO2_atLast, and TO2_atEnd functions.

Table 16. Cursor Returns

Cursor Position TO2_First TO2_atLast TO2_atEnd
x TO2_IS_TRUE TO2_IS_FALSE TO2_IS_FALSE
y TO2_IS_FALSE TO2_IS_TRUE TO2_IS_FALSE
z TO2_IS_FALSE TO2_IS_FALSE TO2_IS_TRUE

Rules for Cursor Movement and Positioning

TPFCS observes the following rules for cursor movement and positioning:

Iterating over Collections

Iterating over all or some elements of a collection is a common operation. The collection library gives you two methods of iteration:

Ordered collections, such as array and sorted set, have a well-defined ordering of their elements. Unordered collections, such as bag and set, have no defined order in which the elements are visited in an iteration; however, for these types of collections, each element is visited exactly once. Similarly, unique collections, such as set and key sorted set, do not allow multiple elements with the same key or value. Nonunique collections, such as bag and key sorted bag, allow duplicate values and keys; again, for these types of collections, each element is visited exactly once.

Iteration Using Cursors

Do not add or remove elements from a collection while you are iterating over a collection except by using the cursor that is doing the iterating or all elements may not be visited once. See Removing Elements for more information about removing elements.

Cursor iteration can be done with a for loop. Consider the following example:

#include <c$to2.h>                /* Needed for TO2 API functions   */
 
TO2_PID       myCollection;
TO2_PID       myCursor;
TO2_ENV_PTR   env_ptr;
MyIntElement *currentElementPtr;
 
TO2_BUF_PTR   bufferPtr;

  ·
  ·
  ·
/*********************************************************************/ /* Access each of the elements in the collection... */ /*********************************************************************/ TO2_createCursor(&myCollection, env_ptr, &myCursor); for (TO2_first(&myCursor, env_ptr), TO2_more(&myCursor, env_ptr), TO2_cursorPlus(&myCursor, env_ptr)) {
  ·
  ·
  ·
if ((bufferPtr = TO2_atCursor(&myCursor,env_ptr)) == TO2_ERROR) { printf("TO2_atCursor failed!\n"); process_error(env_ptr); } else { /* work with currentElement using currentElementPtr.*/ currentElementPtr = (MyIntElement *)bufferPtr->data;
  ·
  ·
  ·
} free(bufferPtr); release returned buffer }
  ·
  ·
  ·
TO2_deleteCursor(myCursor, env_ptr);

In this example, a cursor is created for myCollection. The loop is initialized by pointing the cursor to the beginning of the collection. The loop then iterates over all elements stored in the collection. The data component of each element is accessed and manipulated. The loop ends when there are no more elements remaining to process in the collection. Finally, the cursor is deleted.

Note:
This code example does not show any environment tests for possible errors.

TO2_allElementsDo

Cursor iteration has two possible drawbacks:

The collection library provides the TO2_allElementsDo function, which addresses both drawbacks by calling a user-specified function that is applied to all elements. The user-specified function returns a value that is used internally to indicate the continuation or ending of the iteration. For collections with order, the function is applied in this order. Otherwise, the order is not specified.

Additional arguments that are needed for the iteration can be passed as an extra parameter list on the TO2_allElementsDo function.

Using Cursors for Locking Collections

Cursors are also used to prevent concurrent updating of a collection while you are accessing elements in the collection.

The following summarizes TPFCS operations involving the two different types of cursors:

A different ECB can also do all of the above.

The same ECB cannot create another locking cursor. A different ECB can do all of the above and it can also create another locking cursor, although the request will be deferred until the original locking cursor is deleted.