Static variables

Memory allocation between Windows and real-time context in conjunction with static variables

If global instances are used, be aware of the following:

This code includes three examples of global instances:

class MyClassA
{
public:
    MyClassA() {}
    ~MyClassA() {}
private:
    int v;
}

MyClassA A;

class MyClassB
{
    static MyClassA Value;
};

MyClassA& GetInstance()
{
    static MyClassA a;
    return a;
}

Singletons for the initialization of global instances

In order to delay the time, global or so-called singleton instances can also be created as local static objects. It is very important when using global class instances that the destructors are called late and at this point there is no longer a connection to the TwinCAT system, so that TwinCAT resources must be released beforehand.

Here is a sample code showing a singleton in TwinCAT:

#include "TcInterfaces.h"
class VersionProvider : public ITcVersionProvider
{
public:
       DECLARE_IUNKNOWN_NODELETE()
       VersionProvider()
       {
              m_Version = { 1, 2, 3, 0};
       }
       virtual HRESULT TCOMAPI GetVersion(T_Version& version)
       {
              version = m_Version;
              return S_OK;
       };
private:
       T_Version m_Version;
};
BEGIN_INTERFACE_MAP(VersionProvider)
       INTERFACE_ENTRY(IID_ITcVersionProvider, ITcVersionProvider)
END_INTERFACE_MAP()
class MySingleton
{
public:
       static MySingleton& Instance(ITcVersionProvider* ip = NULL, bool bRelease=false)
       {
              static MySingleton g_instance(ip);
              if (bRelease) g_instance.Release();
              return g_instance;
       }
       T_Version GetVersion()
       {
             T_Version v = {0, 0, 0, 0};
              if (m_spTcInst != NULL)
              {
                     m_spTcInst->GetVersion(v);
              }
              return v;
       }
private:
       MySingleton(ITcVersionProvider* ip = NULL)
              : m_spTcInst(ip)
       {
       }
       void Release()
       {
             m_spTcInst = NULL;
       }
       ITcVersionProviderPtr m_spTcInst;
};

Here the usage is shown:

// actual instance which is an example for a TwinCAT resource
VersionProvider vp; 
// Initialize singleton
MySingleton::Instance(&vp);
// use singleton to access information provided by TwinCAT resource
T_Version v1 = MySingleton::Instance().GetVersion();
Assert::IsTrue( v1.major == 1 && v1.minor == 2 && v1.build == 3 &&  v1.revision == 0);
// Deinitialize singleton and release reference to TwinCAT resource
MySingleton::Instance(NULL, true);
// use singleton after deinitialization which has to implement some default behaviour for this case
T_Version v2 = MySingleton::Instance().GetVersion();
Assert::IsTrue( v2.major == 0 && v2.minor == 0 && v2.build == 0 &&  v2.revision == 0);