/*
 *
 *
 *    multiplex.h
 *
 *    C++ header file for class 'multiplex.'
 *
 *    =========================================================================
 *
 *    Copyright (C) 2001-2003 by Matt Roberts, KK5JY.
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation; either
 *    version 2.1 of the License, or (at your option) any later version.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *    =========================================================================
 *
 *
 */


#ifndef __MULTIPLEX_H
#define __MULTIPLEX_H

	#include <my++/watchable.h>
	#include <my++/exception.h>
	#include <vector>
	#include <sys/time.h>


	namespace my {

		/*
		 *
		 *
		 *    class multiplex
		 *
		 *    This class implements a watching system for multplexing I/O from several
		 *    different sources.
		 *
		 *
		 */

		class multiplex {
			private:
				struct dev_node {
					// associated object -- also primary key for searching
					watchable *dev;

					// associated states during 'watch()'
					bool watch_read;
					bool watch_write;
					bool watch_except;

					/* these are used for searches through std:: containers */
					bool operator == (const dev_node &d) { return (dev == d.dev); };
					bool operator != (const dev_node &d) { return (dev != d.dev); };
					bool operator == (const watchable *d) { return (dev == d);    };
					bool operator != (const watchable *d) { return (dev != d);    };

					/* ctor */
					dev_node (void);
					dev_node (const dev_node &dn);
					dev_node (watchable *w);
					dev_node (watchable &w);
				};

			private:
				typedef std::vector<dev_node> dev_list;
				dev_list devices;
				bool m_signalled;

			public:  // public types
				typedef my::exception_template<my::multiplex> exception;

			public:  // use these to manipulate the list of watched devices
				void add (watchable *d);
				void add (watchable &d) { add(&d); };
				void remove (watchable *d);
				void remove (watchable &d) { remove(&d); };
				bool signal (void) { return m_signalled; };

				// use one of these to watch all devices
				int watch (timeval *timeout = 0); // real function
				int watch (timeval &timeout) { return watch(&timeout); };
				int watch (long &sec, long &usec) {
					timeval timeout;
					timeout.tv_sec = sec;
					timeout.tv_usec = usec;
					int rtn = watch(&timeout);
					sec = timeout.tv_sec;
					usec = timeout.tv_usec;
					return rtn;
				}

			public: // public ctor and dtor
				multiplex (void) : m_signalled(false) { /* noop */ };
				~multiplex (void) { /* noop */ };
		};
	}


	inline my::multiplex::dev_node::dev_node (void) {
		dev = 0;
		watch_read = watch_write = watch_except = false;
	}


	inline my::multiplex::dev_node::dev_node (const dev_node &dn) {
		dev = dn.dev;
		watch_read = watch_write = watch_except = false;
	}


	inline my::multiplex::dev_node::dev_node (watchable *w) {
		dev = w;
		watch_read = watch_write = watch_except = false;
	}


	inline my::multiplex::dev_node::dev_node (watchable &w) {
		dev = &w;
		watch_read = watch_write = watch_except = false;
	}

#endif /* __MULTIPLEX_H */
