// Listenable.h
// * PURPOSE
//   Implements a simple 'listener' mix-in: maintains set of
//   'interested parties' (BHandlers) which may be sent messages
//   as a group.
//
//   Inherits and calls on, but does NOT implement, the ILockable
//   interface.  This may seem inconvenient, but it allows you to
//   use real semaphores only where needed -- in a hierarchically
//   arranged set of objects, this is a Good Thing(tm).
//
// * HISTORY
//   e.moon		7jul99		Cortex
//   e.moon 	9mar99		(BeDub)
//   e.moon 	30sep98		Begun.

#ifndef __Listenable_H__
#define __Listenable_H__

#include <Handler.h>
#include <Messenger.h>

#include <utility>
#include <list>

#include "ILockable.h"

#include "cortex_defs.h"
__BEGIN_CORTEX_NAMESPACE

class Listenable :
	public ILockable {

// [12aug99]
// since Listenable can't be expected to outlive the ILockable
// implementation, it can't automatically broadcast this message
// on deletion.  no big loss -- in many cases you want to send
// a custom message for each Listenable class, anyway.
//public:						// *** messages
//	enum msg_t {
//		// sent automatically by destructor
//		M_DELETED			= Listenable_message_base
//	};
//	
public:						// *** dtor
	virtual ~Listenable();

public:						// *** interface
	virtual status_t addListener(BHandler* handler);
	virtual status_t removeListener(BHandler* handler);
	
protected:					// *** implementation
	typedef pair<BHandler*,BMessenger> listener_pair;

	// broadcast message to all listeners
	// (if bSynchronous is true, wait for reply from each one)
	// The caller retains ownership of (ie. responsibility for
	// deleting) the message.
	// LOCK REQUIRED
	void tellListeners(BMessage* message, bool synchronous=false) const;
	
	// directly access the list of all listeners
	// LOCK REQUIRED
	const list<listener_pair>& listeners() const;
	
private:						// impl. data
	list<listener_pair>			m_listeners;
};

__END_CORTEX_NAMESPACE

#endif /*__Listenable_H__*/