C++ - Notify Call list aka. The chain pattern

2. April 2012 08:00

 

This is a short guide to creating a notify call list which is useful for sending message across an entire program which can work dynamically. The clasic example of these is when a program is about to exit. This can give everything a chance to attach to events like this then handle the outcome.

 

For this particular example it uses a C++ template to create a class which will be able to Add / Remove or Call the list. Which will accept a basic type with a custom argument.

 

template <class T, class P>
	class Notify {
		
		class NotifyItem {
			public:
				void (*m_fp) (T, P);
				P m_priv;
				
		};
		
		private:
			std::list<NotifyItem> m_list;
	
		public:
			void Add(void (*fp) (T, P), P priv) {
#ifdef DEBUG
				//Check for existing item in debug mode
				typename std::list<NotifyItem>::iterator x;

				for(x = m_list.begin(); x != m_list.end(); x++) {
					if (x->m_fp == fp && x->m_priv == priv)
						abort();

				}
#endif			
				NotifyItem tmp;
				tmp.m_fp = fp;
				tmp.m_priv = priv;
				m_list.push_back(tmp);
			}
			
			void Remove(void (*fp) (T, P), P priv) {
				typename std::list<NotifyItem>::iterator x;

				for(x = m_list.begin(); x != m_list.end(); x++) {
					if (x->m_fp == fp && x->m_priv == priv) {
						m_list.erase(x);
						return;
					}

				}				
								
			}
			
			void Call(T arg) {
				typename std::list<NotifyItem>::iterator x;
				
				for(x = m_list.begin(); x != m_list.end(); x++) {
					x->m_fp(arg, x->m_priv);
				}

			}
	};

 

A short example of how to use the template above to pass two int's to a function. As you can see it is quite simple to use. You could of course pass other arguments types or make the functions very generic using something like Notify<int, void *> or pass an interface type class for handling the events.

 

void func(int arg, int priv) {
	printf("%d %d\n", arg, priv);
}


int main(int argc, char **argv) {
	Notify<int, int> inotify;
	
	inotify.Add(func, 10);
	inotify.Add(func, 11);
	inotify.Add(func, 12);
	inotify.Add(func, 13);

	inotify.Remove(func, 12);

	inotify.Call(0);

	printf("Finished\n");
	return 0;
}

 

 

E-mail Kick it! DZone it! del.icio.us Permalink