Event.hh
00001 /*
00002  * Copyright 2011 Nate Koenig & Andrew Howard
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  *
00016 */
00017 
00018 #ifndef EVENT_HH
00019 #define EVENT_HH
00020 
00021 #include <iostream>
00022 #include <vector>
00023 #include <boost/function.hpp>
00024 #include <boost/bind.hpp>
00025 #include <boost/shared_ptr.hpp>
00026 #include <boost/thread/mutex.hpp>
00027 
00028 #include "common/Time.hh"
00029 #include "common/CommonTypes.hh"
00030 #include "gazebo_config.h"
00031 
00032 namespace gazebo
00033 {
00036   namespace event
00037   {
00040 
00042     class Event
00043     { 
00044       public: virtual void Disconnect(ConnectionPtr c) = 0;
00045       public: virtual void Disconnect(int id) = 0;
00046     };
00047 
00049     class Connection
00050     {
00051       public: Connection() :event(NULL), id(-1), uniqueId(-1) {}
00052       public: Connection(Event *e, int i);
00053       public: ~Connection();
00054       public: int GetId() const;
00055       public: int GetUniqueId() const;
00056       private: Event *event;
00057       private: int id;
00058 
00059       private: static int counter;
00060       private: int uniqueId;
00061 
00062       private: common::Time creationTime;
00063       public: template<typename T> friend class EventT;
00064     };
00065     
00067     template< typename T>
00068     class EventT : public Event
00069     {
00070       public: virtual ~EventT();
00071     
00075       public: ConnectionPtr Connect(const boost::function<T> &subscriber);
00076 
00078       public: virtual void Disconnect(ConnectionPtr c);
00079       public: virtual void Disconnect(int id);
00080 
00081       public: void operator()()
00082               { this->Signal(); }
00083 
00084       public: void Signal()
00085               {
00086                 for (unsigned int i=0; i < connections.size(); i++)
00087                 {
00088                   (*this->connections[i])();
00089                 }
00090               }
00091 
00092       public: template< typename P >
00093               void operator()(const P &p)
00094               { this->Signal(p); }
00095 
00096       public: template< typename P1, typename P2 >
00097               void operator()(const P1 &p1, const P2 &p2)
00098               { this->Signal(p1, p2); }
00099 
00100       public: template< typename P1, typename P2, typename P3 >
00101               void operator()(const P1 &p1, const P2 &p2, const P3 &p3)
00102               { this->Signal(p1, p2, p3); }
00103 
00104       public: template< typename P1, typename P2, typename P3, typename P4 >
00105               void operator()(const P1 &p1, const P2 &p2, const P3 &p3, 
00106                               const P4 &p4)
00107               { this->Signal(p1, p2, p3, p4); }
00108 
00109       public: template< typename P1, typename P2, typename P3, typename P4, 
00110                         typename P5 >
00111               void operator()(const P1 &p1, const P2 &p2, const P3 &p3, 
00112                               const P4 &p4, const P5 &p5)
00113               { this->Signal(p1, p2, p3, p4, p5); }
00114 
00115       public: template< typename P1, typename P2, typename P3, typename P4, 
00116                         typename P5, typename P6 >
00117               void operator()(const P1 &p1, const P2 &p2, const P3 &p3, 
00118                               const P4 &p4, const P5 &p5, const P6 &p6)
00119               { this->Signal(p1, p2, p3, p4, p5, p6); }
00120 
00121       public: template< typename P1, typename P2, typename P3, typename P4, 
00122                         typename P5, typename P6, typename P7 >
00123               void operator()(const P1 &p1, const P2 &p2, const P3 &p3, 
00124                               const P4 &p4, const P5 &p5, const P6 &p6,
00125                               const P7 &p7)
00126               { this->Signal(p1, p2, p3, p4, p5, p6, p7); }
00127 
00128       public: template< typename P1, typename P2, typename P3, typename P4, 
00129                         typename P5, typename P6, typename P7, typename P8 >
00130               void operator()(const P1 &p1, const P2 &p2, const P3 &p3, 
00131                               const P4 &p4, const P5 &p5, const P6 &p6,
00132                               const P7 &p7, const P8 &p8)
00133               { this->Signal(p1, p2, p3, p4, p5, p6, p7, p8); }
00134 
00135       public: template< typename P1, typename P2, typename P3, typename P4, 
00136                         typename P5, typename P6, typename P7, typename P8,
00137                         typename P9 >
00138               void operator()(const P1 &p1, const P2 &p2, const P3 &p3, 
00139                               const P4 &p4, const P5 &p5, const P6 &p6,
00140                               const P7 &p7, const P8 &p8, const P9 &p9)
00141               { this->Signal(p1, p2, p3, p4, p5, p6, p7, p8, p9); }
00142 
00143       public: template< typename P1, typename P2, typename P3, typename P4, 
00144                         typename P5, typename P6, typename P7, typename P8,
00145                         typename P9, typename P10 >
00146               void operator()(const P1 &p1, const P2 &p2, const P3 &p3, 
00147                               const P4 &p4, const P5 &p5, const P6 &p6,
00148                               const P7 &p7, const P8 &p8, const P9 &p9,
00149                               const P10 &p10)
00150               { this->Signal(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); }
00151 
00152 
00153       public: template< typename P >
00154               void Signal(const P &p)
00155               {
00156                 for (unsigned int i=0; i < connections.size(); i++)
00157                 {
00158                   (*this->connections[i])(p);
00159                 }
00160               }
00161 
00162       public: template< typename P1, typename P2 >
00163               void Signal(const P1 &p1, const P2 &p2)
00164               {
00165                 for (unsigned int i=0; i < connections.size(); i++)
00166                 {
00167                   (*this->connections[i])(p1, p2);
00168                 }
00169               }
00170 
00171       public: template< typename P1, typename P2, typename P3 >
00172               void Signal(const P1 &p1, const P2 &p2, const P3 &p3)
00173               {
00174                 for (unsigned int i=0; i < connections.size(); i++)
00175                 {
00176                   (*this->connections[i])(p1, p2, p3);
00177                 }
00178               }
00179 
00180       public: template< typename P1, typename P2, typename P3, typename P4 >
00181               void Signal(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4)
00182               {
00183                 for (unsigned int i=0; i < connections.size(); i++)
00184                 {
00185                   (*this->connections[i])(p1, p2, p3, p4);
00186                 }
00187               }
00188 
00189       public: template< typename P1, typename P2, typename P3, typename P4,
00190                         typename P5 >
00191               void Signal(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4,
00192                           const P5 &p5)
00193               {
00194                 for (unsigned int i=0; i < connections.size(); i++)
00195                 {
00196                   (*this->connections[i])(p1, p2, p3, p4, p5);
00197                 }
00198               }
00199 
00200 
00201       public: template< typename P1, typename P2, typename P3, typename P4,
00202                         typename P5, typename P6 >
00203               void Signal(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4,
00204                           const P5 &p5, const P6 &p6)
00205               {
00206                 for (unsigned int i=0; i < connections.size(); i++)
00207                 {
00208                   (*this->connections[i])(p1, p2, p3, p4, p5, p6);
00209                 }
00210               }
00211 
00212       public: template< typename P1, typename P2, typename P3, typename P4,
00213                         typename P5, typename P6, typename P7 >
00214               void Signal(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4,
00215                           const P5 &p5, const P6 &p6, const P7 &p7)
00216               {
00217                 for (unsigned int i=0; i < connections.size(); i++)
00218                 {
00219                   (*this->connections[i])(p1, p2, p3, p4, p5, p6, p7);
00220                 }
00221               }
00222 
00223       public: template< typename P1, typename P2, typename P3, typename P4,
00224                         typename P5, typename P6, typename P7, typename P8 >
00225               void Signal(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4,
00226                           const P5 &p5, const P6 &p6, const P7 &p7, const P8 &p8)
00227               {
00228                 for (unsigned int i=0; i < connections.size(); i++)
00229                 {
00230                   (*this->connections[i])(p1, p2, p3, p4, p5, p6, p7, p8);
00231                 }
00232               }
00233 
00234       public: template< typename P1, typename P2, typename P3, typename P4,
00235                         typename P5, typename P6, typename P7, typename P8,
00236                         typename P9 >
00237               void Signal(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4,
00238                           const P5 &p5, const P6 &p6, const P7 &p7, const P8 &p8,
00239                           const P9 &p9)
00240               {
00241                 for (unsigned int i=0; i < connections.size(); i++)
00242                 {
00243                   (*this->connections[i])(p1, p2, p3, p4, p5, p6, p7, p8, p9);
00244                 }
00245               }
00246 
00247       public: template< typename P1, typename P2, typename P3, typename P4,
00248                         typename P5, typename P6, typename P7, typename P8,
00249                         typename P9, typename P10 >
00250               void Signal(const P1 &p1, const P2 &p2, const P3 &p3,
00251                   const P4 &p4, const P5 &p5, const P6 &p6, const P7 &p7,
00252                   const P8 &p8, const P9 &p9, const P10 &p10)
00253               {
00254                 for (unsigned int i=0; i < connections.size(); i++)
00255                 {
00256                   (*this->connections[i])(p1, p2, p3, p4, p5,
00257                       p6, p7, p8, p9, p10);
00258                 }
00259               }
00260 
00261       private: std::vector<boost::function<T> *> connections;
00262       private: std::vector<int> connectionIds;
00263       private: boost::mutex lock;
00264     };
00265 
00266     template<typename T>
00267     EventT<T>::~EventT()
00268     {
00269       for (unsigned int i = 0; i < this->connections.size(); i++)
00270         delete this->connections[i];
00271       this->connections.clear();
00272       this->connectionIds.clear();
00273     }
00274 
00275     template<typename T>
00276     ConnectionPtr EventT<T>::Connect(const boost::function<T> &_subscriber)
00277     {
00278       //this->lock.lock();
00279       int index = this->connections.size();
00280       this->connections.push_back(new boost::function<T>(_subscriber));
00281       this->connectionIds.push_back(index);
00282       //this->lock.unlock();
00283       return ConnectionPtr(new Connection(this, index));
00284     }
00285     
00286     template<typename T>
00287     void EventT<T>::Disconnect(ConnectionPtr c)
00288     {
00289       this->Disconnect(c->GetId());
00290       c->event = NULL;
00291       c->id = -1;
00292     }
00293 
00294     template<typename T>
00295     void EventT<T>::Disconnect(int _id)
00296     {
00297       //this->lock.lock();
00298       // search for index of the connection based on id
00299       for(unsigned int i=0; i < this->connectionIds.size(); i++)
00300       {
00301         if (_id == this->connectionIds[i])
00302         {
00303           this->connectionIds.erase(this->connectionIds.begin()+i);
00304           this->connections.erase(this->connections.begin()+i);
00305           break;
00306         }
00307       }
00308       //this->lock.unlock();
00309     }
00311   }
00312 }
00313 #endif