rc_event_forwarder.h

Go to the documentation of this file.
00001 // vim:set et sts=4 ts=4 tw=75 sw=4 ai ci cin cino=g0,t0:
00002 /*
00003  * Copyright (C) 2007, Technical Computer Science Group,
00004  *                     University of Bonn
00005  *
00006  * This file is part of the ReChannel library.
00007  *
00008  * The ReChannel library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License as
00010  * published by the Free Software Foundation; either version 2 of the
00011  * License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be
00014  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this library; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
00021  * Boston, MA 02110-1301, USA.
00022  *
00023  * Authors: Andreas Raabe and Armin Felke. Implementation by Armin Felke.
00024  *          {raabe, felke}@cs.uni-bonn.de
00025  */
00037 #ifndef RC_EVENT_FORWARDER_H_
00038 #define RC_EVENT_FORWARDER_H_
00039 
00040 #include "ReChannel/core/rc_common_header.h"
00041 #include "ReChannel/core/rc_process.h"
00042 #include "ReChannel/core/rc_event_filter.h"
00043 
00044 namespace ReChannel {
00045 
00049 class rc_event_forwarder_base
00050 {
00051 public:
00055     virtual bool add_target(
00056         sc_event& target_event, rc_event_filter* filter=NULL) = 0;
00057 
00061     virtual bool add_target(
00062         sc_interface& target_if, rc_event_filter* filter=NULL) = 0;
00063 
00067     virtual int get_target_count() const = 0;
00068 
00072     virtual void clear_targets() = 0;
00073 
00078     virtual void trigger_event() = 0;
00079 
00083     virtual ~rc_event_forwarder_base() {}
00084 };
00085 
00089 template<class IF>
00090 class rc_event_forwarder
00091     : virtual public rc_event_forwarder_base,
00092       virtual protected rc_event_trigger
00093 {
00094     RC_STATIC_ASSERT_VALID_INTERFACE(IF);
00095 
00096 private:
00097     struct target {
00098         target()
00099             : e(NULL), filter(NULL)
00100         { }
00101         target(sc_event* e_, rc_event_filter* filter_)
00102             : e(e_), filter(filter_)
00103         { }
00104         sc_event*        e;
00105         rc_event_filter* filter;
00106     };
00107 
00108 protected:
00116     typedef boost::function<const sc_event& (IF*)> event_getter_type;
00117 
00118     typedef std::vector<target> target_vector;
00119 
00120 public:
00124     rc_event_forwarder(event_getter_type event_getter_method);
00125 
00129     virtual bool add_target(
00130         sc_event& target_event, rc_event_filter* filter=NULL);
00131 
00135     virtual bool add_target(
00136         sc_interface& target_if, rc_event_filter* filter=NULL);
00137 
00141     virtual bool add_target(
00142         IF& target_if, rc_event_filter* filter=NULL);
00143 
00147     virtual int get_target_count() const;
00148 
00152     virtual void clear_targets();
00153 
00158     virtual void trigger_event();
00159 
00163     virtual ~rc_event_forwarder();
00164 
00165 protected:
00166 
00175     virtual void rc_trigger_event(const sc_event& start_event);
00176 
00177 protected:
00181     const event_getter_type m_get_event;
00185     target               m_target1;
00189     target               m_target2;
00193     target_vector        m_targets;
00194 };
00195 
00199 class rc_event_forwarder_host
00200 {
00201 public:
00202     typedef std::vector<std::string> string_vector;
00203 
00204 public:
00208     virtual void add_event_forwarder(
00209         rc_event_forwarder_base& forwarder, const sc_event& e,
00210         const std::string& event_name=NULL) = 0;
00211 
00215     virtual void add_event_forwarder_target(
00216         sc_interface& if_, rc_event_filter* filter=NULL) = 0;
00217 
00221     virtual bool add_event_forwarder_target(
00222         const std::string& event_name, sc_interface& if_,
00223         rc_event_filter* filter=NULL) = 0;
00224 
00228     virtual bool get_event_forwarder_target_count() const = 0;
00229 
00233     virtual void clear_event_forwarder_targets() = 0;
00234 
00238     virtual void clear_event_forwarder_targets(
00239         const std::string& event_name) = 0;
00240 
00244     virtual string_vector get_event_forwarder_names() const = 0;
00245 
00249     virtual void notify_event(const std::string& event_name) = 0;
00250 
00251 protected:
00252 
00256     virtual ~rc_event_forwarder_host() {}
00257 };
00258 
00259 /* template code */
00260 
00261 template<class IF>
00262 rc_event_forwarder<IF>::rc_event_forwarder(
00263     event_getter_type event_getter_method)
00264     : m_get_event(event_getter_method)
00265 {
00266     assert( !event_getter_method.empty() );
00267 }
00268 
00269 template<class IF>
00270 rc_event_forwarder<IF>::~rc_event_forwarder()
00271 { }
00272 
00273 template<class IF>
00274 bool rc_event_forwarder<IF>::add_target(
00275     sc_event& target_event, rc_event_filter* filter)
00276 {
00277     if (m_target1.e == NULL || m_target1.e == &target_event) {
00278         m_target1.e = &target_event;
00279         m_target1.filter = filter;
00280     } else if (m_target2.e == NULL || m_target2.e == &target_event) {
00281         m_target2.e = &target_event;
00282         m_target2.filter = filter;
00283     } else {
00284         for (typename target_vector::iterator it =
00285                 m_targets.begin();
00286             it != m_targets.end();
00287             ++it)
00288         {
00289             target& target_ = (*it);
00290             // target already added?
00291             if (target_.e == &target_event) {
00292                 // update the filter (since it may have changed)
00293                 target_.filter = filter;
00294                 if (filter != NULL) {
00295                     // set *this as the event trigger of target_event
00296                     filter->rc_set_event_trigger(target_event, *this);
00297                 }
00298                 return true;
00299             }
00300         }
00301         // target not found. add it to the vector
00302         m_targets.push_back(target(&target_event, filter));
00303     }
00304     if (filter != NULL) {
00305         // set *this as the event trigger of target_event
00306         filter->rc_set_event_trigger(target_event, *this);
00307     }
00308     return true;
00309 }
00310 
00311 template<class IF>
00312 bool rc_event_forwarder<IF>::add_target(
00313     sc_interface& target_if, rc_event_filter* filter)
00314 {
00315     IF* target_if_ = dynamic_cast<IF*>(&target_if);
00316     if (target_if_ != NULL) {
00317         return this->add_target(*target_if_, filter);
00318     } else {
00319         return false;
00320     }
00321 }
00322 
00323 template<class IF>
00324 bool rc_event_forwarder<IF>::add_target(
00325     IF& target_if, rc_event_filter* filter)
00326 {
00327     // unfortunately, retrieving the event necessiates a const_cast
00328     sc_event& event_ = const_cast<sc_event&>(m_get_event(&target_if));
00329     return this->add_target(event_, filter);
00330 }
00331 
00332 template<class IF>
00333 int rc_event_forwarder<IF>::get_target_count() const
00334 {
00335     return (m_target1.e != NULL ? 1 : 0)
00336             + (m_target2.e != NULL ? 1 + m_targets.size() : 0);
00337 }
00338 
00339 template<class IF>
00340 void rc_event_forwarder<IF>::clear_targets()
00341 {
00342     // clear the first target
00343     if (m_target1.e != NULL) {
00344         if (m_target1.filter != NULL) {
00345             m_target1.filter->rc_clear_event_trigger(*(m_target1.e));
00346         }
00347         m_target1.e = NULL;
00348         m_target1.filter = NULL;
00349     }
00350     // clear the second target
00351     if (m_target2.e != NULL) {
00352         if (m_target2.filter != NULL) {
00353             m_target2.filter->rc_clear_event_trigger(*(m_target2.e));
00354         }
00355         m_target2.e = NULL;
00356         m_target2.filter = NULL;
00357     }
00358     // clear the target chain
00359     for (typename target_vector::iterator it
00360         = m_targets.begin();
00361         it != m_targets.end();
00362         ++it)
00363     {
00364         target target_ = (*it);
00365         if (target_.e != NULL && target_.filter != NULL) {
00366             target_.filter->rc_clear_event_trigger(*(target_.e));
00367         }
00368     }
00369     m_targets.clear();
00370 }
00371 
00372 template<class IF>
00373 void rc_event_forwarder<IF>::trigger_event()
00374 {
00375     if (m_target1.e != NULL)
00376     {
00377         if (m_target1.filter != NULL
00378         && !m_target1.filter->rc_on_event(*(m_target1.e)))
00379         {
00380             return;
00381         }
00382         rc_notify(*(m_target1.e));
00383 
00384         if (m_target2.e != NULL)
00385         {
00386             if (m_target2.filter != NULL
00387             && !m_target2.filter->rc_on_event(*(m_target2.e)))
00388             {
00389                 return;
00390             }
00391             rc_notify(*(m_target2.e));
00392 
00393             if (!m_targets.empty())
00394             {
00395                 for (typename target_vector::iterator it
00396                         = m_targets.begin();
00397                     it != m_targets.end();
00398                     ++it)
00399                 {
00400                     target target_ = (*it);
00401                     assert(target_.e != NULL);
00402 
00403                     if (target_.filter != NULL
00404                     && !target_.filter->rc_on_event(*(target_.e))) 
00405                     {
00406                         return;
00407                     }
00408                     rc_notify(*(target_.e));
00409                 }
00410             }
00411         }
00412     }
00413 }
00414 
00415 template<class IF>
00416 void rc_event_forwarder<IF>::rc_trigger_event(const sc_event& start_event)
00417 {
00418     bool is_started = false;
00419     if (m_target1.e != NULL)
00420     {
00421         bool is_start_event = (m_target1.e == &start_event);
00422         if (is_start_event) {
00423             rc_notify(*(m_target1.e));
00424             is_started = true;
00425         }
00426         if (m_target2.e != NULL)
00427         {
00428             is_start_event = (m_target2.e == &start_event);
00429             if (is_start_event) {
00430                 is_started = true;
00431             }
00432             if (is_started) {
00433                 if (m_target2.filter != NULL
00434                 && !is_start_event
00435                 && m_target2.filter->rc_on_event(*(m_target2.e)))
00436                 {
00437                     return;
00438                 }
00439                 rc_notify(*(m_target2.e));
00440             }
00441             if (!m_targets.empty())
00442             {
00443                 for (typename target_vector::iterator it =
00444                         m_targets.begin();
00445                     it != m_targets.end();
00446                     ++it)
00447                 {
00448                     target target_ = (*it);
00449                     assert(target_.e != NULL);
00450 
00451                     is_start_event = (target_.e == &start_event);
00452                     if (is_start_event) {
00453                         is_started = true;
00454                     }
00455                     if (is_started) {
00456                         if (target_.filter != NULL
00457                         && !is_start_event
00458                         && target_.filter->rc_on_event(*(target_.e)))
00459                         {
00460                             return;
00461                         }
00462                         rc_notify(*(target_.e));
00463                     }
00464                 }
00465             }
00466         }
00467     }
00468 }
00469 
00470 } // namespace ReChannel
00471 
00472 #endif // RC_EVENT_FORWARDER_H_
00473 
00474 //
00475 // $Id: rc_event_forwarder.h,v 1.15 2007/12/20 20:32:36 felke Exp $
00476 // $Source: /var/cvs/projekte/ReChannel-v2/src/ReChannel/communication/rc_event_forwarder.h,v $
00477 //
00478 

Generated on Tue Jan 1 23:13:32 2008 for ReChannel by  doxygen 1.5.3