|
||
Many UNIX programs rely on Writable Static Data (WSD) for data storage. Native Symbian OS applications have been developed without any support for WSD on an Emulator for dynamic link libraries. P.I.P.S. supports WSD and a complete implementation is available for target phones. The implementation of WSD on an Emulator, however, poses certain restrictions for dynamic link libraries.
Note: For information regarding why WSD is not supported by Symbian OS, refer to the Symbian OS » Developer Knowledgebase » FAQ-0907 section in the Symbian OS Library.
The Symbian Emulator uses the Microsoft Windows® process model and each Symbian OS process is emulated within a single Windows process. To preserve P.I.P.S. and Symbian OS semantics, there should be one copy of the global data for each emulated process. However, this is not possible since a DLL on the emulator is just a Windows DLL and Windows gives it a single copy of any global data it needs when it is loaded. Thus, a Symbian DLL with WSD will share the WSD between each process that uses it, giving unexpected results.
A Symbian project's MMP file can specify the
EPOCALLOWDLLDATA
directive to enforce a rule that WSD should not
be shared between processes. The P.I.P.S. STDEXE
target type sets
this directive automatically. The rule imposes the restriction that only one
process can load a DLL with WSD. P.I.P.S. provides a mechanism to avoid these
restrictions.
int refCount = 0;
int IncRefCount()
{
//Increment the reference count
return ++refCount;
}
int DecRefCount()
{
//Decrement the reference count
return --refCount;
}
The UNIX code above will provide indeterminate results on a Symbian
emulator. If the DLL had EPOCALLOWDLLDATA
in its MMP file then
only one process would be able to use the reference counting functions. Without
EPOCALLOWDLLDATA
, the reference count would be global and not
process specific.
The following code demonstrates the use of the
Pls()
function (Process Local Storage), which is the
P.I.P.S. WSD solution to the problem.
#include <pls.h>
#ifdef __WINSCW__
//The next code will run only on the emulator
//Put the global count into a structure
struct DLLData
{
int refCount;
};
//Define a way to access the structure
//On the first call to this function, memory will be allocated with the specified
//UID as an identifier and the Initialization function will be called
//Subsequent calls to this function return the allocated memory
struct DLLData* GetGlobals()
{
return Pls<DLLData>(KDLLUid3, InitializeGlobals);
}
//Initialization function
TInt InitializeGlobals(DLLData* aData)
{
aData->refCount = 0;
return KErrNone;
}
//Access the refCount variable
int& get_refCount()
{
return GetClobals()->refCount;
}
//Macro to replace the variable with our new method
#define refCount get_refCount()
#else
//Target device code
int refCount;
#endif
int IncRefCount()
{
return ++refCount;
}
int DecRefCount()
{
return --refCount;
}