rc_driver_object.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  */
00066 #ifndef RC_DRIVER_OBJECT_H_
00067 #define RC_DRIVER_OBJECT_H_
00068 
00069 #include <vector>
00070 #include <systemc.h>
00071 
00072 #include <boost/bind.hpp>
00073 #include <boost/function.hpp>
00074 #include <boost/utility/addressof.hpp>
00075 #include <boost/type_traits/add_const.hpp> 
00076 #include <boost/type_traits/remove_reference.hpp>
00077 #include <boost/type_traits/is_reference.hpp>
00078 #include <boost/type_traits/is_void.hpp>
00079 
00080 #include "ReChannel/util/rc_throwable.h"
00081 
00082 namespace ReChannel {
00083 
00084 namespace internals {
00085 namespace driver_object {
00086 
00090 template<class R, bool IS_REF = boost::is_reference<R>::value>
00091 class retval;
00092 
00096 template<class R>
00097 class copy_retval;
00098 
00102 class nb_driver_access_call;
00103 
00107 template<class R>
00108 class driver_access_call;
00109 
00110 } // namespace driver_object
00111 } // namespace internals
00112 
00125 class rc_driver_object_base
00126 {
00130     friend class internals::driver_object::nb_driver_access_call;
00134     template<class R>
00135     friend class internals::driver_object::driver_access_call;
00136 
00137 protected:
00141     struct write_call;
00147     typedef boost::function<void (void)>      call_type;
00151     typedef std::vector<write_call>           write_call_vector;
00155     typedef std::vector<write_call>::iterator write_call_iterator;
00156 
00157 protected:
00159     rc_driver_object_base();
00160 
00162     virtual ~rc_driver_object_base();
00163 
00164 protected:
00168     virtual void writer_method_proc();
00169 
00173     virtual void writer_thread_proc();
00174 
00187     static void safe_event_notify(sc_event& e);
00188 
00189 private:
00191     static void s_writer_method_proc();
00193     static sc_process_handle s_create_method_process();
00194 
00195 protected:
00199     sc_process_handle  m_hproc;
00203     write_call_vector* m_write_call_vector; // write call queue
00210     sc_event*          m_pending_write_event;
00217     bool               m_pending_write_event_notified_flag;
00224     bool*              m_pending_write_event_notified;
00225 
00226 protected:
00227 
00232     static sc_process_handle s_hproc;
00237     static write_call_vector s_write_call_vector; // write call queue
00242     static sc_event          s_pending_write_event;
00247     static bool              s_pending_write_event_notified_flag;
00248 
00249 protected:
00256     struct write_call // is used to queue write calls
00257     {
00258         inline write_call(call_type call_);
00259         inline write_call(
00260             call_type call_, sc_event* write_done_event);
00261         inline write_call(
00262             call_type call_, sc_event* write_done_event,
00263             rc_throwable** throw_dest);
00264 
00268         call_type m_call;
00277         sc_event* m_write_done_event; // only exists until being notified!
00287         rc_throwable** m_throw_dest; // destination to forward a throw
00288     };
00289 
00290 private:
00291     // disabled
00293     rc_driver_object_base(const rc_driver_object_base& dobj);
00295     rc_driver_object_base& operator=(const rc_driver_object_base& dobj);
00296 };
00297 
00298 template<class IF, bool IS_THREAD> class rc_driver_object_b;
00299 
00325 template<class IF>
00326 class rc_driver_object_b<IF, false>
00327     : public rc_driver_object_base
00328 {
00329 protected:
00330     // typedefs
00331     class driver_access;
00332     typedef rc_driver_object_b<IF, false>  this_type;
00333     typedef rc_driver_object_base          base_type;
00334 
00335     typedef base_type::write_call          write_call;
00336     typedef base_type::call_type           call_type;
00337     typedef base_type::write_call_vector   write_call_vector;
00338     typedef base_type::write_call_iterator write_call_iterator;
00339 
00340 public:
00347     rc_driver_object_b(IF& channel);
00348 
00352     IF& get_channel()
00353         { return *p_channel;    }
00358     void set_channel(IF& channel)
00359         { p_channel = &channel; }
00360 
00365     bool has_written() const
00366         { return m_write_call_vector->empty(); }
00367 
00375     void cancel()
00376     {
00377 #       if !defined(RC_USE_SHARED_METHOD_DRIVER)
00378             m_write_call_vector->clear();
00379 #       endif
00380     }
00381 
00382 private:
00386     IF* p_channel;
00387 
00388 public:
00392     driver_access access;
00393 
00394 private:
00395     // disabled
00397     rc_driver_object_b(const this_type& dobj);
00399     this_type& operator=(const this_type& dobj);
00400 };
00401 
00425 template<class IF>
00426 class rc_driver_object_b<IF, true>
00427     : public rc_driver_object_base
00428 {
00429 protected:
00430     // typedefs
00431     typedef rc_driver_object_b<IF, true> this_type;
00432     typedef rc_driver_object_base        base_type;
00433 
00434     typedef base_type::write_call          write_call;
00435     typedef base_type::call_type           call_type;
00436     typedef base_type::write_call_vector   write_call_vector;
00437     typedef base_type::write_call_iterator write_call_iterator;
00438 
00439 public:
00440     class driver_access;
00441 
00442 public:
00449     rc_driver_object_b(IF& channel);
00450 
00454     IF& get_channel()
00455         { return *p_channel;    }
00460     void set_channel(IF& channel)
00461         { p_channel = &channel; }
00462 
00467     bool has_written() const
00468         { return m_write_call_vector->empty(); }
00472     void cancel()
00473         { m_write_call_vector->clear(); }
00474 
00475 private:
00479     IF* p_channel;
00480 
00481 public:
00485     driver_access access;
00486 
00487 private:
00488     // disabled
00490     rc_driver_object_b(const this_type& dobj);
00492     this_type& operator=(const this_type& dobj);
00493 };
00494 
00500 template<class IF>
00501 class rc_driver_object
00502     : public rc_driver_object_b<IF, true>
00503 {
00504 public:
00505     // useful typedefs
00506     typedef rc_driver_object<IF>               this_type;
00507     typedef rc_driver_object_b<IF, true>       base_type;
00508     typedef typename base_type::driver_access  driver_access;
00509 public:
00516     rc_driver_object(IF& channel)
00517         : base_type(channel)
00518     { }
00519 };
00520 
00526 template<class IF>
00527 class rc_nb_driver_object
00528     : public rc_driver_object_b<IF, false>
00529 {
00530 public:
00531     // useful typedefs
00532     typedef rc_nb_driver_object<IF>           this_type;
00533     typedef rc_driver_object_b<IF, false>     base_type;
00534     typedef typename base_type::driver_access driver_access;
00535 public:
00542     rc_nb_driver_object(IF& channel)
00543         : base_type(channel)
00544     { }
00545 };
00546 
00547 /* inline code */
00548 
00549 inline rc_driver_object_base::write_call::write_call(
00550     rc_driver_object_base::call_type call_)
00551     : m_call(call_), m_write_done_event(NULL), m_throw_dest(NULL)
00552 { }
00553 
00554 inline rc_driver_object_base::write_call::write_call(
00555     rc_driver_object_base::call_type call_,
00556     sc_event* write_done_event)
00557     : m_call(call_), m_write_done_event(write_done_event),
00558       m_throw_dest(NULL)
00559 { }
00560 
00561 inline rc_driver_object_base::write_call::write_call(
00562     rc_driver_object_base::call_type call_,
00563     sc_event* write_done_event, rc_throwable** throw_dest)
00564     : m_call(call_), m_write_done_event(write_done_event),
00565       m_throw_dest(throw_dest)
00566 { }
00567 
00568 /* template code */
00569 
00570 template<class IF>
00571 rc_driver_object_b<IF, false>::rc_driver_object_b(IF& channel)
00572     : base_type(), p_channel(&channel), access(*this)
00573 {
00574 #if !defined(RC_USE_SHARED_METHOD_DRIVER)
00575     // create a driver method process
00576     std::auto_ptr<write_call_vector> wc_vector(new write_call_vector());
00577     std::auto_ptr<sc_event> pw_event(new sc_event());
00578     m_write_call_vector = wc_vector.get();
00579     m_pending_write_event = pw_event.get();
00580     m_pending_write_event_notified = &m_pending_write_event_notified_flag;
00581     sc_spawn_options opt;
00582     opt.set_sensitivity(m_pending_write_event);
00583     opt.dont_initialize();
00584     opt.spawn_method();
00585     m_hproc = sc_spawn(
00586         sc_bind(&this_type::writer_method_proc, this),
00587         sc_gen_unique_name("_rc_nb_driver_object_proc"),
00588         &opt);
00589     wc_vector.release(); // (note: vector will be deleted by destructor)
00590     pw_event.release();  // (note: event will be deleted by destructor)
00591 #endif // !defined(RC_USE_SHARED_METHOD_DRIVER)
00592 }
00593 
00594 template<class IF>
00595 rc_driver_object_b<IF, true>::rc_driver_object_b(IF& channel)
00596     : base_type(), p_channel(&channel), access(*this)
00597 {
00598     // create a driver thread process
00599     std::auto_ptr<write_call_vector> wc_vector(new write_call_vector());
00600     std::auto_ptr<sc_event> pw_event(new sc_event());
00601     m_write_call_vector = wc_vector.get();
00602     m_pending_write_event = pw_event.get();
00603     m_pending_write_event_notified = &m_pending_write_event_notified_flag;
00604     sc_spawn_options opt;
00605     opt.set_sensitivity(m_pending_write_event);
00606     opt.dont_initialize();
00607     m_hproc = sc_spawn(
00608         sc_bind(&this_type::writer_thread_proc, this),
00609         sc_gen_unique_name("_rc_driver_object_proc"), &opt);
00610     wc_vector.release(); // (note: vector will be deleted by destructor)
00611     pw_event.release();  // (note: event will be deleted by destructor)
00612 }
00613 
00614 /* template parameter dependent implementation variants */
00615 
00616 // non-blocking driver access
00617 template<class IF>
00618 class rc_driver_object_b<IF, false>::driver_access
00619 {
00620     friend class rc_driver_object_b<IF, false>;
00621 
00622 protected:
00623     typedef rc_driver_object_b<IF, false> driver_object_type;
00624     typedef typename internals::driver_object::nb_driver_access_call
00625         nb_driver_access_call;
00626 
00627 public:
00628     /* non-blocking call without return value and no ref. parameters */
00629     template<class IF_>
00630     inline void call(void (IF_::*method)()) const
00631     {
00632         nb_driver_access_call()(
00633             dobj, boost::bind(method, dobj.p_channel));
00634     }
00635 
00636     template<class IF_>
00637     inline void call(void (IF_::*method)() const) const
00638     {
00639         nb_driver_access_call()(
00640             dobj, boost::bind(method, dobj.p_channel));
00641     }
00642 
00643     template<class A1, class A1_, class IF_>
00644     inline void call(void (IF_::*method)(A1_), A1 a1) const
00645     {
00646         nb_driver_access_call()(
00647             dobj, boost::bind(method, dobj.p_channel, a1));
00648     }
00649 
00650     template<class A1, class A1_, class IF_>
00651     inline void call(void (IF_::*method)(A1_) const, A1 a1) const
00652     {
00653         nb_driver_access_call()(
00654             dobj, boost::bind(method, dobj.p_channel, a1));
00655     }
00656 
00657     template<class A1, class A2, class A1_, class A2_, class IF_>
00658     inline void call(void (IF_::*method)(A1_, A2_), A1 a1, A2 a2) const
00659     {
00660         nb_driver_access_call()(
00661             dobj, boost::bind(method, dobj.p_channel, a1, a2));
00662     }
00663 
00664     template<class A1, class A2, class A1_, class A2_, class IF_>
00665     inline void call(void (IF_::*method)(A1_, A2_) const,
00666         A1 a1, A2 a2) const
00667     {
00668         nb_driver_access_call()(
00669             dobj, boost::bind(method, dobj.p_channel, a1, a2));
00670     }
00671 
00672     template<class A1, class A2, class A3,
00673         class A1_, class A2_, class A3_, class IF_>
00674     inline void call(
00675         void (IF_::*method)(A1_, A2_, A3_), A1 a1, A2 a2, A3 a3) const
00676     {
00677         nb_driver_access_call()(
00678             dobj, boost::bind(method, dobj.p_channel, a1, a2, a3));
00679     }
00680 
00681     template<class A1, class A2, class A3,
00682         class A1_, class A2_, class A3_, class IF_>
00683     inline void call(
00684         void (IF_::*method)(A1_, A2_, A3_) const,
00685         A1 a1, A2 a2, A3 a3) const
00686     {
00687         nb_driver_access_call()(
00688             dobj, boost::bind(method, dobj.p_channel, a1, a2, a3));
00689     }
00690 
00691     template<class A1, class A2, class A3, class A4,
00692         class A1_, class A2_, class A3_, class A4_, class IF_>
00693     inline void call(
00694         void (IF_::*method)(A1_, A2_, A3_, A4_),
00695         A1 a1, A2 a2, A3 a3, A4 a4) const
00696     {
00697         nb_driver_access_call()(
00698             dobj, boost::bind(method, dobj.p_channel,
00699             a1, a2, a3, a4));
00700     }
00701 
00702     template<class A1, class A2, class A3, class A4,
00703         class A1_, class A2_, class A3_, class A4_, class IF_>
00704     inline void call(
00705         void (IF_::*method)(A1_, A2_, A3_, A4_) const,
00706         A1 a1, A2 a2, A3 a3, A4 a4) const
00707     {
00708         nb_driver_access_call()(
00709             dobj, boost::bind(method, dobj.p_channel,
00710             a1, a2, a3, a4));
00711     }
00712 
00713     template<class A1, class A2, class A3, class A4, class A5,
00714         class A1_, class A2_, class A3_, class A4_, class A5_, class IF_>
00715     inline void call(
00716         void (IF_::*method)(A1_, A2_, A3_, A4_, A5_),
00717         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
00718     {
00719         nb_driver_access_call()(
00720             dobj, boost::bind(method, dobj.p_channel,
00721             a1, a2, a3, a4, a5));
00722     }
00723 
00724     template<class A1, class A2, class A3, class A4, class A5,
00725         class A1_, class A2_, class A3_, class A4_, class A5_, class IF_>
00726     inline void call(
00727         void (IF_::*method)(A1_, A2_, A3_, A4_, A5_) const,
00728         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
00729     {
00730         nb_driver_access_call()(
00731             dobj, boost::bind(method, dobj.p_channel,
00732             a1, a2, a3, a4, a5));
00733     }
00734 
00735     template<class A1, class A2, class A3, class A4, class A5, class A6,
00736         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
00737         class IF_>
00738     inline void call(
00739         void (IF_::*method)(A1_, A2_, A3_, A4_, A5_, A6_),
00740         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
00741     {
00742         nb_driver_access_call()(
00743             dobj, boost::bind(method, dobj.p_channel,
00744             a1, a2, a3, a4, a5, a6));
00745     }
00746 
00747     template<class A1, class A2, class A3, class A4, class A5, class A6,
00748         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
00749         class IF_>
00750     inline void call(
00751         void (IF_::*method)(A1_, A2_, A3_, A4_, A5_, A6_) const,
00752         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
00753     {
00754         nb_driver_access_call()(
00755             dobj, boost::bind(method, dobj.p_channel,
00756             a1, a2, a3, a4, a5, a6));
00757     }
00758 
00759     template<class A1, class A2, class A3, class A4, class A5, class A6,
00760         class A7,
00761         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
00762         class A7_, class IF_>
00763     inline void call(
00764         void (IF_::*method)(A1_, A2_, A3_, A4_, A5_, A6_, A7_),
00765         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const
00766     {
00767         nb_driver_access_call()(
00768             dobj, boost::bind(method, dobj.p_channel,
00769             a1, a2, a3, a4, a5, a6, a7));
00770     }
00771 
00772     template<class A1, class A2, class A3, class A4, class A5,
00773         class A6, class A7,
00774         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
00775         class A7_, class IF_>
00776     inline void call(
00777         void (IF_::*method)(A1_, A2_, A3_, A4_, A5_, A6_, A7_) const,
00778         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const
00779     {
00780         nb_driver_access_call()(
00781             dobj, boost::bind(method, dobj.p_channel,
00782             a1, a2, a3, a4, a5, a6, a7));
00783     }
00784 
00785     template<class A1, class A2, class A3, class A4, class A5, class A6,
00786         class A7, class A8,
00787         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
00788         class A7_, class A8_, class IF_>
00789     inline void call(
00790         void (IF_::*method)(A1_, A2_, A3_, A4_, A5_, A6_, A7_, A8_),
00791         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
00792     {
00793         nb_driver_access_call()(
00794             dobj, boost::bind(method, dobj.p_channel,
00795             a1, a2, a3, a4, a5, a6, a7, a8));
00796     }
00797 
00798     template<class A1, class A2, class A3, class A4, class A5, class A6,
00799         class A7, class A8,
00800         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
00801         class A7_, class A8_, class IF_>
00802     inline void call(
00803         void (IF_::*method)(A1_, A2_, A3_, A4_, A5_, A6_, A7_, A8_) const,
00804         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
00805     {
00806         nb_driver_access_call()(
00807             dobj, boost::bind(method, dobj.p_channel,
00808             a1, a2, a3, a4, a5, a6, a7, a8));
00809     }
00810 
00811     template<class A1, class A2, class A3, class A4, class A5, class A6,
00812         class A7, class A8, class A9,
00813         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
00814         class A7_, class A8_, class A9_, class IF_>
00815     inline void call(
00816         void (IF_::*method)(A1_, A2_, A3_, A4_, A5_, A6_, A7_, A8_, A9_),
00817         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
00818         A7 a7, A8 a8, A9 a9) const
00819     {
00820         nb_driver_access_call()(
00821             dobj, boost::bind(method, dobj.p_channel,
00822             a1, a2, a3, a4, a5, a6, a7, a8, a9));
00823     }
00824 
00825     template<class A1, class A2, class A3, class A4, class A5, class A6,
00826         class A7, class A8, class A9,
00827         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
00828         class A7_, class A8_, class A9_, class IF_>
00829     inline void call(
00830         void (IF_::*method)(
00831             A1_, A2_, A3_, A4_, A5_, A6_, A7_, A8_, A9_) const,
00832         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
00833         A7 a7, A8 a8, A9 a9) const
00834     {
00835         nb_driver_access_call()(
00836             dobj, boost::bind(method, dobj.p_channel,
00837             a1, a2, a3, a4, a5, a6, a7, a8, a9));
00838     }
00839 
00840     template<class A1, class A2, class A3, class A4, class A5, class A6,
00841         class A7, class A8, class A9, class A10,
00842         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
00843         class A7_, class A8_, class A9_, class A10_, class IF_>
00844     inline void call(
00845         void (IF_::*method)(
00846             A1_, A2_, A3_, A4_, A5_, A6_, A7_, A8_, A9_, A10_),
00847         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
00848         A7 a7, A8 a8, A9 a9, A10 a10) const
00849     {
00850         nb_driver_access_call()(
00851             dobj, boost::bind(method, dobj.p_channel,
00852             a1, a2, a3, a4, a5, a6, a7, a8, a9, a10));
00853     }
00854 
00855     template<class A1, class A2, class A3, class A4, class A5, class A6,
00856         class A7, class A8, class A9, class A10,
00857         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
00858         class A7_, class A8_, class A9_, class A10_, class IF_>
00859     inline void call(
00860         void (IF_::*method)(
00861             A1_, A2_, A3_, A4_, A5_, A6_, A7_, A8_, A9_, A10_) const,
00862         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
00863         A7 a7, A8 a8, A9 a9, A10 a10) const
00864     {
00865         nb_driver_access_call()(
00866             dobj, boost::bind(method, dobj.p_channel,
00867             a1, a2, a3, a4, a5, a6, a7, a8, a9, a10));
00868     }
00869 
00870 private:
00871     driver_access(driver_object_type& dobj_)
00872         : dobj(dobj_)
00873     { }
00874 
00875 private:
00876     driver_object_type& dobj;
00877 
00878 private:
00879     //disabled
00880     driver_access(const driver_access& access);
00881     driver_access& operator=(const driver_access& access);
00882 };
00883 
00884 // blocking driver access
00885 template<class IF>
00886 class rc_driver_object_b<IF, true>::driver_access
00887 {
00888     friend class rc_driver_object_b<IF, true>;
00889 
00890 protected:
00891     typedef rc_driver_object_b<IF, true> driver_object_type;
00892 
00893 public:
00894     /* blocking call */
00895 
00896     template<class R, class IF_>
00897     inline R call(R (IF_::*method)()) const
00898     {
00899         return typename internals::driver_object::driver_access_call<R>()(
00900             dobj, boost::bind(method, dobj.p_channel));
00901     }
00902 
00903     template<class R, class IF_>
00904     inline R call(R (IF_::*method)() const) const
00905     {
00906         return typename internals::driver_object::driver_access_call<R>()(
00907             dobj, boost::bind(method, dobj.p_channel));
00908     }
00909 
00910     template<class R, class A1, class A1_, class IF_>
00911     inline R call(R (IF_::*method)(A1_), A1 a1) const
00912     {
00913         return typename internals::driver_object::driver_access_call<R>()(
00914             dobj, boost::bind(method, dobj.p_channel, a1));
00915     }
00916 
00917     template<class R, class A1, class A1_, class IF_>
00918     inline R call(R (IF_::*method)(A1_) const, A1 a1) const
00919     {
00920         return typename internals::driver_object::driver_access_call<R>()(
00921             dobj, boost::bind(method, dobj.p_channel, a1));
00922     }
00923 
00924     template<class R, class A1, class A2, class A1_, class A2_, class IF_>
00925     inline R call(R (IF_::*method)(A1_, A2_), A1 a1, A2 a2) const
00926     {
00927         return typename internals::driver_object::driver_access_call<R>()(
00928             dobj, boost::bind(
00929                 method, dobj.p_channel, a1, a2));
00930     }
00931 
00932     template<class R, class A1, class A2, class A1_, class A2_, class IF_>
00933     inline R call(R (IF_::*method)(A1_, A2_) const, A1 a1, A2 a2) const
00934     {
00935         return typename internals::driver_object::driver_access_call<R>()(
00936             dobj, boost::bind(
00937                 method, dobj.p_channel, a1, a2));
00938     }
00939 
00940     template<class R, class A1, class A2, class A3,
00941         class A1_, class A2_, class A3_, class IF_>
00942     inline R call(
00943         R (IF_::*method)(A1_, A2_, A3_), A1 a1, A2 a2, A3 a3) const
00944     {
00945         return typename internals::driver_object::driver_access_call<R>()(
00946             dobj, boost::bind(
00947                 method, dobj.p_channel, a1, a2, a3));
00948     }
00949 
00950     template<class R, class A1, class A2, class A3,
00951         class A1_, class A2_, class A3_, class IF_>
00952     inline R call(
00953         R (IF_::*method)(A1_, A2_, A3_) const, A1 a1, A2 a2, A3 a3) const
00954     {
00955         return typename internals::driver_object::driver_access_call<R>()(
00956             dobj, boost::bind(
00957                 method, dobj.p_channel, a1, a2, a3));
00958     }
00959 
00960     template<class R, class A1, class A2, class A3, class A4,
00961         class A1_, class A2_, class A3_, class A4_, class IF_>
00962     inline R call(
00963         R (IF_::*method)(A1_, A2_, A3_, A4_),
00964         A1 a1, A2 a2, A3 a3, A4 a4) const
00965     {
00966         return typename internals::driver_object::driver_access_call<R>()(
00967             dobj, boost::bind(
00968                 method, dobj.p_channel, a1, a2, a3, a4));
00969     }
00970 
00971     template<class R, class A1, class A2, class A3, class A4,
00972         class A1_, class A2_, class A3_, class A4_, class IF_>
00973     inline R call(
00974         R (IF_::*method)(A1_, A2_, A3_, A4_) const,
00975         A1 a1, A2 a2, A3 a3, A4 a4) const
00976     {
00977         return typename internals::driver_object::driver_access_call<R>()(
00978             dobj, boost::bind(
00979                 method, dobj.p_channel, a1, a2, a3, a4));
00980     }
00981 
00982     template<class R, class A1, class A2, class A3, class A4, class A5,
00983         class A1_, class A2_, class A3_, class A4_, class A5_, class IF_>
00984     inline R call(
00985         R (IF_::*method)(A1_, A2_, A3_, A4_, A5_),
00986         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
00987     {
00988         return typename internals::driver_object::driver_access_call<R>()(
00989             dobj, boost::bind(
00990                 method, dobj.p_channel, a1, a2, a3, a4, a5));
00991     }
00992 
00993     template<class R, class A1, class A2, class A3, class A4, class A5,
00994         class A1_, class A2_, class A3_, class A4_, class A5_, class IF_>
00995     inline R call(
00996         R (IF_::*method)(A1_, A2_, A3_, A4_, A5_) const,
00997         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
00998     {
00999         return typename internals::driver_object::driver_access_call<R>()(
01000             dobj, boost::bind(
01001                 method, dobj.p_channel, a1, a2, a3, a4, a5));
01002     }
01003 
01004     template<class R,
01005         class A1, class A2, class A3, class A4, class A5, class A6,
01006         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
01007         class IF_>
01008     inline R call(
01009         R (IF_::*method)(A1_, A2_, A3_, A4_, A5_, A6_),
01010         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
01011     {
01012         return typename internals::driver_object::driver_access_call<R>()(
01013             dobj, boost::bind(
01014                 method, dobj.p_channel, a1, a2, a3, a4, a5, a6));
01015     }
01016 
01017     template<class R,
01018         class A1, class A2, class A3, class A4, class A5, class A6,
01019         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
01020         class IF_>
01021     inline R call(
01022         R (IF_::*method)(A1_, A2_, A3_, A4_, A5_, A6_) const,
01023         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
01024     {
01025         return typename internals::driver_object::driver_access_call<R>()(
01026             dobj, boost::bind(
01027                 method, dobj.p_channel, a1, a2, a3, a4, a5, a6));
01028     }
01029 
01030     template<class R,
01031         class A1, class A2, class A3, class A4, class A5, class A6,
01032         class A7,
01033         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
01034         class A7_, class IF_>
01035     inline R call(
01036         R (IF_::*method)(A1_, A2_, A3_, A4_, A5_, A6_, A7_),
01037         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const
01038     {
01039         return typename internals::driver_object::driver_access_call<R>()(
01040             dobj, boost::bind(
01041                 method, dobj.p_channel, a1, a2, a3, a4, a5, a6, a7));
01042     }
01043 
01044     template<class R,
01045         class A1, class A2, class A3, class A4, class A5, class A6,
01046         class A7,
01047         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
01048         class A7_, class IF_>
01049     inline R call(
01050         R (IF_::*method)(A1_, A2_, A3_, A4_, A5_, A6_, A7_) const,
01051         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const
01052     {
01053         return typename internals::driver_object::driver_access_call<R>()(
01054             dobj, boost::bind(
01055                 method, dobj.p_channel, a1, a2, a3, a4, a5, a6, a7));
01056     }
01057 
01058     template<class R,
01059         class A1, class A2, class A3, class A4, class A5, class A6,
01060         class A7, class A8,
01061         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
01062         class A7_, class A8_, class IF_>
01063     inline R call(
01064         R (IF_::*method)(A1_, A2_, A3_, A4_, A5_, A6_, A7_, A8_),
01065         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
01066     {
01067         return typename internals::driver_object::driver_access_call<R>()(
01068             dobj, boost::bind(
01069                 method, dobj.p_channel, a1, a2, a3, a4, a5, a6, a7, a8));
01070     }
01071 
01072     template<class R,
01073         class A1, class A2, class A3, class A4, class A5, class A6,
01074         class A7, class A8,
01075         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
01076         class A7_, class A8_, class IF_>
01077     inline R call(
01078         R (IF_::*method)(A1_, A2_, A3_, A4_, A5_, A6_, A7_, A8_) const,
01079         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
01080     {
01081         return typename internals::driver_object::driver_access_call<R>()(
01082             dobj, boost::bind(
01083                 method, dobj.p_channel, a1, a2, a3, a4, a5, a6, a7, a8));
01084     }
01085 
01086     template<class R,
01087         class A1, class A2, class A3, class A4, class A5, class A6,
01088         class A7, class A8, class A9,
01089         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
01090         class A7_, class A8_, class A9_, class IF_>
01091     inline R call(
01092         R (IF_::*method)(A1_, A2_, A3_, A4_, A5_, A6_, A7_, A8_, A9_),
01093         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
01094         const
01095     {
01096         return typename internals::driver_object::driver_access_call<R>()(
01097             dobj, boost::bind(
01098                 method, dobj.p_channel,
01099                 a1, a2, a3, a4, a5, a6, a7, a8, a9));
01100     }
01101 
01102     template<class R,
01103         class A1, class A2, class A3, class A4, class A5, class A6,
01104         class A7, class A8, class A9,
01105         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
01106         class A7_, class A8_, class A9_, class IF_>
01107     inline R call(
01108         R (IF_::*method)(
01109             A1_, A2_, A3_, A4_, A5_, A6_, A7_, A8_, A9_) const,
01110         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
01111         const
01112     {
01113         return typename internals::driver_object::driver_access_call<R>()(
01114             dobj, boost::bind(
01115                 method, dobj.p_channel,
01116                 a1, a2, a3, a4, a5, a6, a7, a8, a9));
01117     }
01118 
01119     template<class R,
01120         class A1, class A2, class A3, class A4, class A5, class A6,
01121         class A7, class A8, class A9, class A10,
01122         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
01123         class A7_, class A8_, class A9_, class A10_, class IF_>
01124     inline R call(
01125         R (IF_::*method)(
01126             A1_, A2_, A3_, A4_, A5_, A6_, A7_, A8_, A9_, A10_),
01127         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
01128         A7 a7, A8 a8, A9 a9, A10 a10) const
01129     {
01130         return typename internals::driver_object::driver_access_call<R>()(
01131             dobj, boost::bind(
01132                 method, dobj.p_channel,
01133                 a1, a2, a3, a4, a5, a6, a7, a8, a9, a10));
01134     }
01135 
01136     template<class R,
01137         class A1, class A2, class A3, class A4, class A5, class A6,
01138         class A7, class A8, class A9, class A10,
01139         class A1_, class A2_, class A3_, class A4_, class A5_, class A6_,
01140         class A7_, class A8_, class A9_, class A10_, class IF_>
01141     inline R call(
01142         R (IF_::*method)(
01143             A1_, A2_, A3_, A4_, A5_, A6_, A7_, A8_, A9_, A10_) const,
01144         A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
01145         A7 a7, A8 a8, A9 a9, A10 a10) const
01146     {
01147         return typename internals::driver_object::driver_access_call<R>()(
01148             dobj, boost::bind(
01149                 method, dobj.p_channel,
01150                 a1, a2, a3, a4, a5, a6, a7, a8, a9, a10));
01151     }
01152 
01153 private:
01154     driver_access(driver_object_type& dobj_)
01155         : dobj(dobj_)
01156     { }
01157 
01158 private:
01159     driver_object_type& dobj;
01160 
01161 private:
01162     //disabled
01163     driver_access(const driver_access& access);
01164     driver_access& operator=(const driver_access& access);
01165 };
01166 
01167 namespace internals {
01168 namespace driver_object {
01169 
01175 template<class R>
01176 class copy_retval
01177 {
01178 public:
01179     typedef typename boost::add_const<R>::type src_type;
01180     typedef retval<R, boost::is_reference<R>::value> dest_type;
01181 
01182     void operator()(src_type src, dest_type* dest) const
01183         { (*dest) = src; }
01184 };
01185 
01191 // R is not a reference
01192 template<class R>
01193 class retval<R, false>
01194 {
01195     typedef retval<R, false> this_type;
01196     typedef typename boost::add_const<R>::type const_value_type;
01197 
01198 public:
01199     inline retval() {}
01200     inline operator R() const { return value; }
01201     inline this_type& operator=(const_value_type new_value)
01202     {
01203         value = new_value; /*copy*/
01204         return *this;
01205     }
01206 private:
01207     R value;
01208 };
01209 
01215 // R is a reference
01216 template<class R>
01217 class retval<R, true>
01218 {
01219     typedef retval<R, true> this_type;
01220     typedef typename boost::add_const<R>::type const_value_type;
01221     typedef typename boost::remove_reference<R>::type* value_ptr_type;
01222 public:
01223     inline retval() : value_ptr(NULL) {}
01224     inline operator R() const { return *value_ptr; }
01225     inline this_type& operator=(const_value_type new_value)
01226     {
01227         value_ptr = boost::addressof(new_value);
01228         return *this;
01229     }
01230 private:
01231      value_ptr_type value_ptr;
01232 };
01233 
01237 class nb_driver_access_call
01238 {
01239 private:
01240     typedef ::ReChannel::rc_driver_object_base
01241         driver_object_type;
01242     typedef driver_object_type::call_type  call_type;
01243     typedef driver_object_type::write_call write_call;
01244 
01245 public:
01246     inline nb_driver_access_call() {}
01247 
01248     // TODO: should it be inlined?
01249     void operator()(driver_object_type& dobj, call_type call_obj);
01250 };
01251 
01257 // R is not void
01258 template<class R>
01259 class driver_access_call
01260 {
01261 private:
01262     typedef typename ::ReChannel::rc_driver_object_base
01263         driver_object_type;
01264     typedef typename driver_object_type::write_call
01265         write_call;
01266     typedef typename internals::driver_object::retval<R>
01267         retval;
01268     typedef typename internals::driver_object::copy_retval<R>
01269         copy_retval;
01270 
01271 public:
01272     inline driver_access_call() {}
01273 
01274     // TODO: should it be inlined?
01275     template<class BIND_OBJ>
01276     R operator()(driver_object_type& dobj, BIND_OBJ call_obj) const;
01277 };
01278 
01279 template<class R>
01280 template<class BIND_OBJ>
01281 R driver_access_call<R>::operator()(
01282     driver_object_type& dobj, BIND_OBJ call_obj) const
01283 {
01284     // the returned value will be written to this variable
01285     retval ret;
01286     // create the event that will indicate the execution of the call
01287     sc_event write_done_event;
01288     // initialise the thrown_obj to NULL
01289     rc_throwable* thrown_obj = NULL;
01290     // create the write call and append it to the write call vector
01291     // copy retval has to be used to copy the returned value to variable ret
01292     dobj.m_write_call_vector->push_back(
01293         write_call(
01294             boost::bind(
01295                 copy_retval(), call_obj, &ret),
01296             &write_done_event, &thrown_obj));
01297     // signal the driver object that a new write call is pending
01298     //   by notifying the pending write event
01299     if (!*dobj.m_pending_write_event_notified) {
01300         *dobj.m_pending_write_event_notified = true;
01301         rc_driver_object_base::safe_event_notify(
01302             *dobj.m_pending_write_event);
01303     }
01304     // wait for the call to be executed
01305     ::sc_core::wait(write_done_event);
01306     // if an event of type rc_throwable occured rethrow it in this context
01307     if (thrown_obj != NULL) {
01308         ::ReChannel::rc_throw(thrown_obj);
01309     }
01310     // execution was successful
01311     // return ret
01312     return (R)ret;
01313 }
01314 
01320 // R is void
01321 template<>
01322 class driver_access_call<void>
01323 {
01324 private:
01325     typedef ::ReChannel::rc_driver_object_base
01326         driver_object_type;
01327     typedef driver_object_type::call_type  call_type;
01328     typedef driver_object_type::write_call write_call;
01329 
01330 public:
01331     inline driver_access_call() {}
01332 
01333     // TODO: should it be inlined?
01334     void operator()(driver_object_type& dobj, call_type call_obj) const;
01335 };
01336 
01337 } // namespace driver_object
01338 } // namespace internals
01339 
01340 } // namespace ReChannel
01341 
01342 #endif // RC_DRIVER_OBJECT_H_
01343 
01344 //
01345 // $Id: rc_driver_object.h,v 1.15 2007/12/20 23:07:10 felke Exp $
01346 // $Source: /var/cvs/projekte/ReChannel-v2/src/ReChannel/util/rc_driver_object.h,v $
01347 //

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