Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

RouterModule.h

00001 #ifndef _STR_RouterModule_H_  // -*-c++-*-
00002 
00003 /*
00004  * Copyright 2000-2002 Eric M. Hopper <hopper@omnifarious.org>
00005  * 
00006  *     This program is free software; you can redistribute it and/or modify it
00007  *     under the terms of the GNU Lesser General Public License as published
00008  *     by the Free Software Foundation; either version 2 of the License, or
00009  *     (at your option) any later version.
00010  * 
00011  *     This program is distributed in the hope that it will be useful, but
00012  *     WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *     Lesser General Public License for more details.
00015  * 
00016  *     You should have received a copy of the GNU Lesser General Public
00017  *     License along with this program; if not, write to the Free Software
00018  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #ifdef __GNUG__
00022 #  pragma interface
00023 #endif
00024 
00025 /* $Header: /home/hopper/src/cvs/C++/StrMod/StrMod/RouterModule.h,v 1.7 2002/08/29 00:58:04 hopper Exp $ */
00026 
00027 // For a log, see ../ChangeLog
00028 
00029 #include <cstddef>
00030 #include <iterator>
00031 #include <deque>
00032 #include <StrMod/STR_ClassIdent.h>
00033 #include <StrMod/StreamModule.h>
00034 
00035 #define _STR_RouterModule_H_
00036 
00037 namespace strmod {
00038 namespace unievent {
00039 class Dispatcher;
00040 };
00041 };
00042 
00043 namespace strmod {
00044 namespace strmod {
00045 
00046 /** \class RouterModule RouterModule.h StrMod/RouterModule.h
00047  * \brief Provides an abstract base for classes that route chunks from a plug to
00048  * a set of other plugs based on contents.
00049  */
00050 class RouterModule : public StreamModule
00051 {
00052  protected:
00053    class RPlug;
00054    friend class RPlug;
00055    //! Just a type alias to avoid errors in typing deque<RPlug *>.
00056    typedef std::deque<RPlug *> RPlugList;
00057    //! Just a type alias to avoid errors in typing back_insert_iterator<RPlugList>
00058    typedef std::back_insert_iterator<RPlugList> RPlugAdder;
00059 
00060  public:
00061    static const STR_ClassIdent identifier;
00062 
00063    //! Construct, given the strmod::unievent::Dispatcher to use to post scan events.
00064    explicit RouterModule(unievent::Dispatcher &disp);
00065    //! Destroy the RouterModule and all of its plugs.
00066    virtual ~RouterModule();
00067 
00068    virtual int AreYouA(const lcore::ClassIdent &cid) const {
00069       return((identifier == cid) || StreamModule::AreYouA(cid));
00070    }
00071 
00072    virtual bool canCreate(int side) const = 0;
00073 
00074    virtual bool ownsPlug(const Plug *plug) const;
00075 
00076    virtual bool deletePlug(Plug *plug);
00077 
00078  protected:
00079    virtual const lcore::ClassIdent *i_GetIdent() const  { return &identifier; }
00080 
00081    virtual Plug *i_MakePlug(int side) = 0;
00082 
00083    /** Add a new plug to the internal list of all plugs.
00084     * Must be called before i_MakePlug returns a new plug!
00085     */
00086    void addNewPlug(RPlug *rp);
00087 
00088    /** If a scan event isn't posted, post one.
00089     * A scan is always posted because a piece of data came in from an RPlug, and
00090     * data is only allowed to in from a particular RPlug once per scan.  This is
00091     * to ensure that one RPlug cannot monopolize the RouterModule.
00092     */
00093    inline void postScan();
00094 
00095    /** Compute a list of destination plugs for a given incoming chunk.
00096     * \param chunk The chunk that's going somewhere.
00097     * \param source Where it came from.
00098     * \param begin Beginning of a list of all RPlugs in this RouterModule.
00099     * \param end STL style end of list started at begin.
00100     * \param destlist Output iterator to store destination plugs in.
00101     */
00102    virtual void getDestinations(const StrChunkPtr &chunk,
00103                                 const RPlug &source,
00104                                 const RPlugList::const_iterator &begin,
00105                                 const RPlugList::const_iterator &end,
00106                                 RPlugAdder &destlist) const = 0;
00107 
00108  private:
00109    class ScanEvent;
00110    friend class ScanEvent;
00111    unievent::Dispatcher &disp_;
00112    bool scan_posted_;
00113    ScanEvent * const scan_;
00114    bool inroutingdone_;
00115    RPlugList allplugs_;
00116    RPlugList writeable_;
00117    RPlugList nonwriteable_;
00118    StrChunkPtr routedchunk_;
00119    size_t outgoingcopies_;
00120 
00121    //! Actually post a scan event to dispatcher_.
00122    void doPost();
00123    void doScan();
00124 
00125    void routingDone();
00126    void processIncoming(RPlug &source, const StrChunkPtr &chunk);
00127 };
00128 
00129 //---
00130 
00131 class RouterModule::RPlug : public StreamModule::Plug {
00132    friend class RouterModule;
00133  public:
00134    static const STR_ClassIdent identifier;
00135 
00136    inline virtual int AreYouA(const lcore::ClassIdent &cid) const {
00137       return((identifier == cid) || Plug::AreYouA(cid));
00138    }
00139 
00140    inline RouterModule &getParent() const;
00141 
00142    virtual int side() const = 0;
00143 
00144    //! Get the 'deleted_' flag of this plug.
00145    bool getDeleted() const                               { return(deleted_); }
00146 
00147    //! Set the 'deleted_' flag of this plug.
00148    void setDeleted()                                     { deleted_ = true; }
00149 
00150  protected:
00151    inline RPlug(RouterModule &parent);
00152 
00153    virtual const lcore::ClassIdent *i_GetIdent() const  { return &identifier; }
00154 
00155    virtual const StrChunkPtr i_Read();
00156    virtual void i_Write(const StrChunkPtr &ptr);
00157 
00158  private:
00159    bool deleted_;
00160 };
00161 
00162 //-----------------------------inline functions--------------------------------
00163 
00164 inline void RouterModule::postScan()
00165 {
00166    if (!scan_posted_)
00167    {
00168       scan_posted_ = true;
00169       doPost();
00170    }
00171 }
00172 
00173 //---
00174 
00175 inline RouterModule &RouterModule::RPlug::getParent() const
00176 {
00177    return static_cast<RouterModule &>(Plug::getParent());
00178 }
00179 
00180 inline RouterModule::RPlug::RPlug(RouterModule &parent)
00181      : Plug(parent), deleted_(false)
00182 {
00183 }
00184 
00185 };  // namespace strmod
00186 };  // namespace strmod
00187 
00188 #endif

Generated on Wed Jan 29 00:32:44 2003 for libNet by doxygen1.3-rc1