Agar

Hypertriton Inc.
( Francais )
HOME | SCREENSHOTS | DOWNLOAD | DOCS | FORUMS/LISTS | CHAT | CONTRIBUTE | REPORT BUG | TWITTER | WIKI

Note: The Agar manual pages follow certain conventions, notably concerning function return values. Please read AG_Intro(3) first.


SYNOPSIS

#include <agar/core.h>

DESCRIPTION

The Agar object system provides object-oriented programming functionality (e.g., inheritance, virtual functions) to applications written in different languages (currently C, C++, Objective C, Perl and Ada).

INITIALIZATION AND VFS FUNCTIONS



AG_Object * AG_ObjectNew (AG_Object *parent, const char *name, AG_ObjectClass *classInfo)

void AG_ObjectInit (AG_Object *obj, AG_ObjectClass *classInfo)

void AG_ObjectInitStatic (AG_Object *obj, AG_ObjectClass *classInfo)

void AG_ObjectAttach (AG_Object *new_parent, AG_Object *obj)

void AG_ObjectAttachToNamed (AG_Object *vfsRoot, const char *path, AG_Object *child)

void AG_ObjectDetach (AG_Object *obj)

void AG_ObjectMoveToHead (AG_Object *obj)

void AG_ObjectMoveToTail (AG_Object *obj)

void AG_ObjectMoveUp (AG_Object *obj)

void AG_ObjectMoveDown (AG_Object *obj)

void AG_ObjectDelete (AG_Object *obj)

AG_Object * AG_ObjectRoot (AG_Object *obj)

AG_Object * AG_ObjectParent (AG_Object *obj)

AG_Object * AG_ObjectFind (AG_Object *vfsRoot, const char *format, ...)

AG_Object * AG_ObjectFindS (AG_Object *vfsRoot, const char *name)

AG_Object * AG_ObjectFindParent (AG_Object *obj, const char *name, const char *type)

AG_Object * AG_ObjectFindChild (AG_Object *obj, const char *name)

int AG_ObjectCopyName (AG_Object *obj, char *pathbuf, size_t pathbuf_len)

void AG_ObjectLock (AG_Object *obj)

void AG_ObjectUnlock (AG_Object *obj)

void AG_LockVFS (AG_Object *obj)

void AG_UnlockVFS (AG_Object *obj)

void AG_ObjectSetName (AG_Object *obj, const char *fmt, ...)

void AG_ObjectSetNameS (AG_Object *obj, const char *name)

void AG_ObjectGenName (AG_Object *obj, AG_ObjectClass *classInfo, char *name, size_t len)

void AG_ObjectGenNamePfx (AG_Object *obj, const char *prefix, char *name, size_t len)

void AG_ObjectSetAttachFn (AG_Object *obj, void (*fn)(struct ag_event *), const char *fmt, ...)

void AG_ObjectSetDetachFn (AG_Object *obj, void (*fn)(struct ag_event *), const char *fmt, ...)

void AG_ObjectSetDebugFn (AG_Object *obj, void (*fn)(void *obj, void *userPtr, void *msg), void *userPtr)

AGOBJECT_FOREACH_CHILD (AG_Object *child, AG_Object *parent, TYPE type)


The AG_ObjectNew() function allocates and initializes a new object instance of the given class. The object is attached to parent, unless the argument is NULL. If name is NULL, a unique name of the form <class-name> #<number> is automatically generated. If both parent and name are specified and the parent object already has a child of the given name, AG_ObjectNew() fails and returns NULL.

The AG_ObjectInit() function initializes an object of the specified class. This involves invoking the init() operation associated with every class in the inheritance hierarchy. name specifies a name for the object instance (maximum AG_OBJECT_NAME_MAX bytes and must not contain " / " characters). classInfo should point to an initialized AG_ObjectClass structure (see CLASSES section). The flags argument specifies a default set of flags (see FLAGS section).

The AG_ObjectInitStatic() function is a variant of AG_ObjectInit() which marks the new object as statically-allocated. (see description of the AG_OBJECT_STATIC flag).

Objects are organized in a tree structure. AG_ObjectAttach() attaches an object to a new parent and AG_ObjectDetach() detaches an object from its current parent. These operations raise attached and detached events. Prior to detaching the object, AG_ObjectDetach() cancels scheduled AG_Timeout(3) events where the AG_CANCEL_ONDETACH flag is set. If parent is NULL, AG_ObjectAttach() is a no-op.

The AG_ObjectMoveUp(), AG_ObjectMoveDown(), AG_ObjectMoveToHead() and AG_ObjectMoveToTail() functions move the object in the parent object's list of child objects. These functions are useful when the ordering is important - when the child objects represent a stack, for instance.

The fn AG_ObjectDeleteroutine invokes AG_ObjectDetach() if the object is attached to a parent, followed by AG_ObjectDestroy().

AG_ObjectAttachToNamed() is a variant of AG_ObjectAttach() which looks up the parent inside the specified VFS using the pathname path.

AG_ObjectRoot() returns a pointer to the root of the VFS which the given object is attached to. AG_ObjectParent() returns the immediate parent of the given object.

AG_ObjectFind() performs a pathname lookup on the specified VFS. The function returns a pointer to the target object on success, otherwise NULL is returned.

AG_ObjectFindParent() performs a reverse lookup, starting from the specified object itself, up to the root of the VFS. For each element encountered, the object's name is compared against name (if not-NULL) and the object class is compared against type (if not NULL).

AG_ObjectFindChild() performs a name lookup on the immediate children of the specified object. The function returns the matching object if it was found, otherwise NULL.

AG_ObjectCopyName() copies the absolute pathname of an object instance to a fixed-size buffer. Under multithreading, the returned pathnames can be considered valid only as long as the VFS of the object remains locked.

AG_ObjectLock() and AG_ObjectUnlock() acquire or release the locking device associated with the given object. This is a mutex protecting all read/write members of the AG_Object structure, except parent, root and the list of child objects cobjs which are all considered part of the virtual filesystem and are instead protected by AG_LockVFS(). In most cases, it is best to use the AG_ObjectLock() mutex as a general-purpose locking device for subclasses of AG_Object, because it is guaranteed to be held during processing of events posted to the object, or object operations such as load() and save().

The AG_LockVFS() and AG_UnlockVFS() functions acquire or release the lock protecting the layout of the entire virtual system which the given object is part of.

Note that all lock/unlock functions are turned to no-ops if Agar is compiled without threads support.

AG_ObjectSetName() changes the name of the given object. If the object is attached to a VFS, it is assumed to be locked.

AG_ObjectGenName() generates an object name string unique to the specified parent object obj. The class name is used as prefix, followed by a number. The name is written to the fixed-size buffer name of the given size len. In a multithreaded context, the name is only guaranteed to remain unique as long as the parent object's VFS is locked. Similarly, AG_ObjectGenNamePfx() generates a name using the specified prefix instead of the class name.

AG_ObjectSetAttachFn() and AG_ObjectSetDetachFn() allow custom "attach" and "detach" hooks to be registered. These hooks are used where it is necessary to control the order of the child objects (for example, in the AG_Window(3) system of Agar-GUI, the ordering of window objects is important as it determines the order of rendering). The hook function is expected to insert the child object somewhere into the parent's children list.

AG_ObjectSetDebugFn() specifies a function to process debug messages (as issued by AG_Debug(3)) for the object. This function is a no-op unless Agar was compiled with --enable-debug.

The AGOBJECT_FOREACH_CHILD() macro iterates child over every child object of parent. The child pointer is cast to the given structure type, without type checking. Example:
struct my_class *chld;
AGOBJECT_FOREACH_CHILD(chld, parent, my_class) {
	printf("Child object: %s\\n", AGOBJECT(chld)->name);
}

CLASSES


void AG_RegisterClass (AG_ObjectClass *classInfo)

void AG_UnregisterClass (AG_ObjectClass *classInfo)

void AG_RegisterNamespace (const char *name, const char *prefix, const char *url)

void AG_UnregisterNamespace (const char *name)

AG_ObjectClass * AG_LookupClass (const char *classSpec)

AG_ObjectClass * AG_LoadClass (const char *classSpec)

void AG_RegisterModuleDirectory (const char *path)

void AG_UnregisterModuleDirectory (const char *path)

int AG_OfClass (AG_Object *obj, const char *pattern)

AG_ObjectClass * AG_ObjectSuperclass (AG_Object *obj)

AGOBJECT_FOREACH_CLASS (AG_Object *child, AG_Object *parent, TYPE type, const char *pattern)


The AG_RegisterClass() function registers a new object class. The classInfo argument should point to an initialized AG_ObjectClass structure, which is defined as:
typedef struct ag_object_class {
	const char *name;        /* Class name */
	size_t size;             /* Size of structure */
	AG_Version ver;          /* Version numbers */
	void (*init)(void *obj);
	void (*reinit)(void *obj);
	void (*destroy)(void *obj);
	int  (*load)(void *obj, AG_DataSource *buf, const AG_Version *ver);
	int  (*save)(void *obj, AG_DataSource *buf);
	void *(*edit)(void *obj);
} AG_ObjectClass;

The structure pointed by classInfo is used directly, it is not duplicated.

Note that it is customary to overload AG_ObjectClass. For example, AG_WidgetClass in Agar-GUI (see AG_Widget(3)) augments AG_ObjectClass with widget-specific operations such as draw() and sizeRequest().

The name string specifies the full inheritance hierarchy and name of this class. Subclasses are separated by colons, as in AG_Superclass:AG_Subclass, or alternatively, Namespace(Superclass:Subclass) or Namespace(Superclass:Subclass)@modules. If the optional @modules string exists, it specifies a comma-separated list of dynamically-linked library (modules) accessible from AG_DSO(3). It is implied that AG_Object is the "root class", so there is no need to specify it in the string.

size specifies the size in bytes of the object instance structure. ver is the datafile version number (see AG_Version(3)).

The init() operation initializes an AG_Object instance. reinit() releases any element of the dataset that has been dynamically allocated. It is invoked by the object system prior to load() or destroy().

The destroy() operation is invoked from AG_ObjectDestroy() to release any resources which are not handled by reinit(). Note that destroy() must not free the AG_Object structure itself.

The load() and save() operations are responsible for archiving the dataset (see the ARCHIVING section for more information).

When defined, the edit() operation generates user interface elements allowing the user to edit the object's dataset. It is a generic operation, not dependent on any particular GUI library. If using the Agar-GUI for example, edit() is expected to create a AG_Window(3) or a container widget such as AG_Box(3).

Note that whenever the init(), reinit(), load(), save() and destroy() operations are used, they are invoked for every class in the inheritance hierarchy of the given object.

AG_UnregisterClass() removes the specified object class.

AG_RegisterNamespace() registers a new namespace with the specified name, prefix and informational URL. For example, Agar registers its own namespace using:
  AG_RegisterNamespace("Agar", "AG_", "http://libagar.org/");

Once the namespace is registered, it is possible to specify inheritance hierarchies using the namespace format:
    Agar(Widget:Button):MyLib(MyButton)

or the equivalent expanded format:
    AG_Widget:AG_Button:MY_Button

The AG_UnregisterNamespace() function removes all information about the specified namespace.

The AG_LookupClass() function looks up the AG_ObjectClass structure describing the specified class (in namespace or expanded format). If there is no currently registered class matching the specification, AG_LookupClass() returns NULL.

AG_LoadClass() ensures that the object class specified in classSpec (see AG_RegisterClass() for details on the format) is registered, possibly loading one or more dynamic library files if they are specified in the string. Dynamic library dependencies are given in the form of a terminating @lib1,lib2,... string. AG_LoadClass() scans the registered module directories (see AG_RegisterModuleDirectory()) for the libraries specified in the string. Bare library names are given (the actual filenames are platform-dependent). Libraries that are found (and not already in memory) are loaded via AG_DSO(3). The first library must define a myFooClass symbol (where myFoo is the name of the class transformed from MY_Foo), for an AG_ObjectClass structure describing the class (i.e., the same structure that is passed to AG_RegisterClass()).

AG_UnloadClass() unregisters the specified class and also decrements the reference count of any dynamically-located module associated with it. If this reference count reaches zero, the module is removed from the current process's address space.

The AG_RegisterModuleDirectory() function adds the specified directory to the module search path. AG_UnregisterModuleDirectory() removes the specified directory from the search path.

The AG_OfClass() function returns 1 if the object is an instance of the class specified in the pattern, string. The pattern may contain wildcards such as MyClass:* or MyClass:*:MySubclass:*.

The AG_ObjectSuperclass() function returns a pointer to the AG_ObjectClass structure describing the superclass of the given object (or if the object is an instance of the base class, the base class is returned).

The AGOBJECT_FOREACH_CLASS() macro iterates child over every child object of parent which is an instance of the class specified by pattern. child is cast to the given structure type. Example:
struct my_class *chld;
AGOBJECT_FOREACH_CLASS(chld, parent, my_class, "MyClass") {
	printf("Object %s is an instance of MyClass\\n",
	    AGOBJECT(chld)->name);
}

DEPENDENCIES


int AG_ObjectInUse (AG_Object *obj)

AG_ObjectDep * AG_ObjectAddDep (AG_Object *obj, AG_Object *depobj, int persistent)

void AG_ObjectDelDep (AG_Object *obj, AG_Object *depobj)

Uint32 AG_ObjectEncodeName (AG_Object *obj, AG_Object *depobj)

int AG_ObjectFindDep (AG_Object *obj, Uint32 ind, AG_Object **objp)


AG_ObjectInUse() returns 1 if the given object is being referenced by another object instance or 0 if it isn't.

AG_ObjectAddDep() either creates a new dependency upon depobj or increments the reference count if one exists. If the persistent flag is set, the reference is preserved in object archives. AG_ObjectDelDep() decrements the reference count upon depobj and removes the dependency if the count reaches zero (unless the object has the AG_OBJECT_PRESERVE_DEPS flag set).

AG_ObjectEncodeName() returns a 32-bit integer identifier for the dependency, suitable for writing into data files. It may return the special values 0 (NULL reference) and 1 (self-reference), the meaning of which is object-specific.

AG_ObjectFindDep() tries to resolve the given 32-bit dependency identifier, return 0 on success and -1 on failure.

RELEASING RESOURCES


void AG_ObjectDestroy (AG_Object *obj)

void AG_ObjectFreeDataset (AG_Object *obj)

void AG_ObjectFreeEvents (AG_Object *obj)

void AG_ObjectFreeVariables (AG_Object *obj)

void AG_ObjectFreeDeps (AG_Object *obj)

void AG_ObjectFreeDummyDeps (AG_Object *obj)

void AG_ObjectFreeChildren (AG_Object *obj)


The AG_ObjectFreeDataset() function frees any dynamically allocated resources by invoking the reinit() of every class in the inheritance hierachy. The function also clears the AG_OBJECT_RESIDENT flag. Contrary to the destroy() operation, reinit() must leave the data structures in a consistent state (e.g., for a subsequent load() operation).

The AG_ObjectDestroy() function frees all resources reserved by the given object (and any of its children that is not being referenced). AG_ObjectDestroy() invokes the reinit() and destroy() operations of every class in the inheritance hierarchy. Note that AG_ObjectDestroy() also cancels any AG_Timeout(3) event scheduled for future execution. Unless the AG_OBJECT_STATIC flag is set, AG_ObjectDestroy() invokes free(3) on the structure.

Internally, AG_ObjectDestroy() invokes AG_ObjectFreeEvents(), AG_ObjectFreeVariables(), AG_ObjectFreeDeps() and AG_ObjectFreeChildren(), but these functions may be called directly in order to destroy and reinitialize the event handler list, the AG_Variable(3) table and destroy the child objects, respectively.

In addition to reinitializing the event handler table, AG_ObjectFreeEvents() also cancels scheduled events.

AG_ObjectFreeChildren() releases all resources allocated by child objects, under the specified parent object. The function assumes that none of the child objects are currently in use.

AG_ObjectFreeDummyDeps() removes entries in the dependency table where the reference count is zero (which occur in objects that have the AG_OBJECT_PRESERVE_DEPS flag set).


ARCHIVING


int AG_ObjectLoad (AG_Object *obj)

int AG_ObjectLoadFromFile (AG_Object *obj, const char *file)

int AG_ObjectLoadData (AG_Object *obj)

int AG_ObjectLoadDataFromFile (AG_Object *obj, const char *file)

int AG_ObjectLoadGeneric (AG_Object *obj)

int AG_ObjectLoadGenericFromFile (AG_Object *obj, const char *file)

int AG_ObjectSave (AG_Object *obj)

int AG_ObjectSaveAll (AG_Object *obj)

int AG_ObjectSaveToFile (AG_Object *obj, const char *path)

int AG_ObjectSerialize (AG_Object *obj, AG_DataSource *ds)

int AG_ObjectUnserialize (AG_Object *obj, AG_DataSource *ds)

int AG_ObjectReadHeader (AG_Object *obj, AG_ObjectHeader *header)

int AG_ObjectPageIn (AG_Object *obj)

int AG_ObjectPageOut (AG_Object *obj)


These functions implement archiving (or "serialization") of generic object information and arbitrary datasets to an efficient, machine-independent representation.

The AG_ObjectLoad() function (and its variants) are used to load the generic part or the dataset of either a single object or an object hierarchy, from archived data. AG_ObjectLoad() invokes the load() operation of every class in the inheritance hierarchy of the object.

AG_ObjectLoad(), AG_ObjectLoadGeneric() and AG_ObjectLoadData() look for the archive file in the default search path (using the load-path setting of AG_Config(3)).

AG_ObjectLoadFromFile(), AG_ObjectLoadGenericFromFile() and AG_ObjectLoadDataFromFile() will load the data from a specific file.

Note that when loading object hierarchies, objects will need to be allocated and initialized from scratch. This functionality requires that all classes be registered with AG_RegisterClass().

The AG_ObjectSave() function creates an archive of the given object in the default location (i.e., the save-path setting of AG_Config(3)). AG_ObjectSave() invokes the load() operation of every class in the inheritance hierarchy of the object. The AG_ObjectSaveAll() variant also saves the entire tree of child objects.

AG_ObjectSaveToFile() archives the given object to the specified file.

AG_ObjectSerialize() writes an archive of the given object to the specified AG_DataSource(3), and AG_ObjectUnserialize() reads an archive of the given object. Note that the AG_OBJECT_CHLD_AUTOSAVE feature will not work with these functions.

The AG_ObjectReadHeader() routine decodes a standard Agar object archive header. On success, it returns 0 and writes the information to the header structure:
typedef struct ag_object_header {
	char hier[AG_OBJECT_HIER_MAX];	    /* Inheritance hierarchy */
	char libs[AG_OBJECT_LIBS_MAX];	    /* Library list */
	char classSpec[AG_OBJECT_HIER_MAX]; /* Full class specification */
	Uint32 dataOffs;                    /* Dataset offset */
	AG_Version ver;                     /* AG_Object version */
	Uint flags;                         /* Object flags */
} AG_ObjectHeader;

The AG_ObjectPageIn() function loads an object's dataset into memory, assuming it is a persistent object and its dataset can be found on storage. On success, the AG_OBJECT_RESIDENT flag is set. AG_ObjectPageOut() checks whether an object is referenced by another object and if that is not the case, the dataset is archived to storage and freed from memory. Both functions return 0 on success or -1 if an error occured.

FLAGS

The following public AG_Object flags are defined:
AG_OBJECT_FLOATING_VARSRemove all entries of the AG_Variable(3) table in AG_ObjectLoad(). By default, the existing table is preserved and entries are created or replaced by items found in the archive.
AG_OBJECT_NON_PERSISTENTDisables archiving of the object and its children. If set, AG_ObjectSave() becomes a no-op and AG_ObjectLoad() calls will fail.
AG_OBJECT_INDESTRUCTIBLEAdvisory and application-specific.
AG_OBJECT_RESIDENTRead-only flag set by the object system to indicate that the object's dataset is currently resident in memory. This flag is set by AG_ObjectNew(), AG_ObjectLoadData() and AG_ObjectPageIn() and is cleared by AG_ObjectFreeDataset() and AG_ObjectPageOut().
AG_OBJECT_PRESERVE_DEPSDisable automatic removal of object dependencies when reference counts reach 0.
AG_OBJECT_STATICIndicates that this object is either statically-allocated (or allocated through another facility than malloc(3)). The AG_ObjectDestroy() operation will not call free(3) on the structure.
AG_OBJECT_READONLYAdvisory and application-specific.
AG_OBJECT_REOPEN_ONLOADIf the object has a edit operation, arrange for all graphical interface elements (as returned by edit) to be automatically destroyed and recreated after any AG_ObjectLoad() call. This flag is useful for complex objects where the graphical interface references elements of the dataset.
AG_OBJECT_REMAIN_DATAPrevent the object's dataset from being automatically freed (with AG_ObjectFreeDataset()) as a result of an AG_ObjectPageOut() call, when the reference count reaches zero.
AG_OBJECT_DEBUGEnable per-object debugging; application-specific.
AG_OBJECT_NAME_ONATTACHRequest that AG_ObjectAttach() calls automatically generates a name for the child object being attached. The name will be unique in the parent.
AG_OBJECT_CHLD_AUTOSAVEArrange for child objects to be automatically saved along with the object when AG_ObjectSave*() is invoked.

EVENTS

The AG_Object mechanism generates the following events:
attached (void)
The object has been attached to another. This event originates from the parent object. The linkage lock is held during the execution of the event handler.
detached (void)
The object has been detached from its parent. The linkage lock is held during the execution of the event handler. This event originates from the parent.
child-attached (void)
Same as attached(), except that the event is sent from the child to the parent.
child-detached (void)
Same as detached(), except that the event is sent from the child to the parent.
moved (AG_Object *new_parent)
The object has been moved from its current parent to new_parent. The linkage lock is held during the execution of the event handler. This event originates from the previous parent.
renamed (void)
The object's name has changed.
object-post-load-data (const char *path)
Invoked by AG_ObjectLoadData(), on success. If the object was loaded from file, path is the pathname of the file.
bound (AG_Variable *V)
A new variable binding has been created, or the value of an existing binding has been updated; see AG_Variable(3) for details.

EXAMPLES

See demos/objsystem in the Agar source distribution.

SEE ALSO

AG_Intro(3), AG_Event(3), AG_Variable(3), AG_Timeout(3)

HISTORY

The AG_Object interface appeared in Agar 1.0

Hosted by csoft.net - Secure, High-Availability Unix Hosting