1 #ifndef CONNECT___THREADED_SERVER__HPP 2 #define CONNECT___THREADED_SERVER__HPP 3 4 /* $Id: threaded_server.hpp 575325 2018-11-27 18:22:00Z ucko $ 5 * =========================================================================== 6 * 7 * PUBLIC DOMAIN NOTICE 8 * National Center for Biotechnology Information 9 * 10 * This software/database is a "United States Government Work" under the 11 * terms of the United States Copyright Act. It was written as part of 12 * the author's official duties as a United States Government employee and 13 * thus cannot be copyrighted. This software/database is freely available 14 * to the public for use. The National Library of Medicine and the U.S. 15 * Government have not placed any restriction on its use or reproduction. 16 * 17 * Although all reasonable efforts have been taken to ensure the accuracy 18 * and reliability of the software and data, the NLM and the U.S. 19 * Government do not and cannot warrant the performance or results that 20 * may be obtained by using this software or data. The NLM and the U.S. 21 * Government disclaim all warranties, express or implied, including 22 * warranties of performance, merchantability or fitness for any particular 23 * purpose. 24 * 25 * Please cite the author in any work or product based on this material. 26 * 27 * =========================================================================== 28 * 29 * Author: Aaron Ucko 30 * 31 * File Description: 32 * Framework for a multithreaded network server 33 * 34 */ 35 36 #include <connect/ncbi_conn_exception.hpp> 37 #include <connect/ncbi_core_cxx.hpp> 38 #include <connect/ncbi_socket.hpp> 39 40 41 /** @addtogroup ThreadedServer 42 * 43 * @{ 44 */ 45 46 47 BEGIN_NCBI_SCOPE 48 49 50 /// Exceptions thrown by CThreadedServer::Run 51 class NCBI_XCONNECT_EXPORT CThreadedServerException 52 : EXCEPTION_VIRTUAL_BASE public CConnException 53 { 54 public: 55 enum EErrCode { 56 eBadParameters, ///< Out-of-range parameters given 57 eCouldntListen ///< Unable to bind listening port 58 }; 59 virtual const char* GetErrCodeString(void) const override; 60 NCBI_EXCEPTION_DEFAULT(CThreadedServerException, CConnException); 61 }; 62 63 64 /// CThreadedServer - abstract class for network servers using thread pools. 65 /// This code maintains a pool of threads (initially m_InitThreads, but 66 /// potentially as many as m_MaxThreads) to deal with incoming connections; 67 /// each connection gets assigned to one of the worker threads, allowing 68 /// the server to handle multiple requests in parallel while still checking 69 /// for new requests. 70 /// 71 /// You must define Process() to indicate what to do with each incoming 72 /// connection; .../src/connect/test_threaded_server.cpp illustrates 73 /// how you might do this. 74 /// 75 /// @deprecated Use CServer instead. 76 77 NCBI_DEPRECATED_CLASS NCBI_XCONNECT_EXPORT CThreadedServer 78 : protected CConnIniter 79 { 80 public: 81 CThreadedServer(unsigned short port) : 82 m_InitThreads(5), m_MaxThreads(10), m_QueueSize(20), 83 m_SpawnThreshold(1), m_AcceptTimeout(kInfiniteTimeout), 84 m_TemporarilyStopListening(false), m_Port(port) { } 85 86 virtual ~CThreadedServer() { } 87 88 /// Enter the main loop. 89 void Run(void); 90 91 /// Start listening immediately, or throw an exception if it is 92 /// impossible to do so. (Does nothing if *this* object is 93 /// already listening on the port.) Calling StartListening() 94 /// before Run() will permit detecting port-in-use problems before 95 /// the last minute. (On the other hand, clients that attempt to 96 /// connect in the interim will get no response until the main 97 /// loop actually starts.) 98 void StartListening(void); 99 100 /// Runs asynchronously (from a separate thread) for each request. 101 /// Implementor must take care of closing the socket when done. 102 /// (Using it as the basis of a CConn_SocketStream object will do 103 /// so automatically.) 104 virtual void Process(SOCK sock) = 0; 105 106 /// Get the listening port number back. 107 unsigned short GetPort() const { return m_Port; } 108 109 protected: 110 /// Runs synchronously when request queue is full. 111 /// Implementor must take care of closing socket when done. 112 virtual void ProcessOverflow(SOCK sock) { SOCK_Close(sock); } 113 114 /// Runs synchronously when accept has timed out. 115 virtual void ProcessTimeout(void) {} 116 117 /// Runs synchronously between iterations. 118 virtual bool ShutdownRequested(void) { return false; } 119 120 /// Called at the beginning of Run, before creating thread pool. 121 virtual void SetParams() {} 122 123 /// Settings for thread pool (which is local to Run): 124 125 unsigned int m_InitThreads; ///< Number of initial threads 126 unsigned int m_MaxThreads; ///< Maximum simultaneous threads 127 unsigned int m_QueueSize; ///< Maximum size of request queue 128 unsigned int m_SpawnThreshold; ///< Controls when to spawn more threads 129 const STimeout* m_AcceptTimeout; ///< Maximum time between exit checks 130 131 /// Temporarily close listener when queue fills? 132 bool m_TemporarilyStopListening; 133 134 private: 135 unsigned short m_Port; ///< TCP port to listen on 136 CListeningSocket m_LSock; ///< Listening socket 137 }; 138 139 140 END_NCBI_SCOPE 141 142 143 /* @} */ 144 145 #endif /* CONNECT___THREADED_SERVER__HPP */ 146