Click here to Skip to main content
15,884,986 members
Articles / Desktop Programming / WTL
Article

CAtomT - An ATOM wrapper for WTL

Rate me:
Please Sign up or sign in to vote.
3.40/5 (5 votes)
25 Dec 2006CPOL 36.9K   165   10   6
A simple Win32 ATOM type wrapper.

Introduction

Here is a very simple ATOM type wrapper, which supports the simplest ATOMs API. The class interface is very simple, and doesn't need any description. The class source is really small, so I posted it here:

C++
///////////////////////////////////////////////////////////////////////////////
// CAtomT - ATOM type wrapper

template[bool t_bGlobal]
class CAtomT
{
public:
    ATOM m_Atom;

public:
    enum AtomType
    {
        ATOM_INTEGER = 0,
        ATOM_STRING
    };

public:
    CAtomT(ATOM Atom = 0) : m_Atom(Atom)
    { }

    CAtomT& operator=(const CAtomT& Atom)
    {
        if (this != &Atom)
            m_Atom = Atom;

        return (*this);
    }

    operator ATOM() const
    {
        return m_Atom;
    }

    bool IsValid() const
    {
        return (m_Atom != 0);
    }

    AtomType GetType() const
    {
        ATLASSERT(IsValid());
        return (m_Atom < MAXINTATOM) ? ATOM_INTEGER : ATOM_STRING;
    }

    bool GetName(LPTSTR lpNameBuffer, int nBufferSize) const
    {
        ATLASSERT(IsValid());
        ATLASSERT(lpNameBuffer != NULL);
        if (t_bGlobal)
            return (::GlobalGetAtomName(m_Atom, lpNameBuffer, nBufferSize) != 0);
        else
            return (::GetAtomName(m_Atom, lpNameBuffer, nBufferSize) != 0);
    }

#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
    bool GetName(_CSTRING_NS::CString& strName) const
    {
        ATLASSERT(IsValid());
        const size_t MAX_ATOM_NAME_SIZE = 255;
        LPTSTR lpNameBuffer = strName.GetBufferSetLength(MAX_ATOM_NAME_SIZE);
        if (lpNameBuffer != NULL)
        {
            bool bRes = GetName(lpNameBuffer, MAX_ATOM_NAME_SIZE);
            strName.ReleaseBuffer();
            return bRes;
        }
        else
            return false;
    }
#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)

    bool Delete()
    {
        ATLASSERT(IsValid());
        if (t_bGlobal)
            m_Atom = ::GlobalDeleteAtom(m_Atom);
        else
            m_Atom = ::DeleteAtom(m_Atom);
        return (!IsValid());
    }

public:
    static CAtomT Add(ATL::_U_STRINGorID AtomName)
    {
        if (t_bGlobal)
            return CAtomT(::GlobalAddAtom(AtomName.m_lpstr));
        else
            return CAtomT(::AddAtom(AtomName.m_lpstr));
    }

    static CAtomT Find(ATL::_U_STRINGorID AtomName)
    {
        if (t_bGlobal)
            return CAtomT(::GlobalFindAtom(AtomName.m_lpstr));
        else
            return CAtomT(::FindAtom(AtomName.m_lpstr));
    }
};

#ifndef _WIN32_WCE
typedef CAtomT<false> CAtom;
#endif // _WIN32_WCE
typedef CAtomT<true> CGlobalAtom;

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Russian Federation Russian Federation
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralAbout ATOM and more... Pin
Remon29-Dec-06 12:48
Remon29-Dec-06 12:48 
GeneralRe: About ATOM and more... Pin
Remon29-Dec-06 13:31
Remon29-Dec-06 13:31 
2. ATOMs must be deleted each time it is added and the template does not handle that.

MS says: "Each call to AddAtom should have a corresponding call to DeleteAtom. Do not call DeleteAtom more times than you call AddAtom, or you may delete the atom while other clients are using it."

In fact, the CAtomT should have a destructor that call the Delete member only if the embedded atom was created by the Add member.

But in that case, what about the copy operator ? Copying an ATOM obtain by the Find member is simple since no destruction should occur. But what about an ATOM obtain by the Add member ? The first response is to call the Add member once more. But let's see.

By the other hand, since the template ctor is from a ATOM and the default (the only one) cast operator is to ATOM, one can easily mixed local and global ATOMs.

Mixing local/global atom:

CAtom atm1( CGlobalAtom::Add( TEXT("Urp !!! Mixing local/global atom") ) );

Re-Mixing local/global atom + Memory leak:

atm1 = CAtom( CGlobalAtom::Add( TEXT("Urp !!! re-Mixing local/global atom plus Memory leak") ) );

Decrements the reference count of an atom more that incremented may delete other clients ATOM:

CAtom atm2;<br />
atm2 = atm1;<br />
atm2.Delete();<br />
atm1.Delete();


For those reasons, I think the template should really hide the type ATOM (no CTor which take an ATOM as paramater) and use a reference counted object to hold the ATOM and the "auto-delete" boolean which will solve the problem of the copy without having to call the Add member once more.

Something like that...

		template <class M = LocalPolicy><br />
		class TImpl : public IFace<br />
		{<br />
		public:<br />
			TImpl()<br />
			{<br />
			}<br />
<br />
			TImpl( const Name& AtomName, bool bLookupOnly = false )<br />
			{<br />
				if ( bLookupOnly ) Find( AtomName );<br />
				else Add( AtomName );<br />
			}<br />
<br />
			virtual ~TImpl()<br />
			{<br />
				if ( m_bAutoDelete )<br />
					Delete();<br />
			}<br />
<br />
			bool Add( const Name& AtomName )<br />
			{<br />
				if ( m_bAutoDelete )<br />
					VERIFY( Delete() );<br />
				m_Atom = M::Add(AtomName);<br />
				return( m_bAutoDelete = m_Atom.IsValid() );<br />
			}<br />
<br />
			bool Find( const Name& AtomName )<br />
			{<br />
				if ( m_bAutoDelete )<br />
					VERIFY( Delete() );<br />
				m_Atom = M::Find(AtomName);<br />
				return( m_Atom.IsValid() );<br />
			}<br />
<br />
			bool Delete()<br />
			{<br />
	#ifndef NDEBUG<br />
				if ( M::IsGlobal && m_Atom.IsInteger() )<br />
					TRACE(TEXT("GlobalDeleteAtom has no effect on an integer atom\n"));<br />
	#endif<br />
				if ( m_bAutoDelete )<br />
				{<br />
					ASSERT( m_Atom.IsValid() );<br />
					if ( !M::Delete( m_Atom ) )<br />
						return( false );<br />
				}<br />
				<br />
				m_Atom = (ATOM)0;<br />
				m_bAutoDelete = false;<br />
				return( true );				<br />
			}

QuestionWhat is this ATOM? Pin
armentage28-Dec-06 7:44
armentage28-Dec-06 7:44 
AnswerRe: What is this ATOM? Pin
isemenov28-Dec-06 22:13
isemenov28-Dec-06 22:13 
Question? Pin
Shawn Poulson27-Dec-06 8:29
Shawn Poulson27-Dec-06 8:29 
AnswerRe: ? Pin
isemenov28-Dec-06 22:18
isemenov28-Dec-06 22:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.