Click here to Skip to main content
15,896,557 members
Articles / Programming Languages / C++

The Impossibly Fast C++ Delegates

Rate me:
Please Sign up or sign in to vote.
4.96/5 (67 votes)
17 Jul 2005MIT7 min read 392.8K   6.3K   186  
A implementation of a delegate library which can work faster than "the Fastest Possible C++ Delegates" and is completely compatible with the C++ Standard.
/*
	(c) Sergey Ryazanov (http://home.onego.ru/~ryazanov)

	Fast delegate compatible with C++ Standard.
*/
#ifndef SRUTIL_EVENT_INCLUDED
#define SRUTIL_EVENT_INCLUDED

namespace srutil
{
	template <typename TSink> class event_source;
	template <typename TSink> class event_binder;

	template <typename TSink> class event_binder
	{
	public:
		typedef TSink sink_type;
		typedef event_source<sink_type> event_source_type;

		event_binder() : sink(sink_type()) {next = prev = this;}
		~event_binder() {unbind();}

		void bind(const event_source<sink_type>& source, sink_type sink);
		void unbind()
		{
			prev->next = next;
			next->prev = prev;
			next = prev = this;
		}

	private:		
		event_binder* prev;
		event_binder* next;
		sink_type sink;
		friend class event_source<sink_type>;

		void attach_after(event_binder* that)
		{
			next = that->next;
			next->prev = this;
			that->next = this;
			prev = that;
		}

		event_binder(event_binder const&);
		event_binder const& operator=(event_binder const&);
	};

	template <typename TSink> class event_source
	{
	public:
		typedef TSink sink_type;
		typedef event_binder<sink_type> binder_type;

		void bind(binder_type& bndr, sink_type sink)
		{
			bndr.attach_after(&list_head);
			bndr.sink = sink;
		}

		template <class TInvoker>
		void emit(TInvoker const& invoker)
		{
			binder_type* current = list_head.next;
			while (current != &list_head)
			{
				if (current->sink)
				{
					event_binder<sink_type> bookmark;
					bookmark.attach_after(current);
					invoker(current->sink); // *current may be excluded from list, but mookmark will always keep valid
					current = bookmark.next;
				}
				else
					current = current->next;
			}
		}

	private:
		mutable binder_type list_head;
		friend class event_binder<sink_type>;
	};

	template <typename TSink>
	void event_binder<TSink>::bind(const event_source<sink_type>& source, sink_type sink)
	{
		unbind();

		attach_after(&source.list_head);
		this->sink = sink;
	}
}
#endif// SRUTIL_EVENT_INCLUDED

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Web Developer
Russian Federation Russian Federation
I'm MS in Math (with honor). I've been working as a software engineer in the Vessel Traffic System department since the year 2002.

I like the C++, riddle solving, travelling and sports. My daughter was born when I was participating in a rock climbing competition (4 Jul 2004). Also I took up kayaking and skydiving, but unfortunately now I have no time for it.

I have about 4 years experience in ACM ICPC (ICP contests). The best achievement is 18-th place in World Finals (2002).

Comments and Discussions