Simulating .NET events in native C++

My last post talks about simulating delegates in native C++ and using them asynchronously. This is all nice, but its far from having all the same features as the equivalent from the CLR. For example, its missing events.

An event is basically like a multicast delegate but it is defined but subscriber objects. An event with no subscribers is basically useless, in fact it will even raise an exception if you call it with no subscriptions.

So as a starter to mimic this behavior in native C++ I created a tiny class to follow my previous design (using IDelegate):

class CEvent
{
public:
	CEvent(BOOL bAutoClean = TRUE) :
		m_bAutoClean(bAutoClean)
	{ }

	virtual ~CEvent()
	{
		if (m_bAutoClean)
			for (INT i = 0; i < m_cDelegates.GetSize(); i++)
				delete m_cDelegates[i];
	}

	VOID operator()(ULONG_PTR ulParam)
	{
		for (INT i = 0; i < m_cDelegates.GetSize(); i++)
 			m_cDelegates[i]->Invoke(ulParam);
	}

	const CEvent &operator+=(IDelegate *pDelegate)
	{
		BOOL bRes = m_cDelegates.Add(pDelegate);
		ATLASSERT(bRes != FALSE);
		return *this;
	}

	const CEvent &operator-=(IDelegate *pDelegate)
	{
		BOOL bRes = m_cDelegates.Remove(pDelegate);
		ATLASSERT(bRes != FALSE);
		return *this;
	}

private:
	BOOL m_bAutoClean;
	CSimpleArray m_cDelegates;
};

As we see there is much resemblance between a delegate and an event as they both can be invoked. In fact, in the CLR an event is a type modifier while a delegate is a reference type meaning events are based on delegates.

So to use the above class you can now do something like this:

class X
{
public:
        CEvent Processed;
        ...
};

class Y
{
public:
        VOID Initialize()
        {
                m_x.Processed += MAKECLSDELEGATE(Y, OnProcessed);
                ...
        }

        ULONG_PTR OnProcessed(ULONG_PTR ulParam)
        {
                ...
                return 0;
        }

private:
        X m_x;
};

I find it pretty neat as it makes code more readable and improves decoupling.

Advertisements