netrq.h

Go to the documentation of this file.
00001 /*
00002  * netrq.h
00003  *
00004  * Copyright (c) 2009 Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Simple library for handling network request queues.
00032  */
00033 
00034 #ifndef WAVEPACKET_NETRQ_H__
00035 #define WAVEPACKET_NETRQ_H__
00036 
00037 
00038 // includes --------------------------------------------------------------------
00039 #include "xdrbuf/xdrbuf.h"              // depends on XDR buffer library
00040 
00041 #include "threadsafe/smart_ptr.h"
00042 
00043 
00044 namespace netrq {
00045 
00046 // doxygen block
00047 
00048 /// \ingroup networking
00049 /*@{*/
00050 
00051 ////////////////////////////////////////////////////////////////////////////////
00052 ///
00053 /// \defgroup netrq Network Request Queue
00054 ///
00055 /// \n
00056 /// A network request queue.  Clients can add requests with an ID and priority.
00057 /// Later, clients can pull the most immediate requests from the queue,
00058 /// and that request will be backed off.  Finally, clients can remove requests
00059 /// altogether.
00060 ///
00061 /// The client must construct IDs on its own.
00062 ///
00063 /// This library makes use of a "clock".  In the context of a network request
00064 /// queue, this is just a serial counter, not a timer.  There is a clock tick
00065 /// per datagram sent out.  This library relies on the client maintaining its
00066 /// own clock, and respects whatever the client provides as far as current and
00067 /// requested clock values.
00068 ///
00069 ////////////////////////////////////////////////////////////////////////////////
00070 /*@{*/
00071 
00072 
00073 /// Base class from which clients can inherit.  This is how you can store
00074 /// per-request context (state) in the queue, and have it automatically cleaned
00075 /// up.
00076 class Request {
00077 public:
00078         // virtual destructor --------------------------------------------------
00079         virtual ~Request(void) throw();
00080 
00081         // netrq::Request class interface methods ------------------------------
00082         virtual const char * getId(void) const throw() = 0;
00083         virtual int getMaxBytes(void) const throw() = 0;
00084         virtual void write(IO xdrbuf::Output * output) = 0;
00085 
00086         /// if non-zero, this request is asking to be resent after the
00087         ///     specified clock interval
00088         virtual int getRetryInterval(void) const throw() { return 0; }
00089 };
00090 
00091 
00092 
00093 /// basic network request queue.
00094 ///
00095 /// This class is \b threadsafe .  In some situations (single-threaded client)
00096 /// this may be unnecessary overhead, but given the common use case (reacting to
00097 /// or sending UDP diagrams) this isn't expected to be much overhead.
00098 class Queue {
00099 public:
00100         // public enums --------------------------------------------------------
00101         enum eInsertResult {
00102                 eQueue_Success                            = 0,
00103                 eQueue_Failed_CurrentEntryHasLaterClock   = 1,
00104                 eQueue_Failed_CurrentEntryHasEarlierClock = 2,
00105 
00106                 // keep this last
00107                 eQueue_Failed_Unknown                     = 3
00108         };
00109 
00110         // virtual destructor --------------------------------------------------
00111         virtual ~Queue(void) throw();
00112 
00113         // netrq::Queue class interface methods --------------------------------
00114 
00115         /// Returns count of requests in queue.  Approximate only, since other
00116         /// threads may update the queue by the time the caller gets the count.
00117         virtual int size(void) = 0;
00118 
00119         /// If the addRequest fails due to a collision, the return value will
00120         /// tell the client whether the existing request has an earlier or later
00121         /// clock than what was just requested.
00122         virtual eInsertResult addRequest(
00123                                 IN dword_t sendClock, ///< send at this clock
00124                                 IN smart_ptr<Request>& request) = 0;
00125 
00126         /// returns the next request that should be sent.  The clock value is
00127         /// the current packet count, not the time.  So for instance, if you are
00128         /// using this queue to manage UDP data, increment the clock everytime
00129         /// you send a UDP packet.
00130         virtual bool getNextRequest(IN dword_t clock, ///< current clock
00131                                 OUT smart_ptr<Request>& request) = 0;
00132 
00133         /// does the queue already contain a request with this id?
00134         virtual bool containsRequest(IN const char * id) = 0;
00135 
00136         virtual bool removeRequest(IN const char * id) = 0;
00137 
00138         // static factory methods ----------------------------------------------
00139         static smart_ptr<Queue> create(void);
00140 };
00141 
00142 
00143 
00144 //
00145 // helper methods
00146 //
00147 
00148 /// Given an output buffer, write as many pending requests as possible.  All
00149 /// sent messages are removed from the queue.  Returns the number of messages
00150 /// sent.  See the netrq library comments regarding the clock values.
00151 int sendMessagesFromQueue(IO xdrbuf::Output * output,
00152                                 IN dword_t clock, ///< current clock
00153                                 IO Queue * queue);
00154 
00155 
00156 };      // netrq namespace
00157 
00158 /*@}*/  // end of documentation block
00159 
00160 #endif  // WAVEPACKET_NETRQ_H__
00161