Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

SocketListener.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file SocketListener.d
00004         
00005         Copyright (c) 2004 Kris Bell
00006         
00007         This software is provided 'as-is', without any express or implied
00008         warranty. In no event will the authors be held liable for damages
00009         of any kind arising from the use of this software.
00010         
00011         Permission is hereby granted to anyone to use this software for any 
00012         purpose, including commercial applications, and to alter it and/or 
00013         redistribute it freely, subject to the following restrictions:
00014         
00015         1. The origin of this software must not be misrepresented; you must 
00016            not claim that you wrote the original software. If you use this 
00017            software in a product, an acknowledgment within documentation of 
00018            said product would be appreciated but is not required.
00019 
00020         2. Altered source versions must be plainly marked as such, and must 
00021            not be misrepresented as being the original software.
00022 
00023         3. This notice may not be removed or altered from any distribution
00024            of the source.
00025 
00026         4. Derivative works are permitted, but they must carry this notice
00027            in full and credit the original source.
00028 
00029 
00030                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00031 
00032 
00033         @version        Initial version, June 2004      
00034         @author         Kris
00035 
00036 
00037 *******************************************************************************/
00038 
00039 module mango.io.SocketListener;
00040 
00041 private import  std.thread;
00042 
00043 private import  mango.io.Socket;
00044 
00045 private import  mango.io.model.IBuffer,
00046                 mango.io.model.IWriter;
00047 
00048 /******************************************************************************
00049 
00050         Abstract class to asynchronously listen for incoming data on a 
00051         socket. This can be used with DatagramSocket & MulticastSocket, 
00052         and might possibly be useful with a basic SocketConduit also.
00053         Note that DatagramSocket must first be bound to a local network
00054         address via bind(), and MulticastSocket should first be made a 
00055         member of a multicast group via its join() method. Note also
00056         that the underlying thread is not started by the constructor;
00057         you should do that manually via the start() method.
00058 
00059 ******************************************************************************/
00060 
00061 //version = AltListener;
00062 
00063 version (AltListener)
00064          alias Object FOO;
00065         else
00066          alias Thread FOO;
00067 
00068 class SocketListener : FOO, IListener
00069 {
00070         private bool                    quit;
00071         private IBuffer                 buffer;
00072         private ISocketReader           reader;
00073         private int                     limit = 3;
00074 
00075         /**********************************************************************
00076                
00077                 Construct a listener with the requisite arguments. The
00078                 specified buffer is populated via the provided instance
00079                 of ISocketReader before being passed to the notify()
00080                 method. All arguments are required.
00081 
00082         **********************************************************************/
00083 
00084         this (ISocketReader reader, IBuffer buffer)
00085         in {
00086            assert (reader);
00087            assert (buffer);
00088            }
00089         body
00090         {
00091                 this.buffer = buffer;
00092                 this.reader = reader;
00093                 version (AltListener)
00094                         {
00095                         Thread t = new Thread (&run);
00096                         t.start();
00097                         }
00098         }
00099 
00100         version (AltListener)
00101                  void start(){}
00102 
00103         /***********************************************************************
00104                 
00105                 Notification callback invoked whenever the listener has
00106                 anything to report. The buffer will have whatever content
00107                 was available from the read() operation
00108 
00109         ***********************************************************************/
00110 
00111         abstract void notify (IBuffer buffer);
00112 
00113         /***********************************************************************
00114 
00115                 Handle error conditions from the listener thread.
00116 
00117         ***********************************************************************/
00118 
00119         abstract void exception (char[] msg);
00120 
00121         /**********************************************************************
00122              
00123                 Cancel this listener. The thread will quit only after the 
00124                 current read() request responds, or is interrrupted.
00125 
00126         **********************************************************************/
00127 
00128         void cancel ()
00129         {
00130                 quit = true;
00131         }
00132 
00133         /**********************************************************************
00134              
00135                 Set the maximum contiguous number of exceptions this 
00136                 listener will survive. Setting a limit of zero will 
00137                 not survive any errors at all, whereas a limit of two
00138                 will survive as long as two consecutive errors don't 
00139                 arrive back to back.
00140 
00141         **********************************************************************/
00142 
00143         void setErrorLimit (ushort limit)
00144         {
00145                 this.limit = limit + 1;
00146         }
00147 
00148         /**********************************************************************
00149 
00150                 Execution of this thread is typically stalled on the
00151                 read() method belonging to the ISocketReader specified
00152                 during construction. You can invoke cancel() to indicate
00153                 execution should not proceed further, but that will not
00154                 actually interrupt a blocked read() operation.
00155 
00156                 Note that exceptions are all directed towards the handler
00157                 implemented by the class instance. 
00158 
00159         **********************************************************************/
00160 
00161         int run ()
00162         {
00163                 int lives = limit;
00164 
00165                 while (lives > 0)
00166                        try {
00167                            // start with a clean slate
00168                            buffer.clear ();
00169 
00170                            // wait for incoming content
00171                            reader.read (buffer);
00172 
00173                            // time to quit? Note that a v0.95 compiler bug 
00174                            // prohibits 'break' from exiting the try{} block
00175                            if (quit || Socket.isCancelled ())
00176                                lives = 0;
00177                            else
00178                               {
00179                               // invoke callback                        
00180                               notify (buffer);
00181                               lives = limit;
00182                               }
00183                            } catch (Object x)
00184                                     // time to quit?
00185                                     if (quit || Socket.isCancelled ())
00186                                         break;
00187                                     else
00188                                        {
00189                                        exception (x.toString);
00190                                        if (--lives == 0)
00191                                            exception ("listener thread aborting");
00192                                        }
00193                 version (TraceLinux)
00194                         {
00195                         printf ("SocketListener exiting\n");
00196                         }
00197                 return 0;
00198         }
00199 }
00200 
00201 
00202 

Generated on Sun Mar 6 00:30:58 2005 for Mango by doxygen 1.3.6