1 // -*- mode: c++ -*- 2 // 3 // This file is part of libyacurs. 4 // Copyright (C) 2013 Rafael Ostertag 5 // 6 // This program is free software: you can redistribute it and/or 7 // modify it under the terms of the GNU General Public License as 8 // published by the Free Software Foundation, either version 3 of the 9 // License, or (at your option) any later version. 10 // 11 // This program is distributed in the hope that it will be useful, but 12 // WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 // General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program. If not, see 18 // <http://www.gnu.org/licenses/>. 19 // 20 // 21 // $Id$ 22 23 #ifndef EVENTCONNECTOR_H 24 #define EVENTCONNECTOR_H 1 25 26 // Can't use #ifdef HAVE_STDINT_H since that would require pulling in 27 // config.h or libyacurscfg.h which might cause undesired side 28 // effects. 29 #include <stdint.h> 30 31 #include <cassert> 32 #include <cstdlib> 33 #include <functional> 34 #include <string> 35 #include <typeinfo> 36 37 #include "event.h" 38 #include "yacurstypes.h" 39 40 namespace YACURS { 41 /** 42 * @ingroup Event 43 * 44 * An Event Connector connects an event (@c EventType) to an 45 * handler (function, or member function). 46 * 47 * When connecting an event to a member function, it is expected 48 * that exactly one member function per object for a particular 49 * event is called. Connecting a particular event to several 50 * member functions of the same object result in only the last 51 * connection made taking effect (i.e. the current connection 52 * replaces any previous connections). 53 * 54 * This uniqueness is not enforced by the event connector itself, 55 * but an event connector has to provide an equality operator 56 * allowing to compare event connector for equality. 57 * 58 * See operator==() for more information about equality. 59 * 60 * @see Event 61 * @see EventQueue 62 */ 63 class EventConnectorBase { 64 private: 65 /// The event type the handler is connected to. 66 EventType evt; 67 68 /** 69 * indication whether (@c true) or not (@c false) the 70 * event handler is suspended. Suspended event handler 71 * won't be called. 72 */ 73 bool _suspended; 74 75 public: 76 /** 77 * Constructor. 78 * 79 * @param e the event type 80 * @param s whether or not the handler is suspended. 81 */ 82 EventConnectorBase(const EventType e, bool s = false); 83 84 virtual ~EventConnectorBase(); 85 86 /** 87 * The value returned by id() together with the event type has 88 * to uniquely identifiy the event connector 89 * 90 * @return value of type @c uintptr_t uniquely identifying the 91 * handler. 92 */ 93 virtual uintptr_t id() const = 0; 94 95 /** 96 * Tests two event connector for equality. It tests for 97 * equality by comparing the event type of both connectors and 98 * equality of the value returned by id(). 99 * 100 * When comparing member function event connectors, the 101 * following must hold: 102 * 103 * <pre> 104 * class base { 105 * public: 106 * virtual int handler(Event&); 107 * }; 108 * class derived : public base { 109 * public: 110 * int handler(Event&); 111 * }; 112 * 113 * derived d(); 114 * base* bptr=\&d; 115 * 116 * EventConnectorBase(&d,&derived::handler) == EventConnectorBase(bptr, 117 * &base::handler); 118 * </pre> 119 * 120 * @return @c true if evt and id() are equal, @c false 121 * otherwise. 122 */ 123 bool operator==(const EventConnectorBase& ec) const; 124 125 bool operator!=(const EventConnectorBase& ec) const; 126 127 /** 128 * Compare the event type. 129 * 130 * Compares only the event type of the given Event. 131 * 132 * @param eb reference to an Event object. 133 * 134 * @return @c true if the value of evt and eb.type() are 135 * equal, @c false otherwise. 136 */ 137 bool operator==(const Event& eb) const; 138 139 bool operator!=(const Event& eb) const; 140 141 /** 142 * Compare the event type. 143 * 144 * Compares only the event type. 145 * 146 * @param et event type 147 * 148 * @return @c true if _evt and @c et are equal, @c false 149 * otherwise. 150 */ 151 bool operator==(const EventType et) const; 152 153 bool operator!=(const EventType et) const; 154 155 /** 156 * Returns the event the handler is connected to. 157 * 158 * @return the EventType 159 */ 160 const EventType type() const; 161 162 /** 163 * Set the suspended state to the given value. 164 * 165 * @param s boolean value indicating whether (@c true) or not 166 * (@c false) the event handler is called upon the occurrence 167 * of the event. 168 */ 169 void suspended(bool s); 170 171 /** 172 * Query the suspended state. 173 * 174 * @return @c true if event connector is suspended, @c false 175 * otherwise. 176 */ 177 bool suspended() const; 178 179 /** 180 * Call the handler and pass the event 181 * 182 * @param e event object that caused the call. 183 * 184 * @return the value returned by the handler. 185 */ 186 virtual void call(Event& e) const = 0; 187 188 /** 189 * The EventQueue creates a local copy of the EventConnector 190 * object. This method has to return a copy of the object. The 191 * caller is responsible for freeing the memory. 192 * 193 * @return pointer to a derived EventConnectorBase object. The 194 * caller is responsible for freeing the memory. 195 */ 196 virtual EventConnectorBase* clone() const = 0; 197 198 operator const EventType() const; 199 }; 200 201 /** 202 * @ingroup Event 203 * 204 * Connect a member function to an event. 205 * 206 * The signature of the handler has to be 207 * 208 * <code>Class::handler(Event&)</code> 209 * 210 */ 211 template <class T /* Type of object called */> 212 class EventConnectorMethod1 : public EventConnectorBase { 213 public: 214 typedef void (T::*_mem_fun_t)(Event&); 215 typedef T* _obj_ptr_t; 216 217 private: 218 /// Holds the pointer to the member function of a class of 219 /// type T 220 _mem_fun_t _func; 221 /// Holds the pointer to the object of type T 222 _obj_ptr_t _obj_ptr; 223 224 public: 225 /** 226 * Constructs an EventConnectorMethod1 object. The handler is 227 * connected to a particular event has to have the following 228 * signature: 229 * 230 * <code>Class::handler(Event&)</code> 231 * 232 * @param e the event type to connect 233 * 234 * @param obj_ptr pointer to the object whos member function 235 * will be called. 236 * 237 * @param func the address of the member function to be 238 * called. 239 * 240 * For instance: 241 * 242 * <pre> 243 * class A { 244 * public: 245 * int event_handler(Event& e); 246 * }; 247 * 248 * A a; 249 * EventConnector1<A> c(EVT_RESIZE, &a, &A::event_handler); 250 * </pre> 251 */ EventConnectorMethod1(const EventType e,_obj_ptr_t obj_ptr,_mem_fun_t func)252 EventConnectorMethod1(const EventType e, _obj_ptr_t obj_ptr, 253 _mem_fun_t func) 254 : EventConnectorBase(e), _func(func), _obj_ptr(obj_ptr) { 255 assert(_func != 0); 256 assert(_obj_ptr != 0); 257 } 258 259 /** 260 * The id returned is the pointer to the object converted to 261 * an uintptr_t. 262 * 263 * @return the id used for testing for equality with other 264 * event connectors. 265 */ id()266 uintptr_t id() const { return (uintptr_t)_obj_ptr; } 267 268 /** 269 * The EventQueue calls this function and passes a reference 270 * to the event to it. 271 * 272 * @param e the event that caused the call. 273 * 274 * @return the value returned by the member function called, 275 * or -1 if the connector is suspended 276 */ call(Event & e)277 void call(Event& e) const { 278 assert(_obj_ptr != 0); 279 assert(_func != 0); 280 281 if (suspended()) return; 282 (_obj_ptr->*_func)(e); 283 } 284 285 /** 286 * Creates a copy of this object. The caller is responsible 287 * for freeing the memory. 288 * 289 * @return pointer to the newly created object. 290 */ clone()291 EventConnectorBase* clone() const { 292 return new EventConnectorMethod1<T>(*this); 293 } 294 }; 295 296 /** 297 * @ingroup Event 298 * 299 * Connect a function to an event. 300 * 301 * The signature of the function connected has to be 302 * 303 * <code>int fct(Event&)</code> 304 * 305 * or 306 * 307 * <code>static int Class::handler(Event&)</code> 308 */ 309 class EventConnectorFunction1 : public EventConnectorBase { 310 private: 311 /// Holds the pointer to the function to be called. 312 fptr_t _func; 313 314 public: 315 /** 316 * Create an event connector to a function. 317 * 318 * @param e the type of the event 319 * 320 * @param func the pointer to the function. 321 */ 322 EventConnectorFunction1(const EventType e, fptr_t func); 323 324 /** 325 * The id returned is the pointer to the function converted to 326 * an uintptr_t. 327 * 328 * @return the id used for testing for equality with other 329 * event connectors. 330 */ 331 uintptr_t id() const; 332 333 /** 334 * The EventQueue calls this function and passes a reference 335 * to the event to it. 336 * 337 * @param e the event that caused the call. 338 * 339 * @return the value returned by the function called, 340 * or -1 if the connector is suspended 341 */ 342 void call(Event& e) const; 343 344 /** 345 * Creates a copy of this object. The caller is responsible 346 * for freeing the memory. 347 * 348 * @return pointer to the newly created object. 349 */ 350 EventConnectorBase* clone() const; 351 }; 352 } // namespace YACURS 353 354 #endif // EVENTCONNECTOR_H 355