gtpa2m1w | Application Programming |
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:
The cursor provides methods that allow an application program to move through a collection one element at a time without needing keys or indexes.
When a locking cursor is created for a particular collection, a lock is placed on the entire collection so that only the ECB that created the cursor can update the elements in the collection.
It is more efficient to access multiple elements in a collection using a cursor. Most TPFCS functions are atomic; that is, the element is read into storage, managed, and removed from storage for each function call. This type of processing requires much overhead. With cursors, once a collection is read into storage, it remains there for the life of the cursor. The cursor is temporary and must be deleted by the application program or when the ECB exits.
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.
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.
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).
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.
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.
The first element in a collection is based on the type of collection:
Table 14 summarizes what happens when a cursor is positioned at the
start of a collection (TO2_first returns TO2_IS_TRUE).
Table 14. Cursor Positioned at the Start of a Collection
Function Name | Result | Cursor Status |
---|---|---|
TO2_addAtCursor | Adds the element as the first element. | Positioned to point at the inserted element. |
TO2_atCursor | Reads the first element. | Unchanged. |
TO2_atCursorPut | Updates the first element. | Unchanged. |
TO2_cursorMinus | TO2_ERROR_EODAD | Not valid. |
TO2_cursorPlus | Updates the cursor position (or returns EODAD if the collection contains only one element). | Positioned to point at the next element. |
TO2_remove | Removes the first element. | Positioned to point at the next element, which is now the first. |
The last element in a collection is based on the type of collection:
Table 15 summarizes what happens when a cursor is positioned at the
end of a collection (TO2_atEnd returns TO2_IS_TRUE).
Table 15. Cursor Positioned at the End of a Collection
Function Name | Result | Cursor Status |
---|---|---|
TO2_addAtCursor | Adds the element as the last element. | Positioned to point at the inserted element. |
TO2_atCursor | TO2_ERROR_EODAD | Unchanged. |
TO2_atCursorPut | TO2_ERROR_EODAD | Unchanged. |
TO2_cursorMinus | Successful. | Positioned at the last element. |
TO2_cursorPlus | TO2_ERROR_EODAD | Not valid. |
TO2_remove | TO2_ERROR_EODAD | Unchanged. |
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.
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 |
TPFCS observes the following rules for cursor movement and positioning:
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.
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.
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.
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.