Managing Items


In a multitasking system, tasks often share resources such as RAM, I/O devices, and data structures. If the system doesn't manage those resources carefully, a task that depends on a shared resource can be brutally disappointed. For example, one task creates a data structure for a second task to read and act upon. If the first task dies and its data structure is no longer maintained or ceases to exist, the second task can find itself reading erroneous data that can crash it. In another example, a task creates a data structure and then use an invalid pointer to that structure (typically a NULL or uninitialized pointer). Because the pointer doesn't point where it should, the task can read totally erroneous data or, even worse, try to write to the data structure and crash itself, another task, or the 3DO system.

Note: Using a NULL pointer to read is illegal and causes an abort to occur on 3DO development systems.

Items

To insure the integrity of shared resources, the kernel provides items. An item is a system-maintained handle for a shared resource. The handle contains a globally unique item number and a pointer to the resource. When a task needs access to a shared resource, the task simply asks for the resource by item number instead of using a pointer to point directly at the resource. The kernel checks its list of items and, if it finds the requested item, performs any requested actions on the item. If the kernel finds that the item no longer exists, it informs the requesting task that access failed, and the task can go on without crashing itself or the system.

An item can refer to any one of many system components: a data structure used to create graphics, an I/O device, a folio, or even a task itself. In fact, almost all system-standard structures must be created as items. You'll find one of the most commonly used kernel calls is CreateItem(), which, appropriately enough, creates items. You use it to start a task, to lay out a graphics environment, to create messages to send between tasks, and to handle many other Portfolio functions.

Creating an Item

To create an item, a task typically creates a list of parameters (tag arguments) for the item. The parameters can include a name for the item, its dimensions and contents, and other important information. The task then uses CreateItem() to ask the kernel to create the item. The task supplies an item-type number that specifies the type of item to create, and a pointer to the list of parameters for the item. The kernel has a predefined set of item types (which you can find in the 3DO Portfolio Reference Manual). Each item requires different parameters to define it.

The kernel receives the item parameters, and-if they're correct for the specified item type-creates the item. The item contains a globally unique ID number, the item type, a pointer to the resource handled by the item, and other parameters passed to it. The kernel returns the item number to the task that created the item. The kernel records the fact that the item belongs to that task.

Portfolio contains a large number of convenience calls that let you easily create items; for example, CreateMsgPort() and CreateThread(). It is generally simpler to use these higher-level routines instead of calling CreateItem() directly.

Opening Items

Many system items are predefined and stored on the system boot disk. They don't need to be created from scratch, only opened. To open a system item, a task uses the FindAndOpenItem() call to specify the type of the item to open, provides an array of the arguments required to open the item, and passes that information along to the kernel to open the item. The kernel finds the item on the disk, brings necessary data structures into system memory, assigns the item a number, and returns the item number to the task that asked for the item to be opened. When the task is finished with the opened item, it uses the CloseItem() call to close the item.

Using Items

Once an item is opened or created, tasks can use it by specifying its item number. If a task doesn't have the number for an item it wants to use, or knows the item number but doesn't know what type of item it is, the kernel provides item-handling function calls such as FindItem(), FindNamedItem(), and LookupItem(). These calls help find items by name, number, or other criteria, and then return item type, item number, or other information about the item.

Note: Some types of items, such as folios and devices, must be opened with OpenItem() or FindAndOpenItem() before a task can use the item.

The kernel provides the SetItemPri() call to change the priority of an item within a list of items. It also provides the SetItemOwner() call to change ownership of an item.

Deleting Items

Whenever a task finishes using an item that it created, it can delete the item with DeleteItem(), which removes the item and frees any resources committed to it, such as RAM devoted to the item's data structure. The deleted item's number is not recycled when new items are created, so the kernel can inform tasks trying to use that item number that the item no longer exists.

There is one important rule about item deletion: a task can't delete any item it doesn't own. This means that if a task creates an item and then passes ownership to another task, the first task can't delete the item-only the new owner can delete the item.

Whenever a task or thread quits or dies, the kernel automatically deletes all items that it created, and closes any items that it opened.