ThreadPtr.h

// ThreadPtr.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2007

@import "IObject.h"

namespace ceda
{

template<typename T>
T* GetThreadPtr() { T::this_wont_compile(); return nullptr; }

template<typename T>
void SetThreadPtr(T*) { T::this_wont_compile(); }


@def mDefineThreadPtrGfn(T) = 
{
    $function+ T* GetThread@@T();
    $function+ void SetThread@@T(T* p);
}

@def mDefineThreadPtr(T) =
{
    mDefineThreadPtrGfn(T)

    template <>
    inline T* GetThreadPtr<T>() { return GetThread@@T(); }

    template <>
    inline void SetThreadPtr<T>(T* p) { SetThread@@T(p); }
}

@def mImplementThreadPtr(T) =
{
    static thread_local T* tls_current@@T = nullptr;

    $function+ T* GetThread@@T()
    {
        return tls_current@@T;
    }
    
    $function+ void SetThread@@T(T* p)
    {
        tls_current@@T = p;
    }
}

template<typename T>
class DeclareThreadPtr
{
public:
    DeclareThreadPtr()
    {
        m_prev = GetThreadPtr<T>();
    }

    DeclareThreadPtr(T* p)
    {
        m_prev = GetThreadPtr<T>();
        SetThreadPtr(p);
    }

    static void Set(T* p)
    {
        SetThreadPtr(p);
    }

    ~DeclareThreadPtr()
    {
        SetThreadPtr(m_prev);
    }

private:
    T* m_prev;    
};


@def mDefineNamedThreadPtr(T, Name) =
{
    $function+ T* GetThread@@Name();
    $function+ void SetThread@@Name(T* p);
    
    class DeclareThread@@Name
    {
    public:
        DeclareThread@@Name()
        {
            m_prev = GetThread@@Name();
        }

        DeclareThread@@Name(T* p)
        {
            m_prev = GetThread@@Name();
            SetThread@@Name(p);
        }

        static void Set(T* p)
        {
            SetThread@@Name(p);
        }

        ~DeclareThread@@Name()
        {
            SetThread@@Name(m_prev);
        }

    private:
        T* m_prev;    
    };
}

@def mImplementNamedThreadPtr(T, Name) =
{
    static thread_local T* tls_current@@Name = nullptr;

    $function+ T* GetThread@@Name()
    {
        return tls_current@@Name;
    }
    
    $function+ void SetThread@@Name(T* p)
    {
        tls_current@@Name = p;
    }
}

} // namespace ceda