Symbian
Symbian OS Library

FAQ-0852 How can I use Thread Local Storage to maintain static data in a DLL?

[Index][spacer] [Previous] [Next]



 

Classification: C++ Category: Threads & Processes
Created: 02/28/2003 Modified: 03/13/2003
Number: FAQ-0852
Platform: Not Applicable

Question:
I am maintaining static data in Thread Local Storage in a DLL. What data structure should I use, how should I initialise and destroy my data, and how do I access my data?

Answer:
How can I use Thread Local Storage to maintain static data in a DLL?

1. Determine the appropriate structure for my static data.

A Single static variable is possible although difficult to extend should access to additional variables become necessary.

More useful is to encapsulate all the static data variables into a single Struct or class. Extra data variables can easily be added at a later time.

class TMyStaticData
{
public:
TInt iData;
TInt iMoreData;
};

2. How / When should I create and destroy my static data?

Ideally, within the DLL entry point E32Dll.

On the device when the DLL is attached to a new thread, we should contruct our static data
at this point and store this in Thread Local Storage using Dll::SetTLS().

Similarly, when the Dll is detached from the thread we should delete our static data, and
reset the Thread Local Storage. Note : Thread Local Storage maintains a TAny* pointer so we
need to cast appropriately when accessing our data.

GLDEF_C TInt E32Dll(TDllReason aReason)
{
TInt res=KErrNone;
TMyStaticData* pMyData;
switch (aReason)
{
case EDllThreadAttach:
pMyData=new TMyStaticData;
Dll::SetTls(pMyData);
if (pMyData)
{
pMyData->iData = 100;
pMyData->iMoreData = 200;
}
      break;
case EDllThreadDetach:
pMyData = static_cast(Dll::Tls());
if (pMyData)
delete pMyData;
Dll::SetTls(NULL);
break;
default:
break;
}
return(res);
}

Within the emulator the techique is slighly different. A DLL will be attached to the current
process rather than a thread :

GLDEF_C TInt E32Dll(TDllReason aReason)
{
TInt res=KErrNone;
TMyStaticData* pMyData;
switch (aReason)
{
case EDllProcessAttach:
pMyData=new TMyStaticData;
Dll::SetTls(pMyData);
If (pMyData)
{
          pMyData->iData = 100;
pMyData->iMoreData = 200;
}
break;
case EDllThreadAttach:
break;
case EDllThreadDetach:
break;
case EDllProcessDetach:
pMyData = static_cast(Dll::Tls());
if (pMyData)
delete pMyData;
Dll::SetTls(NULL);
break; }
return(res);
}

3. How can I access my data?

Cast and cache the TAny pointer contained within Thread Local Storage and access the static
variables in the normal way.

It may be useful to create a utility function to make the process simpler and more maintainable:

inline TMyStaticData* GetStaticData()
{return static_cast(Dll::Tls()); }

…

TMyStaticData* pData = GetStaticData();
if (pData)
PData->iData = 300;

…