Proposed
Addition to SDK - Global Data
Introduction
One problem with MMF is that it does not provide an easy way
to handle global objects. The best you can do is store some data
in special section of MMF and then have retrieve that data later.
This is not the best way to do things. What follows is my
proposed changes to the SDK to help make global data universal.
How it Would Work
This process needs to be as simple as humanly possible. That
is the best way to ensure the extension developers will use it.
Here is the process that developers would need to follow to use
global data:
- Define a precompiler constant (maybe #define
USEGLOBALDATA or some such).
- Add any data that is to be global to the GLOBALDATA
structure (which comes predefined).
- Add an option to the edit dialog of the object that
allows to user to toggle globality.
- Add code to the DestroyGlobalData() function to
de-allocate memory referenced by the global data.
That's all there is to it, so using my process for global data
will be very easy.
Changes to the SDK
New Precompiler Constants
USEGLOBALDATA
- The existence of this constant
causes all of the below entities and modifications to be
compiled.
DEFAULTGARRAYSIZE
- The default size that the global
array should have.
- If the developer thinks people may
use lots of his object globally in one application, this
size may need to be increased to improve perfromance, but
that is unlikely.
New Structures
typedef struct tagGDATA
{
char szName[OI_NAMESIZE + 1]; // Name of the object
unsigned int nIndex; // Index in the global array
bool bGlobal; // Whether or not this object is actually global
// The user's global data goes here
} GLOBALDATA;
typedef GLOBALDATA _far * LPGDATA;
The above structure would be used by the
developer to store their global data. The two provided fields are
required by internal functions and should never be changed by the
user.
typedef struct
{
unsigned int nApplications; // Used to keep track of how many
applications have been opened (each sub-application is a new
application). When the count reaches 0, all global data is
destroyed.
LPGDATA * papgdGlobalData; // Used to store the global data. This
array will have some default size (maybe 10) and will be resized
as needed.
unsigned int nGlobalSize; // The size of the global data array.
unsigned int gnGlobalCount; // The number of actual elements in
the global data array.
} GLOBALARRAY;
The above structure is used to maintain
the array of global data.
New Global Variables
GLOBALARRAY ggaGlobalData
- The structure containing
information needed to maintain the array of global data.
New Functions
LPGDATA GetGlobalData(LPRDATA rdPtr,
bool vbGlobal)
- Description: If the object is
global, it will try to find a current instance of its
GLOBALDATA structure. If it does not find one, it will
create one and store it. If the object is not global, it
simply creates a structure for the current object to use.
- Return: A pointer to the GLOBALDATA
structure.
- LPRDATA rdPtr: A pointer to the
object's RUNDATA structure, which is used to get the name
of the object.
- bool bGlobal: True if the object is
global.
LPGDATA GetGlobalData(char * vpacName,
bool vbGlobal)
- Description: If the object is
global, it will try to find a current instance of its
GLOBALDATA structure. If it does not find one, it will
create one and store it. If the object is not global, it
simply creates a structure for the current object to use.
- Return: A pointer to the GLOBALDATA
structure.
- char * vpacName: The name of the
object as recorded by MMF.
- bool bGlobal: True if the object is
global.
void UngetGlobalData(LPGDATA gdPtr)
- Description: If the object is global, does nothing.
Otherwise, it destroys the GLOBALDATA structure.
- Return: None.
- LPGDATA gdPtr: A pointer to the
object's GLOBALDATA structure to be destroyed.
void DestroyGlobalData(LPGDATA gdPtr)
- Description: The developer uses
this function to free any dynamically allocated memory in
the GLOBALDATA structure.
- Return: None.
- LPGDATA gdPtr: A pointer to the
object's GLOBALDATA structure.
LPGDATA GetFromGlobalArray(char *
vpszName)
- Description: Retrieves the
GLOBALDATA structure with the specified name (or creates
a new structure for it and adds it to the global array).
- Return: The structure with the
specified name.
- char * vpszName: The name of the
object whose structure is to be retrieved or created.
void RemoveFromGlobalArray(unsigned int
vnIndex)
- Description: Removes the GLOBALDATA
structure with the specified index. It does NOT destroy
the structure.
- Return: None.
- unsigned int vnIndex: The index of
the structure to be removed.
void DestoryGlobalArray()
- Description: Destroys all
GLOBALDATA structures and frees the global array;
- Return: None.
Modifications to Existing Structures
RUNDATA
- LPGDATA gdPtr will be added to point to the object's
global data.
EDITDATA
- bool bGlobal will be added to store whether or not the
object is global.
Modifications to Existing Functions
CreateObject
- Add the following line of code to default the new object
as local: edPtr->bGlobal = false;
CreateRunObject
- Add the following line of code to get the global data of
the object: rdPtr->gdPtr = GetGlobalData(rdPtr,
edPtr->bGlobal);
DestroyRunObject
- Add the following line of code to unget the global data
of the object: UngetGlobalData(rdPtr->gdPtr);
Initialize
- Add the following line of code to keep track of the
number of applications running:
ggaGlobalData.nApplications++;
Free
- Add the following line of code to keep track of the
number of applications running:
ggaGlobalData.nApplications--;
- Add the following lines of code to destroy global data is
need be: if(ggaGlobalData.nApplications == 0)
DestroyGlobalArray();