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 that allows for
better portability and services. Support for the management of memory and
resources are all present, plus you will also find extensive support for class
management and field and object handling.
The portability of the object kernel has been ensured 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. |
AccessObject | Grants exclusive access to public objects. |
AccessSemaphore | Grants access to semaphores. |
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. |
AllocSemaphore | Allocates a new public semaphore. |
AllocateClassID | Generates dynamic class ID's. |
AllocateID | Generates unique ID's for various purposes within the Pandora Engine. |
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. |
ClearMemory | Clears large blocks of memory very quickly. |
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. |
CurrentTaskID | Returns the object ID of the current Task. |
DPrintF | Sends formatted strings to the debugger. |
DebugState | Turns debug messages on and off. |
DeregisterFD | Removes previously register FD's from the system. |
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. |
FindPrivateObject | Searches for objects by name. |
Forbid | Locks other tasks out of the shared memory and object areas. |
FreeMemory | Frees private memory blocks allocated from AllocMemory(). |
FreeMemoryID | Frees public memory blocks allocated from AllocMemory(). |
FreeSemaphore | Frees an allocated semaphore. |
GetClassID | Returns the class ID of an object. |
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. |
GetOwnerID | Returns the unique ID of an object's owner. |
GetResource | Retrieves miscellaneous resource identifiers. |
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. |
ListObjects | Returns a list of objects that match specific parameters. |
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. |
Permit | Releases a lock obtained from Forbid(). |
ProcessMessages | Processes system messages that are queued in the Task's message buffer. |
RandomNumber | Generates random numbers. |
ReallocMemory | Reallocates memory blocks. |
RegisterFD | Registers a file descriptor for monitoring when the task is asleep. |
ReleaseMemory | Releases memory blocks from access locks. |
ReleaseObject | Releases objects from exclusive use. |
ReleaseSemaphore | Releases a locked semaphore. |
ResolveClassName | Used to resolve unique class ID's from class names. |
ResolveFields | Converts field names into globally supported Field ID's. |
ScanMessages | Scans a message queue for multiple occurances of a message type. |
SelfDestruct | Destroys the task and frees its resources. |
SendError | Sends basic error messages to the active debugger. |
SendMessage | Send messages to message queues. |
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. |
SetOwner | Changes object ownership dynamically. |
SetResource | Sets miscellaneous resource identifiers. |
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. |
SubscribeActionTags | 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. |
SystemTime | Returns the current system time, in milliseconds. |
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. |
UpdateMessage | Updates the data of any message that is queued. |
WaitTime | Waits for a specified amount of seconds and/or microseconds. |
WatchPublicMemory | Monitors public memory blocks for foreign access. |
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. This is compulsory when allocating public memory blocks. |
|
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_NOBLOCKING | If this flag is set against a public memory block then the access blocking mechanism will be permanently turned off for all accesses to that particular memory block. This means that multiple tasks can have full read/write access to the memory block at once regardless of the flags passed to AccessMemory(). |
MEM_NOCLEAR | If this flag is set, the memory block's data will not be cleared by the AllocMemory() function. |
MEM_FIXED | This flag can be applied to public memory blocks that need to be mapped to a fixed address that is common to all tasks. For instance, if the system locks the memory block to address 0x56084000 for your task, then all other tasks that map the memory block will also see it at that address. This flag is typically used for supporting absolute code execution. |
MEM_CALLER | This flag is useable only in routines that support a class method. It forces the memory allocation to be resourced against the object that made the method call. This is particularly important in methods that return memory blocks that do not form a part of the object itself. |
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. |
|
|
AllocSemaphore() |
Allocates a new public semaphore. |
ERROR AllocSemaphore(STRING Name, LONG Value, LONG Flags, LONG *Semaphore) |
Name | The name of the semaphore (up to 12 characters, case-sensitive) that you want to create or find. This argument is optional. |
Value | The starting value of the semaphore can be specified here. The minimum starting value is 1, for a simple blocking semaphore. |
Flags | Special flags, currently SMF_EXISTS is supported. |
Semaphore | A reference to the semaphore will be returned through this pointer. |
|
The AllocSemaphore() function is used to create new semaphores and join
existing ones. To create a simple semaphore for private usage, you only
need to provide this function with a return value in the Semaphore parameter.
If you want to share a semaphore with other processes, you need to give it
a unique name limited to 15 characters. The Value argument is optional and
only needs to be used if you need more complex signalling for your program.
Semaphores are most commonly used to control access to shared resources,
typically in shared memory areas. For instance, if you create a shared memory
area for read/write operations between tasks, you need a control system to
prevent the tasks from writing to the memory at the same time (allowing
multiple read access is usually non-harmful and quite convenient). Using
a semaphore is perfect for controlling this type of situation.
For a simple blocking semaphore, you should set a value of 1 in the Value
parameter. If you want to allow multiple processes to read from the resource
then you should set the Value much higher - 100 or more. In this mode, there
are two ways for processes to access the semaphore - blocking and non-blocking
mode. Either type of access is achieved through the AccessSemaphore()
function. Blocking mode is the default and will grant you full access to
the resource if it succeeds. Non-blocking access grants you limited access
to the resource - typically considered 'read only' access. Multiple processes
can have non-blocking access at the same time, but only one process may have
access when blocking mode is required. If you set a value of 100, then
the number of non-blocking accesses will be limited to 100 processes. Any
more processes than this wishing to use the semaphore will need to wait until
some of the accesses are released. If 50 processes currently have read
access and a new process requires blocking access, it will have to wait until
all 50 read accesses are released. The specifics of this are discussed in the
documentation for AccessSemaphore() and ReleaseSemaphore().
The handle returned in the Semaphore argument is global, so if you want
to secretly share an anonymous semaphore with other processes, you may do
so if you pass the handle to them. The other processes will still need to call
AllocSemaphore() to register their interest, but they need to add the SMF_EXISTS
Flag and also pass the semaphore handle to this function via the Semaphore
parameter.
To free a semaphore after you have allocated it, call the FreeSemaphore()
function. It is possible to call AllocSemaphore() with the same Name as
many times as you like because the calls will nest, but you must match them
all with FreeSemaphore() calls. A semaphore will not be completely freed
from the system until all processes that have gained access drop their
control of the semaphore.
ERR_Okay | The semaphore was successfully allocated. |
ERR_Args | The SemaphoreID argument was not supplied. |
ERR_ArrayFull | Allocation failed as the semaphore array is at full capacity. |
ERR_Forbid | Internal system locking failure. |
|
|
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. |
|
|
NewObject() |
Creates new objects. |
ERROR NewObject(LONG ClassID, LONG Flags, OBJECTPTR *Object, OBJECTID *ObjectID, STRING Name) |
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. |
Name | Enabled only if NF_NAME or NF_UNIQUE are specified as Flags. The Name refers to the name that you want to give the 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_UNTRACKED | 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 can be accessed directly via exclusive access only (refer to the AccessObject() and ReleaseObject() 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. |
NF_UNIQUE | Use this flag if you need to allocate an object which has a guaranteed unique name. By using NF_UNIQUE, you can prevent your code from shadowing an object that exists with the same name. This can be imperative when creating shared and public objects. If it is discovered that an identically named object exists, NewObject() will return ERR_ObjectExists. This flag works in conjunction with the Name argument. |
NF_NAME | If you would like to use the Name argument to give your object a name, you must set the NF_NAME flag or your specification will be ignored. |
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
AccessObject() to lock the object and
retrieve its address pointer. This means that your call to NewObject() must
be matched with a call to the ReleaseObject()
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 SetOwner()
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. |
ERR_ObjectExists | An object with the name you provided already exists in the system (applies only when the NF_UNIQUE flag has been used). |
|
|
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). Note that if you have specified a message handler routine with a call to SetResource(RES_MESSAGEHANDLER, &handler), then user messages will be sent to your message handler automatically. In this case, ProcessMessages() never returns unless your handler returns ERR_Terminate in order to stop message processing. |
For more information on sending and receiving messages, refer to the
GetMessage() and
SendMessage() functions.
ERR_Okay | Incoming messages were processed successfully. |
|
|
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. |
|
|
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. There are also two special tag types available: TUNLISTED and TTRANS.
TUNLISTED will divert the field setting through the SetUnlistedField action.
TTRANS can be used with string fields, forcing the string to first be parsed
through StrTranslate() in the Strings module.
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 (AccessObject(RenderID, 3000, &Drawable) IS ERR_Okay) {
SubscribeAction(Drawable, AC_Draw, Self);
ReleaseObject(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 (AccessObject(RenderID, 3000, &Drawable) IS ERR_Okay) {
SubscribeField(Drawable, FID_Width, Self);
SubscribeField(Drawable, FID_Height, Self);
ReleaseObject(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. |
|
|