The Pandora object kernel is a function library that provides the features
expected of a traditional kernel, while also providing a fully featured object
oriented programming interface. This makes it a unique hybrid, but allows for
better portability and services. Support for the management of memory and
resources are all present, but you will also find extensive support for class
management and field and object handling.
The portability of the object kernel has been enhanced by keeping the
functions as generalised as possible. Depending on the intended platform, the
object kernel can be developed to run independently (i.e. as a real kernel) or
it can leech functionality from a dedicated kernel (as is the case with the
Linux version). It is vital that when running on a host environment that the
temptation to use the host's functions are avoided, or you will lose
compatibility with other computer systems running the Pandora Engine.
For summarised information about how the system works, please refer to the
General Documentation which covers all aspects of the design and object
orientation in the system. From here on in the subject matter is very
technical, so if you do not have any background knowledge of the Pandora
Engine, please read the beginner manuals before continuing.
Function Index |
AccessMemory | Grants access to public memory blocks. |
Action | This function is responsible for executing action routines. |
ActionList | Returns a pointer to the kernel's most current action table. |
ActionMsg | Provides a mechanism for sending actions to objects that belong to other tasks. |
ActionTags | This is a tag-based version of the Action() function. |
AllocMemory | Allocates system memory blocks. |
AllocateClassID | Generates dynamic class ID's. |
AllocateID | Generates unique ID's for various purposes within the Pandora Engine. |
AttemptExclusive | Grants exclusive access to public objects. |
CheckAction | Checks objects to see whether or not they support certain actions. |
CheckMemoryExists | Checks if a memory block still exists. |
CheckObjectExists | Checks if a particular object is still available in the system. |
CloneMemory | Makes an exact duplicate of a memory block. |
CreateObject | Provides a fast way of creating and initialising new objects. |
CurrentContext | Returns a pointer to the object that has the current context. |
CurrentTask | Returns the object ID of the current Task. |
DPrintF | Sends formatted strings to the debugger. |
DebugState | Turns debug messages on and off. |
FastFindObject | Searches for objects by name. |
FindClass | Finds the relevant Class object for a particular Class ID. |
FindObject | Searches for objects by name and class. |
FreeExclusive | Releases objects from exclusive use. |
FreeMemory | Frees private memory blocks allocated from AllocMemory(). |
FreeMemoryID | Frees public memory blocks allocated from AllocMemory(). |
GetClassID | Returns the class ID of an object. |
GetContainerID | Returns the unique ID of an object's container. |
GetField | Retrieves single field values from objects. |
GetFieldVariable | Retrieves field values by converting them into strings. |
GetFields | Retrieves multiple field values in a single function call. |
GetMessage | Reads messages from message queues. |
GetName | Retrieves object names. |
IdentifyData | Used for associating data with object classes. |
ListChildren | Returns a list of all children belonging to an object. |
ListMemory | Returns a list of public or private memory blocks that have been allocated in the system. |
ManageAction | Allows modules to intercept and manage action calls. |
MemoryIDInfo | Returns information on memory ID's. |
MemoryPtrInfo | Returns information on memory addresses. |
NewObject | Creates new objects. |
NotifySubscribers | Used to send notification messages to action subscribers. |
ObtainMethod | Returns a direct pointer to an object's method code. |
ProcessMessages | Processes system messages that are queued in the Task's message buffer. |
RandomNumber | Generates random numbers. |
ReallocMemory | Reallocates memory blocks. |
ReleaseMemory | Releases memory blocks from access locks. |
ResolveClassName | Used to resolve unique class ID's from class names. |
ResolveFields | Converts field names into globally supported Field ID's. |
SelfDestruct | Destroys the task and frees its resources. |
SendError | Sends basic error messages to the active debugger. |
SendMessage | Send messages to message queues. |
SetContainer | Changes object containers dynamically. |
SetContext | Tells the system which object currently has resource control. |
SetField | Used to set field values of objects. |
SetFieldVariable | Sets any field using an abstract string value. |
SetFields | Sets the values of multiple object fields. |
SetName | Sets the name of an object. |
StepBack | Steps back the debugging tree. |
StrCompare | Compares strings to see if they are identical. |
SubscribeAction | Used for listening to action activity in foreign objects. |
SubscribeChannel | Used for listening to the data channels of foreign objects. |
SubscribeField | Used for responding to field activity in foreign objects. |
SubscribeTimer | Subscribes an object to the system's timer service. |
TotalChildren | Calculates the total number of children belonging to an object. |
UnsubscribeAction | Removes action subscriptions from external objects. |
UnsubscribeChannel | Removes data channel subscriptions from an external object. |
UnsubscribeField | Removes field-based subscriptions from an object. |
UnsubscribeTimer | Unsubscribes an object from the system's timer service. |
WaitTime | Waits for a specified amount of seconds and/or microseconds. |
WatchPublicMemory | Monitors public memory blocks for foreign access. |
Action() |
This function is responsible for executing action routines. |
ERROR Action(ACTIONID ActionID, OBJECTPTR Object, APTR Parameters) |
ActionID | An action or method ID must be specified here (e.g. AC_Query). Action ID's are obtained from the "system/actioncodes.h" include file. |
Object | A pointer to the object that is going to perform the action. |
Parameters | If the action or method is documented as taking parameters, point to the relevant parameter structure here. Pre-defined parameter structures are obtained from the "system/actions.h" include file. |
|
This function is the key entry point for executing actions and method
routines. An action is a predefined function call that can be called on
any object, while a method is a function call that is specific to a
particular object type. You can find a complete list of available actions
and their associated details in the
Action List document. If an
object supports methods, they will be listed in the object's class
document.
Here are two examples that demonstrate how to make an action call. The
first performs an initialisation, which does not require any additional
arguments. The second performs a move operation, which requires three
additional arguments to be passed to the Action() function:
1. Action(AC_Init, Picture, NULL);
3. struct acMove move;
move.XChange = 30;
move.YChange = 15;
move.ZChange = 0;
Action(AC_Move, Window, &move);
If the target object does not support the action code that you have
specified, an error code of ERR_NoSupport will be returned. If you need to
test an object to see if it supports a particular action, use the
CheckAction() function.
If you need to send an action to an object that does not belong to your
task space, use
the ActionMsg() function. If you're in a situation
where you only have an object ID and are unsure as to whether or not the object is
in your task space, use ActionMsg() anyway as it
will divert to the Action() function if the object is local.
If you are writing a class and need to know how to add support for a
particular action, look it up in the
Action Support Guide.
ERR_Okay | The function executed successfully. |
ERR_Args | Incorrect arguments passed to function (missing ActionID or Object). |
ERR_NoAction | The action is not supported by the object's supporting class. |
ERR_ObjectCorrupt | The object that was received is badly corrupted in a critical area. |
|
|
ActionList() |
Returns a pointer to the kernel's most current action table. |
struct ActionTable * ActionList(void) |
If you need a dynamic list of all the actions supported by the object
kernel, including information on ID's, names, arguments and structure sizes,
use the ActionList() function. This function will return an array that is
arranged into a look-up table, sorted by action ID. The ActionTable structure
is defined as follows:
struct ActionTable {
STRING Name;
struct FunctionField *Args;
LONG Size;
};
The Name field specifies the name of the action. The Args field refers
to the action's argument definition structure, which lists the argument names
and their relevant types. This is matched by the Size field, which indicates
the byte-size of the action's related argument structure. If the action does
not support arguments, the Args and Size fields will be set to NULL. Here
are two argument definition examples:
struct FunctionField argsCopyData[] = {
{ "Destination", ARG_LONG },
{ NULL, NULL }
};
struct FunctionField argsResize[] = {
{ "Width", ARG_DOUBLE },
{ "Height", ARG_DOUBLE },
{ "Depth", ARG_DOUBLE },
{ NULL, NULL }
};
The argument types that can be set by actions are limited to those listed in
the following table:
ARG_LONG | A 32-bit integer value ranging from -2,147,483,647 to
2,147,483,648. |
ARG_LARGE | A 64-bit integer value. |
ARG_PTR | A standard 32-bit address space pointer. |
ARG_STRING | A 32-bit address space pointer that refers to a
null-terminated string. |
ARG_DOUBLE | A 64-bit floating point value. |
ARG_OBJECT | This flag is sometimes set in conjunction with the
ARG_LONG type. It indicates that the argument refers to an object ID. |
ARG_PTRSIZE | This argument type can only be used if it follows
an ARG_PTR type, and if the argument itself is intended to reflect the size
of the buffer referred to by the previous ARG_PTR argument. |
ARG_RESULT | This special flag is set in conjunction with the
other data-based argument types. Example: If the developer is required to supply a
pointer to a LONG field in which the function will store a result, the correct
argument definition will be ARG_RESULT|ARG_LONG|ARG_PTR. To make the definition
of these argument types easier, ARG_PTRRESULT, ARG_LONGRESULT and
ARG_FLOATRESULT macros are also available for use. |
Result
This function returns a pointer to the object kernel's action table (struct ActionTable *). If a failure occurs, NULL will be returned. Please note that the first entry in the ActionTable list has all fields driven to NULL, because valid action ID's start from one, not zero. The final action in the list is also terminated with NULL fields in order to indicate an end to the list. Knowing this can be helpful if you wish to search the list or calculate the total number of actions supported by the kernel. |
|
|
AllocMemory() |
Allocates system memory blocks. |
ERROR AllocMemory(LONG Size, LONG Flags, APTR *Address, MEMORYID *MemoryID) |
Size | The size of the memory block. |
Flags | Flag specifications - set to NULL to allocate a standard data memory block. |
Address | Set this argument to refer to an APTR type to store an address reference to the allocated memory block. |
MemoryID | Set this argument to refer to a MEMORYID type to store a unique ID reference to the allocated memory block. |
|
The AllocMemory() function is used to allocate blocks of memory from the
system memory pool. To allocate a new block you need to specify its Size,
allocation Flags and Address and/or MemoryID arguments to store references to
the allocation. Here is an example:
APTR Address;
if (AllocMemory(1000, MEM_DATA, &Address, NULL) IS ERR_Okay) {
...
FreeMemory(Address);
}
A number of flag definitions are available that affect the memory
allocation process. They are:
MEM_DATA | The default type, MEM_DATA, is used to indicate a standard memory allocation from system RAM. |
MEM_PUBLIC | Public memory can be allocated by specifying this flag. Public memory blocks are accessible by all tasks, but access can only be gained by knowing the unique memory ID and utilising the AccessMemory() function. |
MEM_CODE | If the memory will contain executable program code, set this flag. |
MEM_UNTRACKED | Allocating an untracked memory block will prevent the memory block from being tracked back to the object holding the current context. |
MEM_STRING | This flag is used to aid debugging - set it if the memory block will be used to store printable string data. |
MEM_NOCLEAR | If this flag is set, the memory block's data will not be cleared by the AllocMemory() function. |
MEM_TASK | Tells the allocation function to track the memory block to the current Task, as opposed to the current object. |
MEM_RESERVED | This special flag is used to allocate shared memory blocks that require reserved ID numbers. When using the MEM_RESERVED flag, you are required to set the longword pointed to by the MemoryID argument to the ID that you wish to reserve. If that memory ID is already taken, the AllocMemory() call will fail. |
You will notice that you have the option of receiving the memory allocation
as an address pointer and/or as a unique memory ID. When allocating private
memory, you can generally just accept an address result and drive the MemoryID
argument to NULL. However when allocating public memory, you should always
retrieve the MemoryID, and optionally the Address pointer if you need immediate
access to the block.
If the block is allocated as private and you retrieve both the MemoryID and
Address pointer, or if the allocation is public and you choose to retrieve the
Address pointer, an internal call will be made to
AccessMemory() to lock the memory block and resolve its address. This
means that before freeing the memory block, you must make a call to the
ReleaseMemory() function to remove the lock, or
it will remain in memory till your Task is terminated.
Memory that is allocated through AllocMemory() is automatically cleared
with zero-byte values. When allocating large blocks it may be wise to turn
off this feature - you can do this by setting the MEM_NOCLEAR flag.
ERR_Okay | The memory block was allocated successfully. |
ERR_Args | Incorrect arguments were specified (no Size, or no Address and no MemoryID). |
ERR_Failed | The block could not be allocated due to insufficient memory space. |
ERR_ArrayFull | Although memory space for the block was available, all available memory records are in use. |
ERR_LockFailed | The function failed to gain access to the public memory control semaphore. |
ERR_SystemCorrupt | The internal tables that manage memory allocations are corrupt. |
ERR_AccessMemory | The block was allocated but access to it was not granted, causing failure. |
ERR_ResourceExists | This error is returned if MEM_RESERVED was used and the memory block ID was found to already exist. |
|
|
CloneMemory() |
Makes an exact duplicate of a memory block. |
ERROR CloneMemory(APTR Address, LONG Flags, APTR *NewAddress, MEMORYID *NewMemoryID) |
Address | Pointer to the memory block that you want to clone. |
Flags | Specifies the memory flags that you want to use for your newly cloned memory block. See AllocMemory() for flag definitions. |
NewAddress | Set this argument to refer to an APTR type, to store an address reference to the cloned memory block. |
NewMemoryID | Set this argument to refer to a MEMORYID type, to store a unique ID reference to the cloned memory block. |
|
This function allows you to make a duplicate of any memory block that has
been allocated from AllocMemory(). The new memory
block will be completely identical to the block you have specified, except
for the type of memory, which you can alter through the Flags argument. The
contents of the original memory block will be copied over to the duplicate
block.
You will notice that you have the option of receiving the cloned memory
as an address pointer and/or as a unique memory ID. When allocating private
memory, you can generally just accept an address result and drive the MemoryID
argument to NULL. However when cloning public memory, you should always
retrieve the MemoryID, and optionally the Address pointer if you need immediate
access to the cloned block.
If the block is cloned as private memory and you retrieve both the MemoryID
and Address pointer, or if the allocation is public and you choose to retrieve
the Address pointer, an internal call will be made to
AccessMemory() to lock the memory block. This
means that before freeing the memory block, you must make a call to the
ReleaseMemory() function to remove the lock, or
it will remain in memory.
Remember to free the cloned memory block when you are finished with it.
ERR_Okay | A duplicate of the memory block was successfully created. |
ERR_Args | Invalid arguments were supplied to the function. |
ERR_AccessMemory | Access to the newly created memory block was denied to the function. |
ERR_AllocMemory | Failed to allocate the duplicate memory block. |
|
|
DPrintF() |
Sends formatted strings to the debugger. |
void DPrintF(STRING Header, STRING Array, ...) |
Header | A short name for the first column. Usually function names are placed here, so that it is obvious who is sending the message. |
Array | The first member of the array must be a string. All other members of the array must be supplied according to the string formatting, 1 parameter for every % symbol that you have used. |
|
The DPrintF() function follows the same functionality and rules as the ANSI
printf() function. The only difference is that it prints directly to the debug
window. Due to internal limits your string is limited to a total of 256 bytes
output, although you should keep everything within 80 bytes to avoid running
onto a second row. You can supply a maximum amount of 5 '%' parameters to this
function.
The following example will print the default width of a Screen object to
the debug window.
if (NewObject(ID_SCREEN, NULL, &Screen, NULL) IS ERR_Okay) {
if (Action(AC_Init, Screen, NULL)) {
DPrintF("Demo:","The width of the screen is: %d", Screen->Width);
}
Action(AC_Free, Screen, NULL);
}
|
|
FastFindObject() |
Searches for objects by name. |
ERROR FastFindObject(STRING Name, CLASSID ClassID, OBJECTID *Array, LONG ArraySize, LONG *Count) |
Name | The name of the object that you are looking for. |
ClassID | Setting this field to a class ID will filter the results down to a specific class type. |
Array | Pointer to the array that will store the results. |
ArraySize | Indicates the size of the array that you have supplied. |
Count | Set this pointer to a longword so that FastFindObject() can tell you how many objects were stored in your array. This argument can be set to NULL if you wish. |
|
The FastFindObject() function is an optimised implementation of the
FindObject() function. You can use it to search
for objects in the system by their name and/or class. Unlike
FindObject(), which will return an allocated
memory block that lists all of the objects that were found, FastFindObject()
requires that you provide a memory area to write the results to. This saves
the cost of allocation time, which can be expensive in some situations.
The following code example is a typical illustration of this function's
use. It finds the most recent object created with a given name:
OBJECTID SystemPointerID;
FastFindObject("SystemPointer", ID_POINTER, &SystemPointerID, 1, NULL);
If FastFindObject() cannot find any objects with the name that you are
looking for, it will return an error code.
The list is sorted so that the oldest private object is placed at the start
of the list, and the most recent public object is placed at the end. This will
assist you in situations where you may be looking for the oldest or youngest
object to have the particular name that you have searched for.
ERR_Okay | At least one object was found and stored in the supplied array. |
ERR_Args | The Name, Array or ArraySize arguments were not supplied. |
ERR_Search | No objects matching the given name could be found. |
ERR_AccessMemory | Access to the RPM_SharedObjects memory block was denied. |
|
|
GetField() |
Retrieves single field values from objects. |
ERROR GetField(OBJECTPTR Object, LONG FieldID, LONG ResultType, APTR Result) |
Object | Pointer to an object. |
FieldID | The ID of the field that you wish to read. |
ResultType | The type of value that the field should be converted to. |
Result | Pointer to the variable that will store the result. |
|
The GetField() function is used to read field values from objects. You
don't need to know anything about the object structure in order to read
information from it - you just need to know what field you want to read.
The following code segment illustrates how to read values from an object:
LONG XCoord, YCoord;
GetField(Object, FID_XCoord, FT_LONG, &XCoord);
GetField(Object, FID_YCoord, FT_LONG, &YCoord);
As GetField() is based on field ID's that reflect field names
("FID's"), you will
find that there are occasions where there is no reserved ID for the field that
you wish to read. To convert field names into their relevant IDs, call the
ResolveFields() function. Reserved field ID's
are listed in the "system/fields.h" include file.
When reading a field you are required to make an educated guess as to
its type, in order to prevent a type mismatch from occurring. For
instance, reading a coordinate field would mean that the field is a number,
so you should read the field as a numeric type rather than choosing a
pointer type.
Available field types are listed in the following table:
FT_FLOAT | A 32-bit floating point value. |
FT_LONG | A 32-bit integer value. |
FT_DOUBLE | A 64-bit floating point value. |
FT_LARGE | A 64-bit integer value. |
FT_POINTER | A standard 32-bit address space pointer. |
FT_STRING | A 32-bit pointer that refers to a string. |
The variable that you point to in the Result argument must match the
ResultType that you have specified, or you will risk crashing your program
code.
ERR_Okay | The field value was read successfully. |
ERR_Args | Invalid arguments were specified. |
ERR_NoFieldAccess | Permissions for this field indicate that it is not readable. |
ERR_UnsupportedField | The FieldID is not supported by the object's class. |
|
|
GetFields() |
Retrieves multiple field values in a single function call. |
ERROR GetFields(OBJECTPTR Object, { FIELD FieldID, APTR Value }...) |
Object | Pointer to the object that you want to access. |
FieldID | The ID of the field that you want to get. |
Value | Points to the storage area that is to receive the field value. |
|
This function can be used to grab the values of multiple fields in a
single function call. It is primarily provided to give a speed increase
over calling the GetField() function multiple
times. The arguments passed to this function are tag-based and must be
terminated with a TAGEND marker, as shown in the following example:
LONG Width, Height;
GetFields(Screen,
FID_Width|TLONG, &Width,
FID_Height|TLONG, &Height,
TAGEND);
The field ID's that you specify must be logically or'd with tag definitions
that indicate the type of values that you want to get from each field. For
instance, if want to retrieve a field in floating point format, then you must
use the TFLOAT tag and supply a pointer to a FLOAT variable. Please note that
failing to set the tag values correctly can often cause a program to crash.
The recognised tag types are TPTR, TSTRING, TLONG, TLARGE, TFLOAT, and
TDOUBLE.
If the GetFields() does not return an ERR_Okay code, you should work on the
assumption that all of the field settings failed, meaning that your routine
should abort in most cases. This function aborts immediately and makes no
attempt to 'salvage' any other fields that may be left in the list, or undo
earlier field settings that were successful.
For information on the field retrieval process, refer to the
GetField() function.
ERR_Okay | The field values were retrieved successfully. |
ERR_Args | Invalid arguments were specified. |
ERR_UnsupportedField | One of the fields is not supported by the target object. |
|
|
GetMessage() |
Reads messages from message queues. |
ERROR GetMessage(MEMORYID MessageID, LONG Type, LONG Flags, APTR Buffer, LONG Size) |
MessageID | The memory ID of the message queue is specified here. If NULL, the message queue of the local Task will be used. |
Type | The message type that you would like to receive, or NULL if you would like to receive the next message on the queue. |
Flags | This argument is reserved for future use. Set it to NULL. |
Buffer | Pointer to a buffer that is large enough to hold the incoming message information. If set to NULL then all accompanying message data will be destroyed. |
Size | The byte-size of the buffer that you have supplied. |
|
The GetMessage() function is used to read messages that have been stored
in message queues. You can use this function to read the next immediate
message stored on the queue, or the first message on the queue that matches a
particular Type. It is also possible to call this function in a loop to clear
out all messages, until an error code other than ERR_Okay is returned.
Messages will often (although not always) carry data that is relevant to
the message type. To retrieve this data you need to supply a buffer, preferably
one that is large enough to receive all the data that you expect from your
messages. If the buffer is too small, the message data will be cut off to fit
inside the buffer.
Message data is written to the supplied buffer with a Message structure
(struct Message), which is immediately followed up with the actual message
data. The message structure includes the following fields:
LONG Type | The message type ID. |
LONG Size | The size of the message data, in bytes. If there is no data associated with the message, the Size will be set to NULL. |
ERR_Okay | The message was successfully retrieved from the message queue. |
ERR_Args | Invalid arguments were supplied to the function. |
ERR_AccessMemory | Failed to gain access to the message queue. |
ERR_Search | No more messages are left on the queue, or no messages that match the given Type are on the queue. |
|
|
NewObject() |
Creates new objects. |
ERROR NewObject(LONG ClassID, LONG Flags, OBJECTPTR *Object, OBJECTID *ObjectID) |
ClassID | One of the ID's as specified in the "system/register.h" file. |
Flags | Flag specifications - set to NULL to allocate a standard private object. |
Object | Set this argument to refer to an OBJECTPTR type to store an address reference to the new object. |
ObjectID | Set this argument to refer to an OBJECTID type to store a unique ID reference to the new object. |
|
The NewObject() function is used to create new objects and register them for
use within the object kernel. It can create all possible object types from any
one of the classes that have been installed on the system. After creating a
new object, you can then proceed to set its fields and initialise it with the
Init action so that it can be used as intended.
The ClassID argument identifies the class that the object is to be based
upon. Pre-defined class ID's are defined in the "system/register.h"
include file and a complete list of known classes is available in the
Class Index. ID's for unregistered
classes can be found dynamically by using the
ResolveClassName() function.
The Flags argument supports a variety of options that affect object
creation. The following table describes all flags permitted for use with the
NewObject() function:
NF_NOTRACK | An object created with this flag will not be tracked back to the object that created it. If combined with the NF_PUBLIC flag, the object can also remain in memory when the object's related Task is terminated. |
NF_PUBLIC | By using the NF_PUBLIC flag, you can allocate public objects rather than the default private type. A public object can be accessed and interacted with by any application directly, because the object structure and its data lies in public memory. Public objects do not use the object messaging system, but it is necessary to gain exclusive access to public objects before you can use them (refer to the AttemptExclusive() and FreeExclusive() functions). |
NF_CHILD | This object type can only be allocated when writing code for a class module. Child objects can only be accessed when the task is running in the context of the child's parent. There is no other way to gain access to these object types. Child objects do not appear in object lists, effectively making them hidden from everything except the parent object. |
NF_SHARED | Use this flag if you want to provide foreign tasks with a means of finding and talking to the created object. If you have already specified the NF_PUBLIC field, it is not necessary to use the NF_SHARED flag, as all public objects have shared attributes. |
You will notice that you have the option of receiving the object allocation
as an address pointer and/or as a unique object ID. When allocating private
objects, you can generally just accept an address result and drive the ObjectID
argument to NULL. However when allocating public objects, you should always
retrieve the ObjectID, along with the Object address so that you can initialise
the new object before releasing it.
If the object is allocated as private and you retrieve both the ObjectID and
Object pointer, or if the allocation is public and you retrieve the Object
pointer, an internal call will be made to
AttemptExclusive() to lock the object and
retrieve its address pointer. This means that your call to NewObject() must
be matched with a call to the FreeExclusive()
function to remove the lock. If the lock is not released, foreign tasks will
never be able to access the object, and attempts to Free the object will fail.
By default, new objects are always tracked to the object that holds the
current context. If necessary, it is possible to track a new object
to a different owner by using the SetContainer()
function after calling NewObject().
To destroy an object created with NewObject(), use the Free action.
ERR_Okay | The object was created successfully. |
ERR_Args | Invalid arguments were supplied to the function. |
ERR_MissingClass | The class that you requested in the ClassID argument could not be found in the system, or the ClassID itself was invalid. |
ERR_Failed | General failure. |
|
|
ProcessMessages() |
Processes system messages that are queued in the Task's message buffer. |
ERROR ProcessMesages(struct NextMsg *NextMsg, LONG Flags) |
NextMsg | Must point to a NextMsg structure to store the function results. If set to NULL, the ProcessMessages() function will not return information on the next message on the queue. |
Flags | Optional flags are specified here. |
|
The ProcessMessages() function is used for two purposes:
- To automatically process system messages that have been sent to the current
Task.
- To report on the current status of the Task's message queue. This
involves returning information on user messages that must be processed by the
code responsible for maintaining the Task's message queue.
Each Task that opens the Pandora Engine is assigned a message queue by
default (refer to the Task class for
details). Responding to incoming messages is vital - the queue is the only
official point of communication that your Task has with the rest of the
system and other Tasks within it. Failing to call the ProcessMessages()
function on a regular basis may cause a back-log of messages to be generated,
as well as causing problems with areas such as the graphical interface.
It is recommended that you call the ProcessMessages() function in
the main loop of your program on a frequent basis - around 10 to 30 times per
second is sufficient, or you can use this function to permanently wait for
messages to arrive.
A "system message" is a pre-defined message type that
has a specific purpose within the object kernel. The most obvious
example of this is the action message type, which is sent by the
ActionMsg() function. Because of the complex code
requirements to translate these message types, the ProcessMessages() function
is designed to handle them automatically, relieving you from having to deal
with them. System messages are never sent to custom message queues -
only Task based queues, which is what this function specifically deals
with.
A "user message" is a message type that has an unrecognised
message type ID, which prevents the ProcessMessages() function from
automatically dealing with it. Such message types must be dealt with by
the Task, which can choose to respond to the message or ignore it, depending
on whether or not it understands the message information. Unique message
ID's can be acquired from the AllocateID()
function.
On occasion this function will return with system messages that cannot
be processed internally, and must be interpreted by the Tasks's message handler.
Currently this includes the following message types:
MSGID_QUIT | Indicates that the user or an external program has requested that the Task be terminated. This message can be sent if the user has hit CTRL-C, or if you have created a main window with a close gadget that has been clicked by the user. |
When calling the ProcessMessages() function you are expected to provide
a NextMsg structure so that the function can return messages requiring
a personal response. If you want to put off responding to these messages
types then you can drive the NextMsg argument to NULL, but be aware that
you must respond to these messages at some point, or they will gradually
fill up the message queue. Before returning, the ProcessMessages() function
will fill the NextMsg structure with information on the next message in the
queue requiring a task-based response. To receive or destroy the message,
you need to follow-up with a call to the
GetMessage() function.
The NextMsg structure consists of the following fields:
LONG Type | The type (ID) of message that is next on the queue. If there are no messages on the queue that require a task based response, the Type field will be set to NULL. |
LONG Size | The size of the next message's data area, in bytes. |
LONG Count | The total number of messages left on the queue that require a task based response. |
A number of flags are available that affect message processing. They
are:
MF_CLEAR | Specifying this flag will cause the ProcessMessages() function to process the system messages on the queue and clear every unrecognised user message type, thus providing a guarantee that the message queue will be empty when the function returns. |
MF_WAIT | This flag causes the function to sleep until new messages arrive. The function will process system messages automatically, and will only return when messages requiring a task-based response are received (e.g. MSGID_QUIT or a user message type). |
For more information on sending and receiving messages, refer to the
GetMessage() and
SendMessage() functions.
ERR_Okay | Incoming messages were processed successfully. |
|
|
SendMessage() |
Send messages to message queues. |
ERROR SendMessage(MEMORYID MessageID, LONG Type, LONG Flags, APTR Data, LONG Size) |
MessageID | The memory ID of the destination message queue. |
Type | The message Type/ID being sent. Unique type ID's can be obtained from AllocateID(). |
Flags | Set to MF_WAIT if you are prepared to wait in situations where the message queue is too full to accept the new message. |
Data | Pointer to the data that will be written to the queue. Set to NULL if there is no data to write. |
Size | The byte-size of the data being written to the message queue. |
|
The SendMessage() function is used to write messages to message queues.
To write a message to a queue, you must know the memory ID of that queue and
be able to provide this function with a message type ID that the queue's
handler will understand. If necessary, you can also attach data to the
message if it has relevance to the message type.
If the message queue is found to be full, or if the size of your message
is larger than the total size of the queue, this function will immediately
return with an ERR_ArrayFull error code. If you are prepared to wait for the
queue handler to process the waiting messages, specify MF_WAIT in the Flag
argument. There is a maximum time-out period of 10 seconds in case the Task
responsible for handling the queue is failing to process its messages.
The available Flags that affect this function's behaviour are:
MF_ADD | The default behaviour - this will add the message to the end of the queue. |
MF_NODUPLICATE | If the Type argument matches a message already inside the queue, the new message will not be added and the function will immediately return with ERR_Okay. |
MF_UPDATE | If the Type argument matches a message already inside the queue, the data for that message will be deleted, then the new message will be added to the end of the queue. |
MF_WAIT | This flag tells the function to wait before adding the message if the queue is at maximum capacity. |
ERR_Okay | The message was successfully written to the message queue. |
ERR_Args | Invalid arguments were passed to the function. |
ERR_ArrayFull | The message queue is full. |
ERR_TimeOut | The message queue is full and the queue handler has failed to process them over a reasonable time period. |
ERR_AccessMemory | Access to the message queue memory was denied. |
|
|
SetContext() |
Tells the system which object currently has resource control. |
OBJECTPTR SetContext(OBJECTPTR Object) |
Object | Pointer to the object that will take on the new context. |
|
This function provides a way of telling the system which object has control
of the current Task. Through the use of this function, you can assign
resources to an object as you allocate them. This is particularly important
for memory and object handling. For example:
Action(AC_Init, Screen, NULL);
PrevContext = SetContext(Screen);
NewObject(ID_BITMAP, NULL, &Bitmap, NULL);
AllocMemory(1000, MEM_DATA, &memory, NULL);;
SetContext(PrevContext);
Action(AC_Free, Screen, NULL);
In the above code we allocated a Bitmap and a memory block, both of which
will be contained by the Screen. When the Free action is called, both the Bitmap
and memory block will be freed automatically because they are dependent on the
Screen's existence. Please keep in mind that the following is incorrect:
Action(AC_Init, Screen, NULL);
PrevContext = SetContext(Screen);
NewObject(ID_BITMAP, NULL, &Bitmap, NULL);
AllocMemory(1000, MEM_DATA, &memory, NULL);
SetContext(PrevContext);
Action(AC_Free, Screen, NULL);
Action(AC_Free, Bitmap, NULL);
FreeMemory(memory);
Freeing the Bitmap and Memory block AFTER the Screen is invalid, however we
are allowed to free them before the Screen if necessary.
SetContext() is intended for use by modules and classes. Only on rare
occasions will you need to concern yourself with this function. The object
kernel will automatically set the correct context when calling any action or
method of a class, as do the field management functions.
Result
Returns a pointer to the previous context. Because contexts will nest, you need to call SetContext() a second time with the returned pointer, in order to keep the Task stable. |
|
|
SetField() |
Used to set field values of objects. |
ERROR SetField(OBJECTPTR Object, FIELD FieldID, LONG ValueType, APTR Value) |
Object | Pointer to the object that you wish to set. |
FieldID | The universal ID of the field you wish to write to. |
ValueType | Indicates the type of value that is being written to the field. |
Value | Points to the value that will be written to the field. |
|
The SetField() function is used to write field values to objects. You
don't need to know anything about the object structure in order to write
information to it - you just need to know what field you want to set.
The following code segment illustrates how to write values to an object:
LONG XCoord, YCoord;
SetField(Object, FID_XCoord, FT_LONG, &XCoord);
SetField(Object, FID_YCoord, FT_LONG, &YCoord);
As SetField() is based on field ID's that reflect field names, you will
find that there are occasions where there is no reserved ID for the field that
you wish to write. To convert field names into their relevant IDs, call the
ResolveFields() function. Reserved field ID's
are listed in the "system/fields.h" include file.
When writing to a field you are required to make an educated guess as to
its type, in order to prevent a type mismatch from occurring. For instance,
writing to a coordinate field would mean that the field is a number, so you
should write to the field with a simple numeric type. If you have read the
object's class documentation to learn the field type, then use that type
in order to prevent a field conversion from taking place.
Available field types are listed in the following table:
FT_FLOAT | A 32-bit floating point value. |
FT_LONG | A 32-bit integer value. |
FT_DOUBLE | A 64-bit floating point value. |
FT_LARGE | A 64-bit integer value. |
FT_POINTER | A standard 32-bit address space pointer. |
FT_STRING | A 32-bit pointer that refers to a string. |
The variable that you point to in the Value argument must match the
ValueType that you have specified, or you will risk crashing your program
code.
ERR_Okay | The field value was updated. |
ERR_Args | Invalid arguments were specified. |
ERR_UnsupportedField | The specified field is not support by the object's class. |
ERR_NoFieldAccess | The field is read-only. |
|
|
SetFields() |
Sets the values of multiple object fields. |
ERROR SetFields(*Object, { LONG FieldID, VARIABLE Value }...) |
Object | Pointer to the object that you want to access. |
FieldID | The ID of the field that you want to set. |
Value | The value that you want to set in the field. |
|
This function can be used to set the values of more than one field in a
single function call, by using tags. It is provided for the purpose of giving
a speed increase over calling the SetField()
function multiple times.
The tags that you pass to this function must be arranged in a format of
field ID's and values. The following example illustrates:
SetFields(Render,
FID_Name|TSTRING, "MyRender",
FID_Width|TLONG, 50,
FID_Height|TLONG, 100,
FID_XCoord|TFLOAT, 86.5,
FID_YCoord|TFLOAT, 40.0,
TAGEND);
The field ID's that you specify must be logically or'd with tag definitions
that indicate the type of values that you have set for each field. For
instance, if you set a floating point value for a field, then you must use
the TFLOAT tag so that the SetFields() function can interpret the paired
value correctly. Please note that failing to set the tag values correctly
can often cause a program to crash.
The recognised tag types are TPTR, TSTRING, TLONG, TLARGE, TFLOAT, and
TDOUBLE.
If this function fails, it should be assumed that all of the field settings
failed. This means that your routine should abort in most cases. This
function makes no attempt to 'salvage' any other fields that may be left in
the list or undo any previously successful field settings.
ERR_Okay | All fields were set successfully. |
ERR_Args | Invalid arguments were specified. |
ERR_UnsupportedField | One of the fields is not supported by the target object. |
ERR_Failed | A field setting failed due to an unspecified error. |
|
|
SubscribeAction() |
Used for listening to action activity in foreign objects. |
ERROR SubscribeAction(OBJECTPTR Object, ACTIONID Action, OBJECTPTR Subscriber) |
Object | Pointer to the object that you wish to subscribe to. |
Action | The ID of the action that you wish to monitor. |
Subscriber | A pointer to the object that you represent goes here. If your program code does not represent a particular object, a pointer to your Task object should be specified. |
|
The SubscribeAction() function is provided for objects that wish to
be notified when actions are being executed on foreign objects. This is
typically referred to as "action monitoring". Action monitoring
is used for a wide variety of purposes and is especially useful for responding
to events in the user interface, including pointer movement, window resizing
and graphics drawing.
To subscribe to the actions of another object, you need to acquire its
address pointer, then call this function with the action ID that you want
to monitor. The Subscriber argument needs to indicate what object you
represent - if you don't represent an object, you need to gain access to
your local Task object and point to it in the Subscriber argument. The
following example illustrates how to listen to a Render object's Draw
action, for the purposes of drawing graphics to it:
if (AttemptExclusive(RenderID, 3000, &Drawable) IS ERR_Okay) {
SubscribeAction(Drawable, AC_Draw, Self);
FreeExclusive(Drawable);
}
When someone calls a matching action on the object that you are listening
to, its code will be executed first, then all relevant action subscribers will
be notified of the event. This is done by sending each subscriber an
action message (AC_ActionNotify) with information on the action ID, the
ID of the object that was called, and a copy of the arguments that were
used. For more detail, refer to the ActionNotify section of the
Action Support Guide.
If you are writing a standard executable rather than a class, refer to one
the graphical example programs provided with Pandora to see how ActionNotify
events can be intercepted through the Task object.
This function does not support subscriptions to methods.
When you need to terminate an action subscription, use the
UnsubscribeAction() function.
ERR_Okay | The subscription was successful. |
ERR_Args | Invalid arguments were supplied to the function. |
ERR_AccessMemory | Access to the Object's subscription list was denied. |
ERR_AllocMemory | A subscription list could not be allocated for the object. |
|
|
SubscribeField() |
Used for responding to field activity in foreign objects. |
ERROR SubscribeField(OBJECTPTR Object, FIELD FieldID, OBJECTPTR Subscriber) |
Object | Pointer to the object that you wish to subscriber to. |
FieldID | The ID of the field that you wish to monitor. |
Subscriber | A pointer to the object that will receive the FieldNotify action must be specified here. If your program code does not represent a particular object, a pointer to your Task object should be specified. |
|
The SubscribeField() function is used for field monitoring purposes. If
you need to be alerted when a foreign object has a field updated through
SetField(), SetFields()
or SetFieldVariable(), you can use a field
subscription to be notified of the alteration.
To subscribe to the field of another object, you need to acquire the
object's address pointer, then call this function with the field ID that you
want to monitor. The Subscriber argument needs to indicate what object you
represent - if you don't represent an object, you need to gain access to
your local Task object and point to it in the Subscriber argument. The
following example illustrates how to listen to a Render object's coordinate
values:
if (AttemptExclusive(RenderID, 3000, &Drawable) IS ERR_Okay) {
SubscribeField(Drawable, FID_Width, Self);
SubscribeField(Drawable, FID_Height, Self);
FreeExclusive(Drawable);
}
When someone writes to a subscribed field using the object kernel, all
relevant field subscribers will be notified of the event. This is done by
sending each subscriber an action message (AC_FieldNotify) with information
on the field ID, the ID of the object that was called, and the new field
value (but only if it is an integer or float - pointers cannot be provided).
For more detail, refer to the FieldNotify section of the
Action Support Guide.
When you need to terminate a field subscription, use the
UnsubscribeField() function.
ERR_Okay | The subscription was successful. |
ERR_Args | Invalid arguments were supplied to the function. |
ERR_AccessMemory | Access to the target object's field subscriber list was denied. |
ERR_AllocMemory | A subscriber list could not be allocated for the object. |
|
|
WatchPublicMemory() |
Monitors public memory blocks for foreign access. |
ERROR WatchPublicMemory(APTR Memory, MEMORYID MemoryID, LONG Timer) |
Memory | Pointer to the memory address of the public block that you are monitoring (address must be obtained through AccessMemory(). |
MemoryID | The ID of the memory block that you are monitoring. |
Timer | The time-out value, measured in milliseconds. If the time-out expires before some other task uses the memory block, ERR_TimeOut will be returned by this function. If the time-out value is set to zero or less, the function will wait indefinitely. |
|
This function is used to "watch" public memory blocks. Calling
this function on a public memory block will cause your Task to stop and
wait until a foreign Task uses and releases that block. When it does so, your
Task will be awoken and the function will return, alerting you to the fact
that someone else has used and possibly altered the memory block.
To wait on a block, you first need to gain access to it with the
AccessMemory() function. After doing so,
call this function with the address that you have locked along with the
ID of the public memory block. Please note that this function will
release the access lock before returning, so do not follow-up
with a ReleaseMemory() call when this function
returns. You will need to call AccessMemory()
again if you want to inspect the memory block afterwards.
To prevent excessive waiting, you can specify a Timer in case the block
you are monitoring is not accessed within a reasonable amount of time. When
the time-out expires, the function will return with an error of ERR_TimeOut.
If you don't mind waiting indefinitely then the Timer argument can be set
to zero, but this is not recommended for normal practice.
This function does not work on private memory blocks.
ERR_Okay | The memory has been accessed and released by a foreign task. |
ERR_Args | Invalid arguments were supplied to the function. |
ERR_LockFailed | The function failed to gain access to the public memory control semaphore. |
ERR_MemoryDoesNotExist | The supplied MemoryID could not be found in internal memory records. |
ERR_TimeOut | The time-out period expired before anyone used the memory block. |
|
|