⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abstractevent.h

📁 C++ class libraries for network-centric, portable applications, integrated perfectly with the C++ St
💻 H
字号:
//// AbstractEvent.h//// $Id: //poco/1.2/Foundation/include/Poco/AbstractEvent.h#3 $//// Library: Foundation// Package: Events// Module:  AbstractEvent//// Definition of the AbstractEvent class.//// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.// and Contributors.//// Permission is hereby granted, free of charge, to any person or organization// obtaining a copy of the software and accompanying documentation covered by// this license (the "Software") to use, reproduce, display, distribute,// execute, and transmit the Software, and to prepare derivative works of the// Software, and to permit third-parties to whom the Software is furnished to// do so, all subject to the following:// // The copyright notices in the Software and this entire statement, including// the above license grant, this restriction and the following disclaimer,// must be included in all copies of the Software, in whole or in part, and// all derivative works of the Software, unless such copies or derivative// works are solely in the form of machine-executable object code generated by// a source language processor.// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER// DEALINGS IN THE SOFTWARE.//#ifndef  Foundation_AbstractFoundation_INCLUDED#define  Foundation_AbstractFoundation_INCLUDED#include "Poco/Foundation.h"#include "Poco/SingletonHolder.h"#include "Poco/SharedPtr.h"#include "Poco/ActiveResult.h"#include "Poco/ActiveMethod.h"#include "Poco/Mutex.h"namespace Poco {template <class TArgs, class TStrategy, class TDelegate> class AbstractEvent	/// An abstractEvent is the super-class of all events. 	/// It works similar to the way C# handles notifications (aka events in C#).	/// Events can be used to send information to a set of observers	/// which are registered at the event. The type of the data is specified with	/// the template parameter TArgs. The TStrategy parameter must be a subclass 	/// of NotificationStrategy. The parameter TDelegate can either be a subclass of AbstractDelegate	/// or of PriorityAbstractDelegate. 	///	/// Note that AbstractEvent should never be used directly. One ought to use	/// one of its subclasses which set the TStrategy and TDelegate template parameters	/// to fixed values. For most use-cases the BasicEvent template will be sufficient.	///	/// Use events by adding them as public members to the object which is throwing notifications:	///	///     class MyData	///     {	///     public:	///         Poco::BasicEvent<int> AgeChanged;	///         	///         MyData();	///         ...	///     };	///	/// Throwing the event can be done either by the events notify or notifyAsync method:	///	///     void MyData::setAge(int i)	///     {	///         this->_age = i;	///         AgeChanged.notify(this, this->_age);	///     }	///	/// Note that notify and notifyAsync do not catch exceptions, i.e. in case a delegate 	/// throws an exception, the notify is immediately aborted and the exception is thrown	/// back to the caller.	///	/// Delegates can register methods at the event. In the case of a BasicEvent or FIFOEvent	/// the Delegate template is used, in case of an PriorityEvent a PriorityDelegate is used.	/// Mixing of observers, e.g. using a PriorityDelegate with a BasicEvent is not possible and 	/// checked for during compile time.	/// Events require the observers to follow the following method signature:	///	///     void onEvent(const void* pSender, TArgs& args);	///	/// For performance reasons arguments are always sent by reference. This also allows observers	/// to modify the sent argument. To prevent that, use <const TArg> as template	/// parameter. A non-conformant method signature leads to compile errors.	///	/// Assuming that the observer meets the method signature requirement, it can register	/// this method with the += operator:	///	///     class MyController	///     {	///     protected:	///         MyData _data;	///         	///         void onDataChanged(void* pSender, int& data);	///         ...	///     };	///         	///     MyController::MyController()	///     {	///         _data.AgeChanged += Delegate<MyController, int>(this, &MyController::onDataChanged);	///     }	///	/// In some cases it might be desirable to work with automatically expiring registrations:	///	///     _data.DataChanged += Expire<int>(Delegate<MyController, int>(this, &MyController::onDataChanged), 1000);	///	/// This will add a delegate to the event which will automatically be removed in 1000 millisecs.	///	/// Unregistering happens via the -= operator. Forgetting to unregister a method will lead to	/// segmentation faults later, when one tries to send a notify to a no longer existing object.	///	///     MyController::~MyController()	///     {	///         _data.DataChanged -= Delegate<MyController, int>(this, &MyController::onDataChanged);	///     }	///	/// For further examples refer to the event testsuites.{public:	AbstractEvent(): 		_executeAsync(this, &AbstractEvent::executeAsyncImpl),		_enabled(true)	{	}	AbstractEvent(const TStrategy& strat): 		_executeAsync(this, &AbstractEvent::executeAsyncImpl),		_strategy(strat),		_enabled(true)	{		}	virtual ~AbstractEvent()	{	}	void operator += (const TDelegate& aDelegate)		/// Adds a delegate to the event. If the observer is equal to an		/// already existing one (determined by the < operator),		/// it will simply replace the existing observer.		/// This behavior is determined by the TStrategy. Current implementations		/// (DefaultStrategy, FIFOStrategy) follow that guideline but future ones		/// can deviate.	{		FastMutex::ScopedLock lock(_mutex);		_strategy.add(aDelegate);	}		void operator -= (const TDelegate& aDelegate)		/// Removes a delegate from the event. If the delegate is equal to an		/// already existing one is determined by the < operator.		/// If the observer is not found, the unregister will be ignored	{		FastMutex::ScopedLock lock(_mutex);		_strategy.remove(aDelegate);	}	void notify(const void* pSender, TArgs& args)		/// Sends a notification to all registered delegates. The order is 		/// determined by the TStrategy. This method is blocking. While executing,		/// other objects can change the list of delegates. These changes don't		/// influence the current active notifications but are activated with		/// the next notify. If one of the delegates throws an exception, the notify		/// method is immediately aborted and the exception is reported to the caller.	{		SharedPtr<TStrategy> ptrStrat;		bool enabled = false;				{			FastMutex::ScopedLock lock(_mutex);			enabled = _enabled;			if (_enabled)			{				// thread-safeness: 				// copy should be faster and safer than blocking until				// execution ends				ptrStrat = new TStrategy(_strategy);			}		}		if (enabled)		{			ptrStrat->notify(pSender, args);		}	}	ActiveResult<TArgs> notifyAsync(const void* pSender, const TArgs& args)		/// Sends a notification to all registered delegates. The order is 		/// determined by the TStrategy. This method is not blocking and will		/// immediately return. The delegates are invoked in a seperate thread.		/// Call activeResult.wait() to wait until the notification has ended.		/// While executing, other objects can change the delegate list. These changes don't		/// influence the current active notifications but are activated with		/// the next notify. If one of the delegates throws an exception, the execution		/// is aborted and the exception is reported to the caller.	{		NotifyAsyncParams params(pSender, args);		{			FastMutex::ScopedLock lock(_mutex);			// thread-safeness: 			// copy should be faster and safer than blocking until			// execution ends			// make a copy of the strategy here to guarantee that			// between notifyAsync and the execution of the method no changes can occur							params.ptrStrat = SharedPtr<TStrategy>(new TStrategy(_strategy));			params.enabled  = _enabled;		}		ActiveResult<TArgs> result = _executeAsync(params);		return result;	}		void enable()		/// Enables the event	{		FastMutex::ScopedLock lock(_mutex);		_enabled = true;	}	void disable()		/// Disables the event. notify and notifyAsnyc will be ignored,		/// but adding/removing delegates is still allowed.	{		FastMutex::ScopedLock lock(_mutex);		_enabled = false;	}	bool isEnabled() const	{		FastMutex::ScopedLock lock(_mutex);		return _enabled;	}	void clear()		/// Removes all delegates.	{		FastMutex::ScopedLock lock(_mutex);		_strategy.clear();	}protected:	struct NotifyAsyncParams	{		SharedPtr<TStrategy> ptrStrat;		const void* pSender;		TArgs       args;		bool        enabled;				NotifyAsyncParams(const void* pSend, const TArgs& a):ptrStrat(), pSender(pSend), args(a), enabled(true)			/// default constructor reduces the need for TArgs to have an empty constructor, only copy constructor is needed.		{		}	};	ActiveMethod<TArgs, NotifyAsyncParams, AbstractEvent> _executeAsync;	TArgs executeAsyncImpl(const NotifyAsyncParams& par)	{		if (!par.enabled)		{			return par.args;		}		NotifyAsyncParams params = par;		TArgs retArgs(params.args);		params.ptrStrat->notify(params.pSender, retArgs);		return retArgs;	}	TStrategy _strategy; /// The strategy used to notify observers.	bool      _enabled;  /// Stores if an event is enabled. Notfies on disabled events have no effect	                     /// but it is possible to change the observers.	mutable FastMutex _mutex;private:	AbstractEvent(const AbstractEvent& other);	AbstractEvent& operator = (const AbstractEvent& other);};} // namespace Poco#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -