Stefan Scholz / ETL
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers observer.h Source File

observer.h

Go to the documentation of this file.
00001 ///\file
00002 
00003 /******************************************************************************
00004 The MIT License(MIT)
00005 
00006 Embedded Template Library.
00007 https://github.com/ETLCPP/etl
00008 http://www.etlcpp.com
00009 
00010 Copyright(c) 2014 jwellbelove
00011 
00012 Permission is hereby granted, free of charge, to any person obtaining a copy
00013 of this software and associated documentation files(the "Software"), to deal
00014 in the Software without restriction, including without limitation the rights
00015 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
00016 copies of the Software, and to permit persons to whom the Software is
00017 furnished to do so, subject to the following conditions :
00018 
00019 The above copyright notice and this permission notice shall be included in all
00020 copies or substantial portions of the Software.
00021 
00022 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00023 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00024 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
00025 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00026 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00027 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00028 SOFTWARE.
00029 ******************************************************************************/
00030 
00031 #ifndef __ETL_OBSERVER__
00032 #define __ETL_OBSERVER__
00033 
00034 //*****************************************************************************
00035 ///\defgroup observer observer
00036 /// A templated implementation to simplify the creation of the observer pattern
00037 /// and attempts to eliminate certain runtime errors by turning them into compile errors.
00038 /// The pattern consists of two template classes.
00039 /// \li <b>Observer</b><br>
00040 /// This template may take up to eight notification types.
00041 /// Each notification type will generate a pure virtual 'notification'
00042 /// function. The class that inherits from this *must* define all
00043 /// of the 'notification' function overloads otherwise the object will
00044 /// remain 'abstract' and will not compile.
00045 /// This ensures that no overload can be forgotten.<br>
00046 ///
00047 /// \li <b>observable</b><br>
00048 /// The class derived from this will be observed by the above class.
00049 /// It keeps a list of registered observers and will notify all
00050 /// of them with the notifications.
00051 ///\ingroup patterns
00052 //*****************************************************************************
00053 
00054 #include <algorithm>
00055 
00056 #include "platform.h "
00057 #include "vector.h "
00058 #include "exception.h "
00059 #include "error_handler.h "
00060 
00061 #undef ETL_FILE
00062 #define ETL_FILE "18"
00063 
00064 namespace etl
00065 {
00066   //***************************************************************************
00067   ///\ingroup observer
00068   /// The base class for observer exceptions.
00069   //***************************************************************************
00070   class observer_exception : public exception
00071   {
00072   public:
00073 
00074     observer_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
00075       : exception(reason_, file_name_, line_number_)
00076     {
00077     }
00078   };
00079 
00080   //***************************************************************************
00081   ///\ingroup observer
00082   /// The exception thrown when the observer list is full.
00083   //***************************************************************************
00084   class observer_list_full : public observer_exception
00085   {
00086   public:
00087 
00088     observer_list_full(string_type file_name_, numeric_type line_number_)
00089       : observer_exception(ETL_ERROR_TEXT("observer:full", ETL_FILE"A"), file_name_, line_number_)
00090     {
00091     }
00092   };
00093 
00094   //*********************************************************************
00095   /// The object that is being observed.
00096   ///\tparam TObserver     The observer type.
00097   ///\tparam MAX_OBSERVERS The maximum number of observers that can be accomodated.
00098   ///\ingroup observer
00099   //*********************************************************************
00100   template <typename TObserver, const size_t MAX_OBSERVERS>
00101   class observable
00102   {
00103   public:
00104 
00105     typedef size_t size_type;
00106 
00107     typedef etl::vector<TObserver*, MAX_OBSERVERS>  Observer_List ;
00108 
00109     //*****************************************************************
00110     /// Add an observer to the list.
00111     /// If asserts or exceptions are enabled then an etl::observable_observer_list_full
00112     /// is emitted if the observer list is already full.
00113     ///\param observer A reference to the observer.
00114     //*****************************************************************
00115     void add_observer(TObserver& observer)
00116     {
00117           // See if we already have it in our list.
00118       typename Observer_List::const_iterator i_observer = std::find(observer_list.begin(),
00119                                                                     observer_list.end(),
00120                                                                     &observer);
00121 
00122           // Not there?
00123       if (i_observer == observer_list.end())
00124       {
00125         // Is there enough room?
00126         ETL_ASSERT(!observer_list.full(), ETL_ERROR(etl::observer_list_full));
00127 
00128         // Add it.
00129         observer_list.push_back(&observer);
00130       }
00131     }
00132 
00133     //*****************************************************************
00134     /// Remove a particular observer from the list.
00135     ///\param observer A reference to the observer.
00136     //*****************************************************************
00137     void remove_observer(TObserver& observer)
00138     {
00139       // See if we have it in our list.
00140       typename Observer_List::iterator i_observer = std::find(observer_list.begin(),
00141                                                               observer_list.end(),
00142                                                               &observer);
00143 
00144       // Found it?
00145       if (i_observer != observer_list.end())
00146       {
00147         // Erase it.
00148         observer_list.erase(i_observer);
00149       }
00150     }
00151 
00152     //*****************************************************************
00153     /// Clear all observers from the list.
00154     //*****************************************************************
00155     void clear_observers()
00156     {
00157       observer_list.clear();
00158     }
00159 
00160     //*****************************************************************
00161     /// Returns the number of observers.
00162     //*****************************************************************
00163     size_type number_of_observers() const
00164     {
00165       return observer_list.size();
00166     }
00167 
00168     //*****************************************************************
00169     /// Notify all of the observers, sending them the notification.
00170     ///\tparam TNotification the notification type.
00171     ///\param n The notification.
00172     //*****************************************************************
00173     template <typename TNotification>
00174     void notify_observers(TNotification n)
00175     {
00176       for (size_t i = 0; i < observer_list.size(); ++i)
00177       {
00178         observer_list[i]->notification(n);
00179       }
00180     }
00181 
00182   private:
00183 
00184     /// The list of observers.
00185     Observer_List observer_list;
00186   };
00187 
00188   //*********************************************************************
00189   /// The observer interface for eight notification types.
00190   ///\ingroup observer
00191   //*********************************************************************
00192   template <typename T1,
00193             typename T2  = void,
00194             typename T3  = void,
00195             typename T4  = void,
00196             typename T5  = void,
00197             typename T6  = void,
00198             typename T7  = void,
00199             typename T8  = void>
00200   class observer
00201   {
00202   public:
00203     virtual ~observer() {}
00204     virtual void notification(T1) = 0;
00205     virtual void notification(T2) = 0;
00206     virtual void notification(T3) = 0;
00207     virtual void notification(T4) = 0;
00208     virtual void notification(T5) = 0;
00209     virtual void notification(T6) = 0;
00210     virtual void notification(T7) = 0;
00211     virtual void notification(T8) = 0;
00212   };
00213 
00214   //*********************************************************************
00215   /// The observer interface for seven notification types.
00216   ///\ingroup observer
00217   //*********************************************************************
00218   template <typename T1,
00219             typename T2,
00220             typename T3,
00221             typename T4,
00222             typename T5,
00223             typename T6,
00224             typename T7>
00225   class observer<T1, T2, T3, T4, T5, T6, T7>
00226   {
00227   public:
00228 
00229     virtual ~observer() {}
00230     virtual void notification(T1) = 0;
00231     virtual void notification(T2) = 0;
00232     virtual void notification(T3) = 0;
00233     virtual void notification(T4) = 0;
00234     virtual void notification(T5) = 0;
00235     virtual void notification(T6) = 0;
00236     virtual void notification(T7) = 0;
00237   };
00238 
00239   //*********************************************************************
00240   /// The observer interface for six notification types.
00241   ///\ingroup observer
00242   //*********************************************************************
00243   template <typename T1,
00244             typename T2,
00245             typename T3,
00246             typename T4,
00247             typename T5,
00248             typename T6>
00249   class observer<T1, T2, T3, T4, T5, T6>
00250   {
00251   public:
00252 
00253     virtual ~observer() {}
00254     virtual void notification(T1) = 0;
00255     virtual void notification(T2) = 0;
00256     virtual void notification(T3) = 0;
00257     virtual void notification(T4) = 0;
00258     virtual void notification(T5) = 0;
00259     virtual void notification(T6) = 0;
00260   };
00261 
00262   //*********************************************************************
00263   /// The observer interface for five notification types.
00264   ///\ingroup observer
00265   //*********************************************************************
00266   template <typename T1,
00267             typename T2,
00268             typename T3,
00269             typename T4,
00270             typename T5>
00271   class observer<T1, T2, T3, T4, T5>
00272   {
00273   public:
00274 
00275     virtual ~observer() {}
00276     virtual void notification(T1) = 0;
00277     virtual void notification(T2) = 0;
00278     virtual void notification(T3) = 0;
00279     virtual void notification(T4) = 0;
00280     virtual void notification(T5) = 0;
00281   };
00282 
00283   //*********************************************************************
00284   /// The observer interface for four notification types.
00285   ///\ingroup observer
00286   //*********************************************************************
00287   template <typename T1,
00288             typename T2,
00289             typename T3,
00290             typename T4>
00291   class observer<T1, T2, T3, T4>
00292   {
00293   public:
00294 
00295     virtual ~observer() {}
00296     virtual void notification(T1) = 0;
00297     virtual void notification(T2) = 0;
00298     virtual void notification(T3) = 0;
00299     virtual void notification(T4) = 0;
00300   };
00301 
00302   //*********************************************************************
00303   /// The observer interface for three notification types.
00304   ///\ingroup observer
00305   //*********************************************************************
00306   template <typename T1,
00307             typename T2,
00308             typename T3>
00309   class observer<T1, T2, T3>
00310   {
00311   public:
00312 
00313     virtual ~observer() {}
00314     virtual void notification(T1) = 0;
00315     virtual void notification(T2) = 0;
00316     virtual void notification(T3) = 0;
00317   };
00318 
00319   //*********************************************************************
00320   /// The observer interface for two notification types.
00321   ///\ingroup observer
00322   //*********************************************************************
00323   template <typename T1,
00324             typename T2>
00325   class observer<T1, T2>
00326   {
00327   public:
00328 
00329     virtual ~observer() {}
00330     virtual void notification(T1) = 0;
00331     virtual void notification(T2) = 0;
00332   };
00333 
00334   //*********************************************************************
00335   /// The observer interface for one notification type.
00336   ///\ingroup observer
00337   //*********************************************************************
00338   template <typename T1>
00339   class observer<T1>
00340   {
00341   public:
00342 
00343     virtual ~observer() {}
00344     virtual void notification(T1) = 0;
00345   };
00346 }
00347 
00348 #undef ETL_FILE
00349 
00350 #endif
00351