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

panda/src/net/connectionReader.h

Go to the documentation of this file.
00001 // Filename: connectionReader.h
00002 // Created by:  drose (08Feb00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #ifndef CONNECTIONREADER_H
00020 #define CONNECTIONREADER_H
00021 
00022 #include <pandabase.h>
00023 
00024 #include "connection.h"
00025 
00026 #include <pointerTo.h>
00027 
00028 #include <prio.h>
00029 #include <prthread.h>
00030 #include <prlock.h>
00031 #include "pvector.h"
00032 #include "pset.h"
00033 
00034 class NetDatagram;
00035 class ConnectionManager;
00036 
00037 ////////////////////////////////////////////////////////////////////
00038 //       Class : ConnectionReader
00039 // Description : This is an abstract base class for a family of
00040 //               classes that listen for activity on a socket and
00041 //               respond to it, for instance by reading a datagram and
00042 //               serving it (or queueing it up for later service).
00043 //
00044 //               A ConnectionReader may define an arbitrary number of
00045 //               threads (at least one) to process datagrams coming in
00046 //               from an arbitrary number of sockets that it is
00047 //               monitoring.  The number of threads is specified at
00048 //               construction time and cannot be changed, but the set
00049 //               of sockets that is to be monitored may be constantly
00050 //               modified at will.
00051 //
00052 //               This is an abstract class because it doesn't define
00053 //               how to process each received datagram.  See
00054 //               QueuedConnectionReader.  Also note that
00055 //               ConnectionListener derives from this class, extending
00056 //               it to accept connections on a rendezvous socket
00057 //               rather than read datagrams.
00058 ////////////////////////////////////////////////////////////////////
00059 class EXPCL_PANDA ConnectionReader {
00060 PUBLISHED:
00061   // The implementation here used to involve NSPR's multi-wait
00062   // interface, but that got too complicated to manage.  It turns out
00063   // to be difficult to protect against memory leaks caused by race
00064   // conditions in that interface, as designed.
00065 
00066   // Instead, we do our own multi-wait type stuff.  Only one thread at
00067   // a time can extract the next-available socket with activity on it.
00068   // That thread will either (a) simply extract the next socket from
00069   // the arrays returned by a previous call to PR_Poll(), or (b)
00070   // execute (and possibly block on) a new call to PR_Poll().
00071 
00072   ConnectionReader(ConnectionManager *manager, int num_threads);
00073   virtual ~ConnectionReader();
00074 
00075   bool add_connection(const PT(Connection) &connection);
00076   bool remove_connection(const PT(Connection) &connection);
00077   bool is_connection_ok(const PT(Connection) &connection);
00078 
00079   void poll();
00080 
00081   ConnectionManager *get_manager() const;
00082   bool is_polling() const;
00083   int get_num_threads() const;
00084 
00085   void set_raw_mode(bool mode);
00086   bool get_raw_mode() const;
00087 
00088 protected:
00089   virtual void receive_datagram(const NetDatagram &datagram)=0;
00090 
00091   class SocketInfo {
00092   public:
00093     SocketInfo(const PT(Connection) &connection);
00094     bool is_udp() const;
00095     PRFileDesc *get_socket() const;
00096 
00097     PT(Connection) _connection;
00098     bool _busy;
00099     bool _error;
00100   };
00101 
00102   void shutdown();
00103   void clear_manager();
00104   void finish_socket(SocketInfo *sinfo);
00105 
00106   virtual void process_incoming_data(SocketInfo *sinfo);
00107   virtual void process_incoming_udp_data(SocketInfo *sinfo);
00108   virtual void process_incoming_tcp_data(SocketInfo *sinfo);
00109   virtual void process_raw_incoming_udp_data(SocketInfo *sinfo);
00110   virtual void process_raw_incoming_tcp_data(SocketInfo *sinfo);
00111 
00112 private:
00113   static void thread_start(void *data);
00114   void thread_run();
00115 
00116   SocketInfo *get_next_available_socket(PRIntervalTime timeout,
00117                                         PRInt32 current_thread_index);
00118 
00119   void rebuild_poll_list();
00120 
00121 protected:
00122   ConnectionManager *_manager;
00123 
00124 private:
00125   bool _raw_mode;
00126   bool _shutdown;
00127 
00128   typedef pvector<PRThread *> Threads;
00129   Threads _threads;
00130   PRLock *_startup_mutex;
00131   bool _polling;
00132 
00133   // These structures are used to manage polling for noise on
00134   // available sockets.
00135   typedef pvector<PRPollDesc> Poll;
00136   typedef pvector<SocketInfo *> Sockets;
00137   Poll _poll;
00138   Sockets _polled_sockets;
00139   int _next_index;
00140   int _num_results;
00141   // Threads go to sleep on this mutex waiting for their chance to
00142   // read a socket.
00143   PRLock *_select_mutex;
00144 
00145   // This is atomically updated with the index (in _threads) of the
00146   // thread that is currently waiting on the PR_Poll() call.  It
00147   // contains -1 if no thread is so waiting.
00148   PRInt32 _currently_polling_thread;
00149 
00150   // These structures track the total set of sockets (connections) we
00151   // know about.
00152   Sockets _sockets;
00153   // This is the list of recently-removed sockets.  We can't actually
00154   // delete them until they're no longer _busy.
00155   Sockets _removed_sockets;
00156   // Threads may set this true to force the polling thread to rebuild
00157   // its Poll() list.
00158   bool _reexamine_sockets;
00159   // Any operations on _sockets are protected by this mutex.
00160   PRLock *_sockets_mutex;
00161 
00162 
00163 friend class ConnectionManager;
00164 };
00165 
00166 #endif

Generated on Fri May 2 00:40:33 2003 for Panda by doxygen1.3