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;

              …