170 likes | 315 Views
The C Implementation of the GAT OO Specification. Hartmut Kaiser hartmut.kaiser@aei.mpg.de MPI for Gravitational Physics, Albert-Einstein-Institut, Golm. Outline. Design Principles Object orientation Derivation, Interfaces, Genericity Memory Management
E N D
The C Implementation of the GAT OO Specification Hartmut Kaiser hartmut.kaiser@aei.mpg.de MPI for Gravitational Physics, Albert-Einstein-Institut, Golm
Outline • Design Principles • Object orientation • Derivation, Interfaces, Genericity • Memory Management • Object lifetime, Instance tracking, Allocation responsibilities • Const Correctness • Error Handling • Portability • Open Source • Open problems Workshop on Grid Application Programming
Object Orientation • GAT Specification is object oriented • What’s an ‘Object’ • Some data and a set of related functions • Representation in C • Internal struct GATFile_S { /*…*/ }; • External typedef struct GATFile_S *GATFile; • Constructor/Destructor GATFile_Create(), GATFile_Destroy() • Naming convention GATResult GATFile_Copy(GATFile, /*…*/); Workshop on Grid Application Programming
Derivation • Every GAT object type has to be derived from the GATObject • What’s ‘Derivation’ • Reuse of common functionality • Conversion from and to GATObject should be possible • Representation in C • Every GAT object type has a common set of functions with an identical signature GATType GATFile_GetType(GATFile_const); GATResult GATFile_Destroy(GATFile *); GATResult GATFile_Clone(GATFile_const, GATFile *); GATResult GATFile_GetInterface(GATFile_const, void **); GATResult GATFile_Equals(GATFile_const, GATFile_const, GATBool *); Workshop on Grid Application Programming
Derivation • Conversion from any GAT type to GATObject should be possible, since all these ‘derived’ from GATObject. • Conversion from GATObject to the corresponding GAT type should be possible as well. • Representation in C • For every GAT type the following functions exist: • Succeeds always: GATObject GATFile_ToGATObject(GATFile); GATObject_constGATFile_ToGATObject_const(GATFile_const); • Succeeds only, if type matches: GATFile GATObject_ToGATFile(GATObject); GATFile_const GATObject_ToGATFile_const(GATObject_const); Workshop on Grid Application Programming
Interfaces • Certain GAT object types have to implement different interfaces (GATStreamable, GATMonitorable) • What’s an interface • A set of related functions, which may be called even not knowing the type of the object • Representation in C • Emulation of virtual functions. Every object has a table of function pointers, one table for each interface • GetInterface(): helper function to get at the different function pointer tables Workshop on Grid Application Programming
GATFile Memory Layout Workshop on Grid Application Programming
Genericity • Possibility to call a function for an arbitrary GAT type not knowing the concrete type • Representation in C • For every interface function exist • Concrete function implementation for every GAT type, which realises this interface GATResult GATFile_Serialise(GATFile file, GATObject stream, GATBool cleardirty); • Generic function allowing to call the type specific function GATResult GATSerialisable_Serialise(GATObject object, GATObject stream, GATBool cleardirty); Workshop on Grid Application Programming
Memory Management • All GAT object types have a …_Create() function, which returns a new instance of this type. • All GAT object types have a …_Destroy function, which frees all associated memory. • You are responsible to call …_Destroy! • for all objects you’ve created GATFile file = GATFile_Create(location); … /* do something useful with ‘file’ */ GATFile_Destroy(&file); • for all non const objects you get back from the engine GATPipe pipe = NULL; GATEndpoint_Connect(endpoint, &pipe); … /* do something useful with ‘pipe’ */ GATPipe_Destry(&pipe); Workshop on Grid Application Programming
Memory Management • The GAT objects returned from the engine are handles! (well actually pointers, but …) typedef struct GATFile_S * GATFile; • You’re free to copy around those ‘objects’ without performance harm. • But watch out! Don’t free any of these objects while you’re holding copies of it, which you still want to use. • Never free a GATObject with free(). • If you are using casting functions (as GATObject_ToGATFile) please note, that the result refers to the same object, so don’t free twice. Workshop on Grid Application Programming
Const correctness • Const correctness introduced wherever possible • Helps to enforce semantics, especially for memory management • You’ll have to free by yourself all objects and memory blocks given back from the engine, which are not const • Objects and memory blocks which are const are controlled by the GAT engine, you don’t want to free these • Representation in C • First temptation to have: GATFile and GATFile const but this doesn’t give, what we want • As a result we’ve got: typedef struct GATFile_S * GATFile; typedef struct GATFile_S const *GATFile_const; Workshop on Grid Application Programming
Error Handling • Every method (except constructor, destructor and certain simple accessors) return a GATResult value • Is a structured 32 bit unsigned int: • Every CPI based object has additional error tracking inside the associated GATContext: • Allows to print an error traceback of the full error history GATContext_GetCurrentStatus(context, &status); GATStatus_ErrorTrace(status); Workshop on Grid Application Programming
Error Handling (Explicit) #include <GAT.h> GATResult RemoteFile_GetFile (GATContext context, char const *source_url, char const *target_url) { GATResult rc = GAT_FAIL; GATStatus status = NULL; GATLocation source = GATLocation_Create (source_url); GATLocation target = GATLocation_Create (target_url); GATFile file = GATFile_Create (context, source, NULL); if (NULL == source || NULL == target || NULL == file) { GATCreateStatus(“RemoteFile_GetFile”, &status, GAT_MEMORYFAILURE, context, __FILE__, __LINE__); return GATContext_SetCurrentStatus (context, &status); } rc = GATFile_Copy(file, target, GATFileMode_Overwrite); if (GAT_FAILED(rc)) { GATCreateStatus(“RemoteFile_GetFile”, &status, rc, context, __FILE__, __LINE__); return GATContext_SetCurrentStatus (context, &status); } GATFile_Destroy (&file); GATLocation_Destroy (&target); GATLocation_Destroy (&source); return GAT_SUCCEEDED; } Workshop on Grid Application Programming
Error Handling (macros) #include <GAT.h> GATResult RemoteFile_GetFile (GATContext context, char const *source_url, char const *target_url) { GAT_USES_STATUS(“RemoteFile_GetFile”, context); GATLocation source = GATLocation_Create (source_url); GATLocation target = GATLocation_Create (target_url); GATFile file = GATFile_Create (context, source, NULL); if (NULL == source || NULL == target || NULL == file) { GAT_CREATE_STATUS(GAT_MEMRORYFAILURE); } else { GAT_CREATE_STATUS(GATFile_Copy(file, target, GATFileMode_Overwrite)); } GATFile_Destroy (&file); GATLocation_Destroy (&target); GATLocation_Destroy (&source); return GAT_RETURN_STATUS(); } Workshop on Grid Application Programming
Portability • All you need is a C compiler and a POSIX conformant library. • Dynamic (shared) library support is helpful • GAT was compiled on a wide variety of systems • Linux, IRIX etc. • Windows (Cygwin and native) • Macintosh • … Workshop on Grid Application Programming
Open Source • Available at http://www.gridlab.org/wp-1 • CVS access at cvsreadonly@cvs.gridlab.org:/cvs/gridlab co wp-1 Workshop on Grid Application Programming
Open problems • Memory management is very tedious • User has to do a lot by himself • Track all GAT object instance copies • Free all GAT object instances • Call constructor and destructor • Error handling is complicated (even with macros) • Always check for error codes, cluttered code. • All of these problems are solved by the C++ wrapper • Asynchronicity is (almost) completely missing • Engine is not thread safe as of today Workshop on Grid Application Programming