├── .clang-tidy ├── .github ├── ISSUE_TEMPLATE │ └── bug_report.md └── issue_template.md ├── .gitignore ├── .travis.yml ├── BUILD.bazel ├── CMakeLists.txt ├── ChangeLog ├── ChangeLog2 ├── License ├── README ├── WORKSPACE ├── build.sh ├── contrib ├── CMakeLists.txt ├── hiredis │ ├── CMakeLists.txt │ ├── Hiredis.cc │ ├── Hiredis.h │ ├── README.md │ └── mrediscli.cc └── thrift │ ├── CMakeLists.txt │ ├── ThriftConnection.cc │ ├── ThriftConnection.h │ ├── ThriftServer.cc │ ├── ThriftServer.h │ └── tests │ ├── .gitignore │ ├── CMakeLists.txt │ ├── echo │ ├── CMakeLists.txt │ ├── EchoServer.cc │ ├── echo.thrift │ └── echoclient.py │ └── ping │ ├── CMakeLists.txt │ ├── PingServer.cc │ ├── ping.thrift │ └── pingclient.py ├── examples ├── CMakeLists.txt ├── ace │ ├── logging │ │ ├── CMakeLists.txt │ │ ├── client.cc │ │ ├── logrecord.proto │ │ └── server.cc │ └── ttcp │ │ ├── CMakeLists.txt │ │ ├── common.cc │ │ ├── common.h │ │ ├── main.cc │ │ ├── ttcp.cc │ │ ├── ttcp_asio_async.cc │ │ ├── ttcp_asio_sync.cc │ │ └── ttcp_blocking.cc ├── asio │ ├── chat │ │ ├── CMakeLists.txt │ │ ├── client.cc │ │ ├── codec.h │ │ ├── loadtest.cc │ │ ├── server.cc │ │ ├── server_threaded.cc │ │ ├── server_threaded_efficient.cc │ │ └── server_threaded_highperformance.cc │ ├── echo_see_simple │ └── tutorial │ │ ├── CMakeLists.txt │ │ ├── daytime_see_simple │ │ ├── there_is_no_timer1 │ │ ├── timer2 │ │ └── timer.cc │ │ ├── timer3 │ │ └── timer.cc │ │ ├── timer4 │ │ └── timer.cc │ │ ├── timer5 │ │ └── timer.cc │ │ └── timer6 │ │ └── timer.cc ├── cdns │ ├── CMakeLists.txt │ ├── Resolver.cc │ ├── Resolver.h │ └── dns.cc ├── curl │ ├── CMakeLists.txt │ ├── Curl.cc │ ├── Curl.h │ ├── README │ ├── download.cc │ └── mcurl.cc ├── fastcgi │ ├── CMakeLists.txt │ ├── fastcgi.cc │ ├── fastcgi.h │ ├── fastcgi_test.cc │ └── nginx.conf ├── filetransfer │ ├── CMakeLists.txt │ ├── download.cc │ ├── download2.cc │ ├── download3.cc │ └── loadtest │ │ ├── Client.java │ │ └── Handler.java ├── hub │ ├── CMakeLists.txt │ ├── README │ ├── codec.cc │ ├── codec.h │ ├── hub.cc │ ├── pub.cc │ ├── pubsub.cc │ ├── pubsub.h │ └── sub.cc ├── idleconnection │ ├── CMakeLists.txt │ ├── echo.cc │ ├── echo.h │ ├── main.cc │ └── sortedlist.cc ├── maxconnection │ ├── CMakeLists.txt │ ├── echo.cc │ ├── echo.h │ └── main.cc ├── memcached │ ├── README │ ├── client │ │ ├── CMakeLists.txt │ │ └── bench.cc │ └── server │ │ ├── CMakeLists.txt │ │ ├── Item.cc │ │ ├── Item.h │ │ ├── MemcacheServer.cc │ │ ├── MemcacheServer.h │ │ ├── Session.cc │ │ ├── Session.h │ │ ├── footprint_test.cc │ │ └── server.cc ├── multiplexer │ ├── CMakeLists.txt │ ├── demux.cc │ ├── harness │ │ ├── run.sh │ │ └── src │ │ │ └── com │ │ │ └── chenshuo │ │ │ └── muduo │ │ │ └── example │ │ │ └── multiplexer │ │ │ ├── DataEvent.java │ │ │ ├── Event.java │ │ │ ├── EventQueue.java │ │ │ ├── EventSource.java │ │ │ ├── MockBackendServer.java │ │ │ ├── MockClient.java │ │ │ ├── MultiplexerTest.java │ │ │ ├── MyCountDownLatch.java │ │ │ ├── TestCase.java │ │ │ ├── TestFailedException.java │ │ │ └── testcase │ │ │ ├── TestOneClientBackendSend.java │ │ │ ├── TestOneClientBothSend.java │ │ │ ├── TestOneClientNoData.java │ │ │ ├── TestOneClientSend.java │ │ │ └── TestTwoClients.java │ ├── multiplexer.cc │ └── multiplexer_simple.cc ├── netty │ ├── discard │ │ ├── CMakeLists.txt │ │ ├── client.cc │ │ └── server.cc │ ├── echo │ │ ├── CMakeLists.txt │ │ ├── client.cc │ │ ├── server.cc │ │ └── server2.cc │ └── uptime │ │ ├── CMakeLists.txt │ │ └── uptime.cc ├── pingpong │ ├── CMakeLists.txt │ ├── bench.cc │ ├── client.cc │ └── server.cc ├── procmon │ ├── CMakeLists.txt │ ├── dummyload.cc │ ├── plot.cc │ ├── plot.h │ ├── plot_test.cc │ └── procmon.cc ├── protobuf │ ├── CMakeLists.txt │ ├── codec │ │ ├── CMakeLists.txt │ │ ├── client.cc │ │ ├── codec.cc │ │ ├── codec.h │ │ ├── codec_test.cc │ │ ├── dispatcher.h │ │ ├── dispatcher_lite.h │ │ ├── dispatcher_lite_test.cc │ │ ├── dispatcher_test.cc │ │ ├── query.proto │ │ └── server.cc │ ├── resolver │ │ ├── CMakeLists.txt │ │ ├── client.cc │ │ ├── resolver.proto │ │ └── server.cc │ ├── rpc │ │ ├── CMakeLists.txt │ │ ├── client.cc │ │ ├── server.cc │ │ └── sudoku.proto │ ├── rpcbalancer │ │ ├── CMakeLists.txt │ │ ├── balancer.cc │ │ └── balancer_raw.cc │ └── rpcbench │ │ ├── CMakeLists.txt │ │ ├── client.cc │ │ ├── echo.proto │ │ └── server.cc ├── roundtrip │ ├── CMakeLists.txt │ ├── roundtrip.cc │ └── roundtrip_udp.cc ├── shorturl │ ├── CMakeLists.txt │ └── shorturl.cc ├── simple │ ├── CMakeLists.txt │ ├── allinone │ │ └── allinone.cc │ ├── chargen │ │ ├── chargen.cc │ │ ├── chargen.h │ │ └── main.cc │ ├── chargenclient │ │ └── chargenclient.cc │ ├── daytime │ │ ├── daytime.cc │ │ ├── daytime.h │ │ └── main.cc │ ├── discard │ │ ├── discard.cc │ │ ├── discard.h │ │ └── main.cc │ ├── echo │ │ ├── echo.cc │ │ ├── echo.h │ │ └── main.cc │ ├── time │ │ ├── main.cc │ │ ├── time.cc │ │ └── time.h │ └── timeclient │ │ └── timeclient.cc ├── socks4a │ ├── CMakeLists.txt │ ├── balancer.cc │ ├── socks4a.cc │ ├── tcprelay.cc │ └── tunnel.h ├── sudoku │ ├── CMakeLists.txt │ ├── batch.cc │ ├── loadtest.cc │ ├── percentile.h │ ├── pipeline.cc │ ├── server_basic.cc │ ├── server_hybrid.cc │ ├── server_multiloop.cc │ ├── server_prod.cc │ ├── server_threadpool.cc │ ├── stat.h │ ├── stat_unittest.cc │ ├── sudoku.cc │ └── sudoku.h ├── twisted │ └── finger │ │ ├── CMakeLists.txt │ │ ├── README │ │ ├── finger01.cc │ │ ├── finger02.cc │ │ ├── finger03.cc │ │ ├── finger04.cc │ │ ├── finger05.cc │ │ ├── finger06.cc │ │ └── finger07.cc ├── wordcount │ ├── CMakeLists.txt │ ├── README │ ├── gen.py │ ├── hash.h │ ├── hasher.cc │ ├── receiver.cc │ └── slowsink.py └── zeromq │ ├── CMakeLists.txt │ ├── README │ ├── local_lat.cc │ └── remote_lat.cc ├── muduo ├── base │ ├── AsyncLogging.cc │ ├── AsyncLogging.h │ ├── Atomic.h │ ├── BUILD.bazel │ ├── BlockingQueue.h │ ├── BoundedBlockingQueue.h │ ├── CMakeLists.txt │ ├── Condition.cc │ ├── Condition.h │ ├── CountDownLatch.cc │ ├── CountDownLatch.h │ ├── CurrentThread.cc │ ├── CurrentThread.h │ ├── Date.cc │ ├── Date.h │ ├── Exception.cc │ ├── Exception.h │ ├── FileUtil.cc │ ├── FileUtil.h │ ├── GzipFile.h │ ├── LogFile.cc │ ├── LogFile.h │ ├── LogStream.cc │ ├── LogStream.h │ ├── Logging.cc │ ├── Logging.h │ ├── Mutex.h │ ├── ProcessInfo.cc │ ├── ProcessInfo.h │ ├── Singleton.h │ ├── StringPiece.h │ ├── Thread.cc │ ├── Thread.h │ ├── ThreadLocal.h │ ├── ThreadLocalSingleton.h │ ├── ThreadPool.cc │ ├── ThreadPool.h │ ├── TimeZone.cc │ ├── TimeZone.h │ ├── Timestamp.cc │ ├── Timestamp.h │ ├── Types.h │ ├── WeakCallback.h │ ├── copyable.h │ ├── noncopyable.h │ └── tests │ │ ├── AsyncLogging_test.cc │ │ ├── Atomic_unittest.cc │ │ ├── BlockingQueue_bench.cc │ │ ├── BlockingQueue_bench2.cc │ │ ├── BlockingQueue_test.cc │ │ ├── BoundedBlockingQueue_test.cc │ │ ├── CMakeLists.txt │ │ ├── Date_unittest.cc │ │ ├── Exception_test.cc │ │ ├── FileUtil_test.cc │ │ ├── Fork_test.cc │ │ ├── GzipFile_test.cc │ │ ├── LogFile_test.cc │ │ ├── LogStream_bench.cc │ │ ├── LogStream_test.cc │ │ ├── Logging_test.cc │ │ ├── Mutex_test.cc │ │ ├── ProcessInfo_test.cc │ │ ├── SingletonThreadLocal_test.cc │ │ ├── Singleton_test.cc │ │ ├── ThreadLocalSingleton_test.cc │ │ ├── ThreadLocal_test.cc │ │ ├── ThreadPool_test.cc │ │ ├── Thread_bench.cc │ │ ├── Thread_test.cc │ │ ├── TimeZone_unittest.cc │ │ ├── TimeZone_util.cc │ │ └── Timestamp_unittest.cc └── net │ ├── Acceptor.cc │ ├── Acceptor.h │ ├── BUILD.bazel │ ├── Buffer.cc │ ├── Buffer.h │ ├── CMakeLists.txt │ ├── Callbacks.h │ ├── Channel.cc │ ├── Channel.h │ ├── Connector.cc │ ├── Connector.h │ ├── Endian.h │ ├── EventLoop.cc │ ├── EventLoop.h │ ├── EventLoopThread.cc │ ├── EventLoopThread.h │ ├── EventLoopThreadPool.cc │ ├── EventLoopThreadPool.h │ ├── InetAddress.cc │ ├── InetAddress.h │ ├── Poller.cc │ ├── Poller.h │ ├── Socket.cc │ ├── Socket.h │ ├── SocketsOps.cc │ ├── SocketsOps.h │ ├── TcpClient.cc │ ├── TcpClient.h │ ├── TcpConnection.cc │ ├── TcpConnection.h │ ├── TcpServer.cc │ ├── TcpServer.h │ ├── Timer.cc │ ├── Timer.h │ ├── TimerId.h │ ├── TimerQueue.cc │ ├── TimerQueue.h │ ├── ZlibStream.h │ ├── boilerplate.cc │ ├── boilerplate.h │ ├── http │ ├── BUILD.bazel │ ├── CMakeLists.txt │ ├── HttpContext.cc │ ├── HttpContext.h │ ├── HttpRequest.h │ ├── HttpResponse.cc │ ├── HttpResponse.h │ ├── HttpServer.cc │ ├── HttpServer.h │ └── tests │ │ ├── HttpRequest_unittest.cc │ │ └── HttpServer_test.cc │ ├── inspect │ ├── BUILD.bazel │ ├── CMakeLists.txt │ ├── Inspector.cc │ ├── Inspector.h │ ├── PerformanceInspector.cc │ ├── PerformanceInspector.h │ ├── ProcessInspector.cc │ ├── ProcessInspector.h │ ├── SystemInspector.cc │ ├── SystemInspector.h │ └── tests │ │ ├── BUILD.bazel │ │ └── Inspector_test.cc │ ├── poller │ ├── DefaultPoller.cc │ ├── EPollPoller.cc │ ├── EPollPoller.h │ ├── PollPoller.cc │ └── PollPoller.h │ ├── protobuf │ ├── BufferStream.h │ ├── CMakeLists.txt │ ├── ProtobufCodecLite.cc │ └── ProtobufCodecLite.h │ ├── protorpc │ ├── CMakeLists.txt │ ├── README │ ├── RpcChannel.cc │ ├── RpcChannel.h │ ├── RpcCodec.cc │ ├── RpcCodec.h │ ├── RpcCodec_test.cc │ ├── RpcServer.cc │ ├── RpcServer.h │ ├── google-inl.h │ ├── rpc.proto │ └── rpcservice.proto │ └── tests │ ├── Buffer_unittest.cc │ ├── CMakeLists.txt │ ├── Channel_test.cc │ ├── EchoClient_unittest.cc │ ├── EchoServer_unittest.cc │ ├── EventLoopThreadPool_unittest.cc │ ├── EventLoopThread_unittest.cc │ ├── EventLoop_unittest.cc │ ├── InetAddress_unittest.cc │ ├── TcpClient_reg1.cc │ ├── TcpClient_reg2.cc │ ├── TcpClient_reg3.cc │ ├── TimerQueue_unittest.cc │ └── ZlibStream_unittest.cc └── patches ├── MacOSX.diff ├── armlinux.diff └── backport.diff /.clang-tidy: -------------------------------------------------------------------------------- 1 | --- 2 | # Only run a few checks for now. 3 | Checks: 'performance-*' 4 | WarningsAsErrors: '' 5 | HeaderFilterRegex: '' 6 | AnalyzeTemporaryDtors: false 7 | FormatStyle: none 8 | User: chenshuo 9 | CheckOptions: 10 | - key: google-runtime-references.WhiteListTypes 11 | value: 'muduo::MutexLock' 12 | - key: llvm-namespace-comment.ShortNamespaceLines 13 | value: '10' 14 | - key: llvm-namespace-comment.SpacesBeforeComments 15 | value: '2' 16 | - key: MuduoRootDirectory 17 | value: '/muduo-cpp11/' 18 | ExtraArgs: 19 | - '-Wno-sign-conversion' 20 | ... 21 | 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | DELETE FROM HERE TO LINE 18 BEFORE OPEN AN ISSUE. 11 | 12 | GitHub issues are for tracking bugs, not for general discussing like a forum. 13 | 14 | If you have a general question to ask, use GitHub discussions: 15 | 16 | https://github.com/chenshuo/muduo/discussions 17 | 18 | When filing an issue of muduo, please provide a [SSCCE](http://sscce.org): 19 | Short, Self Contained, Correct (Compilable), Example. 20 | 21 | If you can't compile muduo, make sure you install `cmake` and `boost` from the 22 | official package repository, e.g. `apt` or `yum`, before opening a bug. 23 | Don't open a bug if you installed boost from a third-party source or 24 | downloaded it by yourself, and couldn't compile muduo, thank you. 25 | 26 | Also specify the exact environment where the issue occurs: 27 | 28 | ## Linux distro and version? x86 or ARM? 32-bit or 64-bit? 29 | 30 | ## Branch (cpp98/cpp11/cpp17) and version of muduo? 31 | 32 | ## Version of cmake, gcc and boost? (If not from distro.) 33 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | DELETE FROM HERE TO LINE 18 BEFORE OPEN AN ISSUE. 2 | 3 | GitHub issues are for tracking bugs, not for general discussing like a forum. 4 | 5 | If you have a general question to ask, use GitHub discussions: 6 | 7 | https://github.com/chenshuo/muduo/discussions 8 | 9 | When filing an issue of muduo, please provide a [SSCCE](http://sscce.org): 10 | Short, Self Contained, Correct (Compilable), Example. 11 | 12 | If you can't compile muduo, make sure you install `cmake` and `boost` from the 13 | official package repository, e.g. `apt` or `yum`, before opening a bug. 14 | Don't open a bug if you installed boost from a third-party source or 15 | downloaded it by yourself, and couldn't compile muduo, thank you. 16 | 17 | Also specify the exact environment where the issue occurs: 18 | 19 | ## Linux distro and version? x86 or ARM? 32-bit or 64-bit? 20 | 21 | ## Branch (cpp98/cpp11/cpp17) and version of muduo? 22 | 23 | ## Version of cmake, gcc and boost? (If not from distro.) 24 | 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | bazel-* 3 | compile_commands.json 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | sudo: required 3 | compiler: 4 | - gcc 5 | - clang 6 | os: 7 | - linux 8 | install: 9 | - sudo apt-get install libboost-dev 10 | - sudo apt-get install libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev 11 | - sudo apt-get install libboost-test-dev libboost-program-options-dev libboost-system-dev 12 | - sudo apt-get install libc-ares-dev libcurl4-openssl-dev 13 | - sudo apt-get install zlib1g-dev libgd-dev 14 | env: 15 | - BUILD_TYPE=debug 16 | - BUILD_TYPE=release 17 | script: 18 | - ./build.sh 19 | -------------------------------------------------------------------------------- /BUILD.bazel: -------------------------------------------------------------------------------- 1 | # See https://github.com/chenshuo/muduo-tutorial for how to use muduo in your project. 2 | -------------------------------------------------------------------------------- /ChangeLog2: -------------------------------------------------------------------------------- 1 | 2018-10-24 Shuo Chen 2 | * First release of C++11 version of muduo. 3 | * Forked after v1.0.9, e6c04c43 is the base. changes in cpp98 branch are integrated 4 | * Replace boost::shared_ptr/boost::weak_ptr with std::shared_ptr/std::weak_ptr. 5 | * Replace boost::function/boost::bind with std::function/std::bind/lambda. 6 | * Replace boost::ptr_vector with std::vector>. 7 | * Replace boost::noncopyable with muduo::noncopyable. 8 | * Replace boost::scoped_ptr with std::unique_ptr. 9 | * Replace BOOST_STATIC_ASSERT with static_assert. 10 | * Replace boost type_traits with std type_traits. 11 | * Version 2.0.0 12 | 13 | -------------------------------------------------------------------------------- /License: -------------------------------------------------------------------------------- 1 | // Muduo - A reactor-based C++ network library for Linux 2 | // Copyright (c) 2010, Shuo Chen. All rights reserved. 3 | // http://code.google.com/p/muduo/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions 7 | // are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright 12 | // notice, this list of conditions and the following disclaimer in the 13 | // documentation and/or other materials provided with the distribution. 14 | // * Neither the name of Shuo Chen nor the names of other contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Muduo is a multithreaded C++ network library based on 2 | the reactor pattern. 3 | 4 | http://github.com/chenshuo/muduo 5 | 6 | Copyright (c) 2010, Shuo Chen. All rights reserved. 7 | 8 | Use of this source code is governed by a BSD-style 9 | license that can be found in the License file. 10 | 11 | Requires: 12 | Linux kernel version >= 2.6.28. 13 | GCC >= 4.7 or Clang >= 3.5 14 | Boost (for boost::any only.) 15 | 16 | Tested on: 17 | Debian 7 and above 18 | Unbuntu 14.04 and above 19 | CentOS 7 and above 20 | 21 | Install required packages: 22 | # Debian, Ubuntu, etc. 23 | $ sudo apt install g++ cmake make libboost-dev 24 | # CentOS 25 | $ sudo yum install gcc-c++ cmake make boost-devel 26 | 27 | See .travis.yml for additional packages for building more examples. 28 | 29 | To build, run: 30 | ./build.sh 31 | 32 | See https://github.com/chenshuo/muduo-tutorial for 33 | how to use muduo in your project. 34 | __ __ _ 35 | | \/ | | | 36 | | \ / |_ _ __| |_ _ ___ 37 | | |\/| | | | |/ _` | | | |/ _ \ 38 | | | | | |_| | (_| | |_| | (_) | 39 | |_| |_|\__,_|\__,_|\__,_|\___/ 40 | 41 | -------------------------------------------------------------------------------- /WORKSPACE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenshuo/muduo/f1fc77e0c13b80e5086ff457362c8a86d1b609d4/WORKSPACE -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -x 4 | 5 | SOURCE_DIR=`pwd` 6 | BUILD_DIR=${BUILD_DIR:-../build} 7 | BUILD_TYPE=${BUILD_TYPE:-release} 8 | INSTALL_DIR=${INSTALL_DIR:-../${BUILD_TYPE}-install-cpp11} 9 | CXX=${CXX:-g++} 10 | 11 | ln -sf $BUILD_DIR/$BUILD_TYPE-cpp11/compile_commands.json 12 | 13 | mkdir -p $BUILD_DIR/$BUILD_TYPE-cpp11 \ 14 | && cd $BUILD_DIR/$BUILD_TYPE-cpp11 \ 15 | && cmake \ 16 | -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ 17 | -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR \ 18 | -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ 19 | $SOURCE_DIR \ 20 | && make $* 21 | 22 | # Use the following command to run all the unit tests 23 | # at the dir $BUILD_DIR/$BUILD_TYPE : 24 | # CTEST_OUTPUT_ON_FAILURE=TRUE make test 25 | 26 | # cd $SOURCE_DIR && doxygen 27 | 28 | -------------------------------------------------------------------------------- /contrib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(HIREDIS_INCLUDE_DIR AND HIREDIS_LIBRARY) 2 | add_subdirectory(hiredis) 3 | else() 4 | add_subdirectory(hiredis EXCLUDE_FROM_ALL) 5 | endif() 6 | 7 | if(THRIFT_COMPILER AND THRIFT_INCLUDE_DIR AND THRIFT_LIBRARY) 8 | add_subdirectory(thrift) 9 | else() 10 | add_subdirectory(thrift EXCLUDE_FROM_ALL) 11 | endif() 12 | -------------------------------------------------------------------------------- /contrib/hiredis/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(mrediscli Hiredis.cc mrediscli.cc) 2 | target_link_libraries(mrediscli muduo_net hiredis) 3 | -------------------------------------------------------------------------------- /contrib/hiredis/README.md: -------------------------------------------------------------------------------- 1 | # Hiredis 2 | 3 | The version of hiredis must be 0.11.0 or greater 4 | 5 | See also issue [#92](https://github.com/chenshuo/muduo/issues/92) 6 | -------------------------------------------------------------------------------- /contrib/thrift/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(MUDUO_THRIFT_SRCS 2 | ThriftConnection.cc 3 | ThriftServer.cc 4 | ) 5 | add_library(muduo_thrift ${MUDUO_THRIFT_SRCS}) 6 | target_link_libraries(muduo_thrift muduo_net thrift) 7 | 8 | if(THRIFT_COMPILER AND THRIFT_INCLUDE_DIR AND THRIFT_LIBRARY) 9 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) 10 | add_subdirectory(tests) 11 | endif() 12 | -------------------------------------------------------------------------------- /contrib/thrift/ThriftServer.cc: -------------------------------------------------------------------------------- 1 | #include "contrib/thrift/ThriftServer.h" 2 | 3 | #include 4 | 5 | #include "muduo/net/EventLoop.h" 6 | 7 | using muduo::MutexLockGuard; 8 | using muduo::Timestamp; 9 | using muduo::net::EventLoop; 10 | using muduo::net::TcpConnectionPtr; 11 | 12 | ThriftServer::~ThriftServer() = default; 13 | 14 | void ThriftServer::serve() 15 | { 16 | start(); 17 | } 18 | 19 | void ThriftServer::start() 20 | { 21 | if (numWorkerThreads_ > 0) 22 | { 23 | workerThreadPool_.start(numWorkerThreads_); 24 | } 25 | server_.start(); 26 | } 27 | 28 | void ThriftServer::stop() 29 | { 30 | if (numWorkerThreads_ > 0) 31 | { 32 | workerThreadPool_.stop(); 33 | } 34 | server_.getLoop()->runAfter(3.0, std::bind(&EventLoop::quit, 35 | server_.getLoop())); 36 | } 37 | 38 | void ThriftServer::onConnection(const TcpConnectionPtr& conn) 39 | { 40 | if (conn->connected()) 41 | { 42 | ThriftConnectionPtr ptr(new ThriftConnection(this, conn)); 43 | MutexLockGuard lock(mutex_); 44 | assert(conns_.find(conn->name()) == conns_.end()); 45 | conns_[conn->name()] = ptr; 46 | } 47 | else 48 | { 49 | MutexLockGuard lock(mutex_); 50 | assert(conns_.find(conn->name()) != conns_.end()); 51 | conns_.erase(conn->name()); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /contrib/thrift/tests/.gitignore: -------------------------------------------------------------------------------- 1 | gen-cpp 2 | gen-py 3 | -------------------------------------------------------------------------------- /contrib/thrift/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(echo) 2 | add_subdirectory(ping) 3 | -------------------------------------------------------------------------------- /contrib/thrift/tests/echo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(gen-cpp) 2 | set(ECHO_THRIFT echo.thrift) 3 | execute_process(COMMAND ${THRIFT_COMPILER} --gen cpp ${ECHO_THRIFT} 4 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 5 | execute_process(COMMAND ${THRIFT_COMPILER} --gen py ${ECHO_THRIFT} 6 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 7 | set(ECHO_THRIFT_SRCS 8 | gen-cpp/echo_constants.cpp 9 | gen-cpp/echo_types.cpp 10 | gen-cpp/Echo.cpp 11 | ) 12 | set(ECHO_SRCS 13 | EchoServer.cc 14 | ) 15 | add_executable(muduo_thrift_echo ${ECHO_SRCS} ${ECHO_THRIFT_SRCS}) 16 | target_link_libraries(muduo_thrift_echo muduo_thrift) 17 | -------------------------------------------------------------------------------- /contrib/thrift/tests/echo/EchoServer.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "muduo/base/Logging.h" 4 | #include "muduo/net/EventLoop.h" 5 | 6 | #include "ThriftServer.h" 7 | 8 | #include "Echo.h" 9 | 10 | using namespace muduo; 11 | using namespace muduo::net; 12 | 13 | using namespace echo; 14 | 15 | class EchoHandler : virtual public EchoIf 16 | { 17 | public: 18 | EchoHandler() 19 | { 20 | } 21 | 22 | void echo(std::string& str, const std::string& s) 23 | { 24 | LOG_INFO << "EchoHandler::echo:" << s; 25 | str = s; 26 | } 27 | 28 | }; 29 | 30 | int NumCPU() 31 | { 32 | return static_cast(sysconf(_SC_NPROCESSORS_ONLN)); 33 | } 34 | 35 | int main(int argc, char **argv) 36 | { 37 | EventLoop eventloop; 38 | InetAddress addr("127.0.0.1", 9090); 39 | string name("EchoServer"); 40 | 41 | boost::shared_ptr handler(new EchoHandler()); 42 | boost::shared_ptr processor(new EchoProcessor(handler)); 43 | 44 | ThriftServer server(processor, &eventloop, addr, name); 45 | server.setWorkerThreadNum(NumCPU() * 2); 46 | server.start(); 47 | eventloop.loop(); 48 | 49 | return 0; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /contrib/thrift/tests/echo/echo.thrift: -------------------------------------------------------------------------------- 1 | namespace cpp echo 2 | namespace py echo 3 | 4 | service Echo 5 | { 6 | string echo(1: string arg); 7 | } 8 | 9 | -------------------------------------------------------------------------------- /contrib/thrift/tests/echo/echoclient.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append('gen-py') 3 | 4 | from thrift.transport import TSocket 5 | from thrift.transport import TTransport 6 | from thrift.protocol import TBinaryProtocol 7 | 8 | from echo import Echo 9 | 10 | 11 | def echo(s): 12 | transport = TSocket.TSocket('127.0.0.1', 9090) 13 | tranport = TTransport.TFramedTransport(transport) 14 | protocol = TBinaryProtocol.TBinaryProtocol(tranport) 15 | client = Echo.Client(protocol) 16 | tranport.open() 17 | s = client.echo(s) 18 | tranport.close() 19 | 20 | return s 21 | 22 | 23 | def main(): 24 | print(echo('42')) 25 | 26 | 27 | if __name__ == '__main__': 28 | main() 29 | -------------------------------------------------------------------------------- /contrib/thrift/tests/ping/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(gen-cpp) 2 | set(PING_THRIFT ping.thrift) 3 | execute_process(COMMAND ${THRIFT_COMPILER} --gen cpp ${PING_THRIFT} 4 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 5 | execute_process(COMMAND ${THRIFT_COMPILER} --gen py ${PING_THRIFT} 6 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 7 | set(PING_THRIFT_SRCS 8 | gen-cpp/ping_constants.cpp 9 | gen-cpp/ping_types.cpp 10 | gen-cpp/Ping.cpp 11 | ) 12 | set(PING_SRCS 13 | PingServer.cc 14 | ) 15 | add_executable(muduo_thrift_ping ${PING_SRCS} ${PING_THRIFT_SRCS}) 16 | target_link_libraries(muduo_thrift_ping muduo_thrift) 17 | -------------------------------------------------------------------------------- /contrib/thrift/tests/ping/PingServer.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/Logging.h" 2 | #include "muduo/net/EventLoop.h" 3 | 4 | #include 5 | 6 | #include "ThriftServer.h" 7 | 8 | #include "Ping.h" 9 | 10 | using namespace muduo; 11 | using namespace muduo::net; 12 | 13 | using apache::thrift::protocol::TCompactProtocolFactory; 14 | 15 | using namespace ping; 16 | 17 | class PingHandler : virtual public PingIf 18 | { 19 | public: 20 | PingHandler() 21 | { 22 | } 23 | 24 | void ping() 25 | { 26 | LOG_INFO << "ping"; 27 | } 28 | 29 | }; 30 | 31 | int main(int argc, char **argv) 32 | { 33 | EventLoop eventloop; 34 | InetAddress addr("127.0.0.1", 9090); 35 | string name("PingServer"); 36 | 37 | boost::shared_ptr handler(new PingHandler()); 38 | boost::shared_ptr processor(new PingProcessor(handler)); 39 | boost::shared_ptr protcolFactory(new TCompactProtocolFactory()); 40 | 41 | ThriftServer server(processor, protcolFactory, &eventloop, addr, name); 42 | server.start(); 43 | eventloop.loop(); 44 | 45 | return 0; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /contrib/thrift/tests/ping/ping.thrift: -------------------------------------------------------------------------------- 1 | namespace cpp ping 2 | namespace py ping 3 | 4 | service Ping 5 | { 6 | void ping(); 7 | } 8 | 9 | -------------------------------------------------------------------------------- /contrib/thrift/tests/ping/pingclient.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append('gen-py') 3 | 4 | from thrift.transport import TSocket 5 | from thrift.transport import TTransport 6 | from thrift.protocol import TCompactProtocol 7 | 8 | from ping import Ping 9 | 10 | 11 | def ping(): 12 | transport = TSocket.TSocket('127.0.0.1', 9090) 13 | tranport = TTransport.TFramedTransport(transport) 14 | protocol = TCompactProtocol.TCompactProtocol(tranport) 15 | client = Ping.Client(protocol) 16 | tranport.open() 17 | client.ping() 18 | tranport.close() 19 | 20 | 21 | def main(): 22 | ping() 23 | 24 | 25 | if __name__ == '__main__': 26 | main() 27 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(ace/ttcp) 2 | add_subdirectory(asio/chat) 3 | add_subdirectory(asio/tutorial) 4 | add_subdirectory(fastcgi) 5 | add_subdirectory(filetransfer) 6 | add_subdirectory(hub) 7 | add_subdirectory(idleconnection) 8 | add_subdirectory(maxconnection) 9 | add_subdirectory(memcached/client) 10 | add_subdirectory(memcached/server) 11 | add_subdirectory(multiplexer) 12 | add_subdirectory(netty/discard) 13 | add_subdirectory(netty/echo) 14 | add_subdirectory(netty/uptime) 15 | add_subdirectory(pingpong) 16 | add_subdirectory(roundtrip) 17 | add_subdirectory(shorturl) 18 | add_subdirectory(simple) 19 | add_subdirectory(socks4a) 20 | add_subdirectory(sudoku) 21 | add_subdirectory(twisted/finger) 22 | add_subdirectory(wordcount) 23 | add_subdirectory(zeromq) 24 | 25 | if(CARES_INCLUDE_DIR AND CARES_LIBRARY) 26 | add_subdirectory(cdns) 27 | else() 28 | add_subdirectory(cdns EXCLUDE_FROM_ALL) 29 | endif() 30 | 31 | if(CURL_FOUND) 32 | add_subdirectory(curl) 33 | else() 34 | add_subdirectory(curl EXCLUDE_FROM_ALL) 35 | endif() 36 | 37 | if(PROTOBUF_FOUND) 38 | add_subdirectory(ace/logging) 39 | add_subdirectory(protobuf) 40 | else() 41 | add_subdirectory(ace/logging EXCLUDE_FROM_ALL) 42 | add_subdirectory(protobuf EXCLUDE_FROM_ALL) 43 | endif() 44 | 45 | if(GD_INCLUDE_DIR AND GD_LIBRARY) 46 | add_subdirectory(procmon) 47 | else() 48 | add_subdirectory(procmon EXCLUDE_FROM_ALL) 49 | endif() 50 | -------------------------------------------------------------------------------- /examples/ace/logging/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_custom_command(OUTPUT logrecord.pb.cc logrecord.pb.h 2 | COMMAND protoc 3 | ARGS --cpp_out . ${CMAKE_CURRENT_SOURCE_DIR}/logrecord.proto -I${CMAKE_CURRENT_SOURCE_DIR} 4 | DEPENDS logrecord.proto 5 | VERBATIM ) 6 | 7 | set_source_files_properties(logrecord.pb.cc PROPERTIES COMPILE_FLAGS "-Wno-conversion -Wno-shadow") 8 | include_directories(${PROJECT_BINARY_DIR}) 9 | 10 | add_library(ace_logging_proto logrecord.pb.cc) 11 | target_link_libraries(ace_logging_proto protobuf pthread) 12 | 13 | add_executable(ace_logging_client client.cc) 14 | set_target_properties(ace_logging_client PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 15 | target_link_libraries(ace_logging_client muduo_protobuf_codec ace_logging_proto) 16 | 17 | add_executable(ace_logging_server server.cc) 18 | set_target_properties(ace_logging_server PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 19 | target_link_libraries(ace_logging_server muduo_protobuf_codec ace_logging_proto) 20 | -------------------------------------------------------------------------------- /examples/ace/logging/logrecord.proto: -------------------------------------------------------------------------------- 1 | package logging; 2 | 3 | message LogRecord { 4 | // must present in first message 5 | message Heartbeat { 6 | required string hostname = 1; 7 | required string process_name = 2; 8 | required int32 process_id = 3; 9 | required int64 process_start_time = 4; // microseconds sinch epoch 10 | required string username = 5; 11 | } 12 | 13 | optional Heartbeat heartbeat = 1; 14 | // muduo/base/Logging.h 15 | // enum LogLevel 16 | // { 17 | // TRACE, // 0 18 | // DEBUG, // 1 19 | // INFO, // 2 20 | // WARN, // 3 21 | // ERROR, // 4 22 | // FATAL, // 5 23 | // }; 24 | required int32 level = 2; 25 | required int32 thread_id = 3; 26 | required int64 timestamp = 4; // microseconds sinch epoch 27 | required string message = 5; 28 | // optional: source file, source line, function name 29 | } 30 | -------------------------------------------------------------------------------- /examples/ace/ttcp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(BOOSTPO_LIBRARY) 2 | add_executable(ttcp_blocking ttcp_blocking.cc common.cc main.cc) 3 | target_link_libraries(ttcp_blocking muduo_base boost_program_options) 4 | set_target_properties(ttcp_blocking PROPERTIES COMPILE_FLAGS "-Wno-error=old-style-cast -Wno-error=conversion") 5 | 6 | add_executable(ttcp_muduo ttcp.cc common.cc main.cc) 7 | target_link_libraries(ttcp_muduo muduo_net boost_program_options) 8 | 9 | if(BOOSTSYSTEM_LIBRARY) 10 | add_executable(ttcp_asio_sync ttcp_asio_sync.cc common.cc main.cc) 11 | target_link_libraries(ttcp_asio_sync muduo_base boost_program_options boost_system) 12 | 13 | add_executable(ttcp_asio_async ttcp_asio_async.cc common.cc main.cc) 14 | target_link_libraries(ttcp_asio_async muduo_base boost_program_options boost_system) 15 | endif() 16 | endif() 17 | 18 | -------------------------------------------------------------------------------- /examples/ace/ttcp/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct Options 7 | { 8 | uint16_t port; 9 | int length; 10 | int number; 11 | bool transmit, receive, nodelay; 12 | std::string host; 13 | Options() 14 | : port(0), length(0), number(0), 15 | transmit(false), receive(false), nodelay(false) 16 | { 17 | } 18 | }; 19 | 20 | bool parseCommandLine(int argc, char* argv[], Options* opt); 21 | struct sockaddr_in resolveOrDie(const char* host, uint16_t port); 22 | 23 | struct SessionMessage 24 | { 25 | int32_t number; 26 | int32_t length; 27 | } __attribute__ ((__packed__)); 28 | 29 | struct PayloadMessage 30 | { 31 | int32_t length; 32 | char data[0]; 33 | }; 34 | 35 | void transmit(const Options& opt); 36 | 37 | void receive(const Options& opt); 38 | -------------------------------------------------------------------------------- /examples/ace/ttcp/main.cc: -------------------------------------------------------------------------------- 1 | #include "examples/ace/ttcp/common.h" 2 | 3 | #include 4 | 5 | int main(int argc, char* argv[]) 6 | { 7 | Options options; 8 | if (parseCommandLine(argc, argv, &options)) 9 | { 10 | if (options.transmit) 11 | { 12 | transmit(options); 13 | } 14 | else if (options.receive) 15 | { 16 | receive(options); 17 | } 18 | else 19 | { 20 | assert(0); 21 | } 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /examples/asio/chat/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(asio_chat_client client.cc) 2 | target_link_libraries(asio_chat_client muduo_net) 3 | 4 | add_executable(asio_chat_loadtest loadtest.cc) 5 | target_link_libraries(asio_chat_loadtest muduo_net) 6 | 7 | add_executable(asio_chat_server server.cc) 8 | target_link_libraries(asio_chat_server muduo_net) 9 | 10 | add_executable(asio_chat_server_threaded server_threaded.cc) 11 | target_link_libraries(asio_chat_server_threaded muduo_net) 12 | 13 | add_executable(asio_chat_server_threaded_efficient server_threaded_efficient.cc) 14 | target_link_libraries(asio_chat_server_threaded_efficient muduo_net) 15 | 16 | add_executable(asio_chat_server_threaded_highperformance server_threaded_highperformance.cc) 17 | target_link_libraries(asio_chat_server_threaded_highperformance muduo_net) 18 | 19 | -------------------------------------------------------------------------------- /examples/asio/echo_see_simple: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenshuo/muduo/f1fc77e0c13b80e5086ff457362c8a86d1b609d4/examples/asio/echo_see_simple -------------------------------------------------------------------------------- /examples/asio/tutorial/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(asio_tutorial_timer2 timer2/timer.cc) 2 | target_link_libraries(asio_tutorial_timer2 muduo_net) 3 | 4 | add_executable(asio_tutorial_timer3 timer3/timer.cc) 5 | target_link_libraries(asio_tutorial_timer3 muduo_net) 6 | 7 | add_executable(asio_tutorial_timer4 timer4/timer.cc) 8 | target_link_libraries(asio_tutorial_timer4 muduo_net) 9 | 10 | add_executable(asio_tutorial_timer5 timer5/timer.cc) 11 | target_link_libraries(asio_tutorial_timer5 muduo_net) 12 | 13 | add_executable(asio_tutorial_timer6 timer6/timer.cc) 14 | target_link_libraries(asio_tutorial_timer6 muduo_net) 15 | 16 | -------------------------------------------------------------------------------- /examples/asio/tutorial/daytime_see_simple: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenshuo/muduo/f1fc77e0c13b80e5086ff457362c8a86d1b609d4/examples/asio/tutorial/daytime_see_simple -------------------------------------------------------------------------------- /examples/asio/tutorial/there_is_no_timer1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenshuo/muduo/f1fc77e0c13b80e5086ff457362c8a86d1b609d4/examples/asio/tutorial/there_is_no_timer1 -------------------------------------------------------------------------------- /examples/asio/tutorial/timer2/timer.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/net/EventLoop.h" 2 | 3 | #include 4 | 5 | void print() 6 | { 7 | std::cout << "Hello, world!\n"; 8 | } 9 | 10 | int main() 11 | { 12 | muduo::net::EventLoop loop; 13 | loop.runAfter(5, print); 14 | loop.loop(); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /examples/asio/tutorial/timer3/timer.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/net/EventLoop.h" 2 | 3 | #include 4 | 5 | void print(muduo::net::EventLoop* loop, int* count) 6 | { 7 | if (*count < 5) 8 | { 9 | std::cout << *count << "\n"; 10 | ++(*count); 11 | 12 | loop->runAfter(1, std::bind(print, loop, count)); 13 | } 14 | else 15 | { 16 | loop->quit(); 17 | } 18 | } 19 | 20 | int main() 21 | { 22 | muduo::net::EventLoop loop; 23 | int count = 0; 24 | // Note: loop.runEvery() is better for this use case. 25 | loop.runAfter(1, std::bind(print, &loop, &count)); 26 | loop.loop(); 27 | std::cout << "Final count is " << count << "\n"; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /examples/asio/tutorial/timer4/timer.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/net/EventLoop.h" 2 | 3 | #include 4 | 5 | class Printer : muduo::noncopyable 6 | { 7 | public: 8 | Printer(muduo::net::EventLoop* loop) 9 | : loop_(loop), 10 | count_(0) 11 | { 12 | // Note: loop.runEvery() is better for this use case. 13 | loop_->runAfter(1, std::bind(&Printer::print, this)); 14 | } 15 | 16 | ~Printer() 17 | { 18 | std::cout << "Final count is " << count_ << "\n"; 19 | } 20 | 21 | void print() 22 | { 23 | if (count_ < 5) 24 | { 25 | std::cout << count_ << "\n"; 26 | ++count_; 27 | 28 | loop_->runAfter(1, std::bind(&Printer::print, this)); 29 | } 30 | else 31 | { 32 | loop_->quit(); 33 | } 34 | } 35 | 36 | private: 37 | muduo::net::EventLoop* loop_; 38 | int count_; 39 | }; 40 | 41 | int main() 42 | { 43 | muduo::net::EventLoop loop; 44 | Printer printer(&loop); 45 | loop.loop(); 46 | } 47 | 48 | -------------------------------------------------------------------------------- /examples/asio/tutorial/timer5/timer.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/Mutex.h" 2 | #include "muduo/net/EventLoop.h" 3 | #include "muduo/net/EventLoopThread.h" 4 | 5 | #include 6 | 7 | class Printer : muduo::noncopyable 8 | { 9 | public: 10 | Printer(muduo::net::EventLoop* loop1, muduo::net::EventLoop* loop2) 11 | : loop1_(loop1), 12 | loop2_(loop2), 13 | count_(0) 14 | { 15 | loop1_->runAfter(1, std::bind(&Printer::print1, this)); 16 | loop2_->runAfter(1, std::bind(&Printer::print2, this)); 17 | } 18 | 19 | ~Printer() 20 | { 21 | std::cout << "Final count is " << count_ << "\n"; 22 | } 23 | 24 | void print1() 25 | { 26 | muduo::MutexLockGuard lock(mutex_); 27 | if (count_ < 10) 28 | { 29 | std::cout << "Timer 1: " << count_ << "\n"; 30 | ++count_; 31 | 32 | loop1_->runAfter(1, std::bind(&Printer::print1, this)); 33 | } 34 | else 35 | { 36 | loop1_->quit(); 37 | } 38 | } 39 | 40 | void print2() 41 | { 42 | muduo::MutexLockGuard lock(mutex_); 43 | if (count_ < 10) 44 | { 45 | std::cout << "Timer 2: " << count_ << "\n"; 46 | ++count_; 47 | 48 | loop2_->runAfter(1, std::bind(&Printer::print2, this)); 49 | } 50 | else 51 | { 52 | loop2_->quit(); 53 | } 54 | } 55 | 56 | private: 57 | 58 | muduo::MutexLock mutex_; 59 | muduo::net::EventLoop* loop1_ PT_GUARDED_BY(mutex_); 60 | muduo::net::EventLoop* loop2_ PT_GUARDED_BY(mutex_); 61 | int count_ GUARDED_BY(mutex_); 62 | }; 63 | 64 | int main() 65 | { 66 | std::unique_ptr printer; // make sure printer lives longer than loops, to avoid 67 | // race condition of calling print2() on destructed object. 68 | muduo::net::EventLoop loop; 69 | muduo::net::EventLoopThread loopThread; 70 | muduo::net::EventLoop* loopInAnotherThread = loopThread.startLoop(); 71 | printer.reset(new Printer(&loop, loopInAnotherThread)); 72 | loop.loop(); 73 | } 74 | 75 | -------------------------------------------------------------------------------- /examples/cdns/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(muduo_cdns Resolver.cc) 2 | target_link_libraries(muduo_cdns muduo_net) 3 | target_link_libraries(muduo_cdns cares) 4 | 5 | install(TARGETS muduo_cdns DESTINATION lib) 6 | install(FILES Resolver.h DESTINATION include/muduo/cdns) 7 | 8 | add_executable(cdns dns.cc) 9 | target_link_libraries(cdns muduo_cdns) 10 | 11 | -------------------------------------------------------------------------------- /examples/cdns/dns.cc: -------------------------------------------------------------------------------- 1 | #include "examples/cdns/Resolver.h" 2 | #include "muduo/net/EventLoop.h" 3 | #include 4 | 5 | using namespace muduo; 6 | using namespace muduo::net; 7 | using namespace cdns; 8 | 9 | EventLoop* g_loop; 10 | int count = 0; 11 | int total = 0; 12 | 13 | void quit() 14 | { 15 | g_loop->quit(); 16 | } 17 | 18 | void resolveCallback(const string& host, const InetAddress& addr) 19 | { 20 | printf("resolveCallback %s -> %s\n", host.c_str(), addr.toIpPort().c_str()); 21 | if (++count == total) 22 | quit(); 23 | } 24 | 25 | void resolve(Resolver* res, const string& host) 26 | { 27 | res->resolve(host, std::bind(&resolveCallback, host, _1)); 28 | } 29 | 30 | int main(int argc, char* argv[]) 31 | { 32 | EventLoop loop; 33 | loop.runAfter(10, quit); 34 | g_loop = &loop; 35 | Resolver resolver(&loop, 36 | argc == 1 ? Resolver::kDNSonly : Resolver::kDNSandHostsFile); 37 | if (argc == 1) 38 | { 39 | total = 3; 40 | resolve(&resolver, "www.chenshuo.com"); 41 | resolve(&resolver, "www.example.com"); 42 | resolve(&resolver, "www.google.com"); 43 | } 44 | else 45 | { 46 | total = argc-1; 47 | for (int i = 1; i < argc; ++i) 48 | resolve(&resolver, argv[i]); 49 | } 50 | loop.loop(); 51 | } 52 | -------------------------------------------------------------------------------- /examples/curl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(muduo_curl Curl.cc) 2 | target_link_libraries(muduo_curl muduo_net) 3 | target_link_libraries(muduo_curl curl) 4 | 5 | install(TARGETS muduo_curl DESTINATION lib) 6 | install(FILES Curl.h DESTINATION include/muduo/curl) 7 | 8 | add_executable(mcurl mcurl.cc) 9 | target_link_libraries(mcurl muduo_curl) 10 | 11 | add_executable(curl_download download.cc) 12 | target_link_libraries(curl_download muduo_curl) 13 | 14 | -------------------------------------------------------------------------------- /examples/curl/README: -------------------------------------------------------------------------------- 1 | This is a proof-of-concept implementation of muduo-curl bridge. 2 | It demostrates the simplest use case of curl with muduo. 3 | 4 | Note: 5 | 1. DNS resolving could be blocking, if your curl is not built with c-ares. 6 | 2. Request object should survive doneCallback. 7 | -------------------------------------------------------------------------------- /examples/curl/mcurl.cc: -------------------------------------------------------------------------------- 1 | #include "examples/curl/Curl.h" 2 | #include "muduo/net/EventLoop.h" 3 | #include 4 | 5 | using namespace muduo::net; 6 | 7 | EventLoop* g_loop = NULL; 8 | 9 | void onData(const char* data, int len) 10 | { 11 | printf("len %d\n", len); 12 | } 13 | 14 | void done(curl::Request* c, int code) 15 | { 16 | printf("done %p %s %d\n", c, c->getEffectiveUrl(), code); 17 | } 18 | 19 | void done2(curl::Request* c, int code) 20 | { 21 | printf("done2 %p %s %d %d\n", c, c->getRedirectUrl(), c->getResponseCode(), code); 22 | // g_loop->quit(); 23 | } 24 | 25 | int main(int argc, char* argv[]) 26 | { 27 | EventLoop loop; 28 | g_loop = &loop; 29 | loop.runAfter(30.0, std::bind(&EventLoop::quit, &loop)); 30 | curl::Curl::initialize(curl::Curl::kCURLssl); 31 | curl::Curl curl(&loop); 32 | 33 | curl::RequestPtr req = curl.getUrl("http://chenshuo.com"); 34 | req->setDataCallback(onData); 35 | req->setDoneCallback(done); 36 | 37 | curl::RequestPtr req2 = curl.getUrl("https://github.com"); 38 | // req2->allowRedirect(5); 39 | req2->setDataCallback(onData); 40 | req2->setDoneCallback(done); 41 | 42 | curl::RequestPtr req3 = curl.getUrl("http://example.com"); 43 | // req3->allowRedirect(5); 44 | req3->setDataCallback(onData); 45 | req3->setDoneCallback(done2); 46 | 47 | loop.loop(); 48 | } 49 | -------------------------------------------------------------------------------- /examples/fastcgi/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(fastcgi_test fastcgi.cc fastcgi_test.cc ../sudoku/sudoku.cc) 2 | target_link_libraries(fastcgi_test muduo_net) 3 | 4 | -------------------------------------------------------------------------------- /examples/filetransfer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(filetransfer_download download.cc) 2 | target_link_libraries(filetransfer_download muduo_net) 3 | 4 | add_executable(filetransfer_download2 download2.cc) 5 | target_link_libraries(filetransfer_download2 muduo_net) 6 | 7 | add_executable(filetransfer_download3 download3.cc) 8 | target_link_libraries(filetransfer_download3 muduo_net) 9 | 10 | -------------------------------------------------------------------------------- /examples/hub/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(hub hub.cc codec.cc) 2 | target_link_libraries(hub muduo_inspect) 3 | 4 | add_library(muduo_pubsub pubsub.cc codec.cc) 5 | target_link_libraries(muduo_pubsub muduo_net) 6 | 7 | add_executable(pub pub.cc) 8 | target_link_libraries(pub muduo_pubsub) 9 | 10 | add_executable(sub sub.cc) 11 | target_link_libraries(sub muduo_pubsub) 12 | 13 | -------------------------------------------------------------------------------- /examples/hub/README: -------------------------------------------------------------------------------- 1 | hub - a server for broadcasting 2 | pubsub - a client library of hub 3 | pub - a command line tool for publishing content on a topic 4 | sub - a demo tool for subscribing a topic 5 | 6 | -------------------------------------------------------------------------------- /examples/hub/codec.cc: -------------------------------------------------------------------------------- 1 | #include "examples/hub/codec.h" 2 | 3 | using namespace muduo; 4 | using namespace muduo::net; 5 | using namespace pubsub; 6 | 7 | ParseResult pubsub::parseMessage(Buffer* buf, 8 | string* cmd, 9 | string* topic, 10 | string* content) 11 | { 12 | ParseResult result = kError; 13 | const char* crlf = buf->findCRLF(); 14 | if (crlf) 15 | { 16 | const char* space = std::find(buf->peek(), crlf, ' '); 17 | if (space != crlf) 18 | { 19 | cmd->assign(buf->peek(), space); 20 | topic->assign(space+1, crlf); 21 | if (*cmd == "pub") 22 | { 23 | const char* start = crlf + 2; 24 | crlf = buf->findCRLF(start); 25 | if (crlf) 26 | { 27 | content->assign(start, crlf); 28 | buf->retrieveUntil(crlf+2); 29 | result = kSuccess; 30 | } 31 | else 32 | { 33 | result = kContinue; 34 | } 35 | } 36 | else 37 | { 38 | buf->retrieveUntil(crlf+2); 39 | result = kSuccess; 40 | } 41 | } 42 | else 43 | { 44 | result = kError; 45 | } 46 | } 47 | else 48 | { 49 | result = kContinue; 50 | } 51 | return result; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /examples/hub/codec.h: -------------------------------------------------------------------------------- 1 | #ifndef MUDUO_EXAMPLES_HUB_CODEC_H 2 | #define MUDUO_EXAMPLES_HUB_CODEC_H 3 | 4 | // internal header file 5 | 6 | #include "muduo/base/Types.h" 7 | #include "muduo/net/Buffer.h" 8 | 9 | namespace pubsub 10 | { 11 | using muduo::string; 12 | 13 | enum ParseResult 14 | { 15 | kError, 16 | kSuccess, 17 | kContinue, 18 | }; 19 | 20 | ParseResult parseMessage(muduo::net::Buffer* buf, 21 | string* cmd, 22 | string* topic, 23 | string* content); 24 | } // namespace pubsub 25 | 26 | #endif // MUDUO_EXAMPLES_HUB_CODEC_H 27 | 28 | -------------------------------------------------------------------------------- /examples/hub/pubsub.h: -------------------------------------------------------------------------------- 1 | #ifndef MUDUO_EXAMPLES_HUB_PUBSUB_H 2 | #define MUDUO_EXAMPLES_HUB_PUBSUB_H 3 | 4 | #include "muduo/net/TcpClient.h" 5 | 6 | namespace pubsub 7 | { 8 | using muduo::string; 9 | 10 | // FIXME: dtor is not thread safe 11 | class PubSubClient : muduo::noncopyable 12 | { 13 | public: 14 | typedef std::function ConnectionCallback; 15 | typedef std::function SubscribeCallback; 18 | 19 | PubSubClient(muduo::net::EventLoop* loop, 20 | const muduo::net::InetAddress& hubAddr, 21 | const string& name); 22 | void start(); 23 | void stop(); 24 | bool connected() const; 25 | 26 | void setConnectionCallback(const ConnectionCallback& cb) 27 | { connectionCallback_ = cb; } 28 | 29 | bool subscribe(const string& topic, const SubscribeCallback& cb); 30 | void unsubscribe(const string& topic); 31 | bool publish(const string& topic, const string& content); 32 | 33 | private: 34 | void onConnection(const muduo::net::TcpConnectionPtr& conn); 35 | void onMessage(const muduo::net::TcpConnectionPtr& conn, 36 | muduo::net::Buffer* buf, 37 | muduo::Timestamp receiveTime); 38 | bool send(const string& message); 39 | 40 | muduo::net::TcpClient client_; 41 | muduo::net::TcpConnectionPtr conn_; 42 | ConnectionCallback connectionCallback_; 43 | SubscribeCallback subscribeCallback_; 44 | }; 45 | } // namespace pubsub 46 | 47 | #endif // MUDUO_EXAMPLES_HUB_PUBSUB_H 48 | -------------------------------------------------------------------------------- /examples/hub/sub.cc: -------------------------------------------------------------------------------- 1 | #include "examples/hub/pubsub.h" 2 | #include "muduo/base/ProcessInfo.h" 3 | #include "muduo/net/EventLoop.h" 4 | 5 | #include 6 | #include 7 | 8 | using namespace muduo; 9 | using namespace muduo::net; 10 | using namespace pubsub; 11 | 12 | EventLoop* g_loop = NULL; 13 | std::vector g_topics; 14 | 15 | void subscription(const string& topic, const string& content, Timestamp) 16 | { 17 | printf("%s: %s\n", topic.c_str(), content.c_str()); 18 | } 19 | 20 | void connection(PubSubClient* client) 21 | { 22 | if (client->connected()) 23 | { 24 | for (std::vector::iterator it = g_topics.begin(); 25 | it != g_topics.end(); ++it) 26 | { 27 | client->subscribe(*it, subscription); 28 | } 29 | } 30 | else 31 | { 32 | g_loop->quit(); 33 | } 34 | } 35 | 36 | int main(int argc, char* argv[]) 37 | { 38 | if (argc > 2) 39 | { 40 | string hostport = argv[1]; 41 | size_t colon = hostport.find(':'); 42 | if (colon != string::npos) 43 | { 44 | string hostip = hostport.substr(0, colon); 45 | uint16_t port = static_cast(atoi(hostport.c_str()+colon+1)); 46 | for (int i = 2; i < argc; ++i) 47 | { 48 | g_topics.push_back(argv[i]); 49 | } 50 | 51 | EventLoop loop; 52 | g_loop = &loop; 53 | string name = ProcessInfo::username()+"@"+ProcessInfo::hostname(); 54 | name += ":" + ProcessInfo::pidString(); 55 | PubSubClient client(&loop, InetAddress(hostip, port), name); 56 | client.setConnectionCallback(connection); 57 | client.start(); 58 | loop.loop(); 59 | } 60 | else 61 | { 62 | printf("Usage: %s hub_ip:port topic [topic ...]\n", argv[0]); 63 | } 64 | } 65 | else 66 | { 67 | printf("Usage: %s hub_ip:port topic [topic ...]\n", argv[0]); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /examples/idleconnection/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(idleconnection_echo echo.cc main.cc) 2 | target_link_libraries(idleconnection_echo muduo_net) 3 | 4 | add_executable(idleconnection_echo2 sortedlist.cc) 5 | target_link_libraries(idleconnection_echo2 muduo_net) 6 | -------------------------------------------------------------------------------- /examples/idleconnection/echo.h: -------------------------------------------------------------------------------- 1 | #ifndef MUDUO_EXAMPLES_IDLECONNECTION_ECHO_H 2 | #define MUDUO_EXAMPLES_IDLECONNECTION_ECHO_H 3 | 4 | #include "muduo/net/TcpServer.h" 5 | //#include 6 | 7 | #include 8 | 9 | #include 10 | 11 | // RFC 862 12 | class EchoServer 13 | { 14 | public: 15 | EchoServer(muduo::net::EventLoop* loop, 16 | const muduo::net::InetAddress& listenAddr, 17 | int idleSeconds); 18 | 19 | void start(); 20 | 21 | private: 22 | void onConnection(const muduo::net::TcpConnectionPtr& conn); 23 | 24 | void onMessage(const muduo::net::TcpConnectionPtr& conn, 25 | muduo::net::Buffer* buf, 26 | muduo::Timestamp time); 27 | 28 | void onTimer(); 29 | 30 | void dumpConnectionBuckets() const; 31 | 32 | typedef std::weak_ptr WeakTcpConnectionPtr; 33 | 34 | struct Entry : public muduo::copyable 35 | { 36 | explicit Entry(const WeakTcpConnectionPtr& weakConn) 37 | : weakConn_(weakConn) 38 | { 39 | } 40 | 41 | ~Entry() 42 | { 43 | muduo::net::TcpConnectionPtr conn = weakConn_.lock(); 44 | if (conn) 45 | { 46 | conn->shutdown(); 47 | } 48 | } 49 | 50 | WeakTcpConnectionPtr weakConn_; 51 | }; 52 | typedef std::shared_ptr EntryPtr; 53 | typedef std::weak_ptr WeakEntryPtr; 54 | typedef std::unordered_set Bucket; 55 | typedef boost::circular_buffer WeakConnectionList; 56 | 57 | muduo::net::TcpServer server_; 58 | WeakConnectionList connectionBuckets_; 59 | }; 60 | 61 | #endif // MUDUO_EXAMPLES_IDLECONNECTION_ECHO_H 62 | -------------------------------------------------------------------------------- /examples/idleconnection/main.cc: -------------------------------------------------------------------------------- 1 | #include "examples/idleconnection/echo.h" 2 | #include 3 | 4 | #include "muduo/base/Logging.h" 5 | #include "muduo/net/EventLoop.h" 6 | 7 | using namespace muduo; 8 | using namespace muduo::net; 9 | 10 | /* 11 | void testHash() 12 | { 13 | boost::hash > h; 14 | std::shared_ptr x1(new int(10)); 15 | std::shared_ptr x2(new int(10)); 16 | h(x1); 17 | assert(h(x1) != h(x2)); 18 | x1 = x2; 19 | assert(h(x1) == h(x2)); 20 | x1.reset(); 21 | assert(h(x1) != h(x2)); 22 | x2.reset(); 23 | assert(h(x1) == h(x2)); 24 | } 25 | */ 26 | 27 | int main(int argc, char* argv[]) 28 | { 29 | // testHash(); 30 | EventLoop loop; 31 | InetAddress listenAddr(2007); 32 | int idleSeconds = 10; 33 | if (argc > 1) 34 | { 35 | idleSeconds = atoi(argv[1]); 36 | } 37 | LOG_INFO << "pid = " << getpid() << ", idle seconds = " << idleSeconds; 38 | EchoServer server(&loop, listenAddr, idleSeconds); 39 | server.start(); 40 | loop.loop(); 41 | } 42 | 43 | -------------------------------------------------------------------------------- /examples/maxconnection/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(maxconnection_echo echo.cc main.cc) 2 | target_link_libraries(maxconnection_echo muduo_net) 3 | -------------------------------------------------------------------------------- /examples/maxconnection/echo.cc: -------------------------------------------------------------------------------- 1 | #include "examples/maxconnection/echo.h" 2 | 3 | #include "muduo/base/Logging.h" 4 | 5 | using namespace muduo; 6 | using namespace muduo::net; 7 | 8 | EchoServer::EchoServer(EventLoop* loop, 9 | const InetAddress& listenAddr, 10 | int maxConnections) 11 | : server_(loop, listenAddr, "EchoServer"), 12 | numConnected_(0), 13 | kMaxConnections_(maxConnections) 14 | { 15 | server_.setConnectionCallback( 16 | std::bind(&EchoServer::onConnection, this, _1)); 17 | server_.setMessageCallback( 18 | std::bind(&EchoServer::onMessage, this, _1, _2, _3)); 19 | } 20 | 21 | void EchoServer::start() 22 | { 23 | server_.start(); 24 | } 25 | 26 | void EchoServer::onConnection(const TcpConnectionPtr& conn) 27 | { 28 | LOG_INFO << "EchoServer - " << conn->peerAddress().toIpPort() << " -> " 29 | << conn->localAddress().toIpPort() << " is " 30 | << (conn->connected() ? "UP" : "DOWN"); 31 | 32 | if (conn->connected()) 33 | { 34 | ++numConnected_; 35 | if (numConnected_ > kMaxConnections_) 36 | { 37 | conn->shutdown(); 38 | conn->forceCloseWithDelay(3.0); // > round trip of the whole Internet. 39 | } 40 | } 41 | else 42 | { 43 | --numConnected_; 44 | } 45 | LOG_INFO << "numConnected = " << numConnected_; 46 | } 47 | 48 | void EchoServer::onMessage(const TcpConnectionPtr& conn, 49 | Buffer* buf, 50 | Timestamp time) 51 | { 52 | string msg(buf->retrieveAllAsString()); 53 | LOG_INFO << conn->name() << " echo " << msg.size() << " bytes at " << time.toString(); 54 | conn->send(msg); 55 | } 56 | 57 | -------------------------------------------------------------------------------- /examples/maxconnection/echo.h: -------------------------------------------------------------------------------- 1 | #ifndef MUDUO_EXAMPLES_MAXCONNECTION_ECHO_H 2 | #define MUDUO_EXAMPLES_MAXCONNECTION_ECHO_H 3 | 4 | #include "muduo/net/TcpServer.h" 5 | 6 | // RFC 862 7 | class EchoServer 8 | { 9 | public: 10 | EchoServer(muduo::net::EventLoop* loop, 11 | const muduo::net::InetAddress& listenAddr, 12 | int maxConnections); 13 | 14 | void start(); 15 | 16 | private: 17 | void onConnection(const muduo::net::TcpConnectionPtr& conn); 18 | 19 | void onMessage(const muduo::net::TcpConnectionPtr& conn, 20 | muduo::net::Buffer* buf, 21 | muduo::Timestamp time); 22 | 23 | muduo::net::TcpServer server_; 24 | int numConnected_; // should be atomic_int 25 | const int kMaxConnections_; 26 | }; 27 | 28 | #endif // MUDUO_EXAMPLES_MAXCONNECTION_ECHO_H 29 | -------------------------------------------------------------------------------- /examples/maxconnection/main.cc: -------------------------------------------------------------------------------- 1 | #include "examples/maxconnection/echo.h" 2 | 3 | #include "muduo/base/Logging.h" 4 | #include "muduo/net/EventLoop.h" 5 | 6 | #include 7 | 8 | using namespace muduo; 9 | using namespace muduo::net; 10 | 11 | int main(int argc, char* argv[]) 12 | { 13 | LOG_INFO << "pid = " << getpid(); 14 | EventLoop loop; 15 | InetAddress listenAddr(2007); 16 | int maxConnections = 5; 17 | if (argc > 1) 18 | { 19 | maxConnections = atoi(argv[1]); 20 | } 21 | LOG_INFO << "maxConnections = " << maxConnections; 22 | EchoServer server(&loop, listenAddr, maxConnections); 23 | server.start(); 24 | loop.loop(); 25 | } 26 | 27 | -------------------------------------------------------------------------------- /examples/memcached/README: -------------------------------------------------------------------------------- 1 | Simple implementation of memcached protocol for both server and client side. 2 | Not meant to replace memcached, but just sample code of network programming with muduo. 3 | 4 | Server limits: 5 | - The memory management is not customized, just uses (tc)malloc. 6 | - It doesn't control the memory footprint 7 | - Unix domain socket is not supported 8 | - Only listen on one TCP port 9 | 10 | Server goals: 11 | - Pass as many feature tests as possible 12 | - Prefer simplicity over performance 13 | 14 | TODO: 15 | - incr/decr 16 | - UDP 17 | - Binary protocol 18 | - expiration 19 | - LRU 20 | -------------------------------------------------------------------------------- /examples/memcached/client/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(BOOSTPO_LIBRARY) 2 | add_executable(memcached_bench bench.cc) 3 | target_link_libraries(memcached_bench muduo_net boost_program_options) 4 | endif() 5 | -------------------------------------------------------------------------------- /examples/memcached/server/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(BOOSTPO_LIBRARY) 2 | add_executable(memcached_debug Item.cc MemcacheServer.cc Session.cc server.cc) 3 | target_link_libraries(memcached_debug muduo_net muduo_inspect boost_program_options) 4 | endif() 5 | 6 | add_executable(memcached_footprint Item.cc MemcacheServer.cc Session.cc footprint_test.cc) 7 | target_link_libraries(memcached_footprint muduo_net muduo_inspect) 8 | 9 | if(TCMALLOC_INCLUDE_DIR AND TCMALLOC_LIBRARY) 10 | set_target_properties(memcached_footprint PROPERTIES COMPILE_FLAGS "-DHAVE_TCMALLOC") 11 | if(BOOSTPO_LIBRARY) 12 | set_target_properties(memcached_debug PROPERTIES COMPILE_FLAGS "-DHAVE_TCMALLOC") 13 | endif() 14 | endif() 15 | 16 | -------------------------------------------------------------------------------- /examples/memcached/server/Item.cc: -------------------------------------------------------------------------------- 1 | #include "examples/memcached/server/Item.h" 2 | 3 | #include "muduo/base/LogStream.h" 4 | #include "muduo/net/Buffer.h" 5 | 6 | #include 7 | 8 | #include // memcpy 9 | #include 10 | 11 | using namespace muduo; 12 | using namespace muduo::net; 13 | 14 | Item::Item(StringPiece keyArg, 15 | uint32_t flagsArg, 16 | int exptimeArg, 17 | int valuelen, 18 | uint64_t casArg) 19 | : keylen_(keyArg.size()), 20 | flags_(flagsArg), 21 | rel_exptime_(exptimeArg), 22 | valuelen_(valuelen), 23 | receivedBytes_(0), 24 | cas_(casArg), 25 | hash_(boost::hash_range(keyArg.begin(), keyArg.end())), 26 | data_(static_cast(::malloc(totalLen()))) 27 | { 28 | assert(valuelen_ >= 2); 29 | assert(receivedBytes_ < totalLen()); 30 | append(keyArg.data(), keylen_); 31 | } 32 | 33 | void Item::append(const char* data, size_t len) 34 | { 35 | assert(len <= neededBytes()); 36 | memcpy(data_ + receivedBytes_, data, len); 37 | receivedBytes_ += static_cast(len); 38 | assert(receivedBytes_ <= totalLen()); 39 | } 40 | 41 | void Item::output(Buffer* out, bool needCas) const 42 | { 43 | out->append("VALUE "); 44 | out->append(data_, keylen_); 45 | LogStream buf; 46 | buf << ' ' << flags_ << ' ' << valuelen_-2; 47 | if (needCas) 48 | { 49 | buf << ' ' << cas_; 50 | } 51 | buf << "\r\n"; 52 | out->append(buf.buffer().data(), buf.buffer().length()); 53 | out->append(value(), valuelen_); 54 | } 55 | 56 | void Item::resetKey(StringPiece k) 57 | { 58 | assert(k.size() <= 250); 59 | keylen_ = k.size(); 60 | receivedBytes_ = 0; 61 | append(k.data(), k.size()); 62 | hash_ = boost::hash_range(k.begin(), k.end()); 63 | } 64 | -------------------------------------------------------------------------------- /examples/memcached/server/server.cc: -------------------------------------------------------------------------------- 1 | #include "examples/memcached/server/MemcacheServer.h" 2 | 3 | #include "muduo/net/EventLoop.h" 4 | #include "muduo/net/EventLoopThread.h" 5 | #include "muduo/net/inspect/Inspector.h" 6 | 7 | #include 8 | 9 | namespace po = boost::program_options; 10 | using namespace muduo::net; 11 | 12 | bool parseCommandLine(int argc, char* argv[], MemcacheServer::Options* options) 13 | { 14 | options->tcpport = 11211; 15 | options->gperfport = 11212; 16 | options->threads = 4; 17 | 18 | po::options_description desc("Allowed options"); 19 | desc.add_options() 20 | ("help,h", "Help") 21 | ("port,p", po::value(&options->tcpport), "TCP port") 22 | ("udpport,U", po::value(&options->udpport), "UDP port") 23 | ("gperf,g", po::value(&options->gperfport), "port for gperftools") 24 | ("threads,t", po::value(&options->threads), "Number of worker threads") 25 | ; 26 | 27 | po::variables_map vm; 28 | po::store(po::parse_command_line(argc, argv, desc), vm); 29 | po::notify(vm); 30 | 31 | if (vm.count("help")) 32 | { 33 | //printf("memcached 1.1.0\n"); 34 | return false; 35 | } 36 | return true; 37 | } 38 | 39 | int main(int argc, char* argv[]) 40 | { 41 | EventLoop loop; 42 | EventLoopThread inspectThread; 43 | MemcacheServer::Options options; 44 | if (parseCommandLine(argc, argv, &options)) 45 | { 46 | // FIXME: how to destruct it safely ? 47 | new Inspector(inspectThread.startLoop(), InetAddress(options.gperfport), "memcached-debug"); 48 | 49 | MemcacheServer server(&loop, options); 50 | server.setThreadNum(options.threads); 51 | server.start(); 52 | loop.loop(); 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /examples/multiplexer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(multiplex_server multiplexer.cc) 2 | target_link_libraries(multiplex_server muduo_net) 3 | 4 | add_executable(multiplex_server_simple multiplexer_simple.cc) 5 | target_link_libraries(multiplex_server_simple muduo_net) 6 | 7 | add_executable(multiplex_demux demux.cc) 8 | target_link_libraries(multiplex_demux muduo_net) 9 | 10 | -------------------------------------------------------------------------------- /examples/multiplexer/harness/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | CLASSPATH=lib/netty-3.2.4.Final.jar:lib/slf4j-api-1.6.1.jar:lib/slf4j-simple-1.6.1.jar:./bin 4 | 5 | export CLASSPATH 6 | mkdir -p bin 7 | javac -d bin ./src/com/chenshuo/muduo/example/multiplexer/*.java ./src/com/chenshuo/muduo/example/multiplexer/testcase/*.java 8 | java -ea -Djava.net.preferIPv4Stack=true com.chenshuo.muduo.example.multiplexer.MultiplexerTest localhost 9 | -------------------------------------------------------------------------------- /examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/DataEvent.java: -------------------------------------------------------------------------------- 1 | package com.chenshuo.muduo.example.multiplexer; 2 | 3 | import java.nio.charset.Charset; 4 | 5 | import org.jboss.netty.buffer.ChannelBuffer; 6 | 7 | public class DataEvent extends Event { 8 | 9 | public final EventSource source; 10 | public final int whichClient; 11 | public final ChannelBuffer data; 12 | 13 | public DataEvent(EventSource source, int whichClient, ChannelBuffer data) { 14 | this.source = source; 15 | this.whichClient = whichClient; 16 | this.data = data; 17 | } 18 | 19 | public String getString() { 20 | return data.toString(Charset.defaultCharset()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/Event.java: -------------------------------------------------------------------------------- 1 | package com.chenshuo.muduo.example.multiplexer; 2 | 3 | public class Event { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/EventQueue.java: -------------------------------------------------------------------------------- 1 | package com.chenshuo.muduo.example.multiplexer; 2 | 3 | import java.util.concurrent.BlockingDeque; 4 | import java.util.concurrent.LinkedBlockingDeque; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | public class EventQueue { 8 | private BlockingDeque queue = new LinkedBlockingDeque(); 9 | 10 | public void put(Event e) { 11 | queue.add(e); 12 | } 13 | 14 | public Event take() { 15 | try { 16 | return queue.poll(5, TimeUnit.SECONDS); 17 | } catch (InterruptedException e) { 18 | return null; 19 | } 20 | } 21 | 22 | public boolean isEmpty() { 23 | return queue.isEmpty(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/EventSource.java: -------------------------------------------------------------------------------- 1 | package com.chenshuo.muduo.example.multiplexer; 2 | 3 | public enum EventSource { 4 | kBackend, kClient 5 | } 6 | -------------------------------------------------------------------------------- /examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/MyCountDownLatch.java: -------------------------------------------------------------------------------- 1 | package com.chenshuo.muduo.example.multiplexer; 2 | 3 | import java.util.concurrent.CountDownLatch; 4 | import java.util.concurrent.TimeUnit; 5 | 6 | public class MyCountDownLatch extends CountDownLatch { 7 | 8 | public MyCountDownLatch(int count) { 9 | super(count); 10 | } 11 | 12 | public void awaitUninterruptibly() { 13 | try { 14 | await(); 15 | } catch (InterruptedException e) { 16 | } 17 | } 18 | 19 | public void awaitUninterruptibly(int millis) { 20 | try { 21 | await(millis, TimeUnit.MILLISECONDS); 22 | } catch (InterruptedException e) { 23 | } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/TestCase.java: -------------------------------------------------------------------------------- 1 | package com.chenshuo.muduo.example.multiplexer; 2 | 3 | import org.jboss.netty.buffer.ChannelBufferFactory; 4 | 5 | public abstract class TestCase { 6 | protected static final ChannelBufferFactory bufferFactory = MultiplexerTest.bufferFactory; 7 | 8 | protected MultiplexerTest god; 9 | protected EventQueue queue; 10 | protected MockBackendServer backend; 11 | 12 | public void setOwner(MultiplexerTest god) { 13 | this.god = god; 14 | queue = god.getEventQueue(); 15 | backend = god.getBackend(); 16 | } 17 | 18 | public void test() { 19 | try { 20 | run(); 21 | } catch (TestFailedException e) { 22 | System.out.printf("%s FAILED: %s\n", this.getClass().getSimpleName(), e.getMessage()); 23 | e.printStackTrace(); 24 | return; 25 | } catch (Exception e) { 26 | System.out.printf("%s FATAL: %s\n", this.getClass().getSimpleName(), e.toString()); 27 | e.printStackTrace(); 28 | return; 29 | } 30 | System.out.printf("%s PASS\n", this.getClass().getSimpleName()); 31 | } 32 | 33 | protected void assertEquals(Object expected, Object actual) { 34 | if (!expected.equals(actual)) 35 | fail("assertEquals failed"); 36 | } 37 | 38 | protected void assertTrue(boolean yes) { 39 | if (!yes) 40 | fail("assertTrue failed"); 41 | } 42 | 43 | protected void fail(String message) { 44 | throw new TestFailedException(message); 45 | } 46 | 47 | public abstract void run(); 48 | } 49 | -------------------------------------------------------------------------------- /examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/TestFailedException.java: -------------------------------------------------------------------------------- 1 | package com.chenshuo.muduo.example.multiplexer; 2 | 3 | public class TestFailedException extends RuntimeException { 4 | private static final long serialVersionUID = 1982L; 5 | 6 | public TestFailedException(String message) { 7 | super(message); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/testcase/TestOneClientNoData.java: -------------------------------------------------------------------------------- 1 | package com.chenshuo.muduo.example.multiplexer.testcase; 2 | 3 | import java.util.regex.Matcher; 4 | 5 | import com.chenshuo.muduo.example.multiplexer.DataEvent; 6 | import com.chenshuo.muduo.example.multiplexer.Event; 7 | import com.chenshuo.muduo.example.multiplexer.EventSource; 8 | import com.chenshuo.muduo.example.multiplexer.MockClient; 9 | import com.chenshuo.muduo.example.multiplexer.TestCase; 10 | 11 | public class TestOneClientNoData extends TestCase { 12 | 13 | @Override 14 | public void run() { 15 | if (!queue.isEmpty()) 16 | fail("EventQueue is not empty"); 17 | 18 | MockClient client = god.newClient(); 19 | Event ev = queue.take(); 20 | DataEvent de = (DataEvent) ev; 21 | assertEquals(EventSource.kBackend, de.source); 22 | 23 | Matcher m = god.commandChannel.matcher(de.getString()); 24 | if (!m.matches()) 25 | fail("command channel message doesn't match."); 26 | 27 | int connId = Integer.parseInt(m.group(1)); 28 | assertTrue(connId > 0); 29 | client.setId(connId); 30 | 31 | assertEquals("UP", m.group(2)); 32 | 33 | client.disconnect(); 34 | de = (DataEvent) queue.take(); 35 | assertEquals(EventSource.kBackend, de.source); 36 | m = god.commandChannel.matcher(de.getString()); 37 | if (!m.matches()) 38 | fail("command channel message doesn't match."); 39 | 40 | assertEquals(connId, Integer.parseInt(m.group(1))); 41 | assertEquals("DOWN", m.group(2)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /examples/netty/discard/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(netty_discard_client client.cc) 2 | target_link_libraries(netty_discard_client muduo_net) 3 | 4 | add_executable(netty_discard_server server.cc) 5 | target_link_libraries(netty_discard_server muduo_net) 6 | 7 | -------------------------------------------------------------------------------- /examples/netty/echo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(netty_echo_client client.cc) 2 | target_link_libraries(netty_echo_client muduo_net) 3 | 4 | add_executable(netty_echo_server server.cc) 5 | target_link_libraries(netty_echo_server muduo_net) 6 | 7 | add_executable(netty_echo_server2 server2.cc) 8 | target_link_libraries(netty_echo_server2 muduo_net) 9 | 10 | -------------------------------------------------------------------------------- /examples/netty/uptime/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(netty_uptime uptime.cc) 2 | target_link_libraries(netty_uptime muduo_net) 3 | 4 | -------------------------------------------------------------------------------- /examples/netty/uptime/uptime.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/net/TcpClient.h" 2 | 3 | #include "muduo/base/Logging.h" 4 | #include "muduo/base/Thread.h" 5 | #include "muduo/net/EventLoop.h" 6 | #include "muduo/net/InetAddress.h" 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | using namespace muduo; 14 | using namespace muduo::net; 15 | 16 | class UptimeClient : noncopyable 17 | { 18 | public: 19 | UptimeClient(EventLoop* loop, const InetAddress& listenAddr) 20 | : client_(loop, listenAddr, "UptimeClient") 21 | { 22 | client_.setConnectionCallback( 23 | std::bind(&UptimeClient::onConnection, this, _1)); 24 | client_.setMessageCallback( 25 | std::bind(&UptimeClient::onMessage, this, _1, _2, _3)); 26 | //client_.enableRetry(); 27 | } 28 | 29 | void connect() 30 | { 31 | client_.connect(); 32 | } 33 | 34 | private: 35 | void onConnection(const TcpConnectionPtr& conn) 36 | { 37 | LOG_TRACE << conn->localAddress().toIpPort() << " -> " 38 | << conn->peerAddress().toIpPort() << " is " 39 | << (conn->connected() ? "UP" : "DOWN"); 40 | } 41 | 42 | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp time) 43 | { 44 | } 45 | 46 | TcpClient client_; 47 | }; 48 | 49 | int main(int argc, char* argv[]) 50 | { 51 | LOG_INFO << "pid = " << getpid() << ", tid = " << CurrentThread::tid(); 52 | if (argc > 2) 53 | { 54 | EventLoop loop; 55 | uint16_t port = static_cast(atoi(argv[2])); 56 | InetAddress serverAddr(argv[1], port); 57 | 58 | UptimeClient client(&loop, serverAddr); 59 | client.connect(); 60 | loop.loop(); 61 | } 62 | else 63 | { 64 | printf("Usage: %s host_ip port\n", argv[0]); 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /examples/pingpong/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(pingpong_client client.cc) 2 | target_link_libraries(pingpong_client muduo_net) 3 | 4 | add_executable(pingpong_server server.cc) 5 | target_link_libraries(pingpong_server muduo_net) 6 | 7 | add_executable(pingpong_bench bench.cc) 8 | target_link_libraries(pingpong_bench muduo_net) 9 | 10 | -------------------------------------------------------------------------------- /examples/pingpong/server.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/net/TcpServer.h" 2 | 3 | #include "muduo/base/Atomic.h" 4 | #include "muduo/base/Logging.h" 5 | #include "muduo/base/Thread.h" 6 | #include "muduo/net/EventLoop.h" 7 | #include "muduo/net/InetAddress.h" 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | using namespace muduo; 15 | using namespace muduo::net; 16 | 17 | void onConnection(const TcpConnectionPtr& conn) 18 | { 19 | if (conn->connected()) 20 | { 21 | conn->setTcpNoDelay(true); 22 | } 23 | } 24 | 25 | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp) 26 | { 27 | conn->send(buf); 28 | } 29 | 30 | int main(int argc, char* argv[]) 31 | { 32 | if (argc < 4) 33 | { 34 | fprintf(stderr, "Usage: server
\n"); 35 | } 36 | else 37 | { 38 | LOG_INFO << "pid = " << getpid() << ", tid = " << CurrentThread::tid(); 39 | Logger::setLogLevel(Logger::WARN); 40 | 41 | const char* ip = argv[1]; 42 | uint16_t port = static_cast(atoi(argv[2])); 43 | InetAddress listenAddr(ip, port); 44 | int threadCount = atoi(argv[3]); 45 | 46 | EventLoop loop; 47 | 48 | TcpServer server(&loop, listenAddr, "PingPong"); 49 | 50 | server.setConnectionCallback(onConnection); 51 | server.setMessageCallback(onMessage); 52 | 53 | if (threadCount > 1) 54 | { 55 | server.setThreadNum(threadCount); 56 | } 57 | 58 | server.start(); 59 | 60 | loop.loop(); 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /examples/procmon/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(procmon procmon.cc plot.cc) 2 | target_link_libraries(procmon muduo_http gd) 3 | 4 | add_executable(plot_test plot_test.cc plot.cc) 5 | target_link_libraries(plot_test muduo_base gd) 6 | 7 | add_executable(dummyload dummyload.cc) 8 | target_link_libraries(dummyload muduo_net) 9 | -------------------------------------------------------------------------------- /examples/procmon/plot.h: -------------------------------------------------------------------------------- 1 | #include "muduo/base/noncopyable.h" 2 | #include "muduo/base/Types.h" 3 | #include 4 | #include // ssize_t 5 | 6 | typedef struct gdImageStruct* gdImagePtr; 7 | 8 | class Plot : muduo::noncopyable 9 | { 10 | public: 11 | Plot(int width, int height, int totalSeconds, int samplingPeriod); 12 | ~Plot(); 13 | muduo::string plotCpu(const std::vector& data); 14 | 15 | private: 16 | muduo::string toPng(); 17 | // pair, int> toPng(); 18 | int getX(ssize_t x, ssize_t total) const; 19 | int getY(double value) const; 20 | void label(double maxValue); 21 | 22 | // gdFont is a typedef of unnamed struct, cannot be forward declared 23 | // wordaround suggested in http://stackoverflow.com/questions/7256436/forward-declarations-of-unnamed-struct 24 | struct MyGdFont; 25 | typedef struct MyGdFont* MyGdFontPtr; 26 | 27 | const int width_; 28 | const int height_; 29 | const int totalSeconds_; 30 | const int samplingPeriod_; 31 | gdImagePtr const image_; 32 | MyGdFontPtr const font_; 33 | const int fontWidth_; 34 | const int fontHeight_; 35 | const int background_; 36 | const int black_; 37 | const int gray_; 38 | const int blue_; 39 | 40 | const int kRightMargin_; 41 | static const int kLeftMargin_ = 5; 42 | static const int kMarginY_ = 5; 43 | 44 | const double ratioX_; 45 | }; 46 | 47 | -------------------------------------------------------------------------------- /examples/procmon/plot_test.cc: -------------------------------------------------------------------------------- 1 | #include "examples/procmon/plot.h" 2 | #include "muduo/base/Timestamp.h" 3 | #include 4 | #include 5 | #include 6 | 7 | int main() 8 | { 9 | std::vector cpu_usage; 10 | cpu_usage.reserve(300); 11 | for (int i = 0; i < 300; ++i) 12 | cpu_usage.push_back(1.0 + sin(pow(i / 30.0, 2))); 13 | Plot plot(640, 100, 600, 2); 14 | muduo::Timestamp start(muduo::Timestamp::now()); 15 | const int N = 10000; 16 | for (int i = 0; i < N; ++i) 17 | muduo::string png = plot.plotCpu(cpu_usage); 18 | double elapsed = timeDifference(muduo::Timestamp::now(), start); 19 | printf("%d plots in %f seconds, %f PNG per second, %f ms per PNG\n", 20 | N, elapsed, N / elapsed, elapsed * 1000 / N); 21 | muduo::string png = plot.plotCpu(cpu_usage); 22 | 23 | FILE* fp = fopen("test.png", "wb"); 24 | fwrite(png.data(), 1, png.size(), fp); 25 | fclose(fp); 26 | printf("Image saved to test.png\n"); 27 | } 28 | -------------------------------------------------------------------------------- /examples/protobuf/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(codec) 2 | add_subdirectory(rpc) 3 | add_subdirectory(rpcbalancer) 4 | add_subdirectory(rpcbench) 5 | 6 | if(CARES_INCLUDE_DIR AND CARES_LIBRARY) 7 | add_subdirectory(resolver) 8 | else() 9 | add_subdirectory(resolver EXCLUDE_FROM_ALL) 10 | endif() 11 | -------------------------------------------------------------------------------- /examples/protobuf/codec/dispatcher_lite_test.cc: -------------------------------------------------------------------------------- 1 | #include "examples/protobuf/codec/dispatcher_lite.h" 2 | 3 | #include "examples/protobuf/codec/query.pb.h" 4 | 5 | #include 6 | 7 | using std::cout; 8 | using std::endl; 9 | 10 | void onUnknownMessageType(const muduo::net::TcpConnectionPtr&, 11 | const MessagePtr& message, 12 | muduo::Timestamp) 13 | { 14 | cout << "onUnknownMessageType: " << message->GetTypeName() << endl; 15 | } 16 | 17 | void onQuery(const muduo::net::TcpConnectionPtr&, 18 | const MessagePtr& message, 19 | muduo::Timestamp) 20 | { 21 | cout << "onQuery: " << message->GetTypeName() << endl; 22 | std::shared_ptr query = muduo::down_pointer_cast(message); 23 | assert(query != NULL); 24 | } 25 | 26 | void onAnswer(const muduo::net::TcpConnectionPtr&, 27 | const MessagePtr& message, 28 | muduo::Timestamp) 29 | { 30 | cout << "onAnswer: " << message->GetTypeName() << endl; 31 | std::shared_ptr answer = muduo::down_pointer_cast(message); 32 | assert(answer != NULL); 33 | } 34 | 35 | int main() 36 | { 37 | GOOGLE_PROTOBUF_VERIFY_VERSION; 38 | 39 | ProtobufDispatcherLite dispatcher(onUnknownMessageType); 40 | dispatcher.registerMessageCallback(muduo::Query::descriptor(), onQuery); 41 | dispatcher.registerMessageCallback(muduo::Answer::descriptor(), onAnswer); 42 | 43 | muduo::net::TcpConnectionPtr conn; 44 | muduo::Timestamp t; 45 | 46 | std::shared_ptr query(new muduo::Query); 47 | std::shared_ptr answer(new muduo::Answer); 48 | std::shared_ptr empty(new muduo::Empty); 49 | dispatcher.onProtobufMessage(conn, query, t); 50 | dispatcher.onProtobufMessage(conn, answer, t); 51 | dispatcher.onProtobufMessage(conn, empty, t); 52 | 53 | google::protobuf::ShutdownProtobufLibrary(); 54 | } 55 | 56 | -------------------------------------------------------------------------------- /examples/protobuf/codec/query.proto: -------------------------------------------------------------------------------- 1 | package muduo; 2 | option java_package = "muduo.codec.tests"; 3 | option java_outer_classname = "QueryProtos"; 4 | 5 | message Query { 6 | required int64 id = 1; 7 | required string questioner = 2; 8 | 9 | repeated string question = 3; 10 | } 11 | 12 | message Answer { 13 | required int64 id = 1; 14 | required string questioner = 2; 15 | required string answerer = 3; 16 | 17 | repeated string solution = 4; 18 | } 19 | 20 | message Empty { 21 | optional int32 id = 1; 22 | } 23 | -------------------------------------------------------------------------------- /examples/protobuf/resolver/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_custom_command(OUTPUT resolver.pb.cc resolver.pb.h 2 | COMMAND protoc 3 | ARGS --cpp_out . ${CMAKE_CURRENT_SOURCE_DIR}/resolver.proto -I${CMAKE_CURRENT_SOURCE_DIR} 4 | DEPENDS resolver.proto) 5 | 6 | set_source_files_properties(resolver.pb.cc PROPERTIES COMPILE_FLAGS "-Wno-conversion -Wno-shadow") 7 | include_directories(${PROJECT_BINARY_DIR}) 8 | 9 | add_library(resolver_proto resolver.pb.cc) 10 | target_link_libraries(resolver_proto protobuf pthread) 11 | 12 | add_executable(protobuf_rpc_resolver_client client.cc) 13 | set_target_properties(protobuf_rpc_resolver_client PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 14 | target_link_libraries(protobuf_rpc_resolver_client resolver_proto muduo_protorpc) 15 | 16 | add_executable(protobuf_rpc_resolver_server server.cc) 17 | set_target_properties(protobuf_rpc_resolver_server PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 18 | target_link_libraries(protobuf_rpc_resolver_server resolver_proto muduo_protorpc muduo_cdns) 19 | -------------------------------------------------------------------------------- /examples/protobuf/resolver/resolver.proto: -------------------------------------------------------------------------------- 1 | package resolver; 2 | option cc_generic_services = true; 3 | option java_generic_services = true; 4 | option py_generic_services = true; 5 | 6 | message ResolveRequest { 7 | required string address = 1; 8 | } 9 | 10 | message ResolveResponse { 11 | optional bool resolved = 1 [default=false]; 12 | repeated fixed32 ip = 2; 13 | repeated int32 port = 3; 14 | } 15 | 16 | service ResolverService { 17 | rpc Resolve (ResolveRequest) returns (ResolveResponse); 18 | } 19 | 20 | -------------------------------------------------------------------------------- /examples/protobuf/rpc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_custom_command(OUTPUT sudoku.pb.cc sudoku.pb.h 2 | COMMAND protoc 3 | ARGS --cpp_out . ${CMAKE_CURRENT_SOURCE_DIR}/sudoku.proto -I${CMAKE_CURRENT_SOURCE_DIR} 4 | DEPENDS sudoku.proto) 5 | 6 | set_source_files_properties(sudoku.pb.cc PROPERTIES COMPILE_FLAGS "-Wno-conversion -Wno-shadow") 7 | include_directories(${PROJECT_BINARY_DIR}) 8 | 9 | add_library(sudoku_proto sudoku.pb.cc) 10 | target_link_libraries(sudoku_proto protobuf pthread) 11 | 12 | add_executable(protobuf_rpc_sudoku_client client.cc) 13 | set_target_properties(protobuf_rpc_sudoku_client PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 14 | target_link_libraries(protobuf_rpc_sudoku_client sudoku_proto muduo_protorpc) 15 | 16 | add_executable(protobuf_rpc_sudoku_server server.cc) 17 | set_target_properties(protobuf_rpc_sudoku_server PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 18 | target_link_libraries(protobuf_rpc_sudoku_server sudoku_proto muduo_protorpc) 19 | 20 | add_custom_target(protobuf_rpc_all 21 | DEPENDS 22 | muduo_protorpc 23 | protobuf_rpc_balancer 24 | protobuf_rpc_balancer_raw 25 | protobuf_rpc_echo_client 26 | protobuf_rpc_echo_server 27 | protobuf_rpc_resolver_client 28 | protobuf_rpc_resolver_server 29 | protobuf_rpc_sudoku_client 30 | protobuf_rpc_sudoku_server 31 | ) 32 | -------------------------------------------------------------------------------- /examples/protobuf/rpc/server.cc: -------------------------------------------------------------------------------- 1 | #include "examples/protobuf/rpc/sudoku.pb.h" 2 | 3 | #include "muduo/base/Logging.h" 4 | #include "muduo/net/EventLoop.h" 5 | #include "muduo/net/protorpc/RpcServer.h" 6 | 7 | #include 8 | 9 | using namespace muduo; 10 | using namespace muduo::net; 11 | 12 | namespace sudoku 13 | { 14 | 15 | class SudokuServiceImpl : public SudokuService 16 | { 17 | public: 18 | virtual void Solve(::google::protobuf::RpcController* controller, 19 | const ::sudoku::SudokuRequest* request, 20 | ::sudoku::SudokuResponse* response, 21 | ::google::protobuf::Closure* done) 22 | { 23 | LOG_INFO << "SudokuServiceImpl::Solve"; 24 | response->set_solved(true); 25 | response->set_checkerboard("1234567"); 26 | done->Run(); 27 | } 28 | }; 29 | 30 | } // namespace sudoku 31 | 32 | int main() 33 | { 34 | LOG_INFO << "pid = " << getpid(); 35 | EventLoop loop; 36 | InetAddress listenAddr(9981); 37 | sudoku::SudokuServiceImpl impl; 38 | RpcServer server(&loop, listenAddr); 39 | server.registerService(&impl); 40 | server.start(); 41 | loop.loop(); 42 | google::protobuf::ShutdownProtobufLibrary(); 43 | } 44 | 45 | -------------------------------------------------------------------------------- /examples/protobuf/rpc/sudoku.proto: -------------------------------------------------------------------------------- 1 | package sudoku; 2 | option cc_generic_services = true; 3 | option java_generic_services = true; 4 | option py_generic_services = true; 5 | 6 | message SudokuRequest { 7 | required string checkerboard = 1; 8 | } 9 | 10 | message SudokuResponse { 11 | optional bool solved = 1 [default=false]; 12 | optional string checkerboard = 2; 13 | } 14 | 15 | service SudokuService { 16 | rpc Solve (SudokuRequest) returns (SudokuResponse); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /examples/protobuf/rpcbalancer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${PROJECT_BINARY_DIR}) 2 | 3 | add_executable(protobuf_rpc_balancer balancer.cc) 4 | set_target_properties(protobuf_rpc_balancer PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 5 | target_link_libraries(protobuf_rpc_balancer muduo_protorpc) 6 | 7 | add_executable(protobuf_rpc_balancer_raw balancer_raw.cc) 8 | set_target_properties(protobuf_rpc_balancer_raw PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 9 | target_link_libraries(protobuf_rpc_balancer_raw muduo_protorpc) 10 | -------------------------------------------------------------------------------- /examples/protobuf/rpcbench/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_custom_command(OUTPUT echo.pb.cc echo.pb.h 2 | COMMAND protoc 3 | ARGS --cpp_out . ${CMAKE_CURRENT_SOURCE_DIR}/echo.proto -I${CMAKE_CURRENT_SOURCE_DIR} 4 | DEPENDS echo.proto) 5 | 6 | set_source_files_properties(echo.pb.cc PROPERTIES COMPILE_FLAGS "-Wno-conversion -Wno-shadow") 7 | include_directories(${PROJECT_BINARY_DIR}) 8 | 9 | add_library(echo_proto echo.pb.cc) 10 | target_link_libraries(echo_proto protobuf pthread) 11 | 12 | add_executable(protobuf_rpc_echo_client client.cc) 13 | set_target_properties(protobuf_rpc_echo_client PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 14 | target_link_libraries(protobuf_rpc_echo_client echo_proto muduo_protorpc) 15 | 16 | add_executable(protobuf_rpc_echo_server server.cc) 17 | set_target_properties(protobuf_rpc_echo_server PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 18 | target_link_libraries(protobuf_rpc_echo_server echo_proto muduo_protorpc) 19 | -------------------------------------------------------------------------------- /examples/protobuf/rpcbench/echo.proto: -------------------------------------------------------------------------------- 1 | package echo; 2 | //option py_generic_services = true; 3 | option cc_generic_services = true; 4 | option java_generic_services = true; 5 | option java_package = "echo"; 6 | option java_outer_classname = "EchoProto"; 7 | 8 | message EchoRequest { 9 | required string payload = 1; 10 | } 11 | 12 | message EchoResponse { 13 | required string payload = 2; 14 | } 15 | 16 | service EchoService { 17 | rpc Echo (EchoRequest) returns (EchoResponse); 18 | } 19 | 20 | -------------------------------------------------------------------------------- /examples/protobuf/rpcbench/server.cc: -------------------------------------------------------------------------------- 1 | #include "examples/protobuf/rpcbench/echo.pb.h" 2 | 3 | #include "muduo/base/Logging.h" 4 | #include "muduo/net/EventLoop.h" 5 | #include "muduo/net/protorpc/RpcServer.h" 6 | 7 | #include 8 | 9 | using namespace muduo; 10 | using namespace muduo::net; 11 | 12 | namespace echo 13 | { 14 | 15 | class EchoServiceImpl : public EchoService 16 | { 17 | public: 18 | virtual void Echo(::google::protobuf::RpcController* controller, 19 | const ::echo::EchoRequest* request, 20 | ::echo::EchoResponse* response, 21 | ::google::protobuf::Closure* done) 22 | { 23 | //LOG_INFO << "EchoServiceImpl::Solve"; 24 | response->set_payload(request->payload()); 25 | done->Run(); 26 | } 27 | }; 28 | 29 | } // namespace echo 30 | 31 | int main(int argc, char* argv[]) 32 | { 33 | int nThreads = argc > 1 ? atoi(argv[1]) : 1; 34 | LOG_INFO << "pid = " << getpid() << " threads = " << nThreads; 35 | EventLoop loop; 36 | int port = argc > 2 ? atoi(argv[2]) : 8888; 37 | InetAddress listenAddr(static_cast(port)); 38 | echo::EchoServiceImpl impl; 39 | RpcServer server(&loop, listenAddr); 40 | server.setThreadNum(nThreads); 41 | server.registerService(&impl); 42 | server.start(); 43 | loop.loop(); 44 | } 45 | 46 | -------------------------------------------------------------------------------- /examples/roundtrip/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(roundtrip roundtrip.cc) 2 | target_link_libraries(roundtrip muduo_net) 3 | 4 | add_executable(roundtrip_udp roundtrip_udp.cc) 5 | target_link_libraries(roundtrip_udp muduo_net) 6 | 7 | -------------------------------------------------------------------------------- /examples/shorturl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(shorturl shorturl.cc) 2 | target_link_libraries(shorturl muduo_http) 3 | 4 | -------------------------------------------------------------------------------- /examples/simple/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(simple_chargen chargen/chargen.cc chargen/main.cc) 2 | target_link_libraries(simple_chargen muduo_net) 3 | 4 | add_executable(simple_daytime daytime/daytime.cc daytime/main.cc) 5 | target_link_libraries(simple_daytime muduo_net) 6 | 7 | add_executable(simple_discard discard/discard.cc discard/main.cc) 8 | target_link_libraries(simple_discard muduo_net) 9 | 10 | add_executable(simple_echo echo/echo.cc echo/main.cc) 11 | target_link_libraries(simple_echo muduo_net) 12 | 13 | add_executable(simple_time time/time.cc time/main.cc) 14 | target_link_libraries(simple_time muduo_net) 15 | 16 | add_executable(simple_allinone 17 | allinone/allinone.cc 18 | chargen/chargen.cc 19 | daytime/daytime.cc 20 | discard/discard.cc 21 | echo/echo.cc 22 | time/time.cc 23 | ) 24 | target_link_libraries(simple_allinone muduo_net) 25 | 26 | add_executable(simple_timeclient timeclient/timeclient.cc) 27 | target_link_libraries(simple_timeclient muduo_net) 28 | 29 | add_executable(simple_chargenclient chargenclient/chargenclient.cc) 30 | target_link_libraries(simple_chargenclient muduo_net) 31 | 32 | -------------------------------------------------------------------------------- /examples/simple/allinone/allinone.cc: -------------------------------------------------------------------------------- 1 | #include "examples/simple/chargen/chargen.h" 2 | #include "examples/simple/daytime/daytime.h" 3 | #include "examples/simple/discard/discard.h" 4 | #include "examples/simple/echo/echo.h" 5 | #include "examples/simple/time/time.h" 6 | 7 | #include "muduo/base/Logging.h" 8 | #include "muduo/net/EventLoop.h" 9 | 10 | #include 11 | 12 | using namespace muduo; 13 | using namespace muduo::net; 14 | 15 | int main() 16 | { 17 | LOG_INFO << "pid = " << getpid(); 18 | EventLoop loop; // one loop shared by multiple servers 19 | 20 | ChargenServer chargenServer(&loop, InetAddress(2019)); 21 | chargenServer.start(); 22 | 23 | DaytimeServer daytimeServer(&loop, InetAddress(2013)); 24 | daytimeServer.start(); 25 | 26 | DiscardServer discardServer(&loop, InetAddress(2009)); 27 | discardServer.start(); 28 | 29 | EchoServer echoServer(&loop, InetAddress(2007)); 30 | echoServer.start(); 31 | 32 | TimeServer timeServer(&loop, InetAddress(2037)); 33 | timeServer.start(); 34 | 35 | loop.loop(); 36 | } 37 | 38 | -------------------------------------------------------------------------------- /examples/simple/chargen/chargen.h: -------------------------------------------------------------------------------- 1 | #ifndef MUDUO_EXAMPLES_SIMPLE_CHARGEN_CHARGEN_H 2 | #define MUDUO_EXAMPLES_SIMPLE_CHARGEN_CHARGEN_H 3 | 4 | #include "muduo/net/TcpServer.h" 5 | 6 | // RFC 864 7 | class ChargenServer 8 | { 9 | public: 10 | ChargenServer(muduo::net::EventLoop* loop, 11 | const muduo::net::InetAddress& listenAddr, 12 | bool print = false); 13 | 14 | void start(); 15 | 16 | private: 17 | void onConnection(const muduo::net::TcpConnectionPtr& conn); 18 | 19 | void onMessage(const muduo::net::TcpConnectionPtr& conn, 20 | muduo::net::Buffer* buf, 21 | muduo::Timestamp time); 22 | 23 | void onWriteComplete(const muduo::net::TcpConnectionPtr& conn); 24 | void printThroughput(); 25 | 26 | muduo::net::TcpServer server_; 27 | 28 | muduo::string message_; 29 | int64_t transferred_; 30 | muduo::Timestamp startTime_; 31 | }; 32 | 33 | #endif // MUDUO_EXAMPLES_SIMPLE_CHARGEN_CHARGEN_H 34 | -------------------------------------------------------------------------------- /examples/simple/chargen/main.cc: -------------------------------------------------------------------------------- 1 | #include "examples/simple/chargen/chargen.h" 2 | 3 | #include "muduo/base/Logging.h" 4 | #include "muduo/net/EventLoop.h" 5 | 6 | #include 7 | 8 | using namespace muduo; 9 | using namespace muduo::net; 10 | 11 | int main() 12 | { 13 | LOG_INFO << "pid = " << getpid(); 14 | EventLoop loop; 15 | InetAddress listenAddr(2019); 16 | ChargenServer server(&loop, listenAddr, true); 17 | server.start(); 18 | loop.loop(); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /examples/simple/chargenclient/chargenclient.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/Logging.h" 2 | #include "muduo/net/EventLoop.h" 3 | #include "muduo/net/InetAddress.h" 4 | #include "muduo/net/TcpClient.h" 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | using namespace muduo; 12 | using namespace muduo::net; 13 | 14 | class ChargenClient : noncopyable 15 | { 16 | public: 17 | ChargenClient(EventLoop* loop, const InetAddress& listenAddr) 18 | : loop_(loop), 19 | client_(loop, listenAddr, "ChargenClient") 20 | { 21 | client_.setConnectionCallback( 22 | std::bind(&ChargenClient::onConnection, this, _1)); 23 | client_.setMessageCallback( 24 | std::bind(&ChargenClient::onMessage, this, _1, _2, _3)); 25 | // client_.enableRetry(); 26 | } 27 | 28 | void connect() 29 | { 30 | client_.connect(); 31 | } 32 | 33 | private: 34 | void onConnection(const TcpConnectionPtr& conn) 35 | { 36 | LOG_INFO << conn->localAddress().toIpPort() << " -> " 37 | << conn->peerAddress().toIpPort() << " is " 38 | << (conn->connected() ? "UP" : "DOWN"); 39 | 40 | if (!conn->connected()) 41 | loop_->quit(); 42 | } 43 | 44 | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp receiveTime) 45 | { 46 | buf->retrieveAll(); 47 | } 48 | 49 | EventLoop* loop_; 50 | TcpClient client_; 51 | }; 52 | 53 | int main(int argc, char* argv[]) 54 | { 55 | LOG_INFO << "pid = " << getpid(); 56 | if (argc > 1) 57 | { 58 | EventLoop loop; 59 | InetAddress serverAddr(argv[1], 2019); 60 | 61 | ChargenClient chargenClient(&loop, serverAddr); 62 | chargenClient.connect(); 63 | loop.loop(); 64 | } 65 | else 66 | { 67 | printf("Usage: %s host_ip\n", argv[0]); 68 | } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /examples/simple/daytime/daytime.cc: -------------------------------------------------------------------------------- 1 | #include "examples/simple/daytime/daytime.h" 2 | 3 | #include "muduo/base/Logging.h" 4 | #include "muduo/net/EventLoop.h" 5 | 6 | using namespace muduo; 7 | using namespace muduo::net; 8 | 9 | DaytimeServer::DaytimeServer(EventLoop* loop, 10 | const InetAddress& listenAddr) 11 | : server_(loop, listenAddr, "DaytimeServer") 12 | { 13 | server_.setConnectionCallback( 14 | std::bind(&DaytimeServer::onConnection, this, _1)); 15 | server_.setMessageCallback( 16 | std::bind(&DaytimeServer::onMessage, this, _1, _2, _3)); 17 | } 18 | 19 | void DaytimeServer::start() 20 | { 21 | server_.start(); 22 | } 23 | 24 | void DaytimeServer::onConnection(const TcpConnectionPtr& conn) 25 | { 26 | LOG_INFO << "DaytimeServer - " << conn->peerAddress().toIpPort() << " -> " 27 | << conn->localAddress().toIpPort() << " is " 28 | << (conn->connected() ? "UP" : "DOWN"); 29 | if (conn->connected()) 30 | { 31 | conn->send(Timestamp::now().toFormattedString() + "\n"); 32 | conn->shutdown(); 33 | } 34 | } 35 | 36 | void DaytimeServer::onMessage(const TcpConnectionPtr& conn, 37 | Buffer* buf, 38 | Timestamp time) 39 | { 40 | string msg(buf->retrieveAllAsString()); 41 | LOG_INFO << conn->name() << " discards " << msg.size() 42 | << " bytes received at " << time.toString(); 43 | } 44 | 45 | -------------------------------------------------------------------------------- /examples/simple/daytime/daytime.h: -------------------------------------------------------------------------------- 1 | #ifndef MUDUO_EXAMPLES_SIMPLE_DAYTIME_DAYTIME_H 2 | #define MUDUO_EXAMPLES_SIMPLE_DAYTIME_DAYTIME_H 3 | 4 | #include "muduo/net/TcpServer.h" 5 | 6 | // RFC 867 7 | class DaytimeServer 8 | { 9 | public: 10 | DaytimeServer(muduo::net::EventLoop* loop, 11 | const muduo::net::InetAddress& listenAddr); 12 | 13 | void start(); 14 | 15 | private: 16 | void onConnection(const muduo::net::TcpConnectionPtr& conn); 17 | 18 | void onMessage(const muduo::net::TcpConnectionPtr& conn, 19 | muduo::net::Buffer* buf, 20 | muduo::Timestamp time); 21 | 22 | muduo::net::TcpServer server_; 23 | }; 24 | 25 | #endif // MUDUO_EXAMPLES_SIMPLE_DAYTIME_DAYTIME_H 26 | -------------------------------------------------------------------------------- /examples/simple/daytime/main.cc: -------------------------------------------------------------------------------- 1 | #include "examples/simple/daytime/daytime.h" 2 | 3 | #include "muduo/base/Logging.h" 4 | #include "muduo/net/EventLoop.h" 5 | 6 | #include 7 | 8 | using namespace muduo; 9 | using namespace muduo::net; 10 | 11 | int main() 12 | { 13 | LOG_INFO << "pid = " << getpid(); 14 | EventLoop loop; 15 | InetAddress listenAddr(2013); 16 | DaytimeServer server(&loop, listenAddr); 17 | server.start(); 18 | loop.loop(); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /examples/simple/discard/discard.cc: -------------------------------------------------------------------------------- 1 | #include "examples/simple/discard/discard.h" 2 | 3 | #include "muduo/base/Logging.h" 4 | 5 | using namespace muduo; 6 | using namespace muduo::net; 7 | 8 | DiscardServer::DiscardServer(EventLoop* loop, 9 | const InetAddress& listenAddr) 10 | : server_(loop, listenAddr, "DiscardServer") 11 | { 12 | server_.setConnectionCallback( 13 | std::bind(&DiscardServer::onConnection, this, _1)); 14 | server_.setMessageCallback( 15 | std::bind(&DiscardServer::onMessage, this, _1, _2, _3)); 16 | } 17 | 18 | void DiscardServer::start() 19 | { 20 | server_.start(); 21 | } 22 | 23 | void DiscardServer::onConnection(const TcpConnectionPtr& conn) 24 | { 25 | LOG_INFO << "DiscardServer - " << conn->peerAddress().toIpPort() << " -> " 26 | << conn->localAddress().toIpPort() << " is " 27 | << (conn->connected() ? "UP" : "DOWN"); 28 | } 29 | 30 | void DiscardServer::onMessage(const TcpConnectionPtr& conn, 31 | Buffer* buf, 32 | Timestamp time) 33 | { 34 | string msg(buf->retrieveAllAsString()); 35 | LOG_INFO << conn->name() << " discards " << msg.size() 36 | << " bytes received at " << time.toString(); 37 | } 38 | 39 | -------------------------------------------------------------------------------- /examples/simple/discard/discard.h: -------------------------------------------------------------------------------- 1 | #ifndef MUDUO_EXAMPLES_SIMPLE_DISCARD_DISCARD_H 2 | #define MUDUO_EXAMPLES_SIMPLE_DISCARD_DISCARD_H 3 | 4 | #include "muduo/net/TcpServer.h" 5 | 6 | // RFC 863 7 | class DiscardServer 8 | { 9 | public: 10 | DiscardServer(muduo::net::EventLoop* loop, 11 | const muduo::net::InetAddress& listenAddr); 12 | 13 | void start(); 14 | 15 | private: 16 | void onConnection(const muduo::net::TcpConnectionPtr& conn); 17 | 18 | void onMessage(const muduo::net::TcpConnectionPtr& conn, 19 | muduo::net::Buffer* buf, 20 | muduo::Timestamp time); 21 | 22 | muduo::net::TcpServer server_; 23 | }; 24 | 25 | #endif // MUDUO_EXAMPLES_SIMPLE_DISCARD_DISCARD_H 26 | -------------------------------------------------------------------------------- /examples/simple/discard/main.cc: -------------------------------------------------------------------------------- 1 | #include "examples/simple/discard/discard.h" 2 | 3 | #include "muduo/base/Logging.h" 4 | #include "muduo/net/EventLoop.h" 5 | 6 | #include 7 | 8 | using namespace muduo; 9 | using namespace muduo::net; 10 | 11 | int main() 12 | { 13 | LOG_INFO << "pid = " << getpid(); 14 | EventLoop loop; 15 | InetAddress listenAddr(2009); 16 | DiscardServer server(&loop, listenAddr); 17 | server.start(); 18 | loop.loop(); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /examples/simple/echo/echo.cc: -------------------------------------------------------------------------------- 1 | #include "examples/simple/echo/echo.h" 2 | 3 | #include "muduo/base/Logging.h" 4 | 5 | using std::placeholders::_1; 6 | using std::placeholders::_2; 7 | using std::placeholders::_3; 8 | 9 | // using namespace muduo; 10 | // using namespace muduo::net; 11 | 12 | EchoServer::EchoServer(muduo::net::EventLoop* loop, 13 | const muduo::net::InetAddress& listenAddr) 14 | : server_(loop, listenAddr, "EchoServer") 15 | { 16 | server_.setConnectionCallback( 17 | std::bind(&EchoServer::onConnection, this, _1)); 18 | server_.setMessageCallback( 19 | std::bind(&EchoServer::onMessage, this, _1, _2, _3)); 20 | } 21 | 22 | void EchoServer::start() 23 | { 24 | server_.start(); 25 | } 26 | 27 | void EchoServer::onConnection(const muduo::net::TcpConnectionPtr& conn) 28 | { 29 | LOG_INFO << "EchoServer - " << conn->peerAddress().toIpPort() << " -> " 30 | << conn->localAddress().toIpPort() << " is " 31 | << (conn->connected() ? "UP" : "DOWN"); 32 | } 33 | 34 | void EchoServer::onMessage(const muduo::net::TcpConnectionPtr& conn, 35 | muduo::net::Buffer* buf, 36 | muduo::Timestamp time) 37 | { 38 | muduo::string msg(buf->retrieveAllAsString()); 39 | LOG_INFO << conn->name() << " echo " << msg.size() << " bytes, " 40 | << "data received at " << time.toString(); 41 | conn->send(msg); 42 | } 43 | 44 | -------------------------------------------------------------------------------- /examples/simple/echo/echo.h: -------------------------------------------------------------------------------- 1 | #ifndef MUDUO_EXAMPLES_SIMPLE_ECHO_ECHO_H 2 | #define MUDUO_EXAMPLES_SIMPLE_ECHO_ECHO_H 3 | 4 | #include "muduo/net/TcpServer.h" 5 | 6 | // RFC 862 7 | class EchoServer 8 | { 9 | public: 10 | EchoServer(muduo::net::EventLoop* loop, 11 | const muduo::net::InetAddress& listenAddr); 12 | 13 | void start(); // calls server_.start(); 14 | 15 | private: 16 | void onConnection(const muduo::net::TcpConnectionPtr& conn); 17 | 18 | void onMessage(const muduo::net::TcpConnectionPtr& conn, 19 | muduo::net::Buffer* buf, 20 | muduo::Timestamp time); 21 | 22 | muduo::net::TcpServer server_; 23 | }; 24 | 25 | #endif // MUDUO_EXAMPLES_SIMPLE_ECHO_ECHO_H 26 | -------------------------------------------------------------------------------- /examples/simple/echo/main.cc: -------------------------------------------------------------------------------- 1 | #include "examples/simple/echo/echo.h" 2 | 3 | #include "muduo/base/Logging.h" 4 | #include "muduo/net/EventLoop.h" 5 | 6 | #include 7 | 8 | // using namespace muduo; 9 | // using namespace muduo::net; 10 | 11 | int main() 12 | { 13 | LOG_INFO << "pid = " << getpid(); 14 | muduo::net::EventLoop loop; 15 | muduo::net::InetAddress listenAddr(2007); 16 | EchoServer server(&loop, listenAddr); 17 | server.start(); 18 | loop.loop(); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /examples/simple/time/main.cc: -------------------------------------------------------------------------------- 1 | #include "examples/simple/time/time.h" 2 | 3 | #include "muduo/base/Logging.h" 4 | #include "muduo/net/EventLoop.h" 5 | 6 | #include 7 | 8 | using namespace muduo; 9 | using namespace muduo::net; 10 | 11 | int main() 12 | { 13 | LOG_INFO << "pid = " << getpid(); 14 | EventLoop loop; 15 | InetAddress listenAddr(2037); 16 | TimeServer server(&loop, listenAddr); 17 | server.start(); 18 | loop.loop(); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /examples/simple/time/time.cc: -------------------------------------------------------------------------------- 1 | #include "examples/simple/time/time.h" 2 | 3 | #include "muduo/base/Logging.h" 4 | #include "muduo/net/Endian.h" 5 | 6 | using namespace muduo; 7 | using namespace muduo::net; 8 | 9 | TimeServer::TimeServer(muduo::net::EventLoop* loop, 10 | const muduo::net::InetAddress& listenAddr) 11 | : server_(loop, listenAddr, "TimeServer") 12 | { 13 | server_.setConnectionCallback( 14 | std::bind(&TimeServer::onConnection, this, _1)); 15 | server_.setMessageCallback( 16 | std::bind(&TimeServer::onMessage, this, _1, _2, _3)); 17 | } 18 | 19 | void TimeServer::start() 20 | { 21 | server_.start(); 22 | } 23 | 24 | void TimeServer::onConnection(const muduo::net::TcpConnectionPtr& conn) 25 | { 26 | LOG_INFO << "TimeServer - " << conn->peerAddress().toIpPort() << " -> " 27 | << conn->localAddress().toIpPort() << " is " 28 | << (conn->connected() ? "UP" : "DOWN"); 29 | if (conn->connected()) 30 | { 31 | time_t now = ::time(NULL); 32 | int32_t be32 = sockets::hostToNetwork32(static_cast(now)); 33 | conn->send(&be32, sizeof be32); 34 | conn->shutdown(); 35 | } 36 | } 37 | 38 | void TimeServer::onMessage(const muduo::net::TcpConnectionPtr& conn, 39 | muduo::net::Buffer* buf, 40 | muduo::Timestamp time) 41 | { 42 | string msg(buf->retrieveAllAsString()); 43 | LOG_INFO << conn->name() << " discards " << msg.size() 44 | << " bytes received at " << time.toString(); 45 | } 46 | 47 | -------------------------------------------------------------------------------- /examples/simple/time/time.h: -------------------------------------------------------------------------------- 1 | #ifndef MUDUO_EXAMPLES_SIMPLE_TIME_TIME_H 2 | #define MUDUO_EXAMPLES_SIMPLE_TIME_TIME_H 3 | 4 | #include "muduo/net/TcpServer.h" 5 | 6 | // RFC 868 7 | class TimeServer 8 | { 9 | public: 10 | TimeServer(muduo::net::EventLoop* loop, 11 | const muduo::net::InetAddress& listenAddr); 12 | 13 | void start(); 14 | 15 | private: 16 | void onConnection(const muduo::net::TcpConnectionPtr& conn); 17 | 18 | void onMessage(const muduo::net::TcpConnectionPtr& conn, 19 | muduo::net::Buffer* buf, 20 | muduo::Timestamp time); 21 | 22 | muduo::net::TcpServer server_; 23 | }; 24 | 25 | #endif // MUDUO_EXAMPLES_SIMPLE_TIME_TIME_H 26 | -------------------------------------------------------------------------------- /examples/socks4a/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(balancer balancer.cc) 2 | target_link_libraries(balancer muduo_net) 3 | 4 | add_executable(tcprelay tcprelay.cc) 5 | target_link_libraries(tcprelay muduo_net) 6 | 7 | add_executable(socks4a socks4a.cc) 8 | target_link_libraries(socks4a muduo_net) 9 | 10 | -------------------------------------------------------------------------------- /examples/sudoku/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(sudoku_solver_basic server_basic.cc sudoku.cc) 2 | target_link_libraries(sudoku_solver_basic muduo_net) 3 | 4 | add_executable(sudoku_solver_multiloop server_multiloop.cc sudoku.cc) 5 | target_link_libraries(sudoku_solver_multiloop muduo_net) 6 | 7 | add_executable(sudoku_solver_threadpool server_threadpool.cc sudoku.cc) 8 | target_link_libraries(sudoku_solver_threadpool muduo_net) 9 | 10 | add_executable(sudoku_solver_hybrid server_hybrid.cc sudoku.cc) 11 | target_link_libraries(sudoku_solver_hybrid muduo_inspect) 12 | 13 | add_executable(sudoku_solver_prod server_prod.cc sudoku.cc) 14 | target_link_libraries(sudoku_solver_prod muduo_inspect) 15 | 16 | 17 | add_executable(sudoku_client_batch batch.cc sudoku.cc) 18 | target_link_libraries(sudoku_client_batch muduo_net) 19 | 20 | add_executable(sudoku_client_pipeline pipeline.cc sudoku.cc) 21 | target_link_libraries(sudoku_client_pipeline muduo_net) 22 | 23 | add_executable(sudoku_loadtest loadtest.cc sudoku.cc) 24 | target_link_libraries(sudoku_loadtest muduo_net) 25 | 26 | 27 | if(BOOSTTEST_LIBRARY) 28 | add_executable(sudoku_stat_unittest stat_unittest.cc) 29 | target_link_libraries(sudoku_stat_unittest muduo_base boost_unit_test_framework) 30 | endif() 31 | 32 | -------------------------------------------------------------------------------- /examples/sudoku/sudoku.h: -------------------------------------------------------------------------------- 1 | #ifndef MUDUO_EXAMPLES_SUDOKU_SUDOKU_H 2 | #define MUDUO_EXAMPLES_SUDOKU_SUDOKU_H 3 | 4 | 5 | #include "muduo/base/Types.h" 6 | #include "muduo/base/StringPiece.h" 7 | 8 | muduo::string solveSudoku(const muduo::StringPiece& puzzle); 9 | const int kCells = 81; 10 | extern const char kNoSolution[]; 11 | 12 | #endif // MUDUO_EXAMPLES_SUDOKU_SUDOKU_H 13 | -------------------------------------------------------------------------------- /examples/twisted/finger/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(twisted_finger01 finger01.cc) 2 | target_link_libraries(twisted_finger01 muduo_net) 3 | 4 | add_executable(twisted_finger02 finger02.cc) 5 | target_link_libraries(twisted_finger02 muduo_net) 6 | 7 | add_executable(twisted_finger03 finger03.cc) 8 | target_link_libraries(twisted_finger03 muduo_net) 9 | 10 | add_executable(twisted_finger04 finger04.cc) 11 | target_link_libraries(twisted_finger04 muduo_net) 12 | 13 | add_executable(twisted_finger05 finger05.cc) 14 | target_link_libraries(twisted_finger05 muduo_net) 15 | 16 | add_executable(twisted_finger06 finger06.cc) 17 | target_link_libraries(twisted_finger06 muduo_net) 18 | 19 | add_executable(twisted_finger07 finger07.cc) 20 | target_link_libraries(twisted_finger07 muduo_net) 21 | 22 | -------------------------------------------------------------------------------- /examples/twisted/finger/README: -------------------------------------------------------------------------------- 1 | The Finger protocol, RFC 1288. 2 | 3 | "Finger is based on the Transmission Control Protocol, using TCP port 4 | 79 decimal (117 octal). The local host opens a TCP connection to a 5 | remote host on the Finger port. An RUIP becomes available on the 6 | remote end of the connection to process the request. The local host 7 | sends the RUIP a one line query based upon the Finger query 8 | specification, and waits for the RUIP to respond. The RUIP receives 9 | and processes the query, returns an answer, then initiates the close 10 | of the connection. The local host receives the answer and the close 11 | signal, then proceeds closing its end of the connection." 12 | 13 | -------------------------------------------------------------------------------- /examples/twisted/finger/finger01.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/net/EventLoop.h" 2 | 3 | using namespace muduo; 4 | using namespace muduo::net; 5 | 6 | int main() 7 | { 8 | EventLoop loop; 9 | loop.loop(); 10 | } 11 | -------------------------------------------------------------------------------- /examples/twisted/finger/finger02.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/net/EventLoop.h" 2 | #include "muduo/net/TcpServer.h" 3 | 4 | using namespace muduo; 5 | using namespace muduo::net; 6 | 7 | int main() 8 | { 9 | EventLoop loop; 10 | TcpServer server(&loop, InetAddress(1079), "Finger"); 11 | server.start(); 12 | loop.loop(); 13 | } 14 | -------------------------------------------------------------------------------- /examples/twisted/finger/finger03.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/net/EventLoop.h" 2 | #include "muduo/net/TcpServer.h" 3 | 4 | using namespace muduo; 5 | using namespace muduo::net; 6 | 7 | void onConnection(const TcpConnectionPtr& conn) 8 | { 9 | if (conn->connected()) 10 | { 11 | conn->shutdown(); 12 | } 13 | } 14 | 15 | int main() 16 | { 17 | EventLoop loop; 18 | TcpServer server(&loop, InetAddress(1079), "Finger"); 19 | server.setConnectionCallback(onConnection); 20 | server.start(); 21 | loop.loop(); 22 | } 23 | -------------------------------------------------------------------------------- /examples/twisted/finger/finger04.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/net/EventLoop.h" 2 | #include "muduo/net/TcpServer.h" 3 | 4 | using namespace muduo; 5 | using namespace muduo::net; 6 | 7 | void onMessage(const TcpConnectionPtr& conn, 8 | Buffer* buf, 9 | Timestamp receiveTime) 10 | { 11 | if (buf->findCRLF()) 12 | { 13 | conn->shutdown(); 14 | } 15 | } 16 | 17 | int main() 18 | { 19 | EventLoop loop; 20 | TcpServer server(&loop, InetAddress(1079), "Finger"); 21 | server.setMessageCallback(onMessage); 22 | server.start(); 23 | loop.loop(); 24 | } 25 | -------------------------------------------------------------------------------- /examples/twisted/finger/finger05.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/net/EventLoop.h" 2 | #include "muduo/net/TcpServer.h" 3 | 4 | using namespace muduo; 5 | using namespace muduo::net; 6 | 7 | void onMessage(const TcpConnectionPtr& conn, 8 | Buffer* buf, 9 | Timestamp receiveTime) 10 | { 11 | if (buf->findCRLF()) 12 | { 13 | conn->send("No such user\r\n"); 14 | conn->shutdown(); 15 | } 16 | } 17 | 18 | int main() 19 | { 20 | EventLoop loop; 21 | TcpServer server(&loop, InetAddress(1079), "Finger"); 22 | server.setMessageCallback(onMessage); 23 | server.start(); 24 | loop.loop(); 25 | } 26 | -------------------------------------------------------------------------------- /examples/twisted/finger/finger06.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/net/EventLoop.h" 2 | #include "muduo/net/TcpServer.h" 3 | 4 | #include 5 | 6 | using namespace muduo; 7 | using namespace muduo::net; 8 | 9 | typedef std::map UserMap; 10 | UserMap users; 11 | 12 | string getUser(const string& user) 13 | { 14 | string result = "No such user"; 15 | UserMap::iterator it = users.find(user); 16 | if (it != users.end()) 17 | { 18 | result = it->second; 19 | } 20 | return result; 21 | } 22 | 23 | void onMessage(const TcpConnectionPtr& conn, 24 | Buffer* buf, 25 | Timestamp receiveTime) 26 | { 27 | const char* crlf = buf->findCRLF(); 28 | if (crlf) 29 | { 30 | string user(buf->peek(), crlf); 31 | conn->send(getUser(user) + "\r\n"); 32 | buf->retrieveUntil(crlf + 2); 33 | conn->shutdown(); 34 | } 35 | } 36 | 37 | int main() 38 | { 39 | EventLoop loop; 40 | TcpServer server(&loop, InetAddress(1079), "Finger"); 41 | server.setMessageCallback(onMessage); 42 | server.start(); 43 | loop.loop(); 44 | } 45 | -------------------------------------------------------------------------------- /examples/twisted/finger/finger07.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/net/EventLoop.h" 2 | #include "muduo/net/TcpServer.h" 3 | 4 | #include 5 | 6 | using namespace muduo; 7 | using namespace muduo::net; 8 | 9 | typedef std::map UserMap; 10 | UserMap users; 11 | 12 | string getUser(const string& user) 13 | { 14 | string result = "No such user"; 15 | UserMap::iterator it = users.find(user); 16 | if (it != users.end()) 17 | { 18 | result = it->second; 19 | } 20 | return result; 21 | } 22 | 23 | void onMessage(const TcpConnectionPtr& conn, 24 | Buffer* buf, 25 | Timestamp receiveTime) 26 | { 27 | const char* crlf = buf->findCRLF(); 28 | if (crlf) 29 | { 30 | string user(buf->peek(), crlf); 31 | conn->send(getUser(user) + "\r\n"); 32 | buf->retrieveUntil(crlf + 2); 33 | conn->shutdown(); 34 | } 35 | } 36 | 37 | int main() 38 | { 39 | users["schen"] = "Happy and well"; 40 | EventLoop loop; 41 | TcpServer server(&loop, InetAddress(1079), "Finger"); 42 | server.setMessageCallback(onMessage); 43 | server.start(); 44 | loop.loop(); 45 | } 46 | -------------------------------------------------------------------------------- /examples/wordcount/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(wordcount_hasher hasher.cc) 2 | target_link_libraries(wordcount_hasher muduo_net) 3 | 4 | add_executable(wordcount_receiver receiver.cc) 5 | target_link_libraries(wordcount_receiver muduo_net) 6 | -------------------------------------------------------------------------------- /examples/wordcount/README: -------------------------------------------------------------------------------- 1 | A distributed word counting example. 2 | 3 | A hasher shards to multiple receivers by hash(word). 4 | 5 | A receiver collects from multiple hashers 6 | and writes the result to disk. 7 | 8 | Example run with 3 hashers and 4 receivers: 9 | 1. run 4 receivers on 4 machines, namely ip1:port1, ip2:port2, ip3:port3, ip4:port4. 10 | a. on ip1, bin/wordcount_receiver port1 3 11 | b. on ip2, bin/wordcount_receiver port2 3 12 | c. on ip3, bin/wordcount_receiver port3 3 13 | d. on ip4, bin/wordcount_receiver port4 3 14 | 2. run 3 hashers on 3 machines. 15 | a. on ip1, bin/wordcount_hasher 'ip1:port1,ip2:port2,ip3:port3,ip4:port4' input1 16 | b. on ip2, bin/wordcount_hasher 'ip1:port1,ip2:port2,ip3:port3,ip4:port4' input2 17 | c. on ip3, bin/wordcount_hasher 'ip1:port1,ip2:port2,ip3:port3,ip4:port4' input3 input4 18 | 3. wait all hashers and receivers exit. 19 | 20 | -------------------------------------------------------------------------------- /examples/wordcount/gen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import random 4 | 5 | words = 1000000 6 | word_len = 5 7 | alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-' 8 | 9 | output = open('random_words', 'w') 10 | for x in xrange(words): 11 | arr = [random.choice(alphabet) for i in range(word_len)] 12 | word = ''.join(arr) 13 | output.write(word) 14 | output.write('\n') 15 | -------------------------------------------------------------------------------- /examples/wordcount/hash.h: -------------------------------------------------------------------------------- 1 | #ifndef MUDUO_EXAMPLES_WORDCOUNT_HASH_H 2 | #define MUDUO_EXAMPLES_WORDCOUNT_HASH_H 3 | 4 | #include 5 | 6 | typedef std::unordered_map WordCountMap; 7 | 8 | #endif // MUDUO_EXAMPLES_WORDCOUNT_HASH_H 9 | -------------------------------------------------------------------------------- /examples/wordcount/slowsink.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import os, socket, sys, time 4 | 5 | host = '' 6 | port = 2007 7 | 8 | if len(sys.argv) > 1: 9 | mps = float(sys.argv[1]) 10 | else: 11 | mps = 1.0 12 | bps = mps * 1000000 13 | BUFSIZE = int(bps/10) # sleep 100ms at full speed 14 | 15 | print "Mbytes/s =", mps 16 | 17 | if len(sys.argv) > 3: 18 | host = sys.argv[2] 19 | port = int(sys.argv[3]) 20 | print "connecting to %s:%d" % (host, port) 21 | else: 22 | print "listening on port", port 23 | 24 | if host: 25 | client_socket = socket.create_connection((host, port)) 26 | print "connected to", client_socket.getpeername() 27 | else: 28 | listen_address = ("", port) 29 | server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 30 | server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 31 | server_socket.bind(listen_address) 32 | server_socket.listen(5) 33 | 34 | (client_socket, client_address) = server_socket.accept() 35 | print "got connection from", client_address 36 | 37 | start = time.time() 38 | total_size = 0 39 | dot = bps 40 | 41 | while True: 42 | data = client_socket.recv(BUFSIZE) 43 | if data: 44 | size = len(data) 45 | total_size += size 46 | if total_size >= dot: 47 | dot += bps 48 | sys.stdout.write('.') 49 | sys.stdout.flush() 50 | time.sleep(size / bps) 51 | else: 52 | print "\ndisconnect" 53 | client_socket.close() 54 | break 55 | 56 | end = time.time() 57 | elapsed = end - start 58 | print "elapsed seconds %.3f" % elapsed 59 | print "total bytes", total_size 60 | print "throughput bytes/s %.2f" % (total_size / elapsed) 61 | print "throughput Mbytes/s %.3f" % (total_size / elapsed / 1000000) 62 | 63 | -------------------------------------------------------------------------------- /examples/zeromq/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(zeromq_local_lat local_lat.cc) 2 | target_link_libraries(zeromq_local_lat muduo_net) 3 | 4 | add_executable(zeromq_remote_lat remote_lat.cc) 5 | target_link_libraries(zeromq_remote_lat muduo_net) 6 | 7 | -------------------------------------------------------------------------------- /examples/zeromq/README: -------------------------------------------------------------------------------- 1 | 2 | local_lat.cc : echo server with LengthHeaderCodec 3 | remote_lat.cc : echo client with LengthHeaderCodec 4 | -------------------------------------------------------------------------------- /examples/zeromq/local_lat.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/Logging.h" 2 | #include "muduo/net/EventLoop.h" 3 | #include "muduo/net/TcpServer.h" 4 | #include "examples/asio/chat/codec.h" 5 | 6 | #include 7 | #include 8 | 9 | using std::placeholders::_1; 10 | using std::placeholders::_2; 11 | using std::placeholders::_3; 12 | using muduo::get_pointer; 13 | 14 | bool g_tcpNoDelay = false; 15 | 16 | void onConnection(const muduo::net::TcpConnectionPtr& conn) 17 | { 18 | if (conn->connected()) 19 | { 20 | conn->setTcpNoDelay(g_tcpNoDelay); 21 | } 22 | } 23 | 24 | void onStringMessage(LengthHeaderCodec* codec, 25 | const muduo::net::TcpConnectionPtr& conn, 26 | const muduo::string& message, 27 | muduo::Timestamp) 28 | { 29 | codec->send(get_pointer(conn), message); 30 | } 31 | 32 | int main(int argc, char* argv[]) 33 | { 34 | if (argc > 1) 35 | { 36 | uint16_t port = static_cast(atoi(argv[1])); 37 | g_tcpNoDelay = argc > 2 ? atoi(argv[2]) : false; 38 | int threadCount = argc > 3 ? atoi(argv[3]) : 0; 39 | 40 | LOG_INFO << "pid = " << getpid() << ", listen port = " << port; 41 | // muduo::Logger::setLogLevel(muduo::Logger::WARN); 42 | muduo::net::EventLoop loop; 43 | muduo::net::InetAddress listenAddr(port); 44 | muduo::net::TcpServer server(&loop, listenAddr, "PingPong"); 45 | LengthHeaderCodec codec(std::bind(onStringMessage, &codec, _1, _2, _3)); 46 | 47 | server.setConnectionCallback(onConnection); 48 | server.setMessageCallback( 49 | std::bind(&LengthHeaderCodec::onMessage, &codec, _1, _2, _3)); 50 | 51 | if (threadCount > 1) 52 | { 53 | server.setThreadNum(threadCount); 54 | } 55 | 56 | server.start(); 57 | 58 | loop.loop(); 59 | } 60 | else 61 | { 62 | fprintf(stderr, "Usage: %s listen_port [tcp_no_delay [threads]]\n", argv[0]); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /muduo/base/AsyncLogging.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef MUDUO_BASE_ASYNCLOGGING_H 7 | #define MUDUO_BASE_ASYNCLOGGING_H 8 | 9 | #include "muduo/base/BlockingQueue.h" 10 | #include "muduo/base/BoundedBlockingQueue.h" 11 | #include "muduo/base/CountDownLatch.h" 12 | #include "muduo/base/Mutex.h" 13 | #include "muduo/base/Thread.h" 14 | #include "muduo/base/LogStream.h" 15 | 16 | #include 17 | #include 18 | 19 | namespace muduo 20 | { 21 | 22 | class AsyncLogging : noncopyable 23 | { 24 | public: 25 | 26 | AsyncLogging(const string& basename, 27 | off_t rollSize, 28 | int flushInterval = 3); 29 | 30 | ~AsyncLogging() 31 | { 32 | if (running_) 33 | { 34 | stop(); 35 | } 36 | } 37 | 38 | void append(const char* logline, int len); 39 | 40 | void start() 41 | { 42 | running_ = true; 43 | thread_.start(); 44 | latch_.wait(); 45 | } 46 | 47 | void stop() NO_THREAD_SAFETY_ANALYSIS 48 | { 49 | running_ = false; 50 | cond_.notify(); 51 | thread_.join(); 52 | } 53 | 54 | private: 55 | 56 | void threadFunc(); 57 | 58 | typedef muduo::detail::FixedBuffer Buffer; 59 | typedef std::vector> BufferVector; 60 | typedef BufferVector::value_type BufferPtr; 61 | 62 | const int flushInterval_; 63 | std::atomic running_; 64 | const string basename_; 65 | const off_t rollSize_; 66 | muduo::Thread thread_; 67 | muduo::CountDownLatch latch_; 68 | muduo::MutexLock mutex_; 69 | muduo::Condition cond_ GUARDED_BY(mutex_); 70 | BufferPtr currentBuffer_ GUARDED_BY(mutex_); 71 | BufferPtr nextBuffer_ GUARDED_BY(mutex_); 72 | BufferVector buffers_ GUARDED_BY(mutex_); 73 | }; 74 | 75 | } // namespace muduo 76 | 77 | #endif // MUDUO_BASE_ASYNCLOGGING_H 78 | -------------------------------------------------------------------------------- /muduo/base/BUILD.bazel: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "base", 3 | srcs = [ 4 | "AsyncLogging.cc", 5 | "Condition.cc", 6 | "CountDownLatch.cc", 7 | "CurrentThread.cc", 8 | "Date.cc", 9 | "Exception.cc", 10 | "FileUtil.cc", 11 | "LogFile.cc", 12 | "LogStream.cc", 13 | "Logging.cc", 14 | "ProcessInfo.cc", 15 | "Thread.cc", 16 | "ThreadPool.cc", 17 | "TimeZone.cc", 18 | "Timestamp.cc", 19 | ], 20 | hdrs = glob(["*.h"]), 21 | linkopts = ["-pthread"], 22 | visibility = ["//visibility:public"], 23 | ) 24 | -------------------------------------------------------------------------------- /muduo/base/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(base_SRCS 2 | AsyncLogging.cc 3 | Condition.cc 4 | CountDownLatch.cc 5 | CurrentThread.cc 6 | Date.cc 7 | Exception.cc 8 | FileUtil.cc 9 | LogFile.cc 10 | Logging.cc 11 | LogStream.cc 12 | ProcessInfo.cc 13 | Timestamp.cc 14 | Thread.cc 15 | ThreadPool.cc 16 | TimeZone.cc 17 | ) 18 | 19 | add_library(muduo_base ${base_SRCS}) 20 | target_link_libraries(muduo_base pthread rt) 21 | 22 | #add_library(muduo_base_cpp11 ${base_SRCS}) 23 | #target_link_libraries(muduo_base_cpp11 pthread rt) 24 | #set_target_properties(muduo_base_cpp11 PROPERTIES COMPILE_FLAGS "-std=c++0x") 25 | 26 | install(TARGETS muduo_base DESTINATION lib) 27 | #install(TARGETS muduo_base_cpp11 DESTINATION lib) 28 | 29 | file(GLOB HEADERS "*.h") 30 | install(FILES ${HEADERS} DESTINATION include/muduo/base) 31 | 32 | if(MUDUO_BUILD_EXAMPLES) 33 | add_subdirectory(tests) 34 | endif() 35 | -------------------------------------------------------------------------------- /muduo/base/Condition.cc: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #include "muduo/base/Condition.h" 7 | 8 | #include 9 | 10 | // returns true if time out, false otherwise. 11 | bool muduo::Condition::waitForSeconds(double seconds) 12 | { 13 | struct timespec abstime; 14 | // FIXME: use CLOCK_MONOTONIC or CLOCK_MONOTONIC_RAW to prevent time rewind. 15 | clock_gettime(CLOCK_REALTIME, &abstime); 16 | 17 | const int64_t kNanoSecondsPerSecond = 1000000000; 18 | int64_t nanoseconds = static_cast(seconds * kNanoSecondsPerSecond); 19 | 20 | abstime.tv_sec += static_cast((abstime.tv_nsec + nanoseconds) / kNanoSecondsPerSecond); 21 | abstime.tv_nsec = static_cast((abstime.tv_nsec + nanoseconds) % kNanoSecondsPerSecond); 22 | 23 | MutexLock::UnassignGuard ug(mutex_); 24 | return ETIMEDOUT == pthread_cond_timedwait(&pcond_, mutex_.getPthreadMutex(), &abstime); 25 | } 26 | 27 | -------------------------------------------------------------------------------- /muduo/base/Condition.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef MUDUO_BASE_CONDITION_H 7 | #define MUDUO_BASE_CONDITION_H 8 | 9 | #include "muduo/base/Mutex.h" 10 | 11 | #include 12 | 13 | namespace muduo 14 | { 15 | 16 | class Condition : noncopyable 17 | { 18 | public: 19 | explicit Condition(MutexLock& mutex) 20 | : mutex_(mutex) 21 | { 22 | MCHECK(pthread_cond_init(&pcond_, NULL)); 23 | } 24 | 25 | ~Condition() 26 | { 27 | MCHECK(pthread_cond_destroy(&pcond_)); 28 | } 29 | 30 | void wait() 31 | { 32 | MutexLock::UnassignGuard ug(mutex_); 33 | MCHECK(pthread_cond_wait(&pcond_, mutex_.getPthreadMutex())); 34 | } 35 | 36 | // returns true if time out, false otherwise. 37 | bool waitForSeconds(double seconds); 38 | 39 | void notify() 40 | { 41 | MCHECK(pthread_cond_signal(&pcond_)); 42 | } 43 | 44 | void notifyAll() 45 | { 46 | MCHECK(pthread_cond_broadcast(&pcond_)); 47 | } 48 | 49 | private: 50 | MutexLock& mutex_; 51 | pthread_cond_t pcond_; 52 | }; 53 | 54 | } // namespace muduo 55 | 56 | #endif // MUDUO_BASE_CONDITION_H 57 | -------------------------------------------------------------------------------- /muduo/base/CountDownLatch.cc: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #include "muduo/base/CountDownLatch.h" 7 | 8 | using namespace muduo; 9 | 10 | CountDownLatch::CountDownLatch(int count) 11 | : mutex_(), 12 | condition_(mutex_), 13 | count_(count) 14 | { 15 | } 16 | 17 | void CountDownLatch::wait() 18 | { 19 | MutexLockGuard lock(mutex_); 20 | while (count_ > 0) 21 | { 22 | condition_.wait(); 23 | } 24 | } 25 | 26 | void CountDownLatch::countDown() 27 | { 28 | MutexLockGuard lock(mutex_); 29 | --count_; 30 | if (count_ == 0) 31 | { 32 | condition_.notifyAll(); 33 | } 34 | } 35 | 36 | int CountDownLatch::getCount() const 37 | { 38 | MutexLockGuard lock(mutex_); 39 | return count_; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /muduo/base/CountDownLatch.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef MUDUO_BASE_COUNTDOWNLATCH_H 7 | #define MUDUO_BASE_COUNTDOWNLATCH_H 8 | 9 | #include "muduo/base/Condition.h" 10 | #include "muduo/base/Mutex.h" 11 | 12 | namespace muduo 13 | { 14 | 15 | class CountDownLatch : noncopyable 16 | { 17 | public: 18 | 19 | explicit CountDownLatch(int count); 20 | 21 | void wait(); 22 | 23 | void countDown(); 24 | 25 | int getCount() const; 26 | 27 | private: 28 | mutable MutexLock mutex_; 29 | Condition condition_ GUARDED_BY(mutex_); 30 | int count_ GUARDED_BY(mutex_); 31 | }; 32 | 33 | } // namespace muduo 34 | #endif // MUDUO_BASE_COUNTDOWNLATCH_H 35 | -------------------------------------------------------------------------------- /muduo/base/CurrentThread.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef MUDUO_BASE_CURRENTTHREAD_H 7 | #define MUDUO_BASE_CURRENTTHREAD_H 8 | 9 | #include "muduo/base/Types.h" 10 | 11 | namespace muduo 12 | { 13 | namespace CurrentThread 14 | { 15 | // internal 16 | extern __thread int t_cachedTid; 17 | extern __thread char t_tidString[32]; 18 | extern __thread int t_tidStringLength; 19 | extern __thread const char* t_threadName; 20 | void cacheTid(); 21 | 22 | inline int tid() 23 | { 24 | if (__builtin_expect(t_cachedTid == 0, 0)) 25 | { 26 | cacheTid(); 27 | } 28 | return t_cachedTid; 29 | } 30 | 31 | inline const char* tidString() // for logging 32 | { 33 | return t_tidString; 34 | } 35 | 36 | inline int tidStringLength() // for logging 37 | { 38 | return t_tidStringLength; 39 | } 40 | 41 | inline const char* name() 42 | { 43 | return t_threadName; 44 | } 45 | 46 | bool isMainThread(); 47 | 48 | void sleepUsec(int64_t usec); // for testing 49 | 50 | string stackTrace(bool demangle); 51 | } // namespace CurrentThread 52 | } // namespace muduo 53 | 54 | #endif // MUDUO_BASE_CURRENTTHREAD_H 55 | -------------------------------------------------------------------------------- /muduo/base/Exception.cc: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #include "muduo/base/Exception.h" 7 | #include "muduo/base/CurrentThread.h" 8 | 9 | namespace muduo 10 | { 11 | 12 | Exception::Exception(string msg) 13 | : message_(std::move(msg)), 14 | stack_(CurrentThread::stackTrace(/*demangle=*/false)) 15 | { 16 | } 17 | 18 | } // namespace muduo 19 | -------------------------------------------------------------------------------- /muduo/base/Exception.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef MUDUO_BASE_EXCEPTION_H 7 | #define MUDUO_BASE_EXCEPTION_H 8 | 9 | #include "muduo/base/Types.h" 10 | #include 11 | 12 | namespace muduo 13 | { 14 | 15 | class Exception : public std::exception 16 | { 17 | public: 18 | Exception(string what); 19 | ~Exception() noexcept override = default; 20 | 21 | // default copy-ctor and operator= are okay. 22 | 23 | const char* what() const noexcept override 24 | { 25 | return message_.c_str(); 26 | } 27 | 28 | const char* stackTrace() const noexcept 29 | { 30 | return stack_.c_str(); 31 | } 32 | 33 | private: 34 | string message_; 35 | string stack_; 36 | }; 37 | 38 | } // namespace muduo 39 | 40 | #endif // MUDUO_BASE_EXCEPTION_H 41 | -------------------------------------------------------------------------------- /muduo/base/LogFile.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef MUDUO_BASE_LOGFILE_H 7 | #define MUDUO_BASE_LOGFILE_H 8 | 9 | #include "muduo/base/Mutex.h" 10 | #include "muduo/base/Types.h" 11 | 12 | #include 13 | 14 | namespace muduo 15 | { 16 | 17 | namespace FileUtil 18 | { 19 | class AppendFile; 20 | } 21 | 22 | class LogFile : noncopyable 23 | { 24 | public: 25 | LogFile(const string& basename, 26 | off_t rollSize, 27 | bool threadSafe = true, 28 | int flushInterval = 3, 29 | int checkEveryN = 1024); 30 | ~LogFile(); 31 | 32 | void append(const char* logline, int len); 33 | void flush(); 34 | bool rollFile(); 35 | 36 | private: 37 | void append_unlocked(const char* logline, int len); 38 | 39 | static string getLogFileName(const string& basename, time_t* now); 40 | 41 | const string basename_; 42 | const off_t rollSize_; 43 | const int flushInterval_; 44 | const int checkEveryN_; 45 | 46 | int count_; 47 | 48 | std::unique_ptr mutex_; 49 | time_t startOfPeriod_; 50 | time_t lastRoll_; 51 | time_t lastFlush_; 52 | std::unique_ptr file_; 53 | 54 | const static int kRollPerSeconds_ = 60*60*24; 55 | }; 56 | 57 | } // namespace muduo 58 | #endif // MUDUO_BASE_LOGFILE_H 59 | -------------------------------------------------------------------------------- /muduo/base/ProcessInfo.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | // 6 | // This is a public header file, it must only include public header files. 7 | 8 | #ifndef MUDUO_BASE_PROCESSINFO_H 9 | #define MUDUO_BASE_PROCESSINFO_H 10 | 11 | #include "muduo/base/StringPiece.h" 12 | #include "muduo/base/Types.h" 13 | #include "muduo/base/Timestamp.h" 14 | #include 15 | #include 16 | 17 | namespace muduo 18 | { 19 | 20 | namespace ProcessInfo 21 | { 22 | pid_t pid(); 23 | string pidString(); 24 | uid_t uid(); 25 | string username(); 26 | uid_t euid(); 27 | Timestamp startTime(); 28 | int clockTicksPerSecond(); 29 | int pageSize(); 30 | bool isDebugBuild(); // constexpr 31 | 32 | string hostname(); 33 | string procname(); 34 | StringPiece procname(const string& stat); 35 | 36 | /// read /proc/self/status 37 | string procStatus(); 38 | 39 | /// read /proc/self/stat 40 | string procStat(); 41 | 42 | /// read /proc/self/task/tid/stat 43 | string threadStat(); 44 | 45 | /// readlink /proc/self/exe 46 | string exePath(); 47 | 48 | int openedFiles(); 49 | int maxOpenFiles(); 50 | 51 | struct CpuTime 52 | { 53 | double userSeconds; 54 | double systemSeconds; 55 | 56 | CpuTime() : userSeconds(0.0), systemSeconds(0.0) { } 57 | 58 | double total() const { return userSeconds + systemSeconds; } 59 | }; 60 | CpuTime cpuTime(); 61 | 62 | int numThreads(); 63 | std::vector threads(); 64 | } // namespace ProcessInfo 65 | 66 | } // namespace muduo 67 | 68 | #endif // MUDUO_BASE_PROCESSINFO_H 69 | -------------------------------------------------------------------------------- /muduo/base/Singleton.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef MUDUO_BASE_SINGLETON_H 7 | #define MUDUO_BASE_SINGLETON_H 8 | 9 | #include "muduo/base/noncopyable.h" 10 | 11 | #include 12 | #include 13 | #include // atexit 14 | 15 | namespace muduo 16 | { 17 | 18 | namespace detail 19 | { 20 | // This doesn't detect inherited member functions! 21 | // http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions 22 | template 23 | struct has_no_destroy 24 | { 25 | template static char test(decltype(&C::no_destroy)); 26 | template static int32_t test(...); 27 | const static bool value = sizeof(test(0)) == 1; 28 | }; 29 | } // namespace detail 30 | 31 | template 32 | class Singleton : noncopyable 33 | { 34 | public: 35 | Singleton() = delete; 36 | ~Singleton() = delete; 37 | 38 | static T& instance() 39 | { 40 | pthread_once(&ponce_, &Singleton::init); 41 | assert(value_ != NULL); 42 | return *value_; 43 | } 44 | 45 | private: 46 | static void init() 47 | { 48 | value_ = new T(); 49 | if (!detail::has_no_destroy::value) 50 | { 51 | ::atexit(destroy); 52 | } 53 | } 54 | 55 | static void destroy() 56 | { 57 | typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1]; 58 | T_must_be_complete_type dummy; (void) dummy; 59 | 60 | delete value_; 61 | value_ = NULL; 62 | } 63 | 64 | private: 65 | static pthread_once_t ponce_; 66 | static T* value_; 67 | }; 68 | 69 | template 70 | pthread_once_t Singleton::ponce_ = PTHREAD_ONCE_INIT; 71 | 72 | template 73 | T* Singleton::value_ = NULL; 74 | 75 | } // namespace muduo 76 | 77 | #endif // MUDUO_BASE_SINGLETON_H 78 | -------------------------------------------------------------------------------- /muduo/base/Thread.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef MUDUO_BASE_THREAD_H 7 | #define MUDUO_BASE_THREAD_H 8 | 9 | #include "muduo/base/Atomic.h" 10 | #include "muduo/base/CountDownLatch.h" 11 | #include "muduo/base/Types.h" 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | namespace muduo 18 | { 19 | 20 | class Thread : noncopyable 21 | { 22 | public: 23 | typedef std::function ThreadFunc; 24 | 25 | explicit Thread(ThreadFunc, const string& name = string()); 26 | // FIXME: make it movable in C++11 27 | ~Thread(); 28 | 29 | void start(); 30 | int join(); // return pthread_join() 31 | 32 | bool started() const { return started_; } 33 | // pthread_t pthreadId() const { return pthreadId_; } 34 | pid_t tid() const { return tid_; } 35 | const string& name() const { return name_; } 36 | 37 | static int numCreated() { return numCreated_.get(); } 38 | 39 | private: 40 | void setDefaultName(); 41 | 42 | bool started_; 43 | bool joined_; 44 | pthread_t pthreadId_; 45 | pid_t tid_; 46 | ThreadFunc func_; 47 | string name_; 48 | CountDownLatch latch_; 49 | 50 | static AtomicInt32 numCreated_; 51 | }; 52 | 53 | } // namespace muduo 54 | #endif // MUDUO_BASE_THREAD_H 55 | -------------------------------------------------------------------------------- /muduo/base/ThreadLocal.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef MUDUO_BASE_THREADLOCAL_H 7 | #define MUDUO_BASE_THREADLOCAL_H 8 | 9 | #include "muduo/base/Mutex.h" 10 | #include "muduo/base/noncopyable.h" 11 | 12 | #include 13 | 14 | namespace muduo 15 | { 16 | 17 | template 18 | class ThreadLocal : noncopyable 19 | { 20 | public: 21 | ThreadLocal() 22 | { 23 | MCHECK(pthread_key_create(&pkey_, &ThreadLocal::destructor)); 24 | } 25 | 26 | ~ThreadLocal() 27 | { 28 | MCHECK(pthread_key_delete(pkey_)); 29 | } 30 | 31 | T& value() 32 | { 33 | T* perThreadValue = static_cast(pthread_getspecific(pkey_)); 34 | if (!perThreadValue) 35 | { 36 | T* newObj = new T(); 37 | MCHECK(pthread_setspecific(pkey_, newObj)); 38 | perThreadValue = newObj; 39 | } 40 | return *perThreadValue; 41 | } 42 | 43 | private: 44 | 45 | static void destructor(void *x) 46 | { 47 | T* obj = static_cast(x); 48 | typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1]; 49 | T_must_be_complete_type dummy; (void) dummy; 50 | delete obj; 51 | } 52 | 53 | private: 54 | pthread_key_t pkey_; 55 | }; 56 | 57 | } // namespace muduo 58 | 59 | #endif // MUDUO_BASE_THREADLOCAL_H 60 | -------------------------------------------------------------------------------- /muduo/base/ThreadLocalSingleton.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef MUDUO_BASE_THREADLOCALSINGLETON_H 7 | #define MUDUO_BASE_THREADLOCALSINGLETON_H 8 | 9 | #include "muduo/base/noncopyable.h" 10 | 11 | #include 12 | #include 13 | 14 | namespace muduo 15 | { 16 | 17 | template 18 | class ThreadLocalSingleton : noncopyable 19 | { 20 | public: 21 | ThreadLocalSingleton() = delete; 22 | ~ThreadLocalSingleton() = delete; 23 | 24 | static T& instance() 25 | { 26 | if (!t_value_) 27 | { 28 | t_value_ = new T(); 29 | deleter_.set(t_value_); 30 | } 31 | return *t_value_; 32 | } 33 | 34 | static T* pointer() 35 | { 36 | return t_value_; 37 | } 38 | 39 | private: 40 | static void destructor(void* obj) 41 | { 42 | assert(obj == t_value_); 43 | typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1]; 44 | T_must_be_complete_type dummy; (void) dummy; 45 | delete t_value_; 46 | t_value_ = 0; 47 | } 48 | 49 | class Deleter 50 | { 51 | public: 52 | Deleter() 53 | { 54 | pthread_key_create(&pkey_, &ThreadLocalSingleton::destructor); 55 | } 56 | 57 | ~Deleter() 58 | { 59 | pthread_key_delete(pkey_); 60 | } 61 | 62 | void set(T* newObj) 63 | { 64 | assert(pthread_getspecific(pkey_) == NULL); 65 | pthread_setspecific(pkey_, newObj); 66 | } 67 | 68 | pthread_key_t pkey_; 69 | }; 70 | 71 | static __thread T* t_value_; 72 | static Deleter deleter_; 73 | }; 74 | 75 | template 76 | __thread T* ThreadLocalSingleton::t_value_ = 0; 77 | 78 | template 79 | typename ThreadLocalSingleton::Deleter ThreadLocalSingleton::deleter_; 80 | 81 | } // namespace muduo 82 | #endif // MUDUO_BASE_THREADLOCALSINGLETON_H 83 | -------------------------------------------------------------------------------- /muduo/base/ThreadPool.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef MUDUO_BASE_THREADPOOL_H 7 | #define MUDUO_BASE_THREADPOOL_H 8 | 9 | #include "muduo/base/Condition.h" 10 | #include "muduo/base/Mutex.h" 11 | #include "muduo/base/Thread.h" 12 | #include "muduo/base/Types.h" 13 | 14 | #include 15 | #include 16 | 17 | namespace muduo 18 | { 19 | 20 | class ThreadPool : noncopyable 21 | { 22 | public: 23 | typedef std::function Task; 24 | 25 | explicit ThreadPool(const string& nameArg = string("ThreadPool")); 26 | ~ThreadPool(); 27 | 28 | // Must be called before start(). 29 | void setMaxQueueSize(int maxSize) { maxQueueSize_ = maxSize; } 30 | void setThreadInitCallback(const Task& cb) 31 | { threadInitCallback_ = cb; } 32 | 33 | void start(int numThreads); 34 | void stop(); 35 | 36 | const string& name() const 37 | { return name_; } 38 | 39 | size_t queueSize() const; 40 | 41 | // Could block if maxQueueSize > 0 42 | // Call after stop() will return immediately. 43 | // There is no move-only version of std::function in C++ as of C++14. 44 | // So we don't need to overload a const& and an && versions 45 | // as we do in (Bounded)BlockingQueue. 46 | // https://stackoverflow.com/a/25408989 47 | void run(Task f); 48 | 49 | private: 50 | bool isFull() const REQUIRES(mutex_); 51 | void runInThread(); 52 | Task take(); 53 | 54 | mutable MutexLock mutex_; 55 | Condition notEmpty_ GUARDED_BY(mutex_); 56 | Condition notFull_ GUARDED_BY(mutex_); 57 | string name_; 58 | Task threadInitCallback_; 59 | std::vector> threads_; 60 | std::deque queue_ GUARDED_BY(mutex_); 61 | size_t maxQueueSize_; 62 | bool running_; 63 | }; 64 | 65 | } // namespace muduo 66 | 67 | #endif // MUDUO_BASE_THREADPOOL_H 68 | -------------------------------------------------------------------------------- /muduo/base/Timestamp.cc: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #include "muduo/base/Timestamp.h" 7 | 8 | #include 9 | #include 10 | 11 | #ifndef __STDC_FORMAT_MACROS 12 | #define __STDC_FORMAT_MACROS 13 | #endif 14 | 15 | #include 16 | 17 | using namespace muduo; 18 | 19 | static_assert(sizeof(Timestamp) == sizeof(int64_t), 20 | "Timestamp should be same size as int64_t"); 21 | 22 | string Timestamp::toString() const 23 | { 24 | char buf[32] = {0}; 25 | int64_t seconds = microSecondsSinceEpoch_ / kMicroSecondsPerSecond; 26 | int64_t microseconds = microSecondsSinceEpoch_ % kMicroSecondsPerSecond; 27 | snprintf(buf, sizeof(buf), "%" PRId64 ".%06" PRId64 "", seconds, microseconds); 28 | return buf; 29 | } 30 | 31 | string Timestamp::toFormattedString(bool showMicroseconds) const 32 | { 33 | char buf[64] = {0}; 34 | time_t seconds = static_cast(microSecondsSinceEpoch_ / kMicroSecondsPerSecond); 35 | struct tm tm_time; 36 | gmtime_r(&seconds, &tm_time); 37 | 38 | if (showMicroseconds) 39 | { 40 | int microseconds = static_cast(microSecondsSinceEpoch_ % kMicroSecondsPerSecond); 41 | snprintf(buf, sizeof(buf), "%4d%02d%02d %02d:%02d:%02d.%06d", 42 | tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday, 43 | tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, 44 | microseconds); 45 | } 46 | else 47 | { 48 | snprintf(buf, sizeof(buf), "%4d%02d%02d %02d:%02d:%02d", 49 | tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday, 50 | tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec); 51 | } 52 | return buf; 53 | } 54 | 55 | Timestamp Timestamp::now() 56 | { 57 | struct timeval tv; 58 | gettimeofday(&tv, NULL); 59 | int64_t seconds = tv.tv_sec; 60 | return Timestamp(seconds * kMicroSecondsPerSecond + tv.tv_usec); 61 | } 62 | 63 | -------------------------------------------------------------------------------- /muduo/base/WeakCallback.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef MUDUO_BASE_WEAKCALLBACK_H 7 | #define MUDUO_BASE_WEAKCALLBACK_H 8 | 9 | #include 10 | #include 11 | 12 | namespace muduo 13 | { 14 | 15 | // A barely usable WeakCallback 16 | 17 | template 18 | class WeakCallback 19 | { 20 | public: 21 | 22 | WeakCallback(const std::weak_ptr& object, 23 | const std::function& function) 24 | : object_(object), function_(function) 25 | { 26 | } 27 | 28 | // Default dtor, copy ctor and assignment are okay 29 | 30 | void operator()(ARGS&&... args) const 31 | { 32 | std::shared_ptr ptr(object_.lock()); 33 | if (ptr) 34 | { 35 | function_(ptr.get(), std::forward(args)...); 36 | } 37 | // else 38 | // { 39 | // LOG_TRACE << "expired"; 40 | // } 41 | } 42 | 43 | private: 44 | 45 | std::weak_ptr object_; 46 | std::function function_; 47 | }; 48 | 49 | template 50 | WeakCallback makeWeakCallback(const std::shared_ptr& object, 51 | void (CLASS::*function)(ARGS...)) 52 | { 53 | return WeakCallback(object, function); 54 | } 55 | 56 | template 57 | WeakCallback makeWeakCallback(const std::shared_ptr& object, 58 | void (CLASS::*function)(ARGS...) const) 59 | { 60 | return WeakCallback(object, function); 61 | } 62 | 63 | } // namespace muduo 64 | 65 | #endif // MUDUO_BASE_WEAKCALLBACK_H 66 | -------------------------------------------------------------------------------- /muduo/base/copyable.h: -------------------------------------------------------------------------------- 1 | #ifndef MUDUO_BASE_COPYABLE_H 2 | #define MUDUO_BASE_COPYABLE_H 3 | 4 | namespace muduo 5 | { 6 | 7 | /// A tag class emphasises the objects are copyable. 8 | /// The empty base class optimization applies. 9 | /// Any derived class of copyable should be a value type. 10 | class copyable 11 | { 12 | protected: 13 | copyable() = default; 14 | ~copyable() = default; 15 | }; 16 | 17 | } // namespace muduo 18 | 19 | #endif // MUDUO_BASE_COPYABLE_H 20 | -------------------------------------------------------------------------------- /muduo/base/noncopyable.h: -------------------------------------------------------------------------------- 1 | #ifndef MUDUO_BASE_NONCOPYABLE_H 2 | #define MUDUO_BASE_NONCOPYABLE_H 3 | 4 | namespace muduo 5 | { 6 | 7 | class noncopyable 8 | { 9 | public: 10 | noncopyable(const noncopyable&) = delete; 11 | void operator=(const noncopyable&) = delete; 12 | 13 | protected: 14 | noncopyable() = default; 15 | ~noncopyable() = default; 16 | }; 17 | 18 | } // namespace muduo 19 | 20 | #endif // MUDUO_BASE_NONCOPYABLE_H 21 | -------------------------------------------------------------------------------- /muduo/base/tests/AsyncLogging_test.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/AsyncLogging.h" 2 | #include "muduo/base/Logging.h" 3 | #include "muduo/base/Timestamp.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | off_t kRollSize = 500*1000*1000; 10 | 11 | muduo::AsyncLogging* g_asyncLog = NULL; 12 | 13 | void asyncOutput(const char* msg, int len) 14 | { 15 | g_asyncLog->append(msg, len); 16 | } 17 | 18 | void bench(bool longLog) 19 | { 20 | muduo::Logger::setOutput(asyncOutput); 21 | 22 | int cnt = 0; 23 | const int kBatch = 1000; 24 | muduo::string empty = " "; 25 | muduo::string longStr(3000, 'X'); 26 | longStr += " "; 27 | 28 | for (int t = 0; t < 30; ++t) 29 | { 30 | muduo::Timestamp start = muduo::Timestamp::now(); 31 | for (int i = 0; i < kBatch; ++i) 32 | { 33 | LOG_INFO << "Hello 0123456789" << " abcdefghijklmnopqrstuvwxyz " 34 | << (longLog ? longStr : empty) 35 | << cnt; 36 | ++cnt; 37 | } 38 | muduo::Timestamp end = muduo::Timestamp::now(); 39 | printf("%f\n", timeDifference(end, start)*1000000/kBatch); 40 | struct timespec ts = { 0, 500*1000*1000 }; 41 | nanosleep(&ts, NULL); 42 | } 43 | } 44 | 45 | int main(int argc, char* argv[]) 46 | { 47 | { 48 | // set max virtual memory to 2GB. 49 | size_t kOneGB = 1000*1024*1024; 50 | rlimit rl = { 2*kOneGB, 2*kOneGB }; 51 | setrlimit(RLIMIT_AS, &rl); 52 | } 53 | 54 | printf("pid = %d\n", getpid()); 55 | 56 | char name[256] = { '\0' }; 57 | strncpy(name, argv[0], sizeof name - 1); 58 | muduo::AsyncLogging log(::basename(name), kRollSize); 59 | log.start(); 60 | g_asyncLog = &log; 61 | 62 | bool longLog = argc > 1; 63 | bench(longLog); 64 | } 65 | -------------------------------------------------------------------------------- /muduo/base/tests/Atomic_unittest.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/Atomic.h" 2 | #include 3 | 4 | int main() 5 | { 6 | { 7 | muduo::AtomicInt64 a0; 8 | assert(a0.get() == 0); 9 | assert(a0.getAndAdd(1) == 0); 10 | assert(a0.get() == 1); 11 | assert(a0.addAndGet(2) == 3); 12 | assert(a0.get() == 3); 13 | assert(a0.incrementAndGet() == 4); 14 | assert(a0.get() == 4); 15 | a0.increment(); 16 | assert(a0.get() == 5); 17 | assert(a0.addAndGet(-3) == 2); 18 | assert(a0.getAndSet(100) == 2); 19 | assert(a0.get() == 100); 20 | } 21 | 22 | { 23 | muduo::AtomicInt32 a1; 24 | assert(a1.get() == 0); 25 | assert(a1.getAndAdd(1) == 0); 26 | assert(a1.get() == 1); 27 | assert(a1.addAndGet(2) == 3); 28 | assert(a1.get() == 3); 29 | assert(a1.incrementAndGet() == 4); 30 | assert(a1.get() == 4); 31 | a1.increment(); 32 | assert(a1.get() == 5); 33 | assert(a1.addAndGet(-3) == 2); 34 | assert(a1.getAndSet(100) == 2); 35 | assert(a1.get() == 100); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /muduo/base/tests/Exception_test.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/CurrentThread.h" 2 | #include "muduo/base/Exception.h" 3 | #include 4 | #include 5 | #include 6 | 7 | class Bar 8 | { 9 | public: 10 | void test(std::vector names = {}) 11 | { 12 | printf("Stack:\n%s\n", muduo::CurrentThread::stackTrace(true).c_str()); 13 | [] { 14 | printf("Stack inside lambda:\n%s\n", muduo::CurrentThread::stackTrace(true).c_str()); 15 | }(); 16 | std::function func([] { 17 | printf("Stack inside std::function:\n%s\n", muduo::CurrentThread::stackTrace(true).c_str()); 18 | }); 19 | func(); 20 | 21 | func = std::bind(&Bar::callback, this); 22 | func(); 23 | 24 | throw muduo::Exception("oops"); 25 | } 26 | 27 | private: 28 | void callback() 29 | { 30 | printf("Stack inside std::bind:\n%s\n", muduo::CurrentThread::stackTrace(true).c_str()); 31 | } 32 | }; 33 | 34 | void foo() 35 | { 36 | Bar b; 37 | b.test(); 38 | } 39 | 40 | int main() 41 | { 42 | try 43 | { 44 | foo(); 45 | } 46 | catch (const muduo::Exception& ex) 47 | { 48 | printf("reason: %s\n", ex.what()); 49 | printf("stack trace:\n%s\n", ex.stackTrace()); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /muduo/base/tests/FileUtil_test.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/FileUtil.h" 2 | 3 | #include 4 | #define __STDC_FORMAT_MACROS 5 | #include 6 | 7 | using namespace muduo; 8 | 9 | int main() 10 | { 11 | string result; 12 | int64_t size = 0; 13 | int err = FileUtil::readFile("/proc/self", 1024, &result, &size); 14 | printf("%d %zd %" PRIu64 "\n", err, result.size(), size); 15 | err = FileUtil::readFile("/proc/self", 1024, &result, NULL); 16 | printf("%d %zd %" PRIu64 "\n", err, result.size(), size); 17 | err = FileUtil::readFile("/proc/self/cmdline", 1024, &result, &size); 18 | printf("%d %zd %" PRIu64 "\n", err, result.size(), size); 19 | err = FileUtil::readFile("/dev/null", 1024, &result, &size); 20 | printf("%d %zd %" PRIu64 "\n", err, result.size(), size); 21 | err = FileUtil::readFile("/dev/zero", 1024, &result, &size); 22 | printf("%d %zd %" PRIu64 "\n", err, result.size(), size); 23 | err = FileUtil::readFile("/notexist", 1024, &result, &size); 24 | printf("%d %zd %" PRIu64 "\n", err, result.size(), size); 25 | err = FileUtil::readFile("/dev/zero", 102400, &result, &size); 26 | printf("%d %zd %" PRIu64 "\n", err, result.size(), size); 27 | err = FileUtil::readFile("/dev/zero", 102400, &result, NULL); 28 | printf("%d %zd %" PRIu64 "\n", err, result.size(), size); 29 | } 30 | 31 | -------------------------------------------------------------------------------- /muduo/base/tests/Fork_test.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/CurrentThread.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace 8 | { 9 | __thread int x = 0; 10 | } 11 | 12 | void print() 13 | { 14 | printf("pid=%d tid=%d x=%d\n", getpid(), muduo::CurrentThread::tid(), x); 15 | } 16 | 17 | int main() 18 | { 19 | printf("parent %d\n", getpid()); 20 | print(); 21 | x = 1; 22 | print(); 23 | pid_t p = fork(); 24 | 25 | if (p == 0) 26 | { 27 | printf("chlid %d\n", getpid()); 28 | // child 29 | print(); 30 | x = 2; 31 | print(); 32 | 33 | if (fork() == 0) 34 | { 35 | printf("grandchlid %d\n", getpid()); 36 | print(); 37 | x = 3; 38 | print(); 39 | } 40 | } 41 | else 42 | { 43 | // parent 44 | print(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /muduo/base/tests/GzipFile_test.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/GzipFile.h" 2 | 3 | #include "muduo/base/Logging.h" 4 | 5 | int main() 6 | { 7 | const char* filename = "/tmp/gzipfile_test.gz"; 8 | ::unlink(filename); 9 | const char data[] = "123456789012345678901234567890123456789012345678901234567890\n"; 10 | { 11 | muduo::GzipFile writer = muduo::GzipFile::openForAppend(filename); 12 | if (writer.valid()) 13 | { 14 | LOG_INFO << "tell " << writer.tell(); 15 | LOG_INFO << "wrote " << writer.write(data); 16 | LOG_INFO << "tell " << writer.tell(); 17 | } 18 | } 19 | 20 | { 21 | printf("testing reader\n"); 22 | muduo::GzipFile reader = muduo::GzipFile::openForRead(filename); 23 | if (reader.valid()) 24 | { 25 | char buf[256]; 26 | LOG_INFO << "tell " << reader.tell(); 27 | int nr = reader.read(buf, sizeof buf); 28 | printf("read %d\n", nr); 29 | if (nr >= 0) 30 | { 31 | buf[nr] = '\0'; 32 | printf("data %s", buf); 33 | } 34 | LOG_INFO << "tell " << reader.tell(); 35 | if (strncmp(buf, data, strlen(data)) != 0) 36 | { 37 | printf("failed!!!\n"); 38 | abort(); 39 | } 40 | else 41 | { 42 | printf("PASSED\n"); 43 | } 44 | } 45 | } 46 | 47 | { 48 | muduo::GzipFile writer = muduo::GzipFile::openForWriteExclusive(filename); 49 | if (writer.valid() || errno != EEXIST) 50 | { 51 | printf("FAILED\n"); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /muduo/base/tests/LogFile_test.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/LogFile.h" 2 | #include "muduo/base/Logging.h" 3 | 4 | #include 5 | 6 | std::unique_ptr g_logFile; 7 | 8 | void outputFunc(const char* msg, int len) 9 | { 10 | g_logFile->append(msg, len); 11 | } 12 | 13 | void flushFunc() 14 | { 15 | g_logFile->flush(); 16 | } 17 | 18 | int main(int argc, char* argv[]) 19 | { 20 | char name[256] = { '\0' }; 21 | strncpy(name, argv[0], sizeof name - 1); 22 | g_logFile.reset(new muduo::LogFile(::basename(name), 200*1000)); 23 | muduo::Logger::setOutput(outputFunc); 24 | muduo::Logger::setFlush(flushFunc); 25 | 26 | muduo::string line = "1234567890 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ "; 27 | 28 | for (int i = 0; i < 10000; ++i) 29 | { 30 | LOG_INFO << line << i; 31 | 32 | usleep(1000); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /muduo/base/tests/LogStream_bench.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/LogStream.h" 2 | #include "muduo/base/Timestamp.h" 3 | 4 | #include 5 | #include 6 | #define __STDC_FORMAT_MACROS 7 | #include 8 | 9 | using namespace muduo; 10 | 11 | const size_t N = 1000000; 12 | 13 | #pragma GCC diagnostic ignored "-Wold-style-cast" 14 | 15 | template 16 | void benchPrintf(const char* fmt) 17 | { 18 | char buf[32]; 19 | Timestamp start(Timestamp::now()); 20 | for (size_t i = 0; i < N; ++i) 21 | snprintf(buf, sizeof buf, fmt, (T)(i)); 22 | Timestamp end(Timestamp::now()); 23 | 24 | printf("benchPrintf %f\n", timeDifference(end, start)); 25 | } 26 | 27 | template 28 | void benchStringStream() 29 | { 30 | Timestamp start(Timestamp::now()); 31 | std::ostringstream os; 32 | 33 | for (size_t i = 0; i < N; ++i) 34 | { 35 | os << (T)(i); 36 | os.seekp(0, std::ios_base::beg); 37 | } 38 | Timestamp end(Timestamp::now()); 39 | 40 | printf("benchStringStream %f\n", timeDifference(end, start)); 41 | } 42 | 43 | template 44 | void benchLogStream() 45 | { 46 | Timestamp start(Timestamp::now()); 47 | LogStream os; 48 | for (size_t i = 0; i < N; ++i) 49 | { 50 | os << (T)(i); 51 | os.resetBuffer(); 52 | } 53 | Timestamp end(Timestamp::now()); 54 | 55 | printf("benchLogStream %f\n", timeDifference(end, start)); 56 | } 57 | 58 | int main() 59 | { 60 | benchPrintf("%d"); 61 | 62 | puts("int"); 63 | benchPrintf("%d"); 64 | benchStringStream(); 65 | benchLogStream(); 66 | 67 | puts("double"); 68 | benchPrintf("%.12g"); 69 | benchStringStream(); 70 | benchLogStream(); 71 | 72 | puts("int64_t"); 73 | benchPrintf("%" PRId64); 74 | benchStringStream(); 75 | benchLogStream(); 76 | 77 | puts("void*"); 78 | benchPrintf("%p"); 79 | benchStringStream(); 80 | benchLogStream(); 81 | 82 | } 83 | -------------------------------------------------------------------------------- /muduo/base/tests/ProcessInfo_test.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/ProcessInfo.h" 2 | #include 3 | #define __STDC_FORMAT_MACROS 4 | #include 5 | 6 | int main() 7 | { 8 | printf("pid = %d\n", muduo::ProcessInfo::pid()); 9 | printf("uid = %d\n", muduo::ProcessInfo::uid()); 10 | printf("euid = %d\n", muduo::ProcessInfo::euid()); 11 | printf("start time = %s\n", muduo::ProcessInfo::startTime().toFormattedString().c_str()); 12 | printf("hostname = %s\n", muduo::ProcessInfo::hostname().c_str()); 13 | printf("opened files = %d\n", muduo::ProcessInfo::openedFiles()); 14 | printf("threads = %zd\n", muduo::ProcessInfo::threads().size()); 15 | printf("num threads = %d\n", muduo::ProcessInfo::numThreads()); 16 | printf("status = %s\n", muduo::ProcessInfo::procStatus().c_str()); 17 | } 18 | -------------------------------------------------------------------------------- /muduo/base/tests/SingletonThreadLocal_test.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/Singleton.h" 2 | #include "muduo/base/CurrentThread.h" 3 | #include "muduo/base/ThreadLocal.h" 4 | #include "muduo/base/Thread.h" 5 | 6 | #include 7 | #include 8 | 9 | class Test : muduo::noncopyable 10 | { 11 | public: 12 | Test() 13 | { 14 | printf("tid=%d, constructing %p\n", muduo::CurrentThread::tid(), this); 15 | } 16 | 17 | ~Test() 18 | { 19 | printf("tid=%d, destructing %p %s\n", muduo::CurrentThread::tid(), this, name_.c_str()); 20 | } 21 | 22 | const muduo::string& name() const { return name_; } 23 | void setName(const muduo::string& n) { name_ = n; } 24 | 25 | private: 26 | muduo::string name_; 27 | }; 28 | 29 | #define STL muduo::Singleton >::instance().value() 30 | 31 | void print() 32 | { 33 | printf("tid=%d, %p name=%s\n", 34 | muduo::CurrentThread::tid(), 35 | &STL, 36 | STL.name().c_str()); 37 | } 38 | 39 | void threadFunc(const char* changeTo) 40 | { 41 | print(); 42 | STL.setName(changeTo); 43 | sleep(1); 44 | print(); 45 | } 46 | 47 | int main() 48 | { 49 | STL.setName("main one"); 50 | muduo::Thread t1(std::bind(threadFunc, "thread1")); 51 | muduo::Thread t2(std::bind(threadFunc, "thread2")); 52 | t1.start(); 53 | t2.start(); 54 | t1.join(); 55 | print(); 56 | t2.join(); 57 | pthread_exit(0); 58 | } 59 | -------------------------------------------------------------------------------- /muduo/base/tests/Singleton_test.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/Singleton.h" 2 | #include "muduo/base/CurrentThread.h" 3 | #include "muduo/base/Thread.h" 4 | 5 | #include 6 | 7 | class Test : muduo::noncopyable 8 | { 9 | public: 10 | Test() 11 | { 12 | printf("tid=%d, constructing %p\n", muduo::CurrentThread::tid(), this); 13 | } 14 | 15 | ~Test() 16 | { 17 | printf("tid=%d, destructing %p %s\n", muduo::CurrentThread::tid(), this, name_.c_str()); 18 | } 19 | 20 | const muduo::string& name() const { return name_; } 21 | void setName(const muduo::string& n) { name_ = n; } 22 | 23 | private: 24 | muduo::string name_; 25 | }; 26 | 27 | class TestNoDestroy : muduo::noncopyable 28 | { 29 | public: 30 | // Tag member for Singleton 31 | void no_destroy(); 32 | 33 | TestNoDestroy() 34 | { 35 | printf("tid=%d, constructing TestNoDestroy %p\n", muduo::CurrentThread::tid(), this); 36 | } 37 | 38 | ~TestNoDestroy() 39 | { 40 | printf("tid=%d, destructing TestNoDestroy %p\n", muduo::CurrentThread::tid(), this); 41 | } 42 | }; 43 | 44 | void threadFunc() 45 | { 46 | printf("tid=%d, %p name=%s\n", 47 | muduo::CurrentThread::tid(), 48 | &muduo::Singleton::instance(), 49 | muduo::Singleton::instance().name().c_str()); 50 | muduo::Singleton::instance().setName("only one, changed"); 51 | } 52 | 53 | int main() 54 | { 55 | muduo::Singleton::instance().setName("only one"); 56 | muduo::Thread t1(threadFunc); 57 | t1.start(); 58 | t1.join(); 59 | printf("tid=%d, %p name=%s\n", 60 | muduo::CurrentThread::tid(), 61 | &muduo::Singleton::instance(), 62 | muduo::Singleton::instance().name().c_str()); 63 | muduo::Singleton::instance(); 64 | printf("with valgrind, you should see %zd-byte memory leak.\n", sizeof(TestNoDestroy)); 65 | } 66 | -------------------------------------------------------------------------------- /muduo/base/tests/ThreadLocalSingleton_test.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/ThreadLocalSingleton.h" 2 | #include "muduo/base/CurrentThread.h" 3 | #include "muduo/base/Thread.h" 4 | 5 | #include 6 | 7 | class Test : muduo::noncopyable 8 | { 9 | public: 10 | Test() 11 | { 12 | printf("tid=%d, constructing %p\n", muduo::CurrentThread::tid(), this); 13 | } 14 | 15 | ~Test() 16 | { 17 | printf("tid=%d, destructing %p %s\n", muduo::CurrentThread::tid(), this, name_.c_str()); 18 | } 19 | 20 | const muduo::string& name() const { return name_; } 21 | void setName(const muduo::string& n) { name_ = n; } 22 | 23 | private: 24 | muduo::string name_; 25 | }; 26 | 27 | void threadFunc(const char* changeTo) 28 | { 29 | printf("tid=%d, %p name=%s\n", 30 | muduo::CurrentThread::tid(), 31 | &muduo::ThreadLocalSingleton::instance(), 32 | muduo::ThreadLocalSingleton::instance().name().c_str()); 33 | muduo::ThreadLocalSingleton::instance().setName(changeTo); 34 | printf("tid=%d, %p name=%s\n", 35 | muduo::CurrentThread::tid(), 36 | &muduo::ThreadLocalSingleton::instance(), 37 | muduo::ThreadLocalSingleton::instance().name().c_str()); 38 | 39 | // no need to manually delete it 40 | // muduo::ThreadLocalSingleton::destroy(); 41 | } 42 | 43 | int main() 44 | { 45 | muduo::ThreadLocalSingleton::instance().setName("main one"); 46 | muduo::Thread t1(std::bind(threadFunc, "thread1")); 47 | muduo::Thread t2(std::bind(threadFunc, "thread2")); 48 | t1.start(); 49 | t2.start(); 50 | t1.join(); 51 | printf("tid=%d, %p name=%s\n", 52 | muduo::CurrentThread::tid(), 53 | &muduo::ThreadLocalSingleton::instance(), 54 | muduo::ThreadLocalSingleton::instance().name().c_str()); 55 | t2.join(); 56 | 57 | pthread_exit(0); 58 | } 59 | -------------------------------------------------------------------------------- /muduo/base/tests/ThreadLocal_test.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/ThreadLocal.h" 2 | #include "muduo/base/CurrentThread.h" 3 | #include "muduo/base/Thread.h" 4 | 5 | #include 6 | 7 | class Test : muduo::noncopyable 8 | { 9 | public: 10 | Test() 11 | { 12 | printf("tid=%d, constructing %p\n", muduo::CurrentThread::tid(), this); 13 | } 14 | 15 | ~Test() 16 | { 17 | printf("tid=%d, destructing %p %s\n", muduo::CurrentThread::tid(), this, name_.c_str()); 18 | } 19 | 20 | const muduo::string& name() const { return name_; } 21 | void setName(const muduo::string& n) { name_ = n; } 22 | 23 | private: 24 | muduo::string name_; 25 | }; 26 | 27 | muduo::ThreadLocal testObj1; 28 | muduo::ThreadLocal testObj2; 29 | 30 | void print() 31 | { 32 | printf("tid=%d, obj1 %p name=%s\n", 33 | muduo::CurrentThread::tid(), 34 | &testObj1.value(), 35 | testObj1.value().name().c_str()); 36 | printf("tid=%d, obj2 %p name=%s\n", 37 | muduo::CurrentThread::tid(), 38 | &testObj2.value(), 39 | testObj2.value().name().c_str()); 40 | } 41 | 42 | void threadFunc() 43 | { 44 | print(); 45 | testObj1.value().setName("changed 1"); 46 | testObj2.value().setName("changed 42"); 47 | print(); 48 | } 49 | 50 | int main() 51 | { 52 | testObj1.value().setName("main one"); 53 | print(); 54 | muduo::Thread t1(threadFunc); 55 | t1.start(); 56 | t1.join(); 57 | testObj2.value().setName("main two"); 58 | print(); 59 | 60 | pthread_exit(0); 61 | } 62 | -------------------------------------------------------------------------------- /muduo/base/tests/TimeZone_util.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/TimeZone.h" 2 | 3 | #include 4 | 5 | #ifndef __STDC_FORMAT_MACROS 6 | #define __STDC_FORMAT_MACROS 7 | #endif 8 | 9 | #include 10 | 11 | #include 12 | 13 | using muduo::DateTime; 14 | using muduo::TimeZone; 15 | 16 | void printUtcAndLocal(int64_t utc, TimeZone local) 17 | { 18 | printf("Unix Time: %" PRId64 "\n", utc); 19 | printf("UTC: %s\n", TimeZone::toUtcTime(utc).toIsoString().c_str()); 20 | int utcOffset = 0; 21 | printf("Local: %s", local.toLocalTime(utc, &utcOffset).toIsoString().c_str()); 22 | printf(" %+03d%02d\n", utcOffset / 3600, utcOffset % 3600 / 60); 23 | } 24 | 25 | int main(int argc, char* argv[]) 26 | { 27 | TimeZone local = TimeZone::loadZoneFile("/etc/localtime"); 28 | if (argc <= 1) 29 | { 30 | time_t now = ::time(NULL); 31 | printUtcAndLocal(now, local); 32 | return 0; 33 | } 34 | 35 | // TODO: input is from a different timezone. 36 | 37 | for (int i = 1; i < argc; ++i) 38 | { 39 | char* end = NULL; 40 | int64_t t = strtol(argv[i], &end, 10); 41 | if (end > argv[i] && *end == '\0') 42 | { 43 | printUtcAndLocal(t, local); 44 | } 45 | else 46 | { 47 | struct tm tm = { }; 48 | end = strptime(argv[i], "%F %T", &tm); 49 | if (end != NULL && *end == '\0') 50 | { 51 | DateTime dt(tm); 52 | t = local.fromLocalTime(dt); 53 | printUtcAndLocal(t, local); 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /muduo/base/tests/Timestamp_unittest.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/base/Timestamp.h" 2 | #include 3 | #include 4 | 5 | using muduo::Timestamp; 6 | 7 | void passByConstReference(const Timestamp& x) 8 | { 9 | printf("%s\n", x.toString().c_str()); 10 | } 11 | 12 | void passByValue(Timestamp x) 13 | { 14 | printf("%s\n", x.toString().c_str()); 15 | } 16 | 17 | void benchmark() 18 | { 19 | const int kNumber = 1000*1000; 20 | 21 | std::vector stamps; 22 | stamps.reserve(kNumber); 23 | for (int i = 0; i < kNumber; ++i) 24 | { 25 | stamps.push_back(Timestamp::now()); 26 | } 27 | printf("%s\n", stamps.front().toString().c_str()); 28 | printf("%s\n", stamps.back().toString().c_str()); 29 | printf("%f\n", timeDifference(stamps.back(), stamps.front())); 30 | 31 | int increments[100] = { 0 }; 32 | int64_t start = stamps.front().microSecondsSinceEpoch(); 33 | for (int i = 1; i < kNumber; ++i) 34 | { 35 | int64_t next = stamps[i].microSecondsSinceEpoch(); 36 | int64_t inc = next - start; 37 | start = next; 38 | if (inc < 0) 39 | { 40 | printf("reverse!\n"); 41 | } 42 | else if (inc < 100) 43 | { 44 | ++increments[inc]; 45 | } 46 | else 47 | { 48 | printf("big gap %d\n", static_cast(inc)); 49 | } 50 | } 51 | 52 | for (int i = 0; i < 100; ++i) 53 | { 54 | printf("%2d: %d\n", i, increments[i]); 55 | } 56 | } 57 | 58 | int main() 59 | { 60 | Timestamp now(Timestamp::now()); 61 | printf("%s\n", now.toString().c_str()); 62 | passByValue(now); 63 | passByConstReference(now); 64 | benchmark(); 65 | } 66 | 67 | -------------------------------------------------------------------------------- /muduo/net/Acceptor.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | // This is an internal header file, you should not include this. 10 | 11 | #ifndef MUDUO_NET_ACCEPTOR_H 12 | #define MUDUO_NET_ACCEPTOR_H 13 | 14 | #include 15 | 16 | #include "muduo/net/Channel.h" 17 | #include "muduo/net/Socket.h" 18 | 19 | namespace muduo 20 | { 21 | namespace net 22 | { 23 | 24 | class EventLoop; 25 | class InetAddress; 26 | 27 | /// 28 | /// Acceptor of incoming TCP connections. 29 | /// 30 | class Acceptor : noncopyable 31 | { 32 | public: 33 | typedef std::function NewConnectionCallback; 34 | 35 | Acceptor(EventLoop* loop, const InetAddress& listenAddr, bool reuseport); 36 | ~Acceptor(); 37 | 38 | void setNewConnectionCallback(const NewConnectionCallback& cb) 39 | { newConnectionCallback_ = cb; } 40 | 41 | void listen(); 42 | 43 | bool listening() const { return listening_; } 44 | 45 | // Deprecated, use the correct spelling one above. 46 | // Leave the wrong spelling here in case one needs to grep it for error messages. 47 | // bool listenning() const { return listening(); } 48 | 49 | private: 50 | void handleRead(); 51 | 52 | EventLoop* loop_; 53 | Socket acceptSocket_; 54 | Channel acceptChannel_; 55 | NewConnectionCallback newConnectionCallback_; 56 | bool listening_; 57 | int idleFd_; 58 | }; 59 | 60 | } // namespace net 61 | } // namespace muduo 62 | 63 | #endif // MUDUO_NET_ACCEPTOR_H 64 | -------------------------------------------------------------------------------- /muduo/net/BUILD.bazel: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "net", 3 | srcs = [ 4 | "Acceptor.cc", 5 | "Buffer.cc", 6 | "Channel.cc", 7 | "Connector.cc", 8 | "EventLoop.cc", 9 | "EventLoopThread.cc", 10 | "EventLoopThreadPool.cc", 11 | "InetAddress.cc", 12 | "Poller.cc", 13 | "Socket.cc", 14 | "SocketsOps.cc", 15 | "TcpClient.cc", 16 | "TcpConnection.cc", 17 | "TcpServer.cc", 18 | "Timer.cc", 19 | "TimerQueue.cc", 20 | "poller/DefaultPoller.cc", 21 | "poller/EPollPoller.cc", 22 | "poller/PollPoller.cc", 23 | ], 24 | hdrs = [ 25 | "Acceptor.h", 26 | "Buffer.h", 27 | "Callbacks.h", 28 | "Channel.h", 29 | "Connector.h", 30 | "Endian.h", 31 | "EventLoop.h", 32 | "EventLoopThread.h", 33 | "EventLoopThreadPool.h", 34 | "InetAddress.h", 35 | "Poller.h", 36 | "Socket.h", 37 | "SocketsOps.h", 38 | "TcpClient.h", 39 | "TcpConnection.h", 40 | "TcpServer.h", 41 | "Timer.h", 42 | "TimerId.h", 43 | "TimerQueue.h", 44 | "poller/EPollPoller.h", 45 | "poller/PollPoller.h", 46 | ], 47 | visibility = ["//visibility:public"], 48 | deps = [ 49 | "//muduo/base", 50 | ], 51 | ) 52 | -------------------------------------------------------------------------------- /muduo/net/Buffer.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | 10 | #include "muduo/net/Buffer.h" 11 | 12 | #include "muduo/net/SocketsOps.h" 13 | 14 | #include 15 | #include 16 | 17 | using namespace muduo; 18 | using namespace muduo::net; 19 | 20 | const char Buffer::kCRLF[] = "\r\n"; 21 | 22 | const size_t Buffer::kCheapPrepend; 23 | const size_t Buffer::kInitialSize; 24 | 25 | ssize_t Buffer::readFd(int fd, int* savedErrno) 26 | { 27 | // saved an ioctl()/FIONREAD call to tell how much to read 28 | char extrabuf[65536]; 29 | struct iovec vec[2]; 30 | const size_t writable = writableBytes(); 31 | vec[0].iov_base = begin()+writerIndex_; 32 | vec[0].iov_len = writable; 33 | vec[1].iov_base = extrabuf; 34 | vec[1].iov_len = sizeof extrabuf; 35 | // when there is enough space in this buffer, don't read into extrabuf. 36 | // when extrabuf is used, we read 128k-1 bytes at most. 37 | const int iovcnt = (writable < sizeof extrabuf) ? 2 : 1; 38 | const ssize_t n = sockets::readv(fd, vec, iovcnt); 39 | if (n < 0) 40 | { 41 | *savedErrno = errno; 42 | } 43 | else if (implicit_cast(n) <= writable) 44 | { 45 | writerIndex_ += n; 46 | } 47 | else 48 | { 49 | writerIndex_ = buffer_.size(); 50 | append(extrabuf, n - writable); 51 | } 52 | // if (n == writable + sizeof extrabuf) 53 | // { 54 | // goto line_30; 55 | // } 56 | return n; 57 | } 58 | 59 | -------------------------------------------------------------------------------- /muduo/net/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(CheckFunctionExists) 2 | 3 | check_function_exists(accept4 HAVE_ACCEPT4) 4 | if(NOT HAVE_ACCEPT4) 5 | set_source_files_properties(SocketsOps.cc PROPERTIES COMPILE_FLAGS "-DNO_ACCEPT4") 6 | endif() 7 | 8 | set(net_SRCS 9 | Acceptor.cc 10 | Buffer.cc 11 | Channel.cc 12 | Connector.cc 13 | EventLoop.cc 14 | EventLoopThread.cc 15 | EventLoopThreadPool.cc 16 | InetAddress.cc 17 | Poller.cc 18 | poller/DefaultPoller.cc 19 | poller/EPollPoller.cc 20 | poller/PollPoller.cc 21 | Socket.cc 22 | SocketsOps.cc 23 | TcpClient.cc 24 | TcpConnection.cc 25 | TcpServer.cc 26 | Timer.cc 27 | TimerQueue.cc 28 | ) 29 | 30 | add_library(muduo_net ${net_SRCS}) 31 | target_link_libraries(muduo_net muduo_base) 32 | 33 | #add_library(muduo_net_cpp11 ${net_SRCS}) 34 | #target_link_libraries(muduo_net_cpp11 muduo_base_cpp11) 35 | #set_target_properties(muduo_net_cpp11 PROPERTIES COMPILE_FLAGS "-std=c++0x") 36 | 37 | install(TARGETS muduo_net DESTINATION lib) 38 | #install(TARGETS muduo_net_cpp11 DESTINATION lib) 39 | 40 | set(HEADERS 41 | Buffer.h 42 | Callbacks.h 43 | Channel.h 44 | Endian.h 45 | EventLoop.h 46 | EventLoopThread.h 47 | EventLoopThreadPool.h 48 | InetAddress.h 49 | TcpClient.h 50 | TcpConnection.h 51 | TcpServer.h 52 | TimerId.h 53 | ) 54 | install(FILES ${HEADERS} DESTINATION include/muduo/net) 55 | 56 | add_subdirectory(http) 57 | add_subdirectory(inspect) 58 | 59 | if(MUDUO_BUILD_EXAMPLES) 60 | add_subdirectory(tests) 61 | endif() 62 | 63 | if(PROTOBUF_FOUND) 64 | add_subdirectory(protobuf) 65 | add_subdirectory(protorpc) 66 | else() 67 | add_subdirectory(protobuf EXCLUDE_FROM_ALL) 68 | add_subdirectory(protorpc EXCLUDE_FROM_ALL) 69 | endif() 70 | -------------------------------------------------------------------------------- /muduo/net/Endian.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | // This is a public header file, it must only include public header files. 10 | 11 | #ifndef MUDUO_NET_ENDIAN_H 12 | #define MUDUO_NET_ENDIAN_H 13 | 14 | #include 15 | #include 16 | 17 | namespace muduo 18 | { 19 | namespace net 20 | { 21 | namespace sockets 22 | { 23 | 24 | // the inline assembler code makes type blur, 25 | // so we disable warnings for a while. 26 | #pragma GCC diagnostic push 27 | #pragma GCC diagnostic ignored "-Wconversion" 28 | #pragma GCC diagnostic ignored "-Wold-style-cast" 29 | inline uint64_t hostToNetwork64(uint64_t host64) 30 | { 31 | return htobe64(host64); 32 | } 33 | 34 | inline uint32_t hostToNetwork32(uint32_t host32) 35 | { 36 | return htobe32(host32); 37 | } 38 | 39 | inline uint16_t hostToNetwork16(uint16_t host16) 40 | { 41 | return htobe16(host16); 42 | } 43 | 44 | inline uint64_t networkToHost64(uint64_t net64) 45 | { 46 | return be64toh(net64); 47 | } 48 | 49 | inline uint32_t networkToHost32(uint32_t net32) 50 | { 51 | return be32toh(net32); 52 | } 53 | 54 | inline uint16_t networkToHost16(uint16_t net16) 55 | { 56 | return be16toh(net16); 57 | } 58 | 59 | #pragma GCC diagnostic pop 60 | 61 | } // namespace sockets 62 | } // namespace net 63 | } // namespace muduo 64 | 65 | #endif // MUDUO_NET_ENDIAN_H 66 | -------------------------------------------------------------------------------- /muduo/net/EventLoopThread.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | 9 | #include "muduo/net/EventLoopThread.h" 10 | 11 | #include "muduo/net/EventLoop.h" 12 | 13 | using namespace muduo; 14 | using namespace muduo::net; 15 | 16 | EventLoopThread::EventLoopThread(const ThreadInitCallback& cb, 17 | const string& name) 18 | : loop_(NULL), 19 | exiting_(false), 20 | thread_(std::bind(&EventLoopThread::threadFunc, this), name), 21 | mutex_(), 22 | cond_(mutex_), 23 | callback_(cb) 24 | { 25 | } 26 | 27 | EventLoopThread::~EventLoopThread() 28 | { 29 | exiting_ = true; 30 | if (loop_ != NULL) // not 100% race-free, eg. threadFunc could be running callback_. 31 | { 32 | // still a tiny chance to call destructed object, if threadFunc exits just now. 33 | // but when EventLoopThread destructs, usually programming is exiting anyway. 34 | loop_->quit(); 35 | thread_.join(); 36 | } 37 | } 38 | 39 | EventLoop* EventLoopThread::startLoop() 40 | { 41 | assert(!thread_.started()); 42 | thread_.start(); 43 | 44 | EventLoop* loop = NULL; 45 | { 46 | MutexLockGuard lock(mutex_); 47 | while (loop_ == NULL) 48 | { 49 | cond_.wait(); 50 | } 51 | loop = loop_; 52 | } 53 | 54 | return loop; 55 | } 56 | 57 | void EventLoopThread::threadFunc() 58 | { 59 | EventLoop loop; 60 | 61 | if (callback_) 62 | { 63 | callback_(&loop); 64 | } 65 | 66 | { 67 | MutexLockGuard lock(mutex_); 68 | loop_ = &loop; 69 | cond_.notify(); 70 | } 71 | 72 | loop.loop(); 73 | //assert(exiting_); 74 | MutexLockGuard lock(mutex_); 75 | loop_ = NULL; 76 | } 77 | 78 | -------------------------------------------------------------------------------- /muduo/net/EventLoopThread.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | // This is a public header file, it must only include public header files. 10 | 11 | #ifndef MUDUO_NET_EVENTLOOPTHREAD_H 12 | #define MUDUO_NET_EVENTLOOPTHREAD_H 13 | 14 | #include "muduo/base/Condition.h" 15 | #include "muduo/base/Mutex.h" 16 | #include "muduo/base/Thread.h" 17 | 18 | namespace muduo 19 | { 20 | namespace net 21 | { 22 | 23 | class EventLoop; 24 | 25 | class EventLoopThread : noncopyable 26 | { 27 | public: 28 | typedef std::function ThreadInitCallback; 29 | 30 | EventLoopThread(const ThreadInitCallback& cb = ThreadInitCallback(), 31 | const string& name = string()); 32 | ~EventLoopThread(); 33 | EventLoop* startLoop(); 34 | 35 | private: 36 | void threadFunc(); 37 | 38 | EventLoop* loop_ GUARDED_BY(mutex_); 39 | bool exiting_; 40 | Thread thread_; 41 | MutexLock mutex_; 42 | Condition cond_ GUARDED_BY(mutex_); 43 | ThreadInitCallback callback_; 44 | }; 45 | 46 | } // namespace net 47 | } // namespace muduo 48 | 49 | #endif // MUDUO_NET_EVENTLOOPTHREAD_H 50 | 51 | -------------------------------------------------------------------------------- /muduo/net/EventLoopThreadPool.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | // This is an internal header file, you should not include this. 10 | 11 | #ifndef MUDUO_NET_EVENTLOOPTHREADPOOL_H 12 | #define MUDUO_NET_EVENTLOOPTHREADPOOL_H 13 | 14 | #include "muduo/base/noncopyable.h" 15 | #include "muduo/base/Types.h" 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | namespace muduo 22 | { 23 | 24 | namespace net 25 | { 26 | 27 | class EventLoop; 28 | class EventLoopThread; 29 | 30 | class EventLoopThreadPool : noncopyable 31 | { 32 | public: 33 | typedef std::function ThreadInitCallback; 34 | 35 | EventLoopThreadPool(EventLoop* baseLoop, const string& nameArg); 36 | ~EventLoopThreadPool(); 37 | void setThreadNum(int numThreads) { numThreads_ = numThreads; } 38 | void start(const ThreadInitCallback& cb = ThreadInitCallback()); 39 | 40 | // valid after calling start() 41 | /// round-robin 42 | EventLoop* getNextLoop(); 43 | 44 | /// with the same hash code, it will always return the same EventLoop 45 | EventLoop* getLoopForHash(size_t hashCode); 46 | 47 | std::vector getAllLoops(); 48 | 49 | bool started() const 50 | { return started_; } 51 | 52 | const string& name() const 53 | { return name_; } 54 | 55 | private: 56 | 57 | EventLoop* baseLoop_; 58 | string name_; 59 | bool started_; 60 | int numThreads_; 61 | int next_; 62 | std::vector> threads_; 63 | std::vector loops_; 64 | }; 65 | 66 | } // namespace net 67 | } // namespace muduo 68 | 69 | #endif // MUDUO_NET_EVENTLOOPTHREADPOOL_H 70 | -------------------------------------------------------------------------------- /muduo/net/Poller.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | 9 | #include "muduo/net/Poller.h" 10 | 11 | #include "muduo/net/Channel.h" 12 | 13 | using namespace muduo; 14 | using namespace muduo::net; 15 | 16 | Poller::Poller(EventLoop* loop) 17 | : ownerLoop_(loop) 18 | { 19 | } 20 | 21 | Poller::~Poller() = default; 22 | 23 | bool Poller::hasChannel(Channel* channel) const 24 | { 25 | assertInLoopThread(); 26 | ChannelMap::const_iterator it = channels_.find(channel->fd()); 27 | return it != channels_.end() && it->second == channel; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /muduo/net/Poller.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | // This is an internal header file, you should not include this. 10 | 11 | #ifndef MUDUO_NET_POLLER_H 12 | #define MUDUO_NET_POLLER_H 13 | 14 | #include 15 | #include 16 | 17 | #include "muduo/base/Timestamp.h" 18 | #include "muduo/net/EventLoop.h" 19 | 20 | namespace muduo 21 | { 22 | namespace net 23 | { 24 | 25 | class Channel; 26 | 27 | /// 28 | /// Base class for IO Multiplexing 29 | /// 30 | /// This class doesn't own the Channel objects. 31 | class Poller : noncopyable 32 | { 33 | public: 34 | typedef std::vector ChannelList; 35 | 36 | Poller(EventLoop* loop); 37 | virtual ~Poller(); 38 | 39 | /// Polls the I/O events. 40 | /// Must be called in the loop thread. 41 | virtual Timestamp poll(int timeoutMs, ChannelList* activeChannels) = 0; 42 | 43 | /// Changes the interested I/O events. 44 | /// Must be called in the loop thread. 45 | virtual void updateChannel(Channel* channel) = 0; 46 | 47 | /// Remove the channel, when it destructs. 48 | /// Must be called in the loop thread. 49 | virtual void removeChannel(Channel* channel) = 0; 50 | 51 | virtual bool hasChannel(Channel* channel) const; 52 | 53 | static Poller* newDefaultPoller(EventLoop* loop); 54 | 55 | void assertInLoopThread() const 56 | { 57 | ownerLoop_->assertInLoopThread(); 58 | } 59 | 60 | protected: 61 | typedef std::map ChannelMap; 62 | ChannelMap channels_; 63 | 64 | private: 65 | EventLoop* ownerLoop_; 66 | }; 67 | 68 | } // namespace net 69 | } // namespace muduo 70 | 71 | #endif // MUDUO_NET_POLLER_H 72 | -------------------------------------------------------------------------------- /muduo/net/Timer.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | 9 | #include "muduo/net/Timer.h" 10 | 11 | using namespace muduo; 12 | using namespace muduo::net; 13 | 14 | AtomicInt64 Timer::s_numCreated_; 15 | 16 | void Timer::restart(Timestamp now) 17 | { 18 | if (repeat_) 19 | { 20 | expiration_ = addTime(now, interval_); 21 | } 22 | else 23 | { 24 | expiration_ = Timestamp::invalid(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /muduo/net/Timer.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | // This is an internal header file, you should not include this. 10 | 11 | #ifndef MUDUO_NET_TIMER_H 12 | #define MUDUO_NET_TIMER_H 13 | 14 | #include "muduo/base/Atomic.h" 15 | #include "muduo/base/Timestamp.h" 16 | #include "muduo/net/Callbacks.h" 17 | 18 | namespace muduo 19 | { 20 | namespace net 21 | { 22 | 23 | /// 24 | /// Internal class for timer event. 25 | /// 26 | class Timer : noncopyable 27 | { 28 | public: 29 | Timer(TimerCallback cb, Timestamp when, double interval) 30 | : callback_(std::move(cb)), 31 | expiration_(when), 32 | interval_(interval), 33 | repeat_(interval > 0.0), 34 | sequence_(s_numCreated_.incrementAndGet()) 35 | { } 36 | 37 | void run() const 38 | { 39 | callback_(); 40 | } 41 | 42 | Timestamp expiration() const { return expiration_; } 43 | bool repeat() const { return repeat_; } 44 | int64_t sequence() const { return sequence_; } 45 | 46 | void restart(Timestamp now); 47 | 48 | static int64_t numCreated() { return s_numCreated_.get(); } 49 | 50 | private: 51 | const TimerCallback callback_; 52 | Timestamp expiration_; 53 | const double interval_; 54 | const bool repeat_; 55 | const int64_t sequence_; 56 | 57 | static AtomicInt64 s_numCreated_; 58 | }; 59 | 60 | } // namespace net 61 | } // namespace muduo 62 | 63 | #endif // MUDUO_NET_TIMER_H 64 | -------------------------------------------------------------------------------- /muduo/net/TimerId.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | // This is a public header file, it must only include public header files. 10 | 11 | #ifndef MUDUO_NET_TIMERID_H 12 | #define MUDUO_NET_TIMERID_H 13 | 14 | #include "muduo/base/copyable.h" 15 | 16 | namespace muduo 17 | { 18 | namespace net 19 | { 20 | 21 | class Timer; 22 | 23 | /// 24 | /// An opaque identifier, for canceling Timer. 25 | /// 26 | class TimerId : public muduo::copyable 27 | { 28 | public: 29 | TimerId() 30 | : timer_(NULL), 31 | sequence_(0) 32 | { 33 | } 34 | 35 | TimerId(Timer* timer, int64_t seq) 36 | : timer_(timer), 37 | sequence_(seq) 38 | { 39 | } 40 | 41 | // default copy-ctor, dtor and assignment are okay 42 | 43 | friend class TimerQueue; 44 | 45 | private: 46 | Timer* timer_; 47 | int64_t sequence_; 48 | }; 49 | 50 | } // namespace net 51 | } // namespace muduo 52 | 53 | #endif // MUDUO_NET_TIMERID_H 54 | -------------------------------------------------------------------------------- /muduo/net/boilerplate.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | 10 | #include "muduo/net/BoilerPlate.h" 11 | 12 | using namespace muduo; 13 | using namespace muduo::net; 14 | 15 | 16 | -------------------------------------------------------------------------------- /muduo/net/boilerplate.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | // This is a public header file, it must only include public header files. 10 | // This is an internal header file, you should not include this. 11 | 12 | #ifndef MUDUO_NET_BOILERPLATE_H 13 | #define MUDUO_NET_BOILERPLATE_H 14 | 15 | #include "muduo/base/noncopyable.h" 16 | 17 | namespace muduo 18 | { 19 | namespace net 20 | { 21 | 22 | class BoilerPlate : noncopyable 23 | { 24 | public: 25 | 26 | private: 27 | }; 28 | 29 | } 30 | } 31 | 32 | #endif // MUDUO_NET_BOILERPLATE_H 33 | -------------------------------------------------------------------------------- /muduo/net/http/BUILD.bazel: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "http", 3 | srcs = glob(["*.cc"]), 4 | hdrs = glob(["*.h"]), 5 | visibility = ["//visibility:public"], 6 | deps = [ 7 | "//muduo/net", 8 | ], 9 | ) 10 | -------------------------------------------------------------------------------- /muduo/net/http/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(http_SRCS 2 | HttpServer.cc 3 | HttpResponse.cc 4 | HttpContext.cc 5 | ) 6 | 7 | add_library(muduo_http ${http_SRCS}) 8 | target_link_libraries(muduo_http muduo_net) 9 | 10 | install(TARGETS muduo_http DESTINATION lib) 11 | set(HEADERS 12 | HttpContext.h 13 | HttpRequest.h 14 | HttpResponse.h 15 | HttpServer.h 16 | ) 17 | install(FILES ${HEADERS} DESTINATION include/muduo/net/http) 18 | 19 | if(MUDUO_BUILD_EXAMPLES) 20 | add_executable(httpserver_test tests/HttpServer_test.cc) 21 | target_link_libraries(httpserver_test muduo_http) 22 | 23 | if(BOOSTTEST_LIBRARY) 24 | add_executable(httprequest_unittest tests/HttpRequest_unittest.cc) 25 | target_link_libraries(httprequest_unittest muduo_http boost_unit_test_framework) 26 | endif() 27 | 28 | endif() 29 | 30 | # add_subdirectory(tests) 31 | -------------------------------------------------------------------------------- /muduo/net/http/HttpContext.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | // This is an internal header file, you should not include this. 10 | 11 | #ifndef MUDUO_NET_HTTP_HTTPCONTEXT_H 12 | #define MUDUO_NET_HTTP_HTTPCONTEXT_H 13 | 14 | #include "muduo/base/copyable.h" 15 | 16 | #include "muduo/net/http/HttpRequest.h" 17 | 18 | namespace muduo 19 | { 20 | namespace net 21 | { 22 | 23 | class Buffer; 24 | 25 | class HttpContext : public muduo::copyable 26 | { 27 | public: 28 | enum HttpRequestParseState 29 | { 30 | kExpectRequestLine, 31 | kExpectHeaders, 32 | kExpectBody, 33 | kGotAll, 34 | }; 35 | 36 | HttpContext() 37 | : state_(kExpectRequestLine) 38 | { 39 | } 40 | 41 | // default copy-ctor, dtor and assignment are fine 42 | 43 | // return false if any error 44 | bool parseRequest(Buffer* buf, Timestamp receiveTime); 45 | 46 | bool gotAll() const 47 | { return state_ == kGotAll; } 48 | 49 | void reset() 50 | { 51 | state_ = kExpectRequestLine; 52 | HttpRequest dummy; 53 | request_.swap(dummy); 54 | } 55 | 56 | const HttpRequest& request() const 57 | { return request_; } 58 | 59 | HttpRequest& request() 60 | { return request_; } 61 | 62 | private: 63 | bool processRequestLine(const char* begin, const char* end); 64 | 65 | HttpRequestParseState state_; 66 | HttpRequest request_; 67 | }; 68 | 69 | } // namespace net 70 | } // namespace muduo 71 | 72 | #endif // MUDUO_NET_HTTP_HTTPCONTEXT_H 73 | -------------------------------------------------------------------------------- /muduo/net/http/HttpResponse.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | 10 | #include "muduo/net/http/HttpResponse.h" 11 | #include "muduo/net/Buffer.h" 12 | 13 | #include 14 | 15 | using namespace muduo; 16 | using namespace muduo::net; 17 | 18 | void HttpResponse::appendToBuffer(Buffer* output) const 19 | { 20 | char buf[32]; 21 | snprintf(buf, sizeof buf, "HTTP/1.1 %d ", statusCode_); 22 | output->append(buf); 23 | output->append(statusMessage_); 24 | output->append("\r\n"); 25 | 26 | if (closeConnection_) 27 | { 28 | output->append("Connection: close\r\n"); 29 | } 30 | else 31 | { 32 | snprintf(buf, sizeof buf, "Content-Length: %zd\r\n", body_.size()); 33 | output->append(buf); 34 | output->append("Connection: Keep-Alive\r\n"); 35 | } 36 | 37 | for (const auto& header : headers_) 38 | { 39 | output->append(header.first); 40 | output->append(": "); 41 | output->append(header.second); 42 | output->append("\r\n"); 43 | } 44 | 45 | output->append("\r\n"); 46 | output->append(body_); 47 | } 48 | -------------------------------------------------------------------------------- /muduo/net/inspect/BUILD.bazel: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "inspect", 3 | srcs = glob(["*.cc"]), 4 | hdrs = glob(["*.h"]), 5 | visibility = ["//visibility:public"], 6 | deps = [ 7 | "//muduo/net/http", 8 | ], 9 | ) 10 | -------------------------------------------------------------------------------- /muduo/net/inspect/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(inspect_SRCS 2 | Inspector.cc 3 | PerformanceInspector.cc 4 | ProcessInspector.cc 5 | SystemInspector.cc 6 | ) 7 | 8 | add_library(muduo_inspect ${inspect_SRCS}) 9 | target_link_libraries(muduo_inspect muduo_http) 10 | 11 | if(TCMALLOC_INCLUDE_DIR AND TCMALLOC_LIBRARY) 12 | set_target_properties(muduo_inspect PROPERTIES COMPILE_FLAGS "-DHAVE_TCMALLOC") 13 | target_link_libraries(muduo_inspect tcmalloc_and_profiler) 14 | endif() 15 | 16 | install(TARGETS muduo_inspect DESTINATION lib) 17 | set(HEADERS 18 | Inspector.h 19 | ) 20 | install(FILES ${HEADERS} DESTINATION include/muduo/net/inspect) 21 | 22 | if(MUDUO_BUILD_EXAMPLES) 23 | add_executable(inspector_test tests/Inspector_test.cc) 24 | target_link_libraries(inspector_test muduo_inspect) 25 | endif() 26 | 27 | -------------------------------------------------------------------------------- /muduo/net/inspect/PerformanceInspector.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | // This is an internal header file, you should not include this. 10 | 11 | #ifndef MUDUO_NET_INSPECT_PERFORMANCEINSPECTOR_H 12 | #define MUDUO_NET_INSPECT_PERFORMANCEINSPECTOR_H 13 | 14 | #include "muduo/net/inspect/Inspector.h" 15 | 16 | namespace muduo 17 | { 18 | namespace net 19 | { 20 | 21 | class PerformanceInspector : noncopyable 22 | { 23 | public: 24 | void registerCommands(Inspector* ins); 25 | 26 | static string heap(HttpRequest::Method, const Inspector::ArgList&); 27 | static string growth(HttpRequest::Method, const Inspector::ArgList&); 28 | static string profile(HttpRequest::Method, const Inspector::ArgList&); 29 | static string cmdline(HttpRequest::Method, const Inspector::ArgList&); 30 | static string memstats(HttpRequest::Method, const Inspector::ArgList&); 31 | static string memhistogram(HttpRequest::Method, const Inspector::ArgList&); 32 | static string releaseFreeMemory(HttpRequest::Method, const Inspector::ArgList&); 33 | 34 | static string symbol(HttpRequest::Method, const Inspector::ArgList&); 35 | }; 36 | 37 | } // namespace net 38 | } // namespace muduo 39 | 40 | #endif // MUDUO_NET_INSPECT_PERFORMANCEINSPECTOR_H 41 | -------------------------------------------------------------------------------- /muduo/net/inspect/ProcessInspector.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | // This is an internal header file, you should not include this. 10 | 11 | #ifndef MUDUO_NET_INSPECT_PROCESSINSPECTOR_H 12 | #define MUDUO_NET_INSPECT_PROCESSINSPECTOR_H 13 | 14 | #include "muduo/net/inspect/Inspector.h" 15 | 16 | namespace muduo 17 | { 18 | namespace net 19 | { 20 | 21 | class ProcessInspector : noncopyable 22 | { 23 | public: 24 | void registerCommands(Inspector* ins); 25 | 26 | static string overview(HttpRequest::Method, const Inspector::ArgList&); 27 | static string pid(HttpRequest::Method, const Inspector::ArgList&); 28 | static string procStatus(HttpRequest::Method, const Inspector::ArgList&); 29 | static string openedFiles(HttpRequest::Method, const Inspector::ArgList&); 30 | static string threads(HttpRequest::Method, const Inspector::ArgList&); 31 | 32 | static string username_; 33 | }; 34 | 35 | } // namespace net 36 | } // namespace muduo 37 | 38 | #endif // MUDUO_NET_INSPECT_PROCESSINSPECTOR_H 39 | -------------------------------------------------------------------------------- /muduo/net/inspect/SystemInspector.h: -------------------------------------------------------------------------------- 1 | // Copyright 2014, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | // This is an internal header file, you should not include this. 10 | 11 | #ifndef MUDUO_NET_INSPECT_SYSTEMINSPECTOR_H 12 | #define MUDUO_NET_INSPECT_SYSTEMINSPECTOR_H 13 | 14 | #include "muduo/net/inspect/Inspector.h" 15 | 16 | namespace muduo 17 | { 18 | namespace net 19 | { 20 | 21 | class SystemInspector : noncopyable 22 | { 23 | public: 24 | void registerCommands(Inspector* ins); 25 | 26 | static string overview(HttpRequest::Method, const Inspector::ArgList&); 27 | static string loadavg(HttpRequest::Method, const Inspector::ArgList&); 28 | static string version(HttpRequest::Method, const Inspector::ArgList&); 29 | static string cpuinfo(HttpRequest::Method, const Inspector::ArgList&); 30 | static string meminfo(HttpRequest::Method, const Inspector::ArgList&); 31 | static string stat(HttpRequest::Method, const Inspector::ArgList&); 32 | }; 33 | 34 | } // namespace net 35 | } // namespace muduo 36 | 37 | #endif // MUDUO_NET_INSPECT_SYSTEMINSPECTOR_H 38 | -------------------------------------------------------------------------------- /muduo/net/inspect/tests/BUILD.bazel: -------------------------------------------------------------------------------- 1 | cc_binary( 2 | name = "inspector", 3 | srcs = ["Inspector_test.cc"], 4 | deps = [ 5 | "//muduo/net/inspect", 6 | ], 7 | ) 8 | -------------------------------------------------------------------------------- /muduo/net/inspect/tests/Inspector_test.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/net/inspect/Inspector.h" 2 | #include "muduo/net/EventLoop.h" 3 | #include "muduo/net/EventLoopThread.h" 4 | 5 | using namespace muduo; 6 | using namespace muduo::net; 7 | 8 | int main() 9 | { 10 | EventLoop loop; 11 | EventLoopThread t; 12 | Inspector ins(t.startLoop(), InetAddress(12345), "test"); 13 | loop.loop(); 14 | } 15 | 16 | -------------------------------------------------------------------------------- /muduo/net/poller/DefaultPoller.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | 9 | #include "muduo/net/Poller.h" 10 | #include "muduo/net/poller/PollPoller.h" 11 | #include "muduo/net/poller/EPollPoller.h" 12 | 13 | #include 14 | 15 | using namespace muduo::net; 16 | 17 | Poller* Poller::newDefaultPoller(EventLoop* loop) 18 | { 19 | if (::getenv("MUDUO_USE_POLL")) 20 | { 21 | return new PollPoller(loop); 22 | } 23 | else 24 | { 25 | return new EPollPoller(loop); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /muduo/net/poller/EPollPoller.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | // This is an internal header file, you should not include this. 10 | 11 | #ifndef MUDUO_NET_POLLER_EPOLLPOLLER_H 12 | #define MUDUO_NET_POLLER_EPOLLPOLLER_H 13 | 14 | #include "muduo/net/Poller.h" 15 | 16 | #include 17 | 18 | struct epoll_event; 19 | 20 | namespace muduo 21 | { 22 | namespace net 23 | { 24 | 25 | /// 26 | /// IO Multiplexing with epoll(4). 27 | /// 28 | class EPollPoller : public Poller 29 | { 30 | public: 31 | EPollPoller(EventLoop* loop); 32 | ~EPollPoller() override; 33 | 34 | Timestamp poll(int timeoutMs, ChannelList* activeChannels) override; 35 | void updateChannel(Channel* channel) override; 36 | void removeChannel(Channel* channel) override; 37 | 38 | private: 39 | static const int kInitEventListSize = 16; 40 | 41 | static const char* operationToString(int op); 42 | 43 | void fillActiveChannels(int numEvents, 44 | ChannelList* activeChannels) const; 45 | void update(int operation, Channel* channel); 46 | 47 | typedef std::vector EventList; 48 | 49 | int epollfd_; 50 | EventList events_; 51 | }; 52 | 53 | } // namespace net 54 | } // namespace muduo 55 | #endif // MUDUO_NET_POLLER_EPOLLPOLLER_H 56 | -------------------------------------------------------------------------------- /muduo/net/poller/PollPoller.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | // This is an internal header file, you should not include this. 10 | 11 | #ifndef MUDUO_NET_POLLER_POLLPOLLER_H 12 | #define MUDUO_NET_POLLER_POLLPOLLER_H 13 | 14 | #include "muduo/net/Poller.h" 15 | 16 | #include 17 | 18 | struct pollfd; 19 | 20 | namespace muduo 21 | { 22 | namespace net 23 | { 24 | 25 | /// 26 | /// IO Multiplexing with poll(2). 27 | /// 28 | class PollPoller : public Poller 29 | { 30 | public: 31 | 32 | PollPoller(EventLoop* loop); 33 | ~PollPoller() override; 34 | 35 | Timestamp poll(int timeoutMs, ChannelList* activeChannels) override; 36 | void updateChannel(Channel* channel) override; 37 | void removeChannel(Channel* channel) override; 38 | 39 | private: 40 | void fillActiveChannels(int numEvents, 41 | ChannelList* activeChannels) const; 42 | 43 | typedef std::vector PollFdList; 44 | PollFdList pollfds_; 45 | }; 46 | 47 | } // namespace net 48 | } // namespace muduo 49 | #endif // MUDUO_NET_POLLER_POLLPOLLER_H 50 | -------------------------------------------------------------------------------- /muduo/net/protobuf/BufferStream.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | // 8 | // This is a public header file, it must only include public header files. 9 | #pragma once 10 | #include "muduo/net/Buffer.h" 11 | #include 12 | namespace muduo 13 | { 14 | namespace net 15 | { 16 | 17 | // FIXME: 18 | // class BufferInputStream : google::protobuf::io::ZeroCopyInputStream 19 | // { 20 | // }; 21 | 22 | class BufferOutputStream : public google::protobuf::io::ZeroCopyOutputStream 23 | { 24 | public: 25 | BufferOutputStream(Buffer* buf) 26 | : buffer_(CHECK_NOTNULL(buf)), 27 | originalSize_(buffer_->readableBytes()) 28 | { 29 | } 30 | 31 | virtual bool Next(void** data, int* size) // override 32 | { 33 | buffer_->ensureWritableBytes(4096); 34 | *data = buffer_->beginWrite(); 35 | *size = static_cast(buffer_->writableBytes()); 36 | buffer_->hasWritten(*size); 37 | return true; 38 | } 39 | 40 | virtual void BackUp(int count) // override 41 | { 42 | buffer_->unwrite(count); 43 | } 44 | 45 | virtual int64_t ByteCount() const // override 46 | { 47 | return buffer_->readableBytes() - originalSize_; 48 | } 49 | 50 | private: 51 | Buffer* buffer_; 52 | size_t originalSize_; 53 | }; 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /muduo/net/protobuf/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(muduo_protobuf_codec ProtobufCodecLite.cc) 2 | set_target_properties(muduo_protobuf_codec PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 3 | target_link_libraries(muduo_protobuf_codec muduo_net protobuf z) 4 | 5 | #add_library(muduo_protobuf_codec_cpp11 ProtobufCodecLite.cc) 6 | #set_target_properties(muduo_protobuf_codec_cpp11 PROPERTIES COMPILE_FLAGS "-std=c++0x -Wno-error=shadow") 7 | #target_link_libraries(muduo_protobuf_codec_cpp11 muduo_net_cpp11 protobuf z) 8 | 9 | 10 | install(TARGETS muduo_protobuf_codec DESTINATION lib) 11 | #install(TARGETS muduo_protobuf_codec_cpp11 DESTINATION lib) 12 | 13 | file(GLOB HEADERS "*.h") 14 | install(FILES ${HEADERS} DESTINATION include/muduo/net/protobuf) 15 | 16 | -------------------------------------------------------------------------------- /muduo/net/protorpc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_custom_command(OUTPUT rpc.pb.cc rpc.pb.h 2 | COMMAND protoc 3 | ARGS --cpp_out . ${CMAKE_CURRENT_SOURCE_DIR}/rpc.proto -I${CMAKE_CURRENT_SOURCE_DIR} 4 | DEPENDS rpc.proto 5 | VERBATIM ) 6 | 7 | set_source_files_properties(rpc.pb.cc PROPERTIES COMPILE_FLAGS "-Wno-conversion") 8 | include_directories(${PROJECT_BINARY_DIR}) 9 | 10 | add_library(muduo_protorpc_wire rpc.pb.cc RpcCodec.cc) 11 | set_target_properties(muduo_protorpc_wire PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 12 | 13 | #add_library(muduo_protorpc_wire_cpp11 rpc.pb.cc RpcCodec.cc) 14 | #set_target_properties(muduo_protorpc_wire_cpp11 PROPERTIES COMPILE_FLAGS "-std=c++0x -Wno-error=shadow") 15 | 16 | if(MUDUO_BUILD_EXAMPLES) 17 | add_executable(protobuf_rpc_wire_test RpcCodec_test.cc) 18 | target_link_libraries(protobuf_rpc_wire_test muduo_protorpc_wire muduo_protobuf_codec) 19 | set_target_properties(protobuf_rpc_wire_test PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 20 | endif() 21 | 22 | add_library(muduo_protorpc RpcChannel.cc RpcServer.cc) 23 | set_target_properties(muduo_protorpc PROPERTIES COMPILE_FLAGS "-Wno-error=shadow") 24 | target_link_libraries(muduo_protorpc muduo_protorpc_wire muduo_protobuf_codec muduo_net protobuf z) 25 | 26 | if(TCMALLOC_LIBRARY) 27 | target_link_libraries(muduo_protorpc tcmalloc_and_profiler) 28 | endif() 29 | 30 | install(TARGETS muduo_protorpc_wire muduo_protorpc DESTINATION lib) 31 | #install(TARGETS muduo_protorpc_wire_cpp11 DESTINATION lib) 32 | 33 | set(HEADERS 34 | RpcCodec.h 35 | RpcChannel.h 36 | RpcServer.h 37 | rpc.proto 38 | rpcservice.proto 39 | ${PROJECT_BINARY_DIR}/muduo/net/protorpc/rpc.pb.h 40 | ) 41 | install(FILES ${HEADERS} DESTINATION include/muduo/net/protorpc) 42 | 43 | -------------------------------------------------------------------------------- /muduo/net/protorpc/README: -------------------------------------------------------------------------------- 1 | This is an proof of concept implementation of Google Protobuf RPC using muduo. 2 | The object lifetime management is for from ideal and doesn't follow the usual 3 | muduo approach. 4 | 5 | Please consider using http://github.com/chenshuo/muduo-protorpc instead. 6 | -------------------------------------------------------------------------------- /muduo/net/protorpc/RpcCodec.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | 9 | #include "muduo/net/protorpc/RpcCodec.h" 10 | 11 | #include "muduo/base/Logging.h" 12 | #include "muduo/net/Endian.h" 13 | #include "muduo/net/TcpConnection.h" 14 | 15 | #include "muduo/net/protorpc/rpc.pb.h" 16 | #include "muduo/net/protorpc/google-inl.h" 17 | 18 | using namespace muduo; 19 | using namespace muduo::net; 20 | 21 | namespace 22 | { 23 | int ProtobufVersionCheck() 24 | { 25 | GOOGLE_PROTOBUF_VERIFY_VERSION; 26 | return 0; 27 | } 28 | int dummy __attribute__ ((unused)) = ProtobufVersionCheck(); 29 | } 30 | 31 | namespace muduo 32 | { 33 | namespace net 34 | { 35 | const char rpctag [] = "RPC0"; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /muduo/net/protorpc/RpcCodec.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | // This is a public header file, it must only include public header files. 10 | 11 | #ifndef MUDUO_NET_PROTORPC_RPCCODEC_H 12 | #define MUDUO_NET_PROTORPC_RPCCODEC_H 13 | 14 | #include "muduo/base/Timestamp.h" 15 | #include "muduo/net/protobuf/ProtobufCodecLite.h" 16 | 17 | namespace muduo 18 | { 19 | namespace net 20 | { 21 | 22 | class Buffer; 23 | class TcpConnection; 24 | typedef std::shared_ptr TcpConnectionPtr; 25 | 26 | class RpcMessage; 27 | typedef std::shared_ptr RpcMessagePtr; 28 | extern const char rpctag[];// = "RPC0"; 29 | 30 | // wire format 31 | // 32 | // Field Length Content 33 | // 34 | // size 4-byte N+8 35 | // "RPC0" 4-byte 36 | // payload N-byte 37 | // checksum 4-byte adler32 of "RPC0"+payload 38 | // 39 | 40 | typedef ProtobufCodecLiteT RpcCodec; 41 | 42 | } // namespace net 43 | } // namespace muduo 44 | 45 | #endif // MUDUO_NET_PROTORPC_RPCCODEC_H 46 | -------------------------------------------------------------------------------- /muduo/net/protorpc/RpcServer.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | // This is a public header file, it must only include public header files. 10 | 11 | #ifndef MUDUO_NET_PROTORPC_RPCSERVER_H 12 | #define MUDUO_NET_PROTORPC_RPCSERVER_H 13 | 14 | #include "muduo/net/TcpServer.h" 15 | 16 | namespace google { 17 | namespace protobuf { 18 | 19 | class Service; 20 | 21 | } // namespace protobuf 22 | } // namespace google 23 | 24 | namespace muduo 25 | { 26 | namespace net 27 | { 28 | 29 | class RpcServer 30 | { 31 | public: 32 | RpcServer(EventLoop* loop, 33 | const InetAddress& listenAddr); 34 | 35 | void setThreadNum(int numThreads) 36 | { 37 | server_.setThreadNum(numThreads); 38 | } 39 | 40 | void registerService(::google::protobuf::Service*); 41 | void start(); 42 | 43 | private: 44 | void onConnection(const TcpConnectionPtr& conn); 45 | 46 | // void onMessage(const TcpConnectionPtr& conn, 47 | // Buffer* buf, 48 | // Timestamp time); 49 | 50 | TcpServer server_; 51 | std::map services_; 52 | }; 53 | 54 | } // namespace net 55 | } // namespace muduo 56 | 57 | #endif // MUDUO_NET_PROTORPC_RPCSERVER_H 58 | -------------------------------------------------------------------------------- /muduo/net/protorpc/rpc.proto: -------------------------------------------------------------------------------- 1 | package muduo.net; 2 | // option go_package = "muduorpc"; 3 | option java_package = "com.chenshuo.muduo.protorpc"; 4 | option java_outer_classname = "RpcProto"; 5 | 6 | enum MessageType 7 | { 8 | REQUEST = 1; 9 | RESPONSE = 2; 10 | ERROR = 3; // not used 11 | } 12 | 13 | enum ErrorCode 14 | { 15 | NO_ERROR = 0; 16 | WRONG_PROTO = 1; 17 | NO_SERVICE = 2; 18 | NO_METHOD = 3; 19 | INVALID_REQUEST = 4; 20 | INVALID_RESPONSE = 5; 21 | TIMEOUT = 6; 22 | } 23 | 24 | message RpcMessage 25 | { 26 | required MessageType type = 1; 27 | required fixed64 id = 2; 28 | 29 | optional string service = 3; 30 | optional string method = 4; 31 | optional bytes request = 5; 32 | 33 | optional bytes response = 6; 34 | 35 | optional ErrorCode error = 7; 36 | } 37 | -------------------------------------------------------------------------------- /muduo/net/protorpc/rpcservice.proto: -------------------------------------------------------------------------------- 1 | package muduo.net; 2 | 3 | option cc_generic_services = true; 4 | option java_generic_services = true; 5 | option py_generic_services = true; 6 | 7 | option java_package = "com.chenshuo.muduo.protorpc"; 8 | option java_outer_classname = "RpcServiceProto"; 9 | 10 | //import "google/protobuf/descriptor.proto"; 11 | import "rpc.proto"; 12 | 13 | message ListRpcRequest 14 | { 15 | optional string service_name = 1; 16 | optional bool list_method = 2; 17 | } 18 | 19 | message ListRpcResponse 20 | { 21 | required ErrorCode error = 1; 22 | repeated string service_name = 2; 23 | repeated string method_name = 3; 24 | } 25 | 26 | message GetServiceRequest 27 | { 28 | required string service_name = 1; 29 | } 30 | 31 | message GetServiceResponse 32 | { 33 | required ErrorCode error = 1; 34 | repeated string proto_file = 2; 35 | repeated string proto_file_name = 3; 36 | } 37 | 38 | // the meta service 39 | service RpcService 40 | { 41 | rpc listRpc (ListRpcRequest) returns (ListRpcResponse); 42 | rpc getService (GetServiceRequest) returns (GetServiceResponse); 43 | } 44 | 45 | -------------------------------------------------------------------------------- /muduo/net/tests/EventLoopThreadPool_unittest.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/net/EventLoopThreadPool.h" 2 | #include "muduo/net/EventLoop.h" 3 | #include "muduo/base/Thread.h" 4 | 5 | #include 6 | #include 7 | 8 | using namespace muduo; 9 | using namespace muduo::net; 10 | 11 | void print(EventLoop* p = NULL) 12 | { 13 | printf("main(): pid = %d, tid = %d, loop = %p\n", 14 | getpid(), CurrentThread::tid(), p); 15 | } 16 | 17 | void init(EventLoop* p) 18 | { 19 | printf("init(): pid = %d, tid = %d, loop = %p\n", 20 | getpid(), CurrentThread::tid(), p); 21 | } 22 | 23 | int main() 24 | { 25 | print(); 26 | 27 | EventLoop loop; 28 | loop.runAfter(11, std::bind(&EventLoop::quit, &loop)); 29 | 30 | { 31 | printf("Single thread %p:\n", &loop); 32 | EventLoopThreadPool model(&loop, "single"); 33 | model.setThreadNum(0); 34 | model.start(init); 35 | assert(model.getNextLoop() == &loop); 36 | assert(model.getNextLoop() == &loop); 37 | assert(model.getNextLoop() == &loop); 38 | } 39 | 40 | { 41 | printf("Another thread:\n"); 42 | EventLoopThreadPool model(&loop, "another"); 43 | model.setThreadNum(1); 44 | model.start(init); 45 | EventLoop* nextLoop = model.getNextLoop(); 46 | nextLoop->runAfter(2, std::bind(print, nextLoop)); 47 | assert(nextLoop != &loop); 48 | assert(nextLoop == model.getNextLoop()); 49 | assert(nextLoop == model.getNextLoop()); 50 | ::sleep(3); 51 | } 52 | 53 | { 54 | printf("Three threads:\n"); 55 | EventLoopThreadPool model(&loop, "three"); 56 | model.setThreadNum(3); 57 | model.start(init); 58 | EventLoop* nextLoop = model.getNextLoop(); 59 | nextLoop->runInLoop(std::bind(print, nextLoop)); 60 | assert(nextLoop != &loop); 61 | assert(nextLoop != model.getNextLoop()); 62 | assert(nextLoop != model.getNextLoop()); 63 | assert(nextLoop == model.getNextLoop()); 64 | } 65 | 66 | loop.loop(); 67 | } 68 | 69 | -------------------------------------------------------------------------------- /muduo/net/tests/EventLoopThread_unittest.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/net/EventLoopThread.h" 2 | #include "muduo/net/EventLoop.h" 3 | #include "muduo/base/Thread.h" 4 | #include "muduo/base/CountDownLatch.h" 5 | 6 | #include 7 | #include 8 | 9 | using namespace muduo; 10 | using namespace muduo::net; 11 | 12 | void print(EventLoop* p = NULL) 13 | { 14 | printf("print: pid = %d, tid = %d, loop = %p\n", 15 | getpid(), CurrentThread::tid(), p); 16 | } 17 | 18 | void quit(EventLoop* p) 19 | { 20 | print(p); 21 | p->quit(); 22 | } 23 | 24 | int main() 25 | { 26 | print(); 27 | 28 | { 29 | EventLoopThread thr1; // never start 30 | } 31 | 32 | { 33 | // dtor calls quit() 34 | EventLoopThread thr2; 35 | EventLoop* loop = thr2.startLoop(); 36 | loop->runInLoop(std::bind(print, loop)); 37 | CurrentThread::sleepUsec(500 * 1000); 38 | } 39 | 40 | { 41 | // quit() before dtor 42 | EventLoopThread thr3; 43 | EventLoop* loop = thr3.startLoop(); 44 | loop->runInLoop(std::bind(quit, loop)); 45 | CurrentThread::sleepUsec(500 * 1000); 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /muduo/net/tests/EventLoop_unittest.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/net/EventLoop.h" 2 | #include "muduo/base/Thread.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace muduo; 9 | using namespace muduo::net; 10 | 11 | EventLoop* g_loop; 12 | 13 | void callback() 14 | { 15 | printf("callback(): pid = %d, tid = %d\n", getpid(), CurrentThread::tid()); 16 | EventLoop anotherLoop; 17 | } 18 | 19 | void threadFunc() 20 | { 21 | printf("threadFunc(): pid = %d, tid = %d\n", getpid(), CurrentThread::tid()); 22 | 23 | assert(EventLoop::getEventLoopOfCurrentThread() == NULL); 24 | EventLoop loop; 25 | assert(EventLoop::getEventLoopOfCurrentThread() == &loop); 26 | loop.runAfter(1.0, callback); 27 | loop.loop(); 28 | } 29 | 30 | int main() 31 | { 32 | printf("main(): pid = %d, tid = %d\n", getpid(), CurrentThread::tid()); 33 | 34 | assert(EventLoop::getEventLoopOfCurrentThread() == NULL); 35 | EventLoop loop; 36 | assert(EventLoop::getEventLoopOfCurrentThread() == &loop); 37 | 38 | Thread thread(threadFunc); 39 | thread.start(); 40 | 41 | loop.loop(); 42 | } 43 | -------------------------------------------------------------------------------- /muduo/net/tests/TcpClient_reg1.cc: -------------------------------------------------------------------------------- 1 | // TcpClient::stop() called in the same iteration of IO event 2 | 3 | #include "muduo/base/Logging.h" 4 | #include "muduo/net/EventLoop.h" 5 | #include "muduo/net/TcpClient.h" 6 | 7 | using namespace muduo; 8 | using namespace muduo::net; 9 | 10 | TcpClient* g_client; 11 | 12 | void timeout() 13 | { 14 | LOG_INFO << "timeout"; 15 | g_client->stop(); 16 | } 17 | 18 | int main(int argc, char* argv[]) 19 | { 20 | EventLoop loop; 21 | InetAddress serverAddr("127.0.0.1", 2); // no such server 22 | TcpClient client(&loop, serverAddr, "TcpClient"); 23 | g_client = &client; 24 | loop.runAfter(0.0, timeout); 25 | loop.runAfter(1.0, std::bind(&EventLoop::quit, &loop)); 26 | client.connect(); 27 | CurrentThread::sleepUsec(100 * 1000); 28 | loop.loop(); 29 | } 30 | -------------------------------------------------------------------------------- /muduo/net/tests/TcpClient_reg2.cc: -------------------------------------------------------------------------------- 1 | // TcpClient destructs when TcpConnection is connected but unique. 2 | 3 | #include "muduo/base/Logging.h" 4 | #include "muduo/base/Thread.h" 5 | #include "muduo/net/EventLoop.h" 6 | #include "muduo/net/TcpClient.h" 7 | 8 | using namespace muduo; 9 | using namespace muduo::net; 10 | 11 | void threadFunc(EventLoop* loop) 12 | { 13 | InetAddress serverAddr("127.0.0.1", 1234); // should succeed 14 | TcpClient client(loop, serverAddr, "TcpClient"); 15 | client.connect(); 16 | 17 | CurrentThread::sleepUsec(1000*1000); 18 | // client destructs when connected. 19 | } 20 | 21 | int main(int argc, char* argv[]) 22 | { 23 | Logger::setLogLevel(Logger::DEBUG); 24 | 25 | EventLoop loop; 26 | loop.runAfter(3.0, std::bind(&EventLoop::quit, &loop)); 27 | Thread thr(std::bind(threadFunc, &loop)); 28 | thr.start(); 29 | loop.loop(); 30 | } 31 | -------------------------------------------------------------------------------- /muduo/net/tests/TcpClient_reg3.cc: -------------------------------------------------------------------------------- 1 | // TcpClient destructs in a different thread. 2 | 3 | #include "muduo/base/Logging.h" 4 | #include "muduo/net/EventLoopThread.h" 5 | #include "muduo/net/TcpClient.h" 6 | 7 | using namespace muduo; 8 | using namespace muduo::net; 9 | 10 | int main(int argc, char* argv[]) 11 | { 12 | Logger::setLogLevel(Logger::DEBUG); 13 | 14 | EventLoopThread loopThread; 15 | { 16 | InetAddress serverAddr("127.0.0.1", 1234); // should succeed 17 | TcpClient client(loopThread.startLoop(), serverAddr, "TcpClient"); 18 | client.connect(); 19 | CurrentThread::sleepUsec(500 * 1000); // wait for connect 20 | client.disconnect(); 21 | } 22 | 23 | CurrentThread::sleepUsec(1000 * 1000); 24 | } 25 | -------------------------------------------------------------------------------- /muduo/net/tests/TimerQueue_unittest.cc: -------------------------------------------------------------------------------- 1 | #include "muduo/net/EventLoop.h" 2 | #include "muduo/net/EventLoopThread.h" 3 | #include "muduo/base/Thread.h" 4 | 5 | #include 6 | #include 7 | 8 | using namespace muduo; 9 | using namespace muduo::net; 10 | 11 | int cnt = 0; 12 | EventLoop* g_loop; 13 | 14 | void printTid() 15 | { 16 | printf("pid = %d, tid = %d\n", getpid(), CurrentThread::tid()); 17 | printf("now %s\n", Timestamp::now().toString().c_str()); 18 | } 19 | 20 | void print(const char* msg) 21 | { 22 | printf("msg %s %s\n", Timestamp::now().toString().c_str(), msg); 23 | if (++cnt == 20) 24 | { 25 | g_loop->quit(); 26 | } 27 | } 28 | 29 | void cancel(TimerId timer) 30 | { 31 | g_loop->cancel(timer); 32 | printf("cancelled at %s\n", Timestamp::now().toString().c_str()); 33 | } 34 | 35 | int main() 36 | { 37 | printTid(); 38 | sleep(1); 39 | { 40 | EventLoop loop; 41 | g_loop = &loop; 42 | 43 | print("main"); 44 | loop.runAfter(1, std::bind(print, "once1")); 45 | loop.runAfter(1.5, std::bind(print, "once1.5")); 46 | loop.runAfter(2.5, std::bind(print, "once2.5")); 47 | loop.runAfter(3.5, std::bind(print, "once3.5")); 48 | TimerId t45 = loop.runAfter(4.5, std::bind(print, "once4.5")); 49 | loop.runAfter(4.2, std::bind(cancel, t45)); 50 | loop.runAfter(4.8, std::bind(cancel, t45)); 51 | loop.runEvery(2, std::bind(print, "every2")); 52 | TimerId t3 = loop.runEvery(3, std::bind(print, "every3")); 53 | loop.runAfter(9.001, std::bind(cancel, t3)); 54 | 55 | loop.loop(); 56 | print("main loop exits"); 57 | } 58 | sleep(1); 59 | { 60 | EventLoopThread loopThread; 61 | EventLoop* loop = loopThread.startLoop(); 62 | loop->runAfter(2, printTid); 63 | sleep(3); 64 | print("thread loop exits"); 65 | } 66 | } 67 | --------------------------------------------------------------------------------