Sirikata
libcore/include/sirikata/core/network/IOService.hpp
Go to the documentation of this file.
00001 /*  Sirikata Network Utilities
00002  *  IOService.hpp
00003  *
00004  *  Copyright (c) 2009, Daniel Reiter Horn
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions are
00009  *  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
00014  *    the documentation and/or other materials provided with the
00015  *    distribution.
00016  *  * Neither the name of Sirikata nor the names of its contributors may
00017  *    be used to endorse or promote products derived from this software
00018  *    without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00021  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00022  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00023  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00024  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00025  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00026  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00027  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00028  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00029  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  */
00032 #ifndef _SIRIKATA_IOSERVICE_HPP_
00033 #define _SIRIKATA_IOSERVICE_HPP_
00034 
00035 #include <sirikata/core/util/Platform.hpp>
00036 #include <sirikata/core/network/IODefs.hpp>
00037 #include <sirikata/core/util/AtomicTypes.hpp>
00038 #include <sirikata/core/util/Noncopyable.hpp>
00039 #include <boost/thread.hpp>
00040 #include <sirikata/core/trace/WindowedStats.hpp>
00041 #include <sirikata/core/task/Time.hpp>
00042 #include <sirikata/core/command/Command.hpp>
00043 
00044 namespace Sirikata {
00045 namespace Network {
00046 
00056 class SIRIKATA_EXPORT IOService : public Noncopyable {
00057     InternalIOService* mImpl;
00058     const String mName;
00059 
00060 #ifdef SIRIKATA_TRACK_EVENT_QUEUES
00061     typedef std::tr1::function<void(const boost::system::error_code& e)> IOCallbackWithError;
00062 
00063     // Track all strands that have been allocated. This needs to be
00064     // thread safe.
00065     typedef boost::mutex Mutex;
00066     typedef boost::lock_guard<Mutex> LockGuard;
00067     Mutex mMutex;
00068     typedef std::tr1::unordered_set<IOStrand*> StrandSet;
00069     StrandSet mStrands;
00070 
00071     AtomicValue<uint32> mTimersEnqueued;
00072     AtomicValue<uint32> mEnqueued;
00073 
00074     // Tracks the latency of recent handlers through the queue
00075     Trace::WindowedStats<Duration> mWindowedTimerLatencyStats;
00076     Trace::WindowedStats<Duration> mWindowedHandlerLatencyStats;
00077 
00078 
00079     struct TagDuration
00080     {
00081         const char* tag;
00082         Duration dur;
00083     };
00084     Trace::WindowedStats<TagDuration> mWindowedLatencyTagStats;
00085 
00086 
00087     // Track tags that trigger events
00088     typedef std::tr1::unordered_map<const char*, uint32> TagCountMap;
00089     TagCountMap mTagCounts;
00090 #endif
00091 
00092     IOService(const IOService&); // Disabled
00093 
00094     // For construction
00095     friend class IOServiceFactory;
00096     // For callbacks to track their lifetimes
00097     friend class IOStrand;
00098 
00099 #ifdef SIRIKATA_TRACK_EVENT_QUEUES
00100     void decrementTimerCount(const boost::system::error_code&e, const Time& start, const Duration& timer_duration, const IOCallbackWithError& cb, const char* tag, const char* tagStat=NULL);
00101     void decrementCount(const Time& start, const IOCallback& cb, const char* tag, const char* tagStat=NULL);
00102 
00103     // Used to get let us add a record of a strand dispatch/post and provide a
00104     // wrapped handler which will let us clean up our record of it. This is
00105     // necessary because we can't do the dispatch/post for the strand using
00106     // a strand-wrapped handler because that doesn't have the same ordering
00107     // guarantees.
00108     IOCallback tracking_wrapper(const IOCallback& handler, const char* tag = NULL, const char* tagStat = NULL);
00109 
00110     // Invoked by strands when they are being destroyed so we can
00111     // track which ones are alive.
00112     void destroyingStrand(IOStrand* child);
00113 #endif
00114 
00115   protected:
00116 
00117     friend class InternalIOStrand;
00118     friend class InternalIOWork;
00119     friend class TCPSocket;
00120     friend class TCPListener;
00121     friend class TCPResolver;
00122     friend class UDPSocket;
00123     friend class UDPResolver;
00124     friend class DeadlineTimer;
00125     friend class IOTimer;
00126 
00127 public:
00128 
00129 
00130     IOService(const String& name);
00131     ~IOService();
00132 
00134     const String& name() const { return mName; }
00135 
00140     InternalIOService& asioService() {
00141         return *mImpl;
00142     }
00147     const InternalIOService& asioService() const {
00148         return *mImpl;
00149     }
00150 
00152     IOStrand* createStrand(const String& name);
00153 
00157     uint32 pollOne();
00161     uint32 poll();
00162 
00166     uint32 runOne();
00172     uint32 run();
00173 
00179     void runNoReturn();
00180 
00182     void stop();
00186     void reset();
00187 
00193     void dispatch(const IOCallback& handler, const char* tag = NULL,
00194         const char* tagStat = NULL);
00195 
00202     void post(const IOCallback& handler, const char* tag = NULL,
00203         const char* tagStat = NULL);
00211     void post(const Duration& waitFor, const IOCallback& handler,
00212         const char* tag = NULL, const char* tagStat=NULL);
00213 
00214 #ifdef SIRIKATA_TRACK_EVENT_QUEUES
00215     uint32 numTimersEnqueued() const { return mTimersEnqueued.read(); }
00216     uint32 numEnqueued() const { return mEnqueued.read(); }
00217 
00218     Duration timerLatency() const { return mWindowedTimerLatencyStats.average(); }
00219     Duration handlerLatency() const { return mWindowedHandlerLatencyStats.average(); }
00220 
00224     void reportStats() const;
00225     void reportStatsFile(const char* filename, bool detailed) const;
00226 
00227     static void reportAllStats();
00228     static void reportAllStatsFile(const char* filename, bool detailed = false);
00229 
00230     // Respond to command to report all stats.
00231     void fillCommandResultWithStats(Command::Result& res);
00232 #endif
00233     void commandReportStats(const Command::Command& cmd, Command::Commander* cmdr, Command::CommandID cmdid);
00234     static void commandReportAllStats(const Command::Command& cmd, Command::Commander* cmdr, Command::CommandID cmdid);
00235 };
00236 
00237 } // namespace Network
00238 } // namespace Sirikata
00239 
00240 #endif //_SIRIKATA_IOSERVICE_HPP_