|
|
• Files |
Primitives The Primitives section is a bit of a pot pourri of constants, enums, abstract classes, templates, and constructible classes. Enumerations The classes TEnum and TEpic provide the underpinnings of enum derived templates XEnum and XEpic, respectively. What these classes try to do, to some measure of success, is facilitate the persistent state of enumerated member variables. It's certainly possible to stream out and stream back in the numeric representation of an enumeration, but any change to the enumerated type, ordering for example, may invalidate what has previously been stored. And unlike classes, there's no good way to version control enumerations. So instead, these templates assist in streaming the actual name of the enumeration. So long as the semantics of the enumerated item's name is not changed, streaming in such a value will give it the corrected value at runtime. And thus the rule for such enumerations becomes, add or change whatever you like, but don't use a name for a new purpose. Pick something else. And if necessary, catch exceptions during the stream in process when a deprecated enumeration is encountered, and fix it up. Polymorphic Objects The AObject abstract class is a base class for persistent objects that require anonymous storage. The Pink/Taligent collection classes made heavy usage of this architectural feature, keying them to their templates and iterators. I almost never use it. In truth, I haven't thought about it for a good many years. It's still there, underlying a lot of the key classes, but it is somewhat superceded by my convention that polymorphism must be by design, not a "just in case" lack of planning. About the only objects currently in Guildhall that make use of it are the subclasses of AValue used by my Codex C++ interpreter. It's useful there, so it can stick around. But it might be just as easy to move the functionality into AValue and get rid of AObject. That's a decision for later. That said, the AStream class (discussed below) provides facilities for streaming out anonymous AObject subclasses, using its Entomb (stream out) and Exhume (stream in) methods. Basically it just grabs the type from the AObject subclass and streams that out first. Then it calls the object to write itself out. On streaming in, the type is read and used to look up an empty copy of the object already known to Guildhall. That empty object is cloned and then used to read the anonymous object from the stream. This works, and has for a while. The trickiest part is making sure that Guildhall knows about those empty objects before any of them have to be read. Fortunately that can be solved with the module initializer discussed below. Streams The abstract class AStream is defined in the Primitives section because every persistent object needs its declarations. As discussed on the Guildhall conventions page, streams stand in for several kinds of persistent and pseudo-persistent storage media. Persistent classes, whether derived from AObject or not, override operator>>= to stream out binary data and operator<<= to stream it back in. Meanwhile, AStream defines global inline operators for every scalar type and binds those operators to individual Read and Write calls. Subclasses of AStream must implement each of the Read and Write routines, handling endian issues as needed. The streaming operators for classes that contain only scalars, such as TPoint which contains two floating point coordinates or TRect which contains four coordinates, can be fully implemented just with the operators AStream provides. An object such as TRoundRect, which includes both a TRect and a TPoint as members, can in turn call the operators defined by TRect and TPoint to implement streaming. In this fashion all the streaming operators can be implemented, complex objects building on more primitive ones. AStream provides support for scalar arrays as well, and subclasses must implement these. It also provides methods for random access to stream storage for reading and writing arrays of each scalar type. And finally, it declares methods for dealing with the data fork, the resource fork, and the version fork, though again these must be implemented by each subclass. Consoles The AConsole class defines the protocol for interacting with the user or developer via a text and graphics based console. It also defines three important subclasses, the null console TNullConsole which tosses all output away, the host console THostConsole, which routes output to the IDE for debugging purposes, and the indirect console TFauxConsole. TFauxConsole allows an applet to use a console without knowing where its output is going to end up. But TFauxConsole can be redirected to another AConsole subclass as circumstances dictate. Initially TFauxConsole is directing all output to the null console. When circumstances change, for example when the user launches Terminusan AConsole subclassing applet, Terminus can install itself as the system console, and subsequent output will be displayed in its console window. You can see how consoles are used on the Terminus page. Pointer Arrays The TPointerArray class, and its related template XPointerArray, provide the foundation for all arrays of objects. Like its near cousins, the scalar arrays, TPointArray provides a common set of access methods. The XPointerArray template adds little code to TPointerArray, but it does facilitate type configuration of the arrays contents. Miscellaneous Classes TEventModifiers is defined at this level, and I can't even remember why. It is a simple class that captures the status of keyboard modifiers when events are created. The TModuleInitializer class certainly belongs here. It cannot be created as a pointer because its new and delete operators are intentionally hidden. Its behavior is very simple. It is constructed as a global object at the end of implementation files that need to register instances of objects with the Guildhall runtime. It contains no members so by itself it has no impact on static initialization or static destruction. It is given one parameter, a function that can be called to create instances needed during runtime, for example the sample objects used by Exhume, mentioned earlier on this page. Actual allocation of those objects is deferred. The function pointer is passed to the runtime, and each function is called after the heap is ready, in other words, after static initialization is complete. In this sense the module intializer is deferring static initialization until the heap is running. This approach also makes it easy for applets to register objects defined within each applet's domain. Helper Functions The Primitives section is where you'll find a variety of global helper functions, especially for handling scalars. It provides methods for comparing scalars, for testing the equality of arrays of scalars, for comparing arrays of scalars, and for copying arrays of scalars. There are helper functions for debugging and floating point type sensitive calls for most routines in the math package, for example fdual2min or fquad2sin. Having such typed calls eliminates a lot of ambiguity caused by C++ promotion of scalar types. Regardless of what you throw in, you know which routine will be called and exactly which scalar type you'll get back as a result. Static Classes
Abstract Classes
Constructible Classes
Class Templates
Global Helper Functions
In the list above, substitute the name of one of the scalar types supported by Guildhall, for example "ULong" for ulong or "FDual" for fdual. |