Full Code of chenshuo/muduo for AI

master f1fc77e0c13b cached
418 files
964.8 KB
287.0k tokens
1371 symbols
1 requests
Download .txt
Showing preview only (1,060K chars total). Download the full file or copy to clipboard to get everything.
Repository: chenshuo/muduo
Branch: master
Commit: f1fc77e0c13b
Files: 418
Total size: 964.8 KB

Directory structure:
gitextract_80xohvuq/

├── .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

================================================
FILE CONTENTS
================================================

================================================
FILE: .clang-tidy
================================================
---
# Only run a few checks for now.
Checks:          'performance-*'
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle:     none
User:            chenshuo
CheckOptions:
  - key:             google-runtime-references.WhiteListTypes
    value:           'muduo::MutexLock'
  - key:             llvm-namespace-comment.ShortNamespaceLines
    value:           '10'
  - key:             llvm-namespace-comment.SpacesBeforeComments
    value:           '2'
  - key:   MuduoRootDirectory
    value: '/muduo-cpp11/'
ExtraArgs:
  - '-Wno-sign-conversion'
...



================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

DELETE FROM HERE TO LINE 18 BEFORE OPEN AN ISSUE.

GitHub issues are for tracking bugs, not for general discussing like a forum.

If you have a general question to ask, use GitHub discussions:

https://github.com/chenshuo/muduo/discussions

When filing an issue of muduo, please provide a [SSCCE](http://sscce.org):
Short, Self Contained, Correct (Compilable), Example.

If you can't compile muduo, make sure you install `cmake` and `boost` from the
official package repository, e.g. `apt` or `yum`, before opening a bug.
Don't open a bug if you installed boost from a third-party source or
downloaded it by yourself, and couldn't compile muduo, thank you.

Also specify the exact environment where the issue occurs:

## Linux distro and version? x86 or ARM? 32-bit or 64-bit?

## Branch (cpp98/cpp11/cpp17) and version of muduo?

## Version of cmake, gcc and boost? (If not from distro.)


================================================
FILE: .github/issue_template.md
================================================
DELETE FROM HERE TO LINE 18 BEFORE OPEN AN ISSUE.

GitHub issues are for tracking bugs, not for general discussing like a forum.

If you have a general question to ask, use GitHub discussions:

https://github.com/chenshuo/muduo/discussions

When filing an issue of muduo, please provide a [SSCCE](http://sscce.org):
Short, Self Contained, Correct (Compilable), Example.

If you can't compile muduo, make sure you install `cmake` and `boost` from the
official package repository, e.g. `apt` or `yum`, before opening a bug.
Don't open a bug if you installed boost from a third-party source or
downloaded it by yourself, and couldn't compile muduo, thank you.

Also specify the exact environment where the issue occurs:

## Linux distro and version? x86 or ARM? 32-bit or 64-bit?

## Branch (cpp98/cpp11/cpp17) and version of muduo?

## Version of cmake, gcc and boost? (If not from distro.)



================================================
FILE: .gitignore
================================================
*.swp
bazel-*
compile_commands.json


================================================
FILE: .travis.yml
================================================
language: cpp
sudo: required
compiler:
  - gcc
  - clang
os:
  - linux
install:
  - sudo apt-get install libboost-dev
  - sudo apt-get install libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev
  - sudo apt-get install libboost-test-dev libboost-program-options-dev libboost-system-dev
  - sudo apt-get install libc-ares-dev libcurl4-openssl-dev
  - sudo apt-get install zlib1g-dev libgd-dev
env:
  - BUILD_TYPE=debug
  - BUILD_TYPE=release
script:
  - ./build.sh


================================================
FILE: BUILD.bazel
================================================
# See https://github.com/chenshuo/muduo-tutorial for how to use muduo in your project.


================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 2.6)

project(muduo C CXX)

enable_testing()

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE "Release")
endif()

# only build examples if this is the main project
if(CMAKE_PROJECT_NAME STREQUAL "muduo")
  option(MUDUO_BUILD_EXAMPLES "Build Muduo examples" ON)
endif()

set(CXX_FLAGS
 -g
 # -DVALGRIND
 -DCHECK_PTHREAD_RETURN_VALUE
 -D_FILE_OFFSET_BITS=64
 -Wall
 -Wextra
 -Werror
 -Wconversion
 -Wno-unused-parameter
 -Wold-style-cast
 -Woverloaded-virtual
 -Wpointer-arith
 -Wshadow
 -Wwrite-strings
 -march=native
 # -MMD
 -std=c++11
 -rdynamic
 )
if(CMAKE_BUILD_BITS EQUAL 32)
  list(APPEND CXX_FLAGS "-m32")
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
  list(APPEND CXX_FLAGS "-Wno-null-dereference")
  list(APPEND CXX_FLAGS "-Wno-sign-conversion")
  list(APPEND CXX_FLAGS "-Wno-unused-local-typedef")
  list(APPEND CXX_FLAGS "-Wthread-safety")
  list(REMOVE_ITEM CXX_FLAGS "-rdynamic")
endif()
string(REPLACE ";" " " CMAKE_CXX_FLAGS "${CXX_FLAGS}")

set(CMAKE_CXX_FLAGS_DEBUG "-O0")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

find_package(Boost REQUIRED)
find_package(Protobuf)
find_package(CURL)
find_package(ZLIB)
find_path(CARES_INCLUDE_DIR ares.h)
find_library(CARES_LIBRARY NAMES cares)
find_path(MHD_INCLUDE_DIR microhttpd.h)
find_library(MHD_LIBRARY NAMES microhttpd)
find_library(BOOSTTEST_LIBRARY NAMES boost_unit_test_framework)
find_library(BOOSTPO_LIBRARY NAMES boost_program_options)
find_library(BOOSTSYSTEM_LIBRARY NAMES boost_system)
find_path(TCMALLOC_INCLUDE_DIR gperftools/heap-profiler.h)
find_library(TCMALLOC_LIBRARY NAMES tcmalloc_and_profiler)
find_path(HIREDIS_INCLUDE_DIR hiredis/hiredis.h)
find_library(HIREDIS_LIBRARY NAMES hiredis)
find_path(GD_INCLUDE_DIR gd.h)
find_library(GD_LIBRARY NAMES gd)
find_program(THRIFT_COMPILER thrift)
find_path(THRIFT_INCLUDE_DIR thrift)
find_library(THRIFT_LIBRARY NAMES thrift)

if(CARES_INCLUDE_DIR AND CARES_LIBRARY)
  message(STATUS "found cares")
endif()
if(CURL_FOUND)
  message(STATUS "found curl")
endif()
if(PROTOBUF_FOUND)
  message(STATUS "found protobuf")
endif()
if(TCMALLOC_INCLUDE_DIR AND TCMALLOC_LIBRARY)
  message(STATUS "found tcmalloc")
endif()
if(ZLIB_FOUND)
  message(STATUS "found zlib")
endif()
if(HIREDIS_INCLUDE_DIR AND HIREDIS_LIBRARY)
  message(STATUS "found hiredis")
endif()
if(GD_INCLUDE_DIR AND GD_LIBRARY)
  message(STATUS "found gd")
endif()
if(THRIFT_COMPILER AND THRIFT_INCLUDE_DIR AND THRIFT_LIBRARY)
  message(STATUS "found thrift")
endif()

include_directories(${Boost_INCLUDE_DIRS})

include_directories(${PROJECT_SOURCE_DIR})

string(TOUPPER ${CMAKE_BUILD_TYPE} BUILD_TYPE)
message(STATUS "CXX_FLAGS = " ${CMAKE_CXX_FLAGS} " " ${CMAKE_CXX_FLAGS_${BUILD_TYPE}})

add_subdirectory(muduo/base)
add_subdirectory(muduo/net)

if(MUDUO_BUILD_EXAMPLES)
  add_subdirectory(contrib)
  add_subdirectory(examples)
else()
  if(CARES_INCLUDE_DIR AND CARES_LIBRARY)
    add_subdirectory(examples/cdns)
  endif()
endif()



================================================
FILE: ChangeLog
================================================
2018-10-22   Shuo Chen  <chenshuo@chenshuo.com>
  * Last version in C++98/03, next version will use C++11
  * Enable Clang Thread Safety Analysis.
  * Fix "off_t does not name a type" for CentOS 7 (#316) by qiao hai-jun
  * Fix warnings for gcc 8.
  * Add ttcp asio examples
  * Implement Procmon::listFiles()

2018-01-18   Shuo Chen  <chenshuo@chenshuo.com>
  * Fix race condition between Thread::tid() and Thread::start().
  * Change protorpc format, add back package name. (Go does this since 1.2)
  * examples/socks4a/tunnel.h stops reading if output buffer is full.
  * Fixes for GCC 6/7
  * Minor fixes by huntinux, liangshaocong, zhoudayang2, octocat_lee,
  jack.xsuperman, ligewei, yqsy.
  * Version 1.1.0

2016-10-25   Shuo Chen  <chenshuo@chenshuo.com>
  * Add Travis CI
  * Add EvevtLoop::queueSize() by <zhuangshi23>
  * Implement TcpClient::retry() by fdxuwei
  * Change Condition::waitForSeconds() parameter type from int to double by ChaoShu
  * Minor fixes by JackDrogon, YuCong, zieckey, wuzhaogai
  * Version 1.0.9

2016-02-11   Shuo Chen  <chenshuo@chenshuo.com>
  * Preliminary support of IPv6.
  * Add stop/startRead in TcpConnection by <zhang.jako>
  * Version 1.0.8

2015-11-09   Shuo Chen  <chenshuo@chenshuo.com>
  * Add stats to Sudoku examples.
  * Add example of PeriodicTimer class.
  * Add thrift examples by <decimalbell>.
  * Move hiredis example by <decimalbell> to contrib/.
  * Move HTTP parseRequest to HttpContext class by <decimalbell>.
  * Other fixes from <harrywong>, <cfreestar>, <qlhuangrui>, <lidw1988>.
  * Version 1.0.7

2015-04-03   Shuo Chen  <chenshuo@chenshuo.com>
  * Fix ProcessInspector::threads().
  * Minor fixes and improvements from liyuan989 and zieckey.
  * More Sudoku examples.
  * Version 1.0.6

2015-01-30   Shuo Chen  <chenshuo@chenshuo.com>
  * Add examples/procmon
  * EventLoop supports set/get context by <zieckey>
  * Fix bug #107
  * Version 1.0.5

2014-10-05   Shuo Chen  <chenshuo@chenshuo.com>
  * Enrich interfaces of EventLoopThreadPool by <zieckey>
  * Buffer supports reading int64_t by <alisper>
  * Add hiredis example by <decimalbell>
  * Fix bug about TcpClient life time again.
  * Other minor fixes, including some from <huahang>
  * Version 1.0.4

2014-08-02   Shuo Chen  <chenshuo@chenshuo.com>
  * Singleton supports 'no_destroy'.
  * Get tcp_info in TcpConnection.
  * Add CurrentThread::tidStringLength().
  * Fix bug about TcpClient life time. More checks.
  * Version 1.0.3

2014-06-30   Shuo Chen  <chenshuo@chenshuo.com>
  * Fix boundary check in Buffer::findEOL() by <renxingsong>.
  * Fix typos in InetAddress.cc by <huangml.zh>.
  * Fix 32-bit integer overflow bug in time_client by <guochy2012>.
  * Update comments in Buffer::readFd() by <huahang>.
  * Add ThreadPool::setThreadInitCallback().
  * Rename GzipStream to ZlibStream.
  * Version 1.0.2

2014-04-10   Shuo Chen  <chenshuo@chenshuo.com>
  * More ProcessInfo functions.
  * Add GzipFile (in C++11 only) and GzipOutputStream.
  * Add SystemInspector.
  * muduo::Threads now sets thread name with prctl().
  * Version 1.0.1

2014-03-12   Shuo Chen  <chenshuo@chenshuo.com>
  * Add TCP and RPC balancer examples
  * Version 1.0.0

2014-03-05   Shuo Chen  <chenshuo@chenshuo.com>
  * Introduce class StringArg for passing C-style string arguments.
  * Support localtime in logging.
  * Version 1.0.0-rc2

2014-02-22   Shuo Chen  <chenshuo@chenshuo.com>
  * Default to release build.
  * Version 1.0.0-rc1

2014-02-22   Shuo Chen  <chenshuo@chenshuo.com>
  * Add base/WeakCallback.h
  * Add TcpConnection::forceCloseWithDelay().
  * Add InetAddress::resolve for sync DNS resolving.
  * Add simple Protobuf codec for single message type.
  * Add ACE ttcp and logging examples.
  * Fix race conditoin in RpcChannel::CallMethod().
  * Version 0.9.8

2014-01-11   Shuo Chen  <chenshuo@chenshuo.com>
  * Add TcpConnection::forceClose().
  * Add fastcgi nginx.conf example
  * Fix iterator invalidation in hub.cc.
  * Version 0.9.7

2013-10-21   Shuo Chen  <chenshuo@chenshuo.com>
  * Minor fixes.
  * Version 0.9.6

2013-08-31   Shuo Chen  <chenshuo@chenshuo.com>
  * Add C++11 rvalue overloads for boost::function parameters
  * Add PerformanceInspector, support remote profiling with gperftools
  * Add examples of memcached server and client
  * Version 0.9.5

2013-07-28   Shuo Chen  <chenshuo@chenshuo.com>
  * Protobuf RPC wire protocol changed,
    package name removed in 'service' field.
  * Add roundtrip_udp as a UDP example
  * More inspect
  * Fix Connector::stop()
  * Fix for protobuf 2.5.0
  * Version 0.9.4

2013-05-11   Shuo Chen  <chenshuo@chenshuo.com>
  * ThreadPool can be blocking
  * Support SO_REUSEPORT, added in kernel 3.9.0
  * Fix Mutex::isLockedByThisThread()
  * Version 0.9.3

2013-03-22   Shuo Chen  <chenshuo@chenshuo.com>
  * Fix bugs
  * Add Sudoku client
  * Version 0.9.2

2013-01-16   Shuo Chen  <chenshuo@chenshuo.com>
  * Fix bug introduced in dd26871
  * Version 0.9.1

2013-01-09   Shuo Chen  <chenshuo@chenshuo.com>
  * Add single thread concurrent download example in examples/curl.
  * Add distributed word counting example.
  * Add simple FastCGI example.
  * Fix HttpRequest for empty header value, contributed by SeasonLee
  * Fix Connector destruction
  * Version 0.9.0

2012-11-06   Shuo Chen  <chenshuo@chenshuo.com>
  * Version for the book
  * Fix Buffer::shrink()
  * Fix race condition of ThreadPool::stop()
  * Version 0.8.2

2012-09-30   Shuo Chen  <chenshuo@chenshuo.com>
  * Add Channel::remove()
  * Logger::SourceFile supports char*
  * Fix for g++ 4.7
  * Version 0.8.1

2012-09-06   Shuo Chen  <chenshuo@chenshuo.com>
  * More Buffer member functions, contributed by SeasonLee
  * Add unit tests for Buffer
  * Fix wait condition in AsyncLogging::threadFunc()
  * Rename fromHostPort to fromIpPort
  * Add hash_value for shared_ptr
  * Add TcpConnection::getMutableContext()
  * Remove unnecessary code, header
  * Add another example in idleconnection
  * Version 0.8.0

2012-06-26   Shuo Chen  <chenshuo@chenshuo.com>

  * Add TimeZone class and unit tests.
  * Inline Buffer::appendInt32() and Buffer::peekInt32().
  * Catch exception in Thread::runInThread().
    Rethrow in catch(...) to make pthread_cancel() working.
  * Avoid deleting incomplete types.
  * Replace delete with boost::ptr_vector
  * Destructs ThreadLocalSingleton
  * Replace __thread object with ThreadLocalSingleton in examples/asio/chat/
  * Fix compile with g++ 4.6
  * With armlinux.diff, muduo compiles on Raspberry Pi with g++ 4.5.
  * Version 0.7.0

2012-06-11   Shuo Chen  <chenshuo@chenshuo.com>

  * Put hostname as part of log file name.
  * Extract muduo/base/CurrentThread.h
  * Optimize logging for thread id and source filename.
  * Add BlockingQueue_bench, improve Thread_bench.
  * Add examples/zeromq, for round-trip latency tests.
  * Demonstrate HighWaterMark callback and weak callback in tcp tunnel.
  * Fix chat codec for invalid length.
  * Version 0.6.0

2012-06-03  Shuo Chen  <chenshuo@chenshuo.com>

  * Replace std::ostream with LogStream.
  * Add LogFile and AsyncLogging.
  * Set SO_KEEPALIVE by default.
  * Add HighWaterMark callback to TcpConnection.
  * Add EventLoop::getEventLoopOfCurrentThread(),
    Add ThreadInitCallback to EventLoopThreadPool.
  * Add asio_chat_server_threaded_highperformance
  * Version 0.5.0

2012-05-18  Shuo Chen  <chenshuo@chenshuo.com>

  * Add FileUtil.
  * Add new functions in ProcessInfo
  * Add example for curl.
  * Add add RPC meta service proto.
  * Add loadtest for asio chat.
  * Version 0.3.5

2012-03-22  Shuo Chen  <chenshuo@chenshuo.com>

  * Add example for async rpc (resolver).
  * Install muduo_cdns
  * Version 0.3.4

2012-03-16  Shuo Chen  <chenshuo@chenshuo.com>

  * Remove net/protorpc2
    moved to http://github.com/chenshuo/muduo-protorpc
  * Install EventLoopThreadPool.h, rpc.proto and rpc.pb.h
  * Version 0.3.3

2012-03-11  Shuo Chen  <chenshuo@chenshuo.com>

  * Add asynchronous DNS stub resolver based on c-ares.
    See also https://github.com/chenshuo/muduo-udns
  * Replace string with StringPiece for function parameters.
  * Change default log level from DEBUG to INFO,
    set MUDUO_LOG_DEBUG=1 to revert.
  * Install Channel.h
  * Version 0.3.2

2012-03-01  Shuo Chen  <chenshuo@chenshuo.com>

  * Support multi-threaded http server.
  * Do not install SocketsOps.h
  * Version 0.3.1

2012-02-24  Shuo Chen  <chenshuo@chenshuo.com>

  * Support Keep-Alive for HTTP/1.0.
  * Check return value of pthread_create.
  * Minor fixes (set TcpNoDelay, stop() in ThreadPool::dtor)
  * Version 0.3.0

2011-09-18  Shuo Chen  <chenshuo@chenshuo.com>

  * EventLoop now supports cancelling timer.
  * Add two examples of asio chat server, demo copy-on-write
  in multithreaded program.
  * Version 0.2.9

2011-09-04  Shuo Chen  <chenshuo@chenshuo.com>

  * Refactored RPC implementation of version 1 and 2,
  programming interface differ, interoperable.
  version 2 is incomplete yet.
  * Find protobuf with cmake find_package().
  * Version 0.2.8

2011-09-03  Shuo Chen  <chenshuo@chenshuo.com>

  * Add a proof of concept implementation of Protobuf RPC.
  * Version 0.2.7

2011-06-27  Shuo Chen  <chenshuo@chenshuo.com>

  * Fix decoding of Sudoku request.
  * Backport to older Linux.
  * Add BoundedBlockingQueue
  * Version 0.2.6

2011-06-15  Shuo Chen  <chenshuo@chenshuo.com>

  * Add examples/sudoku.
  * Add thread benchmark.
  * Version 0.2.5

2011-06-02  Shuo Chen  <chenshuo@chenshuo.com>

  * Add examples/shorturl.
  * Version 0.2.4

2011-05-24  Shuo Chen  <chenshuo@chenshuo.com>

  * Fix warnings on Arch Linux (GCC 4.6.0), thanks to ifreedom
  * Add CMake install instructions, thanks to ifreedom
  * Fix warnings on 32-bit Linux, thanks to highshow
  * Version 0.2.3

2011-05-15  Shuo Chen  <chenshuo@chenshuo.com>

  * Changes from reactor tutorial
  * Version 0.2.2

2011-05-07  Shuo Chen  <chenshuo@chenshuo.com>

  * Try making TcpClient destructable
  * Add demux in examples/multiplexer
  * Add examples/socks4a
  * Changes for reactor tutorial
  * Version 0.2.1

2011-04-27  Shuo Chen  <chenshuo@chenshuo.com>

  * Add kick idle connection example in examples/idleconnection.
  * Add test harness to examples/multiplexer
  * Replace std::list with std::set in TimerQueue.
  * Version 0.2.0

2011-04-11  Shuo Chen  <chenshuo@chenshuo.com>

  * Add Google Protobuf codec and dispatcher
  * Revert 'Add max connection limit to simple echo example.'
  * Add max connection limit example in examples/maxconnection.
  * Version 0.1.9

2011-03-27  Shuo Chen  <chenshuo@chenshuo.com>

  * Add file transfer download examples.
  * Add max connection limit to simple echo example.
  * Make inputBuffer accessible in TcpConnection.
  * Const-ness correct in Buffer class.
  * Add Mutex test for benchmarking.
  * Replace anonymous namespace with muduo::detail in muduo/base.
  * Version 0.1.8

2011-02-03  Shuo Chen  <chenshuo@chenshuo.com>

  * Fix LengthHeaderCodec::onMessage() in examples/asio/chat.
  * Version 0.1.7

2011-02-01  Shuo Chen  <chenshuo@chenshuo.com>

  * Fix onConnection() in simple examples.
  * Reset t_cachedTid after fork().
  * Version 0.1.6

2010-12-15  Shuo Chen  <chenshuo@chenshuo.com>

  * Add examples/multiplexer
  * Fix epoll kNoneEvent
  * Version 0.1.5

2010-11-20  Shuo Chen  <chenshuo@chenshuo.com>

  * Fix retry logic
  * Version 0.1.4

2010-09-26  Shuo Chen  <chenshuo@chenshuo.com>

  * Check SO_ERROR when connection is made.

2010-09-11  Shuo Chen  <chenshuo@chenshuo.com>

  * Gracefully refuse clients when accept(2) returns EMFILE.
  * Version 0.1.3

2010-09-07  Shuo Chen  <chenshuo@chenshuo.com>

  * Libevent benchmark for event handling.
  * Version 0.1.2

2010-09-04  Shuo Chen  <chenshuo@chenshuo.com>

  * Ping-pong benchmark, version 0.1.1

2010-08-30  Shuo Chen  <chenshuo@chenshuo.com>

  * First pre-alpha release, version 0.1.0

2010-08-29  Shuo Chen  <chenshuo@chenshuo.com>

  * Sub works.

2010-08-28  Shuo Chen  <chenshuo@chenshuo.com>

  * Add twisted finger examples.

2010-08-27  Shuo Chen  <chenshuo@chenshuo.com>

  * Add simple chargen example.

2010-08-07  Shuo Chen  <chenshuo@chenshuo.com>

  * Add Date.

2010-05-15  Shuo Chen  <chenshuo@chenshuo.com>

  * Hub works.

2010-05-14  Shuo Chen  <chenshuo@chenshuo.com>

  * Inspects opened files and threads.

2010-05-11  Shuo Chen  <chenshuo@chenshuo.com>

  * Add inspector for process info.

2010-05-04  Shuo Chen  <chenshuo@chenshuo.com>

  * Add simple http server and client.

2010-04-25  Shuo Chen  <chenshuo@chenshuo.com>

  * Add examples.

2010-04-11  Shuo Chen  <chenshuo@chenshuo.com>

  * TcpClient works.

2010-04-03  Shuo Chen  <chenshuo@chenshuo.com>

  * TcpServer works.

2010-03-15  Shuo Chen  <chenshuo@chenshuo.com>

  * TcpConnection at server side works.

2010-03-14  Shuo Chen  <chenshuo@chenshuo.com>

  * Acceptor works.

2010-03-13  Shuo Chen  <chenshuo@chenshuo.com>

  * TimerQueue works.

2010-03-12  Shuo Chen  <chenshuo@chenshuo.com>

  * Starts working on Muduo.


================================================
FILE: ChangeLog2
================================================
2018-10-24   Shuo Chen  <chenshuo@chenshuo.com>
  * First release of C++11 version of muduo.
  * Forked after v1.0.9, e6c04c43 is the base. changes in cpp98 branch are integrated
  * Replace boost::shared_ptr/boost::weak_ptr with std::shared_ptr/std::weak_ptr.
  * Replace boost::function/boost::bind with std::function/std::bind/lambda.
  * Replace boost::ptr_vector<T> with std::vector<std::unique_ptr<T>>.
  * Replace boost::noncopyable with muduo::noncopyable.
  * Replace boost::scoped_ptr with std::unique_ptr.
  * Replace BOOST_STATIC_ASSERT with static_assert.
  * Replace boost type_traits with std type_traits.
  * Version 2.0.0



================================================
FILE: License
================================================
// Muduo - A reactor-based C++ network library for Linux
// Copyright (c) 2010, Shuo Chen.  All rights reserved.
// http://code.google.com/p/muduo/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//   * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//   * Neither the name of Shuo Chen nor the names of other contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.



================================================
FILE: README
================================================
Muduo is a multithreaded C++ network library based on
the reactor pattern.

http://github.com/chenshuo/muduo

Copyright (c) 2010, Shuo Chen.  All rights reserved.

Use of this source code is governed by a BSD-style
license that can be found in the License file.

Requires:
  Linux kernel version >= 2.6.28.
  GCC >= 4.7 or Clang >= 3.5
  Boost (for boost::any only.)

Tested on:
  Debian 7 and above
  Unbuntu 14.04 and above
  CentOS 7 and above

Install required packages:
  # Debian, Ubuntu, etc.
  $ sudo apt install g++ cmake make libboost-dev
  # CentOS
  $ sudo yum install gcc-c++ cmake make boost-devel

See .travis.yml for additional packages for building more examples.

To build, run:
  ./build.sh

See https://github.com/chenshuo/muduo-tutorial for
how to use muduo in your project.
  __  __           _
 |  \/  |         | |
 | \  / |_   _  __| |_   _  ___
 | |\/| | | | |/ _` | | | |/ _ \
 | |  | | |_| | (_| | |_| | (_) |
 |_|  |_|\__,_|\__,_|\__,_|\___/



================================================
FILE: WORKSPACE
================================================


================================================
FILE: build.sh
================================================
#!/bin/sh

set -x

SOURCE_DIR=`pwd`
BUILD_DIR=${BUILD_DIR:-../build}
BUILD_TYPE=${BUILD_TYPE:-release}
INSTALL_DIR=${INSTALL_DIR:-../${BUILD_TYPE}-install-cpp11}
CXX=${CXX:-g++}

ln -sf $BUILD_DIR/$BUILD_TYPE-cpp11/compile_commands.json

mkdir -p $BUILD_DIR/$BUILD_TYPE-cpp11 \
  && cd $BUILD_DIR/$BUILD_TYPE-cpp11 \
  && cmake \
           -DCMAKE_BUILD_TYPE=$BUILD_TYPE \
           -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR \
           -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
           $SOURCE_DIR \
  && make $*

# Use the following command to run all the unit tests
# at the dir $BUILD_DIR/$BUILD_TYPE :
# CTEST_OUTPUT_ON_FAILURE=TRUE make test

# cd $SOURCE_DIR && doxygen



================================================
FILE: contrib/CMakeLists.txt
================================================
if(HIREDIS_INCLUDE_DIR AND HIREDIS_LIBRARY)
  add_subdirectory(hiredis)
else()
  add_subdirectory(hiredis EXCLUDE_FROM_ALL)
endif()

if(THRIFT_COMPILER AND THRIFT_INCLUDE_DIR AND THRIFT_LIBRARY)
  add_subdirectory(thrift)
else()
  add_subdirectory(thrift EXCLUDE_FROM_ALL)
endif()


================================================
FILE: contrib/hiredis/CMakeLists.txt
================================================
add_executable(mrediscli Hiredis.cc mrediscli.cc)
target_link_libraries(mrediscli muduo_net hiredis)


================================================
FILE: contrib/hiredis/Hiredis.cc
================================================
#include "contrib/hiredis/Hiredis.h"

#include "muduo/base/Logging.h"
#include "muduo/net/Channel.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/SocketsOps.h"

#include <hiredis/async.h>

using namespace muduo;
using namespace muduo::net;
using namespace hiredis;

static void dummy(const std::shared_ptr<Channel>&)
{
}

Hiredis::Hiredis(EventLoop* loop, const InetAddress& serverAddr)
  : loop_(loop),
    serverAddr_(serverAddr),
    context_(NULL)
{
}

Hiredis::~Hiredis()
{
  LOG_DEBUG << this;
  assert(!channel_ || channel_->isNoneEvent());
  ::redisAsyncFree(context_);
}

bool Hiredis::connected() const
{
  return channel_ && context_ && (context_->c.flags & REDIS_CONNECTED);
}

const char* Hiredis::errstr() const
{
  assert(context_ != NULL);
  return context_->errstr;
}

void Hiredis::connect()
{
  assert(!context_);

  context_ = ::redisAsyncConnect(serverAddr_.toIp().c_str(), serverAddr_.port());

  context_->ev.addRead = addRead;
  context_->ev.delRead = delRead;
  context_->ev.addWrite = addWrite;
  context_->ev.delWrite = delWrite;
  context_->ev.cleanup = cleanup;
  context_->ev.data = this;

  setChannel();

  assert(context_->onConnect == NULL);
  assert(context_->onDisconnect == NULL);
  ::redisAsyncSetConnectCallback(context_, connectCallback);
  ::redisAsyncSetDisconnectCallback(context_, disconnectCallback);
}

void Hiredis::disconnect()
{
  if (connected())
  {
    LOG_DEBUG << this;
    ::redisAsyncDisconnect(context_);
  }
}

int Hiredis::fd() const
{
  assert(context_);
  return context_->c.fd;
}

void Hiredis::setChannel()
{
  LOG_DEBUG << this;
  assert(!channel_);
  channel_.reset(new Channel(loop_, fd()));
  channel_->setReadCallback(std::bind(&Hiredis::handleRead, this, _1));
  channel_->setWriteCallback(std::bind(&Hiredis::handleWrite, this));
}

void Hiredis::removeChannel()
{
  LOG_DEBUG << this;
  channel_->disableAll();
  channel_->remove();
  loop_->queueInLoop(std::bind(dummy, channel_));
  channel_.reset();
}

void Hiredis::handleRead(muduo::Timestamp receiveTime)
{
  LOG_TRACE << "receiveTime = " << receiveTime.toString();
  ::redisAsyncHandleRead(context_);
}

void Hiredis::handleWrite()
{
  if (!(context_->c.flags & REDIS_CONNECTED))
  {
    removeChannel();
  }
  ::redisAsyncHandleWrite(context_);
}

/* static */ Hiredis* Hiredis::getHiredis(const redisAsyncContext* ac)
{
  Hiredis* hiredis = static_cast<Hiredis*>(ac->ev.data);
  assert(hiredis->context_ == ac);
  return hiredis;
}

void Hiredis::logConnection(bool up) const
{
  InetAddress localAddr(sockets::getLocalAddr(fd()));
  InetAddress peerAddr(sockets::getPeerAddr(fd()));

  LOG_INFO << localAddr.toIpPort() << " -> "
           << peerAddr.toIpPort() << " is "
           << (up ? "UP" : "DOWN");
}

/* static */ void Hiredis::connectCallback(const redisAsyncContext* ac, int status)
{
  LOG_TRACE;
  getHiredis(ac)->connectCallback(status);
}

void Hiredis::connectCallback(int status)
{
  if (status != REDIS_OK)
  {
    LOG_ERROR << context_->errstr << " failed to connect to " << serverAddr_.toIpPort();
  }
  else
  {
    logConnection(true);
    setChannel();
  }

  if (connectCb_)
  {
    connectCb_(this, status);
  }
}

/* static */ void Hiredis::disconnectCallback(const redisAsyncContext* ac, int status)
{
  LOG_TRACE;
  getHiredis(ac)->disconnectCallback(status);
}

void Hiredis::disconnectCallback(int status)
{
  logConnection(false);
  removeChannel();

  if (disconnectCb_)
  {
    disconnectCb_(this, status);
  }
}

void Hiredis::addRead(void* privdata)
{
  LOG_TRACE;
  Hiredis* hiredis = static_cast<Hiredis*>(privdata);
  hiredis->channel_->enableReading();
}

void Hiredis::delRead(void* privdata)
{
  LOG_TRACE;
  Hiredis* hiredis = static_cast<Hiredis*>(privdata);
  hiredis->channel_->disableReading();
}

void Hiredis::addWrite(void* privdata)
{
  LOG_TRACE;
  Hiredis* hiredis = static_cast<Hiredis*>(privdata);
  hiredis->channel_->enableWriting();
}

void Hiredis::delWrite(void* privdata)
{
  LOG_TRACE;
  Hiredis* hiredis = static_cast<Hiredis*>(privdata);
  hiredis->channel_->disableWriting();
}

void Hiredis::cleanup(void* privdata)
{
  Hiredis* hiredis = static_cast<Hiredis*>(privdata);
  LOG_DEBUG << hiredis;
}

int Hiredis::command(const CommandCallback& cb, muduo::StringArg cmd, ...)
{
  if (!connected()) return REDIS_ERR;

  LOG_TRACE;
  CommandCallback* p = new CommandCallback(cb);
  va_list args;
  va_start(args, cmd);
  int ret = ::redisvAsyncCommand(context_, commandCallback, p, cmd.c_str(), args);
  va_end(args);
  return ret;
}

/* static */ void Hiredis::commandCallback(redisAsyncContext* ac, void* r, void* privdata)
{
  redisReply* reply = static_cast<redisReply*>(r);
  CommandCallback* cb = static_cast<CommandCallback*>(privdata);
  getHiredis(ac)->commandCallback(reply, cb);
}

void Hiredis::commandCallback(redisReply* reply, CommandCallback* cb)
{
  (*cb)(this, reply);
  delete cb;
}

int Hiredis::ping()
{
  return command(std::bind(&Hiredis::pingCallback, this, _1, _2), "PING");
}

void Hiredis::pingCallback(Hiredis* me, redisReply* reply)
{
  assert(this == me);
  LOG_DEBUG << reply->str;
}


================================================
FILE: contrib/hiredis/Hiredis.h
================================================
#ifndef MUDUO_CONTRIB_HIREDIS_HIREDIS_H
#define MUDUO_CONTRIB_HIREDIS_HIREDIS_H

#include "muduo/base/noncopyable.h"
#include "muduo/base/StringPiece.h"
#include "muduo/base/Types.h"
#include "muduo/net/Callbacks.h"
#include "muduo/net/InetAddress.h"

#include <hiredis/hiredis.h>

struct redisAsyncContext;

namespace muduo
{
namespace net
{
class Channel;
class EventLoop;
}
}

namespace hiredis
{

class Hiredis : public std::enable_shared_from_this<Hiredis>,
                muduo::noncopyable
{
 public:
  typedef std::function<void(Hiredis*, int)> ConnectCallback;
  typedef std::function<void(Hiredis*, int)> DisconnectCallback;
  typedef std::function<void(Hiredis*, redisReply*)> CommandCallback;

  Hiredis(muduo::net::EventLoop* loop, const muduo::net::InetAddress& serverAddr);
  ~Hiredis();

  const muduo::net::InetAddress& serverAddress() const { return serverAddr_; }
  // redisAsyncContext* context() { return context_; }
  bool connected() const;
  const char* errstr() const;

  void setConnectCallback(const ConnectCallback& cb) { connectCb_ = cb; }
  void setDisconnectCallback(const DisconnectCallback& cb) { disconnectCb_ = cb; }

  void connect();
  void disconnect();  // FIXME: implement this with redisAsyncDisconnect

  int command(const CommandCallback& cb, muduo::StringArg cmd, ...);

  int ping();

 private:
  void handleRead(muduo::Timestamp receiveTime);
  void handleWrite();

  int fd() const;
  void logConnection(bool up) const;
  void setChannel();
  void removeChannel();

  void connectCallback(int status);
  void disconnectCallback(int status);
  void commandCallback(redisReply* reply, CommandCallback* privdata);

  static Hiredis* getHiredis(const redisAsyncContext* ac);

  static void connectCallback(const redisAsyncContext* ac, int status);
  static void disconnectCallback(const redisAsyncContext* ac, int status);
  // command callback
  static void commandCallback(redisAsyncContext* ac, void*, void*);

  static void addRead(void* privdata);
  static void delRead(void* privdata);
  static void addWrite(void* privdata);
  static void delWrite(void* privdata);
  static void cleanup(void* privdata);

  void pingCallback(Hiredis* me, redisReply* reply);

 private:
  muduo::net::EventLoop* loop_;
  const muduo::net::InetAddress serverAddr_;
  redisAsyncContext* context_;
  std::shared_ptr<muduo::net::Channel> channel_;
  ConnectCallback connectCb_;
  DisconnectCallback disconnectCb_;
};

}  // namespace hiredis

#endif  // MUDUO_CONTRIB_HIREDIS_HIREDIS_H


================================================
FILE: contrib/hiredis/README.md
================================================
# Hiredis

The version of hiredis must be 0.11.0 or greater

See also issue [#92](https://github.com/chenshuo/muduo/issues/92)


================================================
FILE: contrib/hiredis/mrediscli.cc
================================================
#include "contrib/hiredis/Hiredis.h"

#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"

#include <string>

using namespace muduo;
using namespace muduo::net;

string toString(long long value)
{
  char buf[32];
  snprintf(buf, sizeof buf, "%lld", value);
  return buf;
}

string redisReplyToString(const redisReply* reply)
{
  static const char* const types[] = { "",
      "REDIS_REPLY_STRING", "REDIS_REPLY_ARRAY",
      "REDIS_REPLY_INTEGER", "REDIS_REPLY_NIL",
      "REDIS_REPLY_STATUS", "REDIS_REPLY_ERROR" };
  string str;
  if (!reply) return str;

  str += types[reply->type] + string("(") + toString(reply->type) + ") ";

  str += "{ ";
  if (reply->type == REDIS_REPLY_STRING ||
      reply->type == REDIS_REPLY_STATUS ||
      reply->type == REDIS_REPLY_ERROR)
  {
    str += '"' + string(reply->str, reply->len) + '"';
  }
  else if (reply->type == REDIS_REPLY_INTEGER)
  {
    str += toString(reply->integer);
  }
  else if (reply->type == REDIS_REPLY_ARRAY)
  {
    str += toString(reply->elements) + " ";
    for (size_t i = 0; i < reply->elements; i++)
    {
      str += " " + redisReplyToString(reply->element[i]);
    }
  }
  str += " }";

  return str;
}

void connectCallback(hiredis::Hiredis* c, int status)
{
  if (status != REDIS_OK)
  {
    LOG_ERROR << "connectCallback Error:" << c->errstr();
  }
  else
  {
    LOG_INFO << "Connected...";
  }
}

void disconnectCallback(hiredis::Hiredis* c, int status)
{
  if (status != REDIS_OK)
  {
    LOG_ERROR << "disconnectCallback Error:" << c->errstr();
  }
  else
  {
    LOG_INFO << "Disconnected...";
  }
}

void timeCallback(hiredis::Hiredis* c, redisReply* reply)
{
  LOG_INFO << "time " << redisReplyToString(reply);
}

void echoCallback(hiredis::Hiredis* c, redisReply* reply, string* echo)
{
  LOG_INFO << *echo << " " << redisReplyToString(reply);
  c->disconnect();
}

void dbsizeCallback(hiredis::Hiredis* c, redisReply* reply)
{
  LOG_INFO << "dbsize " << redisReplyToString(reply);
}

void selectCallback(hiredis::Hiredis* c, redisReply* reply, uint16_t* index)
{
  LOG_INFO << "select " << *index << " " << redisReplyToString(reply);
}

void authCallback(hiredis::Hiredis* c, redisReply* reply, string* password)
{
  LOG_INFO << "auth " << *password << " " << redisReplyToString(reply);
}

void echo(hiredis::Hiredis* c, string* s)
{
  c->command(std::bind(echoCallback, _1, _2, s), "echo %s", s->c_str());
}

int main(int argc, char** argv)
{
  Logger::setLogLevel(Logger::DEBUG);

  EventLoop loop;

  InetAddress serverAddr("127.0.0.1", 6379);
  hiredis::Hiredis hiredis(&loop, serverAddr);

  hiredis.setConnectCallback(connectCallback);
  hiredis.setDisconnectCallback(disconnectCallback);
  hiredis.connect();

  //hiredis.ping();
  loop.runEvery(1.0, std::bind(&hiredis::Hiredis::ping, &hiredis));

  hiredis.command(timeCallback, "time");

  string hi = "hi";
  hiredis.command(std::bind(echoCallback, _1, _2, &hi), "echo %s", hi.c_str());
  loop.runEvery(2.0, std::bind(echo, &hiredis, &hi));

  hiredis.command(dbsizeCallback, "dbsize");

  uint16_t index = 8;
  hiredis.command(std::bind(selectCallback, _1, _2, &index), "select %d", index);

  string password = "password";
  hiredis.command(std::bind(authCallback, _1, _2, &password), "auth %s", password.c_str());

  loop.loop();

  return 0;
}


================================================
FILE: contrib/thrift/CMakeLists.txt
================================================
set(MUDUO_THRIFT_SRCS
    ThriftConnection.cc
    ThriftServer.cc
    )
add_library(muduo_thrift ${MUDUO_THRIFT_SRCS})
target_link_libraries(muduo_thrift muduo_net thrift)

if(THRIFT_COMPILER AND THRIFT_INCLUDE_DIR AND THRIFT_LIBRARY)
  include_directories(${CMAKE_CURRENT_SOURCE_DIR})
  add_subdirectory(tests)
endif()


================================================
FILE: contrib/thrift/ThriftConnection.cc
================================================
#include "contrib/thrift/ThriftConnection.h"

#include <functional>

#include "muduo/base/Logging.h"

#include <thrift/transport/TTransportException.h>

#include "contrib/thrift/ThriftServer.h"

using muduo::Timestamp;
using muduo::net::Buffer;
using muduo::net::TcpConnectionPtr;
using muduo::_1;
using muduo::_2;
using muduo::_3;

ThriftConnection::ThriftConnection(ThriftServer* server,
                                  const TcpConnectionPtr& conn)
  : server_(server),
    conn_(conn),
    state_(kExpectFrameSize),
    frameSize_(0)
{
  conn_->setMessageCallback(std::bind(&ThriftConnection::onMessage,
                                        this, _1, _2, _3));
  nullTransport_.reset(new TNullTransport());
  inputTransport_.reset(new TMemoryBuffer(NULL, 0));
  outputTransport_.reset(new TMemoryBuffer());

  factoryInputTransport_ = server_->getInputTransportFactory()->getTransport(inputTransport_);
  factoryOutputTransport_ = server_->getOutputTransportFactory()->getTransport(outputTransport_);

  inputProtocol_ = server_->getInputProtocolFactory()->getProtocol(factoryInputTransport_);
  outputProtocol_ = server_->getOutputProtocolFactory()->getProtocol(factoryOutputTransport_);

  processor_ = server_->getProcessor(inputProtocol_, outputProtocol_, nullTransport_);
}

void ThriftConnection::onMessage(const TcpConnectionPtr& conn,
                                 Buffer* buffer,
                                 Timestamp receiveTime)
{
  bool more = true;
  while (more)
  {
    if (state_ == kExpectFrameSize)
    {
      if (buffer->readableBytes() >= 4)
      {
        frameSize_ = static_cast<uint32_t>(buffer->readInt32());
        state_ = kExpectFrame;
      }
      else
      {
        more = false;
      }
    }
    else if (state_ == kExpectFrame)
    {
      if (buffer->readableBytes() >= frameSize_)
      {
        uint8_t* buf = reinterpret_cast<uint8_t*>((const_cast<char*>(buffer->peek())));

        inputTransport_->resetBuffer(buf, frameSize_, TMemoryBuffer::COPY);
        outputTransport_->resetBuffer();
        outputTransport_->getWritePtr(4);
        outputTransport_->wroteBytes(4);

        if (server_->isWorkerThreadPoolProcessing())
        {
          server_->workerThreadPool().run(std::bind(&ThriftConnection::process, this));
        }
        else
        {
          process();
        }

        buffer->retrieve(frameSize_);
        state_ = kExpectFrameSize;
      }
      else
      {
        more = false;
      }
    }
  }
}

void ThriftConnection::process()
{
  try
  {
    processor_->process(inputProtocol_, outputProtocol_, NULL);

    uint8_t* buf;
    uint32_t size;
    outputTransport_->getBuffer(&buf, &size);

    assert(size >= 4);
    uint32_t frameSize = static_cast<uint32_t>(htonl(size - 4));
    memcpy(buf, &frameSize, 4);

    conn_->send(buf, size);
  } catch (const TTransportException& ex)
  {
    LOG_ERROR << "ThriftServer TTransportException: " << ex.what();
    close();
  } catch (const std::exception& ex)
  {
    LOG_ERROR << "ThriftServer std::exception: " << ex.what();
    close();
  } catch (...)
  {
    LOG_ERROR << "ThriftServer unknown exception";
    close();
  }
}

void ThriftConnection::close()
{
  nullTransport_->close();
  factoryInputTransport_->close();
  factoryOutputTransport_->close();
}


================================================
FILE: contrib/thrift/ThriftConnection.h
================================================
#ifndef MUDUO_CONTRIB_THRIFT_THRIFTCONNECTION_H
#define MUDUO_CONTRIB_THRIFT_THRIFTCONNECTION_H

#include <boost/enable_shared_from_this.hpp>
#include <boost/noncopyable.hpp>

#include "muduo/net/TcpConnection.h"

#include <thrift/protocol/TProtocol.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/transport/TTransportUtils.h>

using apache::thrift::TProcessor;
using apache::thrift::protocol::TProtocol;
using apache::thrift::transport::TMemoryBuffer;
using apache::thrift::transport::TNullTransport;
using apache::thrift::transport::TTransport;
using apache::thrift::transport::TTransportException;

class ThriftServer;

class ThriftConnection : boost::noncopyable,
                         public boost::enable_shared_from_this<ThriftConnection>
{
 public:
  enum State
  {
    kExpectFrameSize,
    kExpectFrame
  };

  ThriftConnection(ThriftServer* server, const muduo::net::TcpConnectionPtr& conn);

 private:
  void onMessage(const muduo::net::TcpConnectionPtr& conn,
                 muduo::net::Buffer* buffer,
                 muduo::Timestamp receiveTime);

  void process();

  void close();

 private:
  ThriftServer* server_;
  muduo::net::TcpConnectionPtr conn_;

  boost::shared_ptr<TNullTransport> nullTransport_;

  boost::shared_ptr<TMemoryBuffer> inputTransport_;
  boost::shared_ptr<TMemoryBuffer> outputTransport_;

  boost::shared_ptr<TTransport> factoryInputTransport_;
  boost::shared_ptr<TTransport> factoryOutputTransport_;

  boost::shared_ptr<TProtocol> inputProtocol_;
  boost::shared_ptr<TProtocol> outputProtocol_;

  boost::shared_ptr<TProcessor> processor_;

  enum State state_;
  uint32_t frameSize_;
};

typedef boost::shared_ptr<ThriftConnection> ThriftConnectionPtr;

#endif  // MUDUO_CONTRIB_THRIFT_THRIFTCONNECTION_H


================================================
FILE: contrib/thrift/ThriftServer.cc
================================================
#include "contrib/thrift/ThriftServer.h"

#include <functional>

#include "muduo/net/EventLoop.h"

using muduo::MutexLockGuard;
using muduo::Timestamp;
using muduo::net::EventLoop;
using muduo::net::TcpConnectionPtr;

ThriftServer::~ThriftServer() = default;

void ThriftServer::serve()
{
  start();
}

void ThriftServer::start()
{
  if (numWorkerThreads_ > 0)
  {
    workerThreadPool_.start(numWorkerThreads_);
  }
  server_.start();
}

void ThriftServer::stop()
{
  if (numWorkerThreads_ > 0)
  {
    workerThreadPool_.stop();
  }
  server_.getLoop()->runAfter(3.0, std::bind(&EventLoop::quit,
                                               server_.getLoop()));
}

void ThriftServer::onConnection(const TcpConnectionPtr& conn)
{
  if (conn->connected())
  {
    ThriftConnectionPtr ptr(new ThriftConnection(this, conn));
    MutexLockGuard lock(mutex_);
    assert(conns_.find(conn->name()) == conns_.end());
    conns_[conn->name()] = ptr;
  }
  else
  {
    MutexLockGuard lock(mutex_);
    assert(conns_.find(conn->name()) != conns_.end());
    conns_.erase(conn->name());
  }
}


================================================
FILE: contrib/thrift/ThriftServer.h
================================================
#ifndef MUDUO_CONTRIB_THRIFT_THRIFTSERVER_H
#define MUDUO_CONTRIB_THRIFT_THRIFTSERVER_H

#include <functional>
#include <map>

#include <boost/noncopyable.hpp>

#include "muduo/base/ThreadPool.h"
#include "muduo/net/TcpServer.h"

#include <thrift/server/TServer.h>

#include "contrib/thrift/ThriftConnection.h"

using apache::thrift::TProcessor;
using apache::thrift::TProcessorFactory;
using apache::thrift::protocol::TProtocolFactory;
using apache::thrift::server::TServer;
using apache::thrift::transport::TTransportFactory;

class ThriftServer : boost::noncopyable,
                     public TServer
{
 public:
  ThriftServer(const boost::shared_ptr<TProcessorFactory>& processorFactory,
               muduo::net::EventLoop* eventloop,
               const muduo::net::InetAddress& addr,
               const muduo::string& name)
    : TServer(processorFactory),
      server_(eventloop, addr, name),
      numWorkerThreads_(0),
      workerThreadPool_(name + muduo::string("WorkerThreadPool"))
  {
    server_.setConnectionCallback(std::bind(&ThriftServer::onConnection,
                                              this, muduo::_1));
  }

  ThriftServer(const boost::shared_ptr<TProcessor>& processor,
               muduo::net::EventLoop* eventloop,
               const muduo::net::InetAddress& addr,
               const muduo::string& name)
    : TServer(processor),
      server_(eventloop, addr, name),
      numWorkerThreads_(0),
      workerThreadPool_(name + muduo::string("WorkerThreadPool"))
  {
    server_.setConnectionCallback(std::bind(&ThriftServer::onConnection,
                                              this, muduo::_1));
  }

  ThriftServer(const boost::shared_ptr<TProcessorFactory>& processorFactory,
               const boost::shared_ptr<TProtocolFactory>& protocolFactory,
               muduo::net::EventLoop* eventloop,
               const muduo::net::InetAddress& addr,
               const muduo::string& name)
    : TServer(processorFactory),
      server_(eventloop, addr, name),
      numWorkerThreads_(0),
      workerThreadPool_(name + muduo::string("WorkerThreadPool"))
  {
    server_.setConnectionCallback(std::bind(&ThriftServer::onConnection,
                                              this, muduo::_1));
    setInputProtocolFactory(protocolFactory);
    setOutputProtocolFactory(protocolFactory);
  }

  ThriftServer(const boost::shared_ptr<TProcessor>& processor,
               const boost::shared_ptr<TProtocolFactory>& protocolFactory,
               muduo::net::EventLoop* eventloop,
               const muduo::net::InetAddress& addr,
               const muduo::string& name)
    : TServer(processor),
      server_(eventloop, addr, name),
      numWorkerThreads_(0),
      workerThreadPool_(name + muduo::string("WorkerThreadPool"))
  {
    server_.setConnectionCallback(std::bind(&ThriftServer::onConnection,
                                              this, muduo::_1));
    setInputProtocolFactory(protocolFactory);
    setOutputProtocolFactory(protocolFactory);
  }

  ThriftServer(const boost::shared_ptr<TProcessorFactory>& processorFactory,
               const boost::shared_ptr<TTransportFactory>& transportFactory,
               const boost::shared_ptr<TProtocolFactory>& protocolFactory,
               muduo::net::EventLoop* eventloop,
               const muduo::net::InetAddress& addr,
               const muduo::string& name)
    : TServer(processorFactory),
      server_(eventloop, addr, name),
      numWorkerThreads_(0),
      workerThreadPool_(name + muduo::string("WorkerThreadPool"))
  {
    server_.setConnectionCallback(std::bind(&ThriftServer::onConnection,
                                              this, muduo::_1));
    setInputTransportFactory(transportFactory);
    setOutputTransportFactory(transportFactory);
    setInputProtocolFactory(protocolFactory);
    setOutputProtocolFactory(protocolFactory);
  }

  ThriftServer(const boost::shared_ptr<TProcessor>& processor,
               const boost::shared_ptr<TTransportFactory>& transportFactory,
               const boost::shared_ptr<TProtocolFactory>& protocolFactory,
               muduo::net::EventLoop* eventloop,
               const muduo::net::InetAddress& addr,
               const muduo::string& name)
    : TServer(processor),
      server_(eventloop, addr, name),
      numWorkerThreads_(0),
      workerThreadPool_(name + muduo::string("WorkerThreadPool"))
  {
    server_.setConnectionCallback(std::bind(&ThriftServer::onConnection,
                                              this, muduo::_1));
    setInputTransportFactory(transportFactory);
    setOutputTransportFactory(transportFactory);
    setInputProtocolFactory(protocolFactory);
    setOutputProtocolFactory(protocolFactory);
  }

  ThriftServer(const boost::shared_ptr<TProcessorFactory>& processorFactory,
               const boost::shared_ptr<TTransportFactory>& inputTransportFactory,
               const boost::shared_ptr<TTransportFactory>& outputTransportFactory,
               const boost::shared_ptr<TProtocolFactory>& inputProtocolFactory,
               const boost::shared_ptr<TProtocolFactory>& outputProtocolFactory,
               muduo::net::EventLoop* eventloop,
               const muduo::net::InetAddress& addr,
               const muduo::string& name)
    : TServer(processorFactory),
      server_(eventloop, addr, name),
      numWorkerThreads_(0),
      workerThreadPool_(name + muduo::string("WorkerThreadPool"))
  {
    server_.setConnectionCallback(std::bind(&ThriftServer::onConnection,
                                              this, muduo::_1));
    setInputTransportFactory(inputTransportFactory);
    setOutputTransportFactory(outputTransportFactory);
    setInputProtocolFactory(inputProtocolFactory);
    setOutputProtocolFactory(outputProtocolFactory);
  }

  ThriftServer(const boost::shared_ptr<TProcessor>& processor,
               const boost::shared_ptr<TTransportFactory>& inputTransportFactory,
               const boost::shared_ptr<TTransportFactory>& outputTransportFactory,
               const boost::shared_ptr<TProtocolFactory>& inputProtocolFactory,
               const boost::shared_ptr<TProtocolFactory>& outputProtocolFactory,
               muduo::net::EventLoop* eventloop,
               const muduo::net::InetAddress& addr,
               const muduo::string& name)
    : TServer(processor),
      server_(eventloop, addr, name),
      numWorkerThreads_(0),
      workerThreadPool_(name + muduo::string("WorkerThreadPool"))
  {
    server_.setConnectionCallback(std::bind(&ThriftServer::onConnection,
                                              this, muduo::_1));
    setInputTransportFactory(inputTransportFactory);
    setOutputTransportFactory(outputTransportFactory);
    setInputProtocolFactory(inputProtocolFactory);
    setOutputProtocolFactory(outputProtocolFactory);
  }

  virtual ~ThriftServer();

  void serve();

  void start();

  void stop();

  muduo::ThreadPool& workerThreadPool()
  {
    return workerThreadPool_;
  }

  bool isWorkerThreadPoolProcessing() const
  {
    return numWorkerThreads_ != 0;
  }

  void setThreadNum(int numThreads)
  {
    server_.setThreadNum(numThreads);
  }

  void setWorkerThreadNum(int numWorkerThreads)
  {
    assert(numWorkerThreads > 0);
    numWorkerThreads_ = numWorkerThreads;
  }

 private:
  friend class ThriftConnection;

  void onConnection(const muduo::net::TcpConnectionPtr& conn);

 private:
  muduo::net::TcpServer server_;
  int numWorkerThreads_;
  muduo::ThreadPool workerThreadPool_;
  muduo::MutexLock mutex_;
  std::map<muduo::string, ThriftConnectionPtr> conns_;
};

#endif  // MUDUO_CONTRIB_THRIFT_THRIFTSERVER_H


================================================
FILE: contrib/thrift/tests/.gitignore
================================================
gen-cpp
gen-py


================================================
FILE: contrib/thrift/tests/CMakeLists.txt
================================================
add_subdirectory(echo)
add_subdirectory(ping)


================================================
FILE: contrib/thrift/tests/echo/CMakeLists.txt
================================================
include_directories(gen-cpp)
set(ECHO_THRIFT echo.thrift)
execute_process(COMMAND ${THRIFT_COMPILER} --gen cpp ${ECHO_THRIFT}
                WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
execute_process(COMMAND ${THRIFT_COMPILER} --gen py ${ECHO_THRIFT}
                WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
set(ECHO_THRIFT_SRCS
    gen-cpp/echo_constants.cpp
    gen-cpp/echo_types.cpp
    gen-cpp/Echo.cpp
    )
set(ECHO_SRCS
    EchoServer.cc
    )
add_executable(muduo_thrift_echo ${ECHO_SRCS} ${ECHO_THRIFT_SRCS})
target_link_libraries(muduo_thrift_echo muduo_thrift)


================================================
FILE: contrib/thrift/tests/echo/EchoServer.cc
================================================
#include <unistd.h>

#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"

#include "ThriftServer.h"

#include "Echo.h"

using namespace muduo;
using namespace muduo::net;

using namespace echo;

class EchoHandler : virtual public EchoIf
{
 public:
  EchoHandler()
  {
  }

  void echo(std::string& str, const std::string& s)
  {
    LOG_INFO << "EchoHandler::echo:" << s;
    str = s;
  }

};

int NumCPU()
{
  return static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN));
}

int main(int argc, char **argv)
{
  EventLoop eventloop;
  InetAddress addr("127.0.0.1", 9090);
  string name("EchoServer");

  boost::shared_ptr<EchoHandler> handler(new EchoHandler());
  boost::shared_ptr<TProcessor> processor(new EchoProcessor(handler));

  ThriftServer server(processor, &eventloop, addr, name);
  server.setWorkerThreadNum(NumCPU() * 2);
  server.start();
  eventloop.loop();

  return 0;
}



================================================
FILE: contrib/thrift/tests/echo/echo.thrift
================================================
namespace cpp echo
namespace py echo

service Echo
{
  string echo(1: string arg);
}



================================================
FILE: contrib/thrift/tests/echo/echoclient.py
================================================
import sys
sys.path.append('gen-py')

from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol

from echo import Echo


def echo(s):
    transport = TSocket.TSocket('127.0.0.1', 9090)
    tranport = TTransport.TFramedTransport(transport)
    protocol = TBinaryProtocol.TBinaryProtocol(tranport)
    client = Echo.Client(protocol)
    tranport.open()
    s = client.echo(s)
    tranport.close()

    return s


def main():
    print(echo('42'))


if __name__ == '__main__':
    main()


================================================
FILE: contrib/thrift/tests/ping/CMakeLists.txt
================================================
include_directories(gen-cpp)
set(PING_THRIFT ping.thrift)
execute_process(COMMAND ${THRIFT_COMPILER} --gen cpp ${PING_THRIFT}
                WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
execute_process(COMMAND ${THRIFT_COMPILER} --gen py ${PING_THRIFT}
                WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
set(PING_THRIFT_SRCS
    gen-cpp/ping_constants.cpp
    gen-cpp/ping_types.cpp
    gen-cpp/Ping.cpp
    )
set(PING_SRCS
    PingServer.cc
    )
add_executable(muduo_thrift_ping ${PING_SRCS} ${PING_THRIFT_SRCS})
target_link_libraries(muduo_thrift_ping muduo_thrift)


================================================
FILE: contrib/thrift/tests/ping/PingServer.cc
================================================
#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"

#include <thrift/protocol/TCompactProtocol.h>

#include "ThriftServer.h"

#include "Ping.h"

using namespace muduo;
using namespace muduo::net;

using apache::thrift::protocol::TCompactProtocolFactory;

using namespace ping;

class PingHandler : virtual public PingIf
{
 public:
  PingHandler()
  {
  }

  void ping()
  {
    LOG_INFO << "ping";
  }

};

int main(int argc, char **argv)
{
  EventLoop eventloop;
  InetAddress addr("127.0.0.1", 9090);
  string name("PingServer");

  boost::shared_ptr<PingHandler> handler(new PingHandler());
  boost::shared_ptr<TProcessor> processor(new PingProcessor(handler));
  boost::shared_ptr<TProtocolFactory> protcolFactory(new TCompactProtocolFactory());

  ThriftServer server(processor, protcolFactory, &eventloop, addr, name);
  server.start();
  eventloop.loop();

  return 0;
}



================================================
FILE: contrib/thrift/tests/ping/ping.thrift
================================================
namespace cpp ping
namespace py ping

service Ping
{
  void ping();
}



================================================
FILE: contrib/thrift/tests/ping/pingclient.py
================================================
import sys
sys.path.append('gen-py')

from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TCompactProtocol

from ping import Ping


def ping():
    transport = TSocket.TSocket('127.0.0.1', 9090)
    tranport = TTransport.TFramedTransport(transport)
    protocol = TCompactProtocol.TCompactProtocol(tranport)
    client = Ping.Client(protocol)
    tranport.open()
    client.ping()
    tranport.close()


def main():
    ping()


if __name__ == '__main__':
    main()


================================================
FILE: examples/CMakeLists.txt
================================================
add_subdirectory(ace/ttcp)
add_subdirectory(asio/chat)
add_subdirectory(asio/tutorial)
add_subdirectory(fastcgi)
add_subdirectory(filetransfer)
add_subdirectory(hub)
add_subdirectory(idleconnection)
add_subdirectory(maxconnection)
add_subdirectory(memcached/client)
add_subdirectory(memcached/server)
add_subdirectory(multiplexer)
add_subdirectory(netty/discard)
add_subdirectory(netty/echo)
add_subdirectory(netty/uptime)
add_subdirectory(pingpong)
add_subdirectory(roundtrip)
add_subdirectory(shorturl)
add_subdirectory(simple)
add_subdirectory(socks4a)
add_subdirectory(sudoku)
add_subdirectory(twisted/finger)
add_subdirectory(wordcount)
add_subdirectory(zeromq)

if(CARES_INCLUDE_DIR AND CARES_LIBRARY)
  add_subdirectory(cdns)
else()
  add_subdirectory(cdns EXCLUDE_FROM_ALL)
endif()

if(CURL_FOUND)
  add_subdirectory(curl)
else()
  add_subdirectory(curl EXCLUDE_FROM_ALL)
endif()

if(PROTOBUF_FOUND)
  add_subdirectory(ace/logging)
  add_subdirectory(protobuf)
else()
  add_subdirectory(ace/logging EXCLUDE_FROM_ALL)
  add_subdirectory(protobuf EXCLUDE_FROM_ALL)
endif()

if(GD_INCLUDE_DIR AND GD_LIBRARY)
  add_subdirectory(procmon)
else()
  add_subdirectory(procmon EXCLUDE_FROM_ALL)
endif()


================================================
FILE: examples/ace/logging/CMakeLists.txt
================================================
add_custom_command(OUTPUT logrecord.pb.cc logrecord.pb.h
  COMMAND protoc
  ARGS --cpp_out . ${CMAKE_CURRENT_SOURCE_DIR}/logrecord.proto -I${CMAKE_CURRENT_SOURCE_DIR}
  DEPENDS logrecord.proto
  VERBATIM )

set_source_files_properties(logrecord.pb.cc PROPERTIES COMPILE_FLAGS "-Wno-conversion -Wno-shadow")
include_directories(${PROJECT_BINARY_DIR})

add_library(ace_logging_proto logrecord.pb.cc)
target_link_libraries(ace_logging_proto protobuf pthread)

add_executable(ace_logging_client client.cc)
set_target_properties(ace_logging_client PROPERTIES COMPILE_FLAGS "-Wno-error=shadow")
target_link_libraries(ace_logging_client muduo_protobuf_codec ace_logging_proto)

add_executable(ace_logging_server server.cc)
set_target_properties(ace_logging_server PROPERTIES COMPILE_FLAGS "-Wno-error=shadow")
target_link_libraries(ace_logging_server muduo_protobuf_codec ace_logging_proto)


================================================
FILE: examples/ace/logging/client.cc
================================================
#include "examples/ace/logging/logrecord.pb.h"

#include "muduo/base/Mutex.h"
#include "muduo/base/Logging.h"
#include "muduo/base/ProcessInfo.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/EventLoopThread.h"
#include "muduo/net/TcpClient.h"
#include "muduo/net/protobuf/ProtobufCodecLite.h"

#include <iostream>
#include <stdio.h>

using namespace muduo;
using namespace muduo::net;

// just to verify the protocol, not for practical usage.

namespace logging
{
extern const char logtag[] = "LOG0";
typedef ProtobufCodecLiteT<LogRecord, logtag> Codec;

// same as asio/char/client.cc
class LogClient : noncopyable
{
 public:
  LogClient(EventLoop* loop, const InetAddress& serverAddr)
    : client_(loop, serverAddr, "LogClient"),
      codec_(std::bind(&LogClient::onMessage, this, _1, _2, _3))
  {
    client_.setConnectionCallback(
        std::bind(&LogClient::onConnection, this, _1));
    client_.setMessageCallback(
        std::bind(&Codec::onMessage, &codec_, _1, _2, _3));
    client_.enableRetry();
  }

  void connect()
  {
    client_.connect();
  }

  void disconnect()
  {
    client_.disconnect();
  }

  void write(const StringPiece& message)
  {
    MutexLockGuard lock(mutex_);
    updateLogRecord(message);
    if (connection_)
    {
      codec_.send(connection_, logRecord_);
    }
    else
    {
      LOG_WARN << "NOT CONNECTED";
    }
  }

 private:
  void onConnection(const TcpConnectionPtr& conn)
  {
    LOG_INFO << conn->localAddress().toIpPort() << " -> "
             << conn->peerAddress().toIpPort() << " is "
             << (conn->connected() ? "UP" : "DOWN");

    MutexLockGuard lock(mutex_);
    if (conn->connected())
    {
      connection_ = conn;
      LogRecord_Heartbeat* hb = logRecord_.mutable_heartbeat();
      hb->set_hostname(ProcessInfo::hostname().c_str());
      hb->set_process_name(ProcessInfo::procname().c_str());
      hb->set_process_id(ProcessInfo::pid());
      hb->set_process_start_time(ProcessInfo::startTime().microSecondsSinceEpoch());
      hb->set_username(ProcessInfo::username().c_str());
      updateLogRecord("Heartbeat");
      codec_.send(connection_, logRecord_);
      logRecord_.clear_heartbeat();
      LOG_INFO << "Type message below:";
    }
    else
    {
      connection_.reset();
    }
  }

  void onMessage(const TcpConnectionPtr&,
                 const MessagePtr& message,
                 Timestamp)
  {
    // SHOULD NOT HAPPEN
    LogRecord* logRecord = muduo::down_cast<LogRecord*>(message.get());
    LOG_WARN << logRecord->DebugString();
  }

  void updateLogRecord(const StringPiece& message) REQUIRES(mutex_)
  {
    mutex_.assertLocked();
    logRecord_.set_level(1);
    logRecord_.set_thread_id(CurrentThread::tid());
    logRecord_.set_timestamp(Timestamp::now().microSecondsSinceEpoch());
    logRecord_.set_message(message.data(), message.size());
  }

  TcpClient client_;
  Codec codec_;
  MutexLock mutex_;
  LogRecord logRecord_ GUARDED_BY(mutex_);
  TcpConnectionPtr connection_ GUARDED_BY(mutex_);
};

}  // namespace logging

int main(int argc, char* argv[])
{
  if (argc < 3)
  {
    printf("usage: %s server_ip server_port\n", argv[0]);
  }
  else
  {
    EventLoopThread loopThread;
    uint16_t port = static_cast<uint16_t>(atoi(argv[2]));
    InetAddress serverAddr(argv[1], port);

    logging::LogClient client(loopThread.startLoop(), serverAddr);
    client.connect();
    std::string line;
    while (std::getline(std::cin, line))
    {
      client.write(line);
    }
    client.disconnect();
    CurrentThread::sleepUsec(1000*1000);  // wait for disconnect, then safe to destruct LogClient (esp. TcpClient). Otherwise mutex_ is used after dtor.
  }
  google::protobuf::ShutdownProtobufLibrary();
}


================================================
FILE: examples/ace/logging/logrecord.proto
================================================
package logging;

message LogRecord {
  // must present in first message
  message Heartbeat {
    required string hostname = 1;
    required string process_name = 2;
    required int32 process_id = 3;
    required int64 process_start_time = 4; // microseconds sinch epoch
    required string username = 5;
  }

  optional Heartbeat heartbeat = 1;
  // muduo/base/Logging.h
  // enum LogLevel
  // {
  //   TRACE, // 0
  //   DEBUG, // 1
  //   INFO,  // 2
  //   WARN,  // 3
  //   ERROR, // 4
  //   FATAL, // 5
  // };
  required int32 level = 2;
  required int32 thread_id = 3;
  required int64 timestamp = 4; // microseconds sinch epoch
  required string message = 5;
  // optional: source file, source line, function name
}


================================================
FILE: examples/ace/logging/server.cc
================================================
#include "examples/ace/logging/logrecord.pb.h"

#include "muduo/base/Atomic.h"
#include "muduo/base/FileUtil.h"
#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/TcpServer.h"
#include "muduo/net/protobuf/ProtobufCodecLite.h"

#include <stdio.h>

using namespace muduo;
using namespace muduo::net;

namespace logging
{
extern const char logtag[] = "LOG0";
typedef ProtobufCodecLiteT<LogRecord, logtag> Codec;

class Session : noncopyable
{
 public:
  explicit Session(const TcpConnectionPtr& conn)
    : codec_(std::bind(&Session::onMessage, this, _1, _2, _3)),
      file_(getFileName(conn))
  {
    conn->setMessageCallback(
        std::bind(&Codec::onMessage, &codec_, _1, _2, _3));
  }

 private:

  // FIXME: duplicate code LogFile
  // or use LogFile instead
  string getFileName(const TcpConnectionPtr& conn)
  {
    string filename;
    filename += conn->peerAddress().toIp();

    char timebuf[32];
    struct tm tm;
    time_t now = time(NULL);
    gmtime_r(&now, &tm); // FIXME: localtime_r ?
    strftime(timebuf, sizeof timebuf, ".%Y%m%d-%H%M%S.", &tm);
    filename += timebuf;

    char buf[32];
    snprintf(buf, sizeof buf, "%d", globalCount_.incrementAndGet());
    filename += buf;

    filename += ".log";
    LOG_INFO << "Session of " << conn->name() << " file " << filename;
    return filename;
  }

  void onMessage(const TcpConnectionPtr& conn,
                 const MessagePtr& message,
                 Timestamp time)
  {
    LogRecord* logRecord = muduo::down_cast<LogRecord*>(message.get());
    if (logRecord->has_heartbeat())
    {
      // FIXME ?
    }
    const char* sep = "==========\n";
    std::string str = logRecord->DebugString();
    file_.append(str.c_str(), str.size());
    file_.append(sep, strlen(sep));
    LOG_DEBUG << str;
  }

  Codec codec_;
  FileUtil::AppendFile file_;
  static AtomicInt32 globalCount_;
};
typedef std::shared_ptr<Session> SessionPtr;

AtomicInt32 Session::globalCount_;

class LogServer : noncopyable
{
 public:
  LogServer(EventLoop* loop, const InetAddress& listenAddr, int numThreads)
    : loop_(loop),
      server_(loop_, listenAddr, "AceLoggingServer")
  {
    server_.setConnectionCallback(
        std::bind(&LogServer::onConnection, this, _1));
    if (numThreads > 1)
    {
      server_.setThreadNum(numThreads);
    }
  }

  void start()
  {
    server_.start();
  }

 private:
  void onConnection(const TcpConnectionPtr& conn)
  {
    if (conn->connected())
    {
      SessionPtr session(new Session(conn));
      conn->setContext(session);
    }
    else
    {
      conn->setContext(SessionPtr());
    }
  }

  EventLoop* loop_;
  TcpServer server_;
};

}  // namespace logging

int main(int argc, char* argv[])
{
  EventLoop loop;
  int port = argc > 1 ? atoi(argv[1]) : 50000;
  LOG_INFO << "Listen on port " << port;
  InetAddress listenAddr(static_cast<uint16_t>(port));
  int numThreads = argc > 2 ? atoi(argv[2]) : 1;
  logging::LogServer server(&loop, listenAddr, numThreads);
  server.start();
  loop.loop();

}


================================================
FILE: examples/ace/ttcp/CMakeLists.txt
================================================
if(BOOSTPO_LIBRARY)
  add_executable(ttcp_blocking ttcp_blocking.cc common.cc main.cc)
  target_link_libraries(ttcp_blocking muduo_base boost_program_options)
  set_target_properties(ttcp_blocking PROPERTIES COMPILE_FLAGS "-Wno-error=old-style-cast -Wno-error=conversion")

  add_executable(ttcp_muduo ttcp.cc common.cc main.cc)
  target_link_libraries(ttcp_muduo muduo_net boost_program_options)

  if(BOOSTSYSTEM_LIBRARY)
    add_executable(ttcp_asio_sync ttcp_asio_sync.cc common.cc main.cc)
    target_link_libraries(ttcp_asio_sync muduo_base boost_program_options boost_system)

    add_executable(ttcp_asio_async ttcp_asio_async.cc common.cc main.cc)
    target_link_libraries(ttcp_asio_async muduo_base boost_program_options boost_system)
  endif()
endif()



================================================
FILE: examples/ace/ttcp/common.cc
================================================
#include "examples/ace/ttcp/common.h"
#include "muduo/base/Types.h"

#include <boost/program_options.hpp>

#include <iostream>

#include <netdb.h>
#include <stdio.h>

namespace po = boost::program_options;

bool parseCommandLine(int argc, char* argv[], Options* opt)
{
  po::options_description desc("Allowed options");
  desc.add_options()
      ("help,h", "Help")
      ("port,p", po::value<uint16_t>(&opt->port)->default_value(5001), "TCP port")
      ("length,l", po::value<int>(&opt->length)->default_value(65536), "Buffer length")
      ("number,n", po::value<int>(&opt->number)->default_value(8192), "Number of buffers")
      ("trans,t",  po::value<std::string>(&opt->host), "Transmit")
      ("recv,r", "Receive")
      ("nodelay,D", "set TCP_NODELAY")
      ;

  po::variables_map vm;
  po::store(po::parse_command_line(argc, argv, desc), vm);
  po::notify(vm);

  opt->transmit = vm.count("trans");
  opt->receive = vm.count("recv");
  opt->nodelay = vm.count("nodelay");
  if (vm.count("help"))
  {
    std::cout << desc << std::endl;
    return false;
  }

  if (opt->transmit == opt->receive)
  {
    printf("either -t or -r must be specified.\n");
    return false;
  }

  printf("port = %d\n", opt->port);
  if (opt->transmit)
  {
    printf("buffer length = %d\n", opt->length);
    printf("number of buffers = %d\n", opt->number);
  }
  else
  {
    printf("accepting...\n");
  }
  return true;
}

#pragma GCC diagnostic ignored "-Wold-style-cast"

struct sockaddr_in resolveOrDie(const char* host, uint16_t port)
{
  struct hostent* he = ::gethostbyname(host);
  if (!he)
  {
    perror("gethostbyname");
    exit(1);
  }
  assert(he->h_addrtype == AF_INET && he->h_length == sizeof(uint32_t));
  struct sockaddr_in addr;
  muduo::memZero(&addr, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);
  addr.sin_addr = *reinterpret_cast<struct in_addr*>(he->h_addr);
  return addr;
}



================================================
FILE: examples/ace/ttcp/common.h
================================================
#pragma once

#include <string>
#include <stdint.h>

struct Options
{
  uint16_t port;
  int length;
  int number;
  bool transmit, receive, nodelay;
  std::string host;
  Options()
    : port(0), length(0), number(0),
      transmit(false), receive(false), nodelay(false)
  {
  }
};

bool parseCommandLine(int argc, char* argv[], Options* opt);
struct sockaddr_in resolveOrDie(const char* host, uint16_t port);

struct SessionMessage
{
  int32_t number;
  int32_t length;
} __attribute__ ((__packed__));

struct PayloadMessage
{
  int32_t length;
  char data[0];
};

void transmit(const Options& opt);

void receive(const Options& opt);


================================================
FILE: examples/ace/ttcp/main.cc
================================================
#include "examples/ace/ttcp/common.h"

#include <assert.h>

int main(int argc, char* argv[])
{
  Options options;
  if (parseCommandLine(argc, argv, &options))
  {
    if (options.transmit)
    {
      transmit(options);
    }
    else if (options.receive)
    {
      receive(options);
    }
    else
    {
      assert(0);
    }
  }
}



================================================
FILE: examples/ace/ttcp/ttcp.cc
================================================
#include "examples/ace/ttcp/common.h"

#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/TcpClient.h"
#include "muduo/net/TcpServer.h"

#include <stdio.h>

using namespace muduo;
using namespace muduo::net;

EventLoop* g_loop;

struct Context
{
  int count;
  int64_t bytes;
  SessionMessage session;
  Buffer output;

  Context()
    : count(0),
      bytes(0)
  {
    session.number = 0;
    session.length = 0;
  }
};

/////////////////////////////////////////////////////////////////////
// T R A N S M I T
/////////////////////////////////////////////////////////////////////

namespace trans
{

void onConnection(const Options& opt, const TcpConnectionPtr& conn)
{
  if (conn->connected())
  {
    printf("connected\n");
    Context context;
    context.count = 1;
    context.bytes = opt.length;
    context.session.number = opt.number;
    context.session.length = opt.length;
    context.output.appendInt32(opt.length);
    context.output.ensureWritableBytes(opt.length);
    for (int i = 0; i < opt.length; ++i)
    {
      context.output.beginWrite()[i] = "0123456789ABCDEF"[i % 16];
    }
    context.output.hasWritten(opt.length);
    conn->setContext(context);

    SessionMessage sessionMessage = { 0, 0 };
    sessionMessage.number = htonl(opt.number);
    sessionMessage.length = htonl(opt.length);
    conn->send(&sessionMessage, sizeof(sessionMessage));

    conn->send(context.output.toStringPiece());
  }
  else
  {
    const Context& context = boost::any_cast<Context>(conn->getContext());
    LOG_INFO << "payload bytes " << context.bytes;
    conn->getLoop()->quit();
  }
}

void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp time)
{
  Context* context = boost::any_cast<Context>(conn->getMutableContext());
  while (buf->readableBytes() >= sizeof(int32_t))
  {
    int32_t length = buf->readInt32();
    if (length == context->session.length)
    {
      if (context->count < context->session.number)
      {
        conn->send(context->output.toStringPiece());
        ++context->count;
        context->bytes += length;
      }
      else
      {
        conn->shutdown();
        break;
      }
    }
    else
    {
      conn->shutdown();
      break;
    }
  }
}

}  // namespace trans

void transmit(const Options& opt)
{
  InetAddress addr(opt.port);
  if (!InetAddress::resolve(opt.host, &addr))
  {
    LOG_FATAL << "Unable to resolve " << opt.host;
  }
  muduo::Timestamp start(muduo::Timestamp::now());
  EventLoop loop;
  g_loop = &loop;
  TcpClient client(&loop, addr, "TtcpClient");
  client.setConnectionCallback(
      std::bind(&trans::onConnection, opt, _1));
  client.setMessageCallback(
      std::bind(&trans::onMessage, _1, _2, _3));
  client.connect();
  loop.loop();
  double elapsed = timeDifference(muduo::Timestamp::now(), start);
  double total_mb = 1.0 * opt.length * opt.number / 1024 / 1024;
  printf("%.3f MiB transferred\n%.3f MiB/s\n", total_mb, total_mb / elapsed);
}

/////////////////////////////////////////////////////////////////////
// R E C E I V E
/////////////////////////////////////////////////////////////////////

namespace receiving
{

void onConnection(const TcpConnectionPtr& conn)
{
  if (conn->connected())
  {
    Context context;
    conn->setContext(context);
  }
  else
  {
    const Context& context = boost::any_cast<Context>(conn->getContext());
    LOG_INFO << "payload bytes " << context.bytes;
    conn->getLoop()->quit();
  }
}

void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp time)
{
  while (buf->readableBytes() >= sizeof(int32_t))
  {
    Context* context = boost::any_cast<Context>(conn->getMutableContext());
    SessionMessage& session = context->session;
    if (session.number == 0 && session.length == 0)
    {
      if (buf->readableBytes() >= sizeof(SessionMessage))
      {
        session.number = buf->readInt32();
        session.length = buf->readInt32();
        context->output.appendInt32(session.length);
        printf("receive number = %d\nreceive length = %d\n",
               session.number, session.length);
      }
      else
      {
        break;
      }
    }
    else
    {
      const unsigned total_len = session.length + static_cast<int>(sizeof(int32_t));
      const int32_t length = buf->peekInt32();
      if (length == session.length)
      {
        if (buf->readableBytes() >= total_len)
        {
          buf->retrieve(total_len);
          conn->send(context->output.toStringPiece());
          ++context->count;
          context->bytes += length;
          if (context->count >= session.number)
          {
            conn->shutdown();
            break;
          }
        }
        else
        {
          break;
        }
      }
      else
      {
        printf("wrong length %d\n", length);
        conn->shutdown();
        break;
      }
    }
  }
}

}  // namespace receiving

void receive(const Options& opt)
{
  EventLoop loop;
  g_loop = &loop;
  InetAddress listenAddr(opt.port);
  TcpServer server(&loop, listenAddr, "TtcpReceive");
  server.setConnectionCallback(
      std::bind(&receiving::onConnection, _1));
  server.setMessageCallback(
      std::bind(&receiving::onMessage, _1, _2, _3));
  server.start();
  loop.loop();
}


================================================
FILE: examples/ace/ttcp/ttcp_asio_async.cc
================================================
#include "examples/ace/ttcp/common.h"

#include "muduo/base/Logging.h"
#include <boost/asio.hpp>
#include <stdio.h>

using boost::asio::ip::tcp;

void transmit(const Options& opt)
{
  try
  {
  }
  catch (std::exception& e)
  {
    LOG_ERROR << e.what();
  }
}

class TtcpServerConnection : public std::enable_shared_from_this<TtcpServerConnection>,
                             muduo::noncopyable
{
 public:
#if BOOST_VERSION < 107000L
  TtcpServerConnection(boost::asio::io_service& io_service)
    : socket_(io_service), count_(0), payload_(NULL), ack_(0)
#else
  TtcpServerConnection(const tcp::socket::executor_type& executor)
    : socket_(executor), count_(0), payload_(NULL), ack_(0)
#endif
  {
    sessionMessage_.number = 0;
    sessionMessage_.length = 0;
  }

  ~TtcpServerConnection()
  {
    ::free(payload_);
  }

  tcp::socket& socket() { return socket_; }

  void start()
  {
    std::ostringstream oss;
    oss << socket_.remote_endpoint();
    LOG_INFO << "Got connection from " << oss.str();
    doReadSession();
  }

 private:
  void doReadSession()
  {
    auto self(shared_from_this());
    boost::asio::async_read(
        socket_, boost::asio::buffer(&sessionMessage_, sizeof(sessionMessage_)),
        [this, self](const boost::system::error_code& error, size_t len)
        {
          if (!error && len == sizeof sessionMessage_)
          {
            sessionMessage_.number = ntohl(sessionMessage_.number);
            sessionMessage_.length = ntohl(sessionMessage_.length);
            printf("receive number = %d\nreceive length = %d\n",
                   sessionMessage_.number, sessionMessage_.length);
            const int total_len = static_cast<int>(sizeof(int32_t) + sessionMessage_.length);
            payload_ = static_cast<PayloadMessage*>(::malloc(total_len));
            doReadLength();
          }
          else
          {
            LOG_ERROR << "read session message: " << error.message();
          }
        });
  }

  void doReadLength()
  {
    auto self(shared_from_this());
    payload_->length = 0;
    boost::asio::async_read(
        socket_, boost::asio::buffer(&payload_->length, sizeof payload_->length),
        [this, self](const boost::system::error_code& error, size_t len)
        {
          if (!error && len == sizeof payload_->length)
          {
            payload_->length = ntohl(payload_->length);
            doReadPayload();
          }
          else
          {
            LOG_ERROR << "read length: " << error.message();
          }
        });
  }

  void doReadPayload()
  {
    assert(payload_->length == sessionMessage_.length);
    auto self(shared_from_this());
    boost::asio::async_read(
        socket_, boost::asio::buffer(&payload_->data, payload_->length),
        [this, self](const boost::system::error_code& error, size_t len)
        {
          if (!error && len == static_cast<size_t>(payload_->length))
          {
            doWriteAck();
          }
          else
          {
            LOG_ERROR << "read payload data: " << error.message();
          }
        });
  }

  void doWriteAck()
  {
    auto self(shared_from_this());
    ack_ = htonl(payload_->length);
    boost::asio::async_write(
        socket_, boost::asio::buffer(&ack_, sizeof ack_),
        [this, self](const boost::system::error_code& error, size_t len)
        {
          if (!error && len == sizeof ack_)
          {
            if (++count_ < sessionMessage_.number)
            {
              doReadLength();
            }
            else
            {
              LOG_INFO << "Done";
            }
          }
          else
          {
            LOG_ERROR << "write ack: " << error.message();
          }
        });
  }

  tcp::socket socket_;
  int count_;
  struct SessionMessage sessionMessage_;
  struct PayloadMessage* payload_;
  int32_t ack_;
};
typedef std::shared_ptr<TtcpServerConnection> TtcpServerConnectionPtr;

void doAccept(tcp::acceptor& acceptor)
{
#if BOOST_VERSION < 107000L
  // no need to pre-create new_connection if we use asio 1.12 or boost 1.66+
  TtcpServerConnectionPtr new_connection(new TtcpServerConnection(acceptor.get_io_service()));
#else
  TtcpServerConnectionPtr new_connection(new TtcpServerConnection(acceptor.get_executor()));
#endif
  acceptor.async_accept(
      new_connection->socket(),
      [&acceptor, new_connection](boost::system::error_code error)  // move new_connection in C++14
      {
        if (!error)
        {
          new_connection->start();
        }
        doAccept(acceptor);
      });
}

void receive(const Options& opt)
{
  try
  {
    boost::asio::io_service io_service;
    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), opt.port));
    doAccept(acceptor);
    io_service.run();
  }
  catch (std::exception& e)
  {
    LOG_ERROR << e.what();
  }
}



================================================
FILE: examples/ace/ttcp/ttcp_asio_sync.cc
================================================
#include "examples/ace/ttcp/common.h"

#include "muduo/base/Logging.h"
#include <boost/asio.hpp>
#include <stdio.h>

using boost::asio::ip::tcp;

void transmit(const Options& opt)
{
  try
  {
  }
  catch (std::exception& e)
  {
    LOG_ERROR << e.what();
  }
}

void receive(const Options& opt)
{
  try
  {
    boost::asio::io_service io_service;
    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), opt.port));
    tcp::socket socket(io_service);
    acceptor.accept(socket);

    struct SessionMessage sessionMessage = { 0, 0 };
    boost::system::error_code error;
    size_t nr = boost::asio::read(socket, boost::asio::buffer(&sessionMessage, sizeof sessionMessage),
#if BOOST_VERSION < 104700L
                                  boost::asio::transfer_all(),
#endif
                                  error);
    if (nr != sizeof sessionMessage)
    {
      LOG_ERROR << "read session message: " << error.message();
      exit(1);
    }

    sessionMessage.number = ntohl(sessionMessage.number);
    sessionMessage.length = ntohl(sessionMessage.length);
    printf("receive number = %d\nreceive length = %d\n",
           sessionMessage.number, sessionMessage.length);
    const int total_len = static_cast<int>(sizeof(int32_t) + sessionMessage.length);
    PayloadMessage* payload = static_cast<PayloadMessage*>(::malloc(total_len));
    std::unique_ptr<PayloadMessage, void (*)(void*)> freeIt(payload, ::free);
    assert(payload);

    for (int i = 0; i < sessionMessage.number; ++i)
    {
      payload->length = 0;
      if (boost::asio::read(socket, boost::asio::buffer(&payload->length, sizeof(payload->length)),
#if BOOST_VERSION < 104700L
                            boost::asio::transfer_all(),
#endif
                            error) != sizeof(payload->length))
      {
        LOG_ERROR << "read length: " << error.message();
        exit(1);
      }
      payload->length = ntohl(payload->length);
      assert(payload->length == sessionMessage.length);
      if (boost::asio::read(socket, boost::asio::buffer(payload->data, payload->length),
#if BOOST_VERSION < 104700L
                            boost::asio::transfer_all(),
#endif
                            error) != static_cast<size_t>(payload->length))
      {
        LOG_ERROR << "read payload data: " << error.message();
        exit(1);
      }
      int32_t ack = htonl(payload->length);
      if (boost::asio::write(socket, boost::asio::buffer(&ack, sizeof(ack))) != sizeof(ack))
      {
        LOG_ERROR << "write ack: " << error.message();
        exit(1);
      }
    }
  }
  catch (std::exception& e)
  {
    LOG_ERROR << e.what();
  }
}


================================================
FILE: examples/ace/ttcp/ttcp_blocking.cc
================================================
#include "examples/ace/ttcp/common.h"
#include "muduo/base/Timestamp.h"
#include "muduo/base/Types.h"

#undef NDEBUG

#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>

#include <netinet/in.h>
#include <arpa/inet.h>

static int acceptOrDie(uint16_t port)
{
  int listenfd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  assert(listenfd >= 0);

  int yes = 1;
  if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
  {
    perror("setsockopt");
    exit(1);
  }

  struct sockaddr_in addr;
  muduo::memZero(&addr, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);
  addr.sin_addr.s_addr = INADDR_ANY;
  if (bind(listenfd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)))
  {
    perror("bind");
    exit(1);
  }

  if (listen(listenfd, 5))
  {
    perror("listen");
    exit(1);
  }

  struct sockaddr_in peer_addr;
  muduo::memZero(&peer_addr, sizeof(peer_addr));
  socklen_t addrlen = 0;
  int sockfd = ::accept(listenfd, reinterpret_cast<struct sockaddr*>(&peer_addr), &addrlen);
  if (sockfd < 0)
  {
    perror("accept");
    exit(1);
  }
  ::close(listenfd);
  return sockfd;
}

static int write_n(int sockfd, const void* buf, int length)
{
  int written = 0;
  while (written < length)
  {
    ssize_t nw = ::write(sockfd, static_cast<const char*>(buf) + written, length - written);
    if (nw > 0)
    {
      written += static_cast<int>(nw);
    }
    else if (nw == 0)
    {
      break;  // EOF
    }
    else if (errno != EINTR)
    {
      perror("write");
      break;
    }
  }
  return written;
}

static int read_n(int sockfd, void* buf, int length)
{
  int nread = 0;
  while (nread < length)
  {
    ssize_t nr = ::read(sockfd, static_cast<char*>(buf) + nread, length - nread);
    if (nr > 0)
    {
      nread += static_cast<int>(nr);
    }
    else if (nr == 0)
    {
      break;  // EOF
    }
    else if (errno != EINTR)
    {
      perror("read");
      break;
    }
  }
  return nread;
}

void transmit(const Options& opt)
{
  struct sockaddr_in addr = resolveOrDie(opt.host.c_str(), opt.port);
  printf("connecting to %s:%d\n", inet_ntoa(addr.sin_addr), opt.port);

  int sockfd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  assert(sockfd >= 0);
  int ret = ::connect(sockfd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr));
  if (ret)
  {
    perror("connect");
    printf("Unable to connect %s\n", opt.host.c_str());
    ::close(sockfd);
    return;
  }

  printf("connected\n");
  muduo::Timestamp start(muduo::Timestamp::now());
  struct SessionMessage sessionMessage = { 0, 0 };
  sessionMessage.number = htonl(opt.number);
  sessionMessage.length = htonl(opt.length);
  if (write_n(sockfd, &sessionMessage, sizeof(sessionMessage)) != sizeof(sessionMessage))
  {
    perror("write SessionMessage");
    exit(1);
  }

  const int total_len = static_cast<int>(sizeof(int32_t) + opt.length);
  PayloadMessage* payload = static_cast<PayloadMessage*>(::malloc(total_len));
  assert(payload);
  payload->length = htonl(opt.length);
  for (int i = 0; i < opt.length; ++i)
  {
    payload->data[i] = "0123456789ABCDEF"[i % 16];
  }

  double total_mb = 1.0 * opt.length * opt.number / 1024 / 1024;
  printf("%.3f MiB in total\n", total_mb);

  for (int i = 0; i < opt.number; ++i)
  {
    int nw = write_n(sockfd, payload, total_len);
    assert(nw == total_len);

    int ack = 0;
    int nr = read_n(sockfd, &ack, sizeof(ack));
    assert(nr == sizeof(ack));
    ack = ntohl(ack);
    assert(ack == opt.length);
  }

  ::free(payload);
  ::close(sockfd);
  double elapsed = timeDifference(muduo::Timestamp::now(), start);
  printf("%.3f seconds\n%.3f MiB/s\n", elapsed, total_mb / elapsed);
}

void receive(const Options& opt)
{
  int sockfd = acceptOrDie(opt.port);

  struct SessionMessage sessionMessage = { 0, 0 };
  if (read_n(sockfd, &sessionMessage, sizeof(sessionMessage)) != sizeof(sessionMessage))
  {
    perror("read SessionMessage");
    exit(1);
  }

  sessionMessage.number = ntohl(sessionMessage.number);
  sessionMessage.length = ntohl(sessionMessage.length);
  printf("receive number = %d\nreceive length = %d\n",
         sessionMessage.number, sessionMessage.length);
  const int total_len = static_cast<int>(sizeof(int32_t) + sessionMessage.length);
  PayloadMessage* payload = static_cast<PayloadMessage*>(::malloc(total_len));
  assert(payload);

  for (int i = 0; i < sessionMessage.number; ++i)
  {
    payload->length = 0;
    if (read_n(sockfd, &payload->length, sizeof(payload->length)) != sizeof(payload->length))
    {
      perror("read length");
      exit(1);
    }
    payload->length = ntohl(payload->length);
    assert(payload->length == sessionMessage.length);
    if (read_n(sockfd, payload->data, payload->length) != payload->length)
    {
      perror("read payload data");
      exit(1);
    }
    int32_t ack = htonl(payload->length);
    if (write_n(sockfd, &ack, sizeof(ack)) != sizeof(ack))
    {
      perror("write ack");
      exit(1);
    }
  }
  ::free(payload);
  ::close(sockfd);
}



================================================
FILE: examples/asio/chat/CMakeLists.txt
================================================
add_executable(asio_chat_client client.cc)
target_link_libraries(asio_chat_client muduo_net)

add_executable(asio_chat_loadtest loadtest.cc)
target_link_libraries(asio_chat_loadtest muduo_net)

add_executable(asio_chat_server server.cc)
target_link_libraries(asio_chat_server muduo_net)

add_executable(asio_chat_server_threaded server_threaded.cc)
target_link_libraries(asio_chat_server_threaded muduo_net)

add_executable(asio_chat_server_threaded_efficient server_threaded_efficient.cc)
target_link_libraries(asio_chat_server_threaded_efficient muduo_net)

add_executable(asio_chat_server_threaded_highperformance server_threaded_highperformance.cc)
target_link_libraries(asio_chat_server_threaded_highperformance muduo_net)



================================================
FILE: examples/asio/chat/client.cc
================================================
#include "examples/asio/chat/codec.h"

#include "muduo/base/Logging.h"
#include "muduo/base/Mutex.h"
#include "muduo/net/EventLoopThread.h"
#include "muduo/net/TcpClient.h"

#include <iostream>
#include <stdio.h>
#include <unistd.h>

using namespace muduo;
using namespace muduo::net;

class ChatClient : noncopyable
{
 public:
  ChatClient(EventLoop* loop, const InetAddress& serverAddr)
    : client_(loop, serverAddr, "ChatClient"),
      codec_(std::bind(&ChatClient::onStringMessage, this, _1, _2, _3))
  {
    client_.setConnectionCallback(
        std::bind(&ChatClient::onConnection, this, _1));
    client_.setMessageCallback(
        std::bind(&LengthHeaderCodec::onMessage, &codec_, _1, _2, _3));
    client_.enableRetry();
  }

  void connect()
  {
    client_.connect();
  }

  void disconnect()
  {
    client_.disconnect();
  }

  void write(const StringPiece& message)
  {
    MutexLockGuard lock(mutex_);
    if (connection_)
    {
      codec_.send(get_pointer(connection_), message);
    }
  }

 private:
  void onConnection(const TcpConnectionPtr& conn)
  {
    LOG_INFO << conn->localAddress().toIpPort() << " -> "
             << conn->peerAddress().toIpPort() << " is "
             << (conn->connected() ? "UP" : "DOWN");

    MutexLockGuard lock(mutex_);
    if (conn->connected())
    {
      connection_ = conn;
    }
    else
    {
      connection_.reset();
    }
  }

  void onStringMessage(const TcpConnectionPtr&,
                       const string& message,
                       Timestamp)
  {
    printf("<<< %s\n", message.c_str());
  }

  TcpClient client_;
  LengthHeaderCodec codec_;
  MutexLock mutex_;
  TcpConnectionPtr connection_ GUARDED_BY(mutex_);
};

int main(int argc, char* argv[])
{
  LOG_INFO << "pid = " << getpid();
  if (argc > 2)
  {
    EventLoopThread loopThread;
    uint16_t port = static_cast<uint16_t>(atoi(argv[2]));
    InetAddress serverAddr(argv[1], port);

    ChatClient client(loopThread.startLoop(), serverAddr);
    client.connect();
    std::string line;
    while (std::getline(std::cin, line))
    {
      client.write(line);
    }
    client.disconnect();
    CurrentThread::sleepUsec(1000*1000);  // wait for disconnect, see ace/logging/client.cc
  }
  else
  {
    printf("Usage: %s host_ip port\n", argv[0]);
  }
}



================================================
FILE: examples/asio/chat/codec.h
================================================
#ifndef MUDUO_EXAMPLES_ASIO_CHAT_CODEC_H
#define MUDUO_EXAMPLES_ASIO_CHAT_CODEC_H

#include "muduo/base/Logging.h"
#include "muduo/net/Buffer.h"
#include "muduo/net/Endian.h"
#include "muduo/net/TcpConnection.h"

class LengthHeaderCodec : muduo::noncopyable
{
 public:
  typedef std::function<void (const muduo::net::TcpConnectionPtr&,
                                const muduo::string& message,
                                muduo::Timestamp)> StringMessageCallback;

  explicit LengthHeaderCodec(const StringMessageCallback& cb)
    : messageCallback_(cb)
  {
  }

  void onMessage(const muduo::net::TcpConnectionPtr& conn,
                 muduo::net::Buffer* buf,
                 muduo::Timestamp receiveTime)
  {
    while (buf->readableBytes() >= kHeaderLen) // kHeaderLen == 4
    {
      // FIXME: use Buffer::peekInt32()
      const void* data = buf->peek();
      int32_t be32 = *static_cast<const int32_t*>(data); // SIGBUS
      const int32_t len = muduo::net::sockets::networkToHost32(be32);
      if (len > 65536 || len < 0)
      {
        LOG_ERROR << "Invalid length " << len;
        conn->shutdown();  // FIXME: disable reading
        break;
      }
      else if (buf->readableBytes() >= len + kHeaderLen)
      {
        buf->retrieve(kHeaderLen);
        muduo::string message(buf->peek(), len);
        messageCallback_(conn, message, receiveTime);
        buf->retrieve(len);
      }
      else
      {
        break;
      }
    }
  }

  // FIXME: TcpConnectionPtr
  void send(muduo::net::TcpConnection* conn,
            const muduo::StringPiece& message)
  {
    muduo::net::Buffer buf;
    buf.append(message.data(), message.size());
    int32_t len = static_cast<int32_t>(message.size());
    int32_t be32 = muduo::net::sockets::hostToNetwork32(len);
    buf.prepend(&be32, sizeof be32);
    conn->send(&buf);
  }

 private:
  StringMessageCallback messageCallback_;
  const static size_t kHeaderLen = sizeof(int32_t);
};

#endif  // MUDUO_EXAMPLES_ASIO_CHAT_CODEC_H


================================================
FILE: examples/asio/chat/loadtest.cc
================================================
#include "examples/asio/chat/codec.h"

#include "muduo/base/Atomic.h"
#include "muduo/base/Logging.h"
#include "muduo/base/Mutex.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/EventLoopThreadPool.h"
#include "muduo/net/TcpClient.h"

#include <stdio.h>
#include <unistd.h>

using namespace muduo;
using namespace muduo::net;

int g_connections = 0;
AtomicInt32 g_aliveConnections;
AtomicInt32 g_messagesReceived;
Timestamp g_startTime;
std::vector<Timestamp> g_receiveTime;
EventLoop* g_loop;
std::function<void()> g_statistic;

class ChatClient : noncopyable
{
 public:
  ChatClient(EventLoop* loop, const InetAddress& serverAddr)
    : loop_(loop),
      client_(loop, serverAddr, "LoadTestClient"),
      codec_(std::bind(&ChatClient::onStringMessage, this, _1, _2, _3))
  {
    client_.setConnectionCallback(
        std::bind(&ChatClient::onConnection, this, _1));
    client_.setMessageCallback(
        std::bind(&LengthHeaderCodec::onMessage, &codec_, _1, _2, _3));
    //client_.enableRetry();
  }

  void connect()
  {
    client_.connect();
  }

  void disconnect()
  {
    // client_.disconnect();
  }

  Timestamp receiveTime() const { return receiveTime_; }

 private:
  void onConnection(const TcpConnectionPtr& conn)
  {
    LOG_INFO << conn->localAddress().toIpPort() << " -> "
             << conn->peerAddress().toIpPort() << " is "
             << (conn->connected() ? "UP" : "DOWN");

    if (conn->connected())
    {
      connection_ = conn;
      if (g_aliveConnections.incrementAndGet() == g_connections)
      {
        LOG_INFO << "all connected";
        loop_->runAfter(10.0, std::bind(&ChatClient::send, this));
      }
    }
    else
    {
      connection_.reset();
    }
  }

  void onStringMessage(const TcpConnectionPtr&,
                       const string& message,
                       Timestamp)
  {
    // printf("<<< %s\n", message.c_str());
    receiveTime_ = loop_->pollReturnTime();
    int received = g_messagesReceived.incrementAndGet();
    if (received == g_connections)
    {
      Timestamp endTime = Timestamp::now();
      LOG_INFO << "all received " << g_connections << " in "
               << timeDifference(endTime, g_startTime);
      g_loop->queueInLoop(g_statistic);
    }
    else if (received % 1000 == 0)
    {
      LOG_DEBUG << received;
    }
  }

  void send()
  {
    g_startTime = Timestamp::now();
    codec_.send(get_pointer(connection_), "hello");
    LOG_DEBUG << "sent";
  }

  EventLoop* loop_;
  TcpClient client_;
  LengthHeaderCodec codec_;
  TcpConnectionPtr connection_;
  Timestamp receiveTime_;
};

void statistic(const std::vector<std::unique_ptr<ChatClient>>& clients)
{
  LOG_INFO << "statistic " << clients.size();
  std::vector<double> seconds(clients.size());
  for (size_t i = 0; i < clients.size(); ++i)
  {
    seconds[i] = timeDifference(clients[i]->receiveTime(), g_startTime);
  }

  std::sort(seconds.begin(), seconds.end());
  for (size_t i = 0; i < clients.size(); i += std::max(static_cast<size_t>(1), clients.size()/20))
  {
    printf("%6zd%% %.6f\n", i*100/clients.size(), seconds[i]);
  }
  if (clients.size() >= 100)
  {
    printf("%6d%% %.6f\n", 99, seconds[clients.size() - clients.size()/100]);
  }
  printf("%6d%% %.6f\n", 100, seconds.back());
}

int main(int argc, char* argv[])
{
  LOG_INFO << "pid = " << getpid();
  if (argc > 3)
  {
    uint16_t port = static_cast<uint16_t>(atoi(argv[2]));
    InetAddress serverAddr(argv[1], port);
    g_connections = atoi(argv[3]);
    int threads = 0;
    if (argc > 4)
    {
      threads = atoi(argv[4]);
    }

    EventLoop loop;
    g_loop = &loop;
    EventLoopThreadPool loopPool(&loop, "chat-loadtest");
    loopPool.setThreadNum(threads);
    loopPool.start();

    g_receiveTime.reserve(g_connections);
    std::vector<std::unique_ptr<ChatClient>> clients(g_connections);
    g_statistic = std::bind(statistic, std::ref(clients));

    for (int i = 0; i < g_connections; ++i)
    {
      clients[i].reset(new ChatClient(loopPool.getNextLoop(), serverAddr));
      clients[i]->connect();
      usleep(200);
    }

    loop.loop();
    // client.disconnect();
  }
  else
  {
    printf("Usage: %s host_ip port connections [threads]\n", argv[0]);
  }
}




================================================
FILE: examples/asio/chat/server.cc
================================================
#include "examples/asio/chat/codec.h"

#include "muduo/base/Logging.h"
#include "muduo/base/Mutex.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/TcpServer.h"

#include <set>
#include <stdio.h>
#include <unistd.h>

using namespace muduo;
using namespace muduo::net;

class ChatServer : noncopyable
{
 public:
  ChatServer(EventLoop* loop,
             const InetAddress& listenAddr)
  : server_(loop, listenAddr, "ChatServer"),
    codec_(std::bind(&ChatServer::onStringMessage, this, _1, _2, _3))
  {
    server_.setConnectionCallback(
        std::bind(&ChatServer::onConnection, this, _1));
    server_.setMessageCallback(
        std::bind(&LengthHeaderCodec::onMessage, &codec_, _1, _2, _3));
  }

  void start()
  {
    server_.start();
  }

 private:
  void onConnection(const TcpConnectionPtr& conn)
  {
    LOG_INFO << conn->peerAddress().toIpPort() << " -> "
             << conn->localAddress().toIpPort() << " is "
             << (conn->connected() ? "UP" : "DOWN");

    if (conn->connected())
    {
      connections_.insert(conn);
    }
    else
    {
      connections_.erase(conn);
    }
  }

  void onStringMessage(const TcpConnectionPtr&,
                       const string& message,
                       Timestamp)
  {
    for (ConnectionList::iterator it = connections_.begin();
        it != connections_.end();
        ++it)
    {
      codec_.send(get_pointer(*it), message);
    }
  }

  typedef std::set<TcpConnectionPtr> ConnectionList;
  TcpServer server_;
  LengthHeaderCodec codec_;
  ConnectionList connections_;
};

int main(int argc, char* argv[])
{
  LOG_INFO << "pid = " << getpid();
  if (argc > 1)
  {
    EventLoop loop;
    uint16_t port = static_cast<uint16_t>(atoi(argv[1]));
    InetAddress serverAddr(port);
    ChatServer server(&loop, serverAddr);
    server.start();
    loop.loop();
  }
  else
  {
    printf("Usage: %s port\n", argv[0]);
  }
}



================================================
FILE: examples/asio/chat/server_threaded.cc
================================================
#include "examples/asio/chat/codec.h"

#include "muduo/base/Logging.h"
#include "muduo/base/Mutex.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/TcpServer.h"

#include <set>
#include <stdio.h>
#include <unistd.h>

using namespace muduo;
using namespace muduo::net;

class ChatServer : noncopyable
{
 public:
  ChatServer(EventLoop* loop,
             const InetAddress& listenAddr)
  : server_(loop, listenAddr, "ChatServer"),
    codec_(std::bind(&ChatServer::onStringMessage, this, _1, _2, _3))
  {
    server_.setConnectionCallback(
        std::bind(&ChatServer::onConnection, this, _1));
    server_.setMessageCallback(
        std::bind(&LengthHeaderCodec::onMessage, &codec_, _1, _2, _3));
  }

  void setThreadNum(int numThreads)
  {
    server_.setThreadNum(numThreads);
  }

  void start()
  {
    server_.start();
  }

 private:
  void onConnection(const TcpConnectionPtr& conn)
  {
    LOG_INFO << conn->peerAddress().toIpPort() << " -> "
        << conn->localAddress().toIpPort() << " is "
        << (conn->connected() ? "UP" : "DOWN");

    MutexLockGuard lock(mutex_);
    if (conn->connected())
    {
      connections_.insert(conn);
    }
    else
    {
      connections_.erase(conn);
    }
  }

  void onStringMessage(const TcpConnectionPtr&,
                       const string& message,
                       Timestamp)
  {
    MutexLockGuard lock(mutex_);
    for (ConnectionList::iterator it = connections_.begin();
        it != connections_.end();
        ++it)
    {
      codec_.send(get_pointer(*it), message);
    }
  }

  typedef std::set<TcpConnectionPtr> ConnectionList;
  TcpServer server_;
  LengthHeaderCodec codec_;
  MutexLock mutex_;
  ConnectionList connections_ GUARDED_BY(mutex_);
};

int main(int argc, char* argv[])
{
  LOG_INFO << "pid = " << getpid();
  if (argc > 1)
  {
    EventLoop loop;
    uint16_t port = static_cast<uint16_t>(atoi(argv[1]));
    InetAddress serverAddr(port);
    ChatServer server(&loop, serverAddr);
    if (argc > 2)
    {
      server.setThreadNum(atoi(argv[2]));
    }
    server.start();
    loop.loop();
  }
  else
  {
    printf("Usage: %s port [thread_num]\n", argv[0]);
  }
}



================================================
FILE: examples/asio/chat/server_threaded_efficient.cc
================================================
#include "examples/asio/chat/codec.h"

#include "muduo/base/Logging.h"
#include "muduo/base/Mutex.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/TcpServer.h"

#include <set>
#include <stdio.h>
#include <unistd.h>

using namespace muduo;
using namespace muduo::net;

class ChatServer : noncopyable
{
 public:
  ChatServer(EventLoop* loop,
             const InetAddress& listenAddr)
  : server_(loop, listenAddr, "ChatServer"),
    codec_(std::bind(&ChatServer::onStringMessage, this, _1, _2, _3)),
    connections_(new ConnectionList)
  {
    server_.setConnectionCallback(
        std::bind(&ChatServer::onConnection, this, _1));
    server_.setMessageCallback(
        std::bind(&LengthHeaderCodec::onMessage, &codec_, _1, _2, _3));
  }

  void setThreadNum(int numThreads)
  {
    server_.setThreadNum(numThreads);
  }

  void start()
  {
    server_.start();
  }

 private:
  void onConnection(const TcpConnectionPtr& conn)
  {
    LOG_INFO << conn->peerAddress().toIpPort() << " -> "
        << conn->localAddress().toIpPort() << " is "
        << (conn->connected() ? "UP" : "DOWN");

    MutexLockGuard lock(mutex_);
    if (!connections_.unique())
    {
      connections_.reset(new ConnectionList(*connections_));
    }
    assert(connections_.unique());

    if (conn->connected())
    {
      connections_->insert(conn);
    }
    else
    {
      connections_->erase(conn);
    }
  }

  typedef std::set<TcpConnectionPtr> ConnectionList;
  typedef std::shared_ptr<ConnectionList> ConnectionListPtr;

  void onStringMessage(const TcpConnectionPtr&,
                       const string& message,
                       Timestamp)
  {
    ConnectionListPtr connections = getConnectionList();
    for (ConnectionList::iterator it = connections->begin();
        it != connections->end();
        ++it)
    {
      codec_.send(get_pointer(*it), message);
    }
  }

  ConnectionListPtr getConnectionList()
  {
    MutexLockGuard lock(mutex_);
    return connections_;
  }

  TcpServer server_;
  LengthHeaderCodec codec_;
  MutexLock mutex_;
  ConnectionListPtr connections_ GUARDED_BY(mutex_);
};

int main(int argc, char* argv[])
{
  LOG_INFO << "pid = " << getpid();
  if (argc > 1)
  {
    EventLoop loop;
    uint16_t port = static_cast<uint16_t>(atoi(argv[1]));
    InetAddress serverAddr(port);
    ChatServer server(&loop, serverAddr);
    if (argc > 2)
    {
      server.setThreadNum(atoi(argv[2]));
    }
    server.start();
    loop.loop();
  }
  else
  {
    printf("Usage: %s port [thread_num]\n", argv[0]);
  }
}



================================================
FILE: examples/asio/chat/server_threaded_highperformance.cc
================================================
#include "examples/asio/chat/codec.h"

#include "muduo/base/Logging.h"
#include "muduo/base/Mutex.h"
#include "muduo/base/ThreadLocalSingleton.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/TcpServer.h"

#include <set>
#include <stdio.h>
#include <unistd.h>

using namespace muduo;
using namespace muduo::net;

class ChatServer : noncopyable
{
 public:
  ChatServer(EventLoop* loop,
             const InetAddress& listenAddr)
  : server_(loop, listenAddr, "ChatServer"),
    codec_(std::bind(&ChatServer::onStringMessage, this, _1, _2, _3))
  {
    server_.setConnectionCallback(
        std::bind(&ChatServer::onConnection, this, _1));
    server_.setMessageCallback(
        std::bind(&LengthHeaderCodec::onMessage, &codec_, _1, _2, _3));
  }

  void setThreadNum(int numThreads)
  {
    server_.setThreadNum(numThreads);
  }

  void start()
  {
    server_.setThreadInitCallback(std::bind(&ChatServer::threadInit, this, _1));
    server_.start();
  }

 private:
  void onConnection(const TcpConnectionPtr& conn)
  {
    LOG_INFO << conn->peerAddress().toIpPort() << " -> "
             << conn->localAddress().toIpPort() << " is "
             << (conn->connected() ? "UP" : "DOWN");

    if (conn->connected())
    {
      LocalConnections::instance().insert(conn);
    }
    else
    {
      LocalConnections::instance().erase(conn);
    }
  }

  void onStringMessage(const TcpConnectionPtr&,
                       const string& message,
                       Timestamp)
  {
    EventLoop::Functor f = std::bind(&ChatServer::distributeMessage, this, message);
    LOG_DEBUG;

    MutexLockGuard lock(mutex_);
    for (std::set<EventLoop*>::iterator it = loops_.begin();
        it != loops_.end();
        ++it)
    {
      (*it)->queueInLoop(f);
    }
    LOG_DEBUG;
  }

  typedef std::set<TcpConnectionPtr> ConnectionList;

  void distributeMessage(const string& message)
  {
    LOG_DEBUG << "begin";
    for (ConnectionList::iterator it = LocalConnections::instance().begin();
        it != LocalConnections::instance().end();
        ++it)
    {
      codec_.send(get_pointer(*it), message);
    }
    LOG_DEBUG << "end";
  }

  void threadInit(EventLoop* loop)
  {
    assert(LocalConnections::pointer() == NULL);
    LocalConnections::instance();
    assert(LocalConnections::pointer() != NULL);
    MutexLockGuard lock(mutex_);
    loops_.insert(loop);
  }

  TcpServer server_;
  LengthHeaderCodec codec_;
  typedef ThreadLocalSingleton<ConnectionList> LocalConnections;

  MutexLock mutex_;
  std::set<EventLoop*> loops_ GUARDED_BY(mutex_);
};

int main(int argc, char* argv[])
{
  LOG_INFO << "pid = " << getpid();
  if (argc > 1)
  {
    EventLoop loop;
    uint16_t port = static_cast<uint16_t>(atoi(argv[1]));
    InetAddress serverAddr(port);
    ChatServer server(&loop, serverAddr);
    if (argc > 2)
    {
      server.setThreadNum(atoi(argv[2]));
    }
    server.start();
    loop.loop();
  }
  else
  {
    printf("Usage: %s port [thread_num]\n", argv[0]);
  }
}




================================================
FILE: examples/asio/echo_see_simple
================================================


================================================
FILE: examples/asio/tutorial/CMakeLists.txt
================================================
add_executable(asio_tutorial_timer2 timer2/timer.cc)
target_link_libraries(asio_tutorial_timer2 muduo_net)

add_executable(asio_tutorial_timer3 timer3/timer.cc)
target_link_libraries(asio_tutorial_timer3 muduo_net)

add_executable(asio_tutorial_timer4 timer4/timer.cc)
target_link_libraries(asio_tutorial_timer4 muduo_net)

add_executable(asio_tutorial_timer5 timer5/timer.cc)
target_link_libraries(asio_tutorial_timer5 muduo_net)

add_executable(asio_tutorial_timer6 timer6/timer.cc)
target_link_libraries(asio_tutorial_timer6 muduo_net)



================================================
FILE: examples/asio/tutorial/daytime_see_simple
================================================


================================================
FILE: examples/asio/tutorial/there_is_no_timer1
================================================


================================================
FILE: examples/asio/tutorial/timer2/timer.cc
================================================
#include "muduo/net/EventLoop.h"

#include <iostream>

void print()
{
  std::cout << "Hello, world!\n";
}

int main()
{
  muduo::net::EventLoop loop;
  loop.runAfter(5, print);
  loop.loop();
}



================================================
FILE: examples/asio/tutorial/timer3/timer.cc
================================================
#include "muduo/net/EventLoop.h"

#include <iostream>

void print(muduo::net::EventLoop* loop, int* count)
{
  if (*count < 5)
  {
    std::cout << *count << "\n";
    ++(*count);

    loop->runAfter(1, std::bind(print, loop, count));
  }
  else
  {
    loop->quit();
  }
}

int main()
{
  muduo::net::EventLoop loop;
  int count = 0;
  // Note: loop.runEvery() is better for this use case.
  loop.runAfter(1, std::bind(print, &loop, &count));
  loop.loop();
  std::cout << "Final count is " << count << "\n";
}



================================================
FILE: examples/asio/tutorial/timer4/timer.cc
================================================
#include "muduo/net/EventLoop.h"

#include <iostream>

class Printer : muduo::noncopyable
{
 public:
  Printer(muduo::net::EventLoop* loop)
    : loop_(loop),
      count_(0)
  {
    // Note: loop.runEvery() is better for this use case.
    loop_->runAfter(1, std::bind(&Printer::print, this));
  }

  ~Printer()
  {
    std::cout << "Final count is " << count_ << "\n";
  }

  void print()
  {
    if (count_ < 5)
    {
      std::cout << count_ << "\n";
      ++count_;

      loop_->runAfter(1, std::bind(&Printer::print, this));
    }
    else
    {
      loop_->quit();
    }
  }

private:
  muduo::net::EventLoop* loop_;
  int count_;
};

int main()
{
  muduo::net::EventLoop loop;
  Printer printer(&loop);
  loop.loop();
}



================================================
FILE: examples/asio/tutorial/timer5/timer.cc
================================================
#include "muduo/base/Mutex.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/EventLoopThread.h"

#include <iostream>

class Printer : muduo::noncopyable
{
 public:
  Printer(muduo::net::EventLoop* loop1, muduo::net::EventLoop* loop2)
    : loop1_(loop1),
      loop2_(loop2),
      count_(0)
  {
    loop1_->runAfter(1, std::bind(&Printer::print1, this));
    loop2_->runAfter(1, std::bind(&Printer::print2, this));
  }

  ~Printer()
  {
    std::cout << "Final count is " << count_ << "\n";
  }

  void print1()
  {
    muduo::MutexLockGuard lock(mutex_);
    if (count_ < 10)
    {
      std::cout << "Timer 1: " << count_ << "\n";
      ++count_;

      loop1_->runAfter(1, std::bind(&Printer::print1, this));
    }
    else
    {
      loop1_->quit();
    }
  }

  void print2()
  {
    muduo::MutexLockGuard lock(mutex_);
    if (count_ < 10)
    {
      std::cout << "Timer 2: " << count_ << "\n";
      ++count_;

      loop2_->runAfter(1, std::bind(&Printer::print2, this));
    }
    else
    {
      loop2_->quit();
    }
  }

private:

  muduo::MutexLock mutex_;
  muduo::net::EventLoop* loop1_ PT_GUARDED_BY(mutex_);
  muduo::net::EventLoop* loop2_ PT_GUARDED_BY(mutex_);
  int count_ GUARDED_BY(mutex_);
};

int main()
{
  std::unique_ptr<Printer> printer;  // make sure printer lives longer than loops, to avoid
                                     // race condition of calling print2() on destructed object.
  muduo::net::EventLoop loop;
  muduo::net::EventLoopThread loopThread;
  muduo::net::EventLoop* loopInAnotherThread = loopThread.startLoop();
  printer.reset(new Printer(&loop, loopInAnotherThread));
  loop.loop();
}



================================================
FILE: examples/asio/tutorial/timer6/timer.cc
================================================
#include "muduo/base/Mutex.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/EventLoopThread.h"

#include <stdio.h>

//
// Minimize locking
//

class Printer : muduo::noncopyable
{
 public:
  Printer(muduo::net::EventLoop* loop1, muduo::net::EventLoop* loop2)
    : loop1_(loop1),
      loop2_(loop2),
      count_(0)
  {
    loop1_->runAfter(1, std::bind(&Printer::print1, this));
    loop2_->runAfter(1, std::bind(&Printer::print2, this));
  }

  ~Printer()
  {
    // cout is not thread safe
    //std::cout << "Final count is " << count_ << "\n";
    printf("Final count is %d\n", count_);
  }

  void print1()
  {
    bool shouldQuit = false;
    int count = 0;

    {
      muduo::MutexLockGuard lock(mutex_);
      if (count_ < 10)
      {
        count = count_;
        ++count_;
      }
      else
      {
        shouldQuit = true;
      }
    }

    // out of lock
    if (shouldQuit)
    {
      // printf("loop1_->quit()\n");
      loop1_->quit();
    }
    else
    {
      // cout is not thread safe
      //std::cout << "Timer 1: " << count << "\n";
      printf("Timer 1: %d\n", count);
      loop1_->runAfter(1, std::bind(&Printer::print1, this));
    }
  }

  void print2()
  {
    bool shouldQuit = false;
    int count = 0;

    {
      muduo::MutexLockGuard lock(mutex_);
      if (count_ < 10)
      {
        count = count_;
        ++count_;
      }
      else
      {
        shouldQuit = true;
      }
    }

    // out of lock
    if (shouldQuit)
    {
      // printf("loop2_->quit()\n");
      loop2_->quit();
    }
    else
    {
      // cout is not thread safe
      //std::cout << "Timer 2: " << count << "\n";
      printf("Timer 2: %d\n", count);
      loop2_->runAfter(1, std::bind(&Printer::print2, this));
    }
  }

private:

  muduo::MutexLock mutex_;
  muduo::net::EventLoop* loop1_;
  muduo::net::EventLoop* loop2_;
  int count_ GUARDED_BY(mutex_);
};

int main()
{
  std::unique_ptr<Printer> printer;  // make sure printer lives longer than loops, to avoid
                                     // race condition of calling print2() on destructed object.
  muduo::net::EventLoop loop;
  muduo::net::EventLoopThread loopThread;
  muduo::net::EventLoop* loopInAnotherThread = loopThread.startLoop();
  printer.reset(new Printer(&loop, loopInAnotherThread));
  loop.loop();
}



================================================
FILE: examples/cdns/CMakeLists.txt
================================================
add_library(muduo_cdns Resolver.cc)
target_link_libraries(muduo_cdns muduo_net)
target_link_libraries(muduo_cdns cares)

install(TARGETS muduo_cdns DESTINATION lib)
install(FILES Resolver.h DESTINATION include/muduo/cdns)

add_executable(cdns dns.cc)
target_link_libraries(cdns muduo_cdns)



================================================
FILE: examples/cdns/Resolver.cc
================================================
#include "examples/cdns/Resolver.h"

#include "muduo/base/Logging.h"
#include "muduo/net/Channel.h"
#include "muduo/net/EventLoop.h"

#include <ares.h>
#include <netdb.h>
#include <arpa/inet.h>  // inet_ntop
#include <netinet/in.h>

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

using namespace muduo;
using namespace muduo::net;
using namespace cdns;

namespace
{
double getSeconds(struct timeval* tv)
{
  if (tv)
    return double(tv->tv_sec) + double(tv->tv_usec)/1000000.0;
  else
    return -1.0;
}

const char* getSocketType(int type)
{
  if (type == SOCK_DGRAM)
    return "UDP";
  else if (type == SOCK_STREAM)
    return "TCP";
  else
    return "Unknown";
}

const bool kDebug = false;
}  // namespace

Resolver::Resolver(EventLoop* loop, Option opt)
  : loop_(loop),
    ctx_(NULL),
    timerActive_(false)
{
  static char lookups[] = "b";
  struct ares_options options;
  int optmask = ARES_OPT_FLAGS;
  options.flags = ARES_FLAG_NOCHECKRESP;
  options.flags |= ARES_FLAG_STAYOPEN;
  options.flags |= ARES_FLAG_IGNTC; // UDP only
  optmask |= ARES_OPT_SOCK_STATE_CB;
  options.sock_state_cb = &Resolver::ares_sock_state_callback;
  options.sock_state_cb_data = this;
  optmask |= ARES_OPT_TIMEOUT;
  options.timeout = 2;
  if (opt == kDNSonly)
  {
    optmask |= ARES_OPT_LOOKUPS;
    options.lookups = lookups;
  }

  int status = ares_init_options(&ctx_, &options, optmask);
  if (status != ARES_SUCCESS)
  {
    assert(0);
  }
  ares_set_socket_callback(ctx_, &Resolver::ares_sock_create_callback, this);
}

Resolver::~Resolver()
{
  ares_destroy(ctx_);
}

bool Resolver::resolve(StringArg hostname, const Callback& cb)
{
  loop_->assertInLoopThread();
  QueryData* queryData = new QueryData(this, cb);
  ares_gethostbyname(ctx_, hostname.c_str(), AF_INET,
      &Resolver::ares_host_callback, queryData);
  struct timeval tv;
  struct timeval* tvp = ares_timeout(ctx_, NULL, &tv);
  double timeout = getSeconds(tvp);
  LOG_DEBUG << "timeout " <<  timeout << " active " << timerActive_;
  if (!timerActive_)
  {
    loop_->runAfter(timeout, std::bind(&Resolver::onTimer, this));
    timerActive_ = true;
  }
  return queryData != NULL;
}

void Resolver::onRead(int sockfd, Timestamp t)
{
  LOG_DEBUG << "onRead " << sockfd << " at " << t.toString();
  ares_process_fd(ctx_, sockfd, ARES_SOCKET_BAD);
}

void Resolver::onTimer()
{
  assert(timerActive_ == true);
  ares_process_fd(ctx_, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
  struct timeval tv;
  struct timeval* tvp = ares_timeout(ctx_, NULL, &tv);
  double timeout = getSeconds(tvp);
  LOG_DEBUG << loop_->pollReturnTime().toString() << " next timeout " <<  timeout;

  if (timeout < 0)
  {
    timerActive_ = false;
  }
  else
  {
    loop_->runAfter(timeout, std::bind(&Resolver::onTimer, this));
  }
}

void Resolver::onQueryResult(int status, struct hostent* result, const Callback& callback)
{
  LOG_DEBUG << "onQueryResult " << status;
  struct sockaddr_in addr;
  memZero(&addr, sizeof addr);
  addr.sin_family = AF_INET;
  addr.sin_port = 0;
  if (result)
  {
    addr.sin_addr = *reinterpret_cast<in_addr*>(result->h_addr);
    if (kDebug)
    {
      printf("h_name %s\n", result->h_name);
      for (char** alias = result->h_aliases; *alias != NULL; ++alias)
      {
        printf("alias: %s\n", *alias);
      }
      // printf("ttl %d\n", ttl);
      // printf("h_length %d\n", result->h_length);
      for (char** haddr = result->h_addr_list; *haddr != NULL; ++haddr)
      {
        char buf[32];
        inet_ntop(AF_INET, *haddr, buf, sizeof buf);
        printf("  %s\n", buf);
      }
    }
  }
  InetAddress inet(addr);
  callback(inet);
}

void Resolver::onSockCreate(int sockfd, int type)
{
  loop_->assertInLoopThread();
  assert(channels_.find(sockfd) == channels_.end());
  Channel* channel = new Channel(loop_, sockfd);
  channel->setReadCallback(std::bind(&Resolver::onRead, this, sockfd, _1));
  channel->enableReading();
  channels_[sockfd].reset(channel);
}

void Resolver::onSockStateChange(int sockfd, bool read, bool write)
{
  loop_->assertInLoopThread();
  ChannelList::iterator it = channels_.find(sockfd);
  assert(it != channels_.end());
  if (read)
  {
    // update
    // if (write) { } else { }
  }
  else
  {
    // remove
    it->second->disableAll();
    it->second->remove();
    channels_.erase(it);
  }
}

void Resolver::ares_host_callback(void* data, int status, int timeouts, struct hostent* hostent)
{
  QueryData* query = static_cast<QueryData*>(data);

  query->owner->onQueryResult(status, hostent, query->callback);
  delete query;
}

int Resolver::ares_sock_create_callback(int sockfd, int type, void* data)
{
  LOG_TRACE << "sockfd=" << sockfd << " type=" << getSocketType(type);
  static_cast<Resolver*>(data)->onSockCreate(sockfd, type);
  return 0;
}

void Resolver::ares_sock_state_callback(void* data, int sockfd, int read, int write)
{
  LOG_TRACE << "sockfd=" << sockfd << " read=" << read << " write=" << write;
  static_cast<Resolver*>(data)->onSockStateChange(sockfd, read, write);
}



================================================
FILE: examples/cdns/Resolver.h
================================================
#ifndef MUDUO_EXAMPLES_CDNS_RESOLVER_H
#define MUDUO_EXAMPLES_CDNS_RESOLVER_H

#include "muduo/base/noncopyable.h"
#include "muduo/base/StringPiece.h"
#include "muduo/base/Timestamp.h"
#include "muduo/net/InetAddress.h"

#include <functional>
#include <map>
#include <memory>

extern "C"
{
  struct hostent;
  struct ares_channeldata;
  typedef struct ares_channeldata* ares_channel;
}

namespace muduo
{
namespace net
{
class Channel;
class EventLoop;
}
}

namespace cdns
{

class Resolver : muduo::noncopyable
{
 public:
  typedef std::function<void(const muduo::net::InetAddress&)> Callback;
  enum Option
  {
    kDNSandHostsFile,
    kDNSonly,
  };

  explicit Resolver(muduo::net::EventLoop* loop, Option opt = kDNSandHostsFile);
  ~Resolver();

  bool resolve(muduo::StringArg hostname, const Callback& cb);

 private:

  struct QueryData
  {
    Resolver* owner;
    Callback callback;
    QueryData(Resolver* o, const Callback& cb)
      : owner(o), callback(cb)
    {
    }
  };

  muduo::net::EventLoop* loop_;
  ares_channel ctx_;
  bool timerActive_;
  typedef std::map<int, std::unique_ptr<muduo::net::Channel>> ChannelList;
  ChannelList channels_;

  void onRead(int sockfd, muduo::Timestamp t);
  void onTimer();
  void onQueryResult(int status, struct hostent* result, const Callback& cb);
  void onSockCreate(int sockfd, int type);
  void onSockStateChange(int sockfd, bool read, bool write);

  static void ares_host_callback(void* data, int status, int timeouts, struct hostent* hostent);
  static int ares_sock_create_callback(int sockfd, int type, void* data);
  static void ares_sock_state_callback(void* data, int sockfd, int read, int write);
};
}  // namespace cdns

#endif  // MUDUO_EXAMPLES_CDNS_RESOLVER_H


================================================
FILE: examples/cdns/dns.cc
================================================
#include "examples/cdns/Resolver.h"
#include "muduo/net/EventLoop.h"
#include <stdio.h>

using namespace muduo;
using namespace muduo::net;
using namespace cdns;

EventLoop* g_loop;
int count = 0;
int total = 0;

void quit()
{
  g_loop->quit();
}

void resolveCallback(const string& host, const InetAddress& addr)
{
  printf("resolveCallback %s -> %s\n", host.c_str(), addr.toIpPort().c_str());
  if (++count == total)
    quit();
}

void resolve(Resolver* res, const string& host)
{
  res->resolve(host, std::bind(&resolveCallback, host, _1));
}

int main(int argc, char* argv[])
{
  EventLoop loop;
  loop.runAfter(10, quit);
  g_loop = &loop;
  Resolver resolver(&loop,
                   argc == 1 ? Resolver::kDNSonly : Resolver::kDNSandHostsFile);
  if (argc == 1)
  {
    total = 3;
    resolve(&resolver, "www.chenshuo.com");
    resolve(&resolver, "www.example.com");
    resolve(&resolver, "www.google.com");
  }
  else
  {
    total = argc-1;
    for (int i = 1; i < argc; ++i)
      resolve(&resolver, argv[i]);
  }
  loop.loop();
}


================================================
FILE: examples/curl/CMakeLists.txt
================================================
add_library(muduo_curl Curl.cc)
target_link_libraries(muduo_curl muduo_net)
target_link_libraries(muduo_curl curl)

install(TARGETS muduo_curl DESTINATION lib)
install(FILES Curl.h DESTINATION include/muduo/curl)

add_executable(mcurl mcurl.cc)
target_link_libraries(mcurl muduo_curl)

add_executable(curl_download download.cc)
target_link_libraries(curl_download muduo_curl)



================================================
FILE: examples/curl/Curl.cc
================================================
#include "examples/curl/Curl.h"
#include "muduo/base/Logging.h"
#include "muduo/net/Channel.h"
#include "muduo/net/EventLoop.h"

#include <curl/curl.h>
#include <assert.h>

using namespace curl;
using namespace muduo;
using namespace muduo::net;

static void dummy(const std::shared_ptr<Channel>&)
{
}

Request::Request(Curl* owner, const char* url)
  : owner_(owner),
    curl_(CHECK_NOTNULL(curl_easy_init()))
{
  setopt(CURLOPT_URL, url);
  setopt(CURLOPT_WRITEFUNCTION, &Request::writeData);
  setopt(CURLOPT_WRITEDATA, this);
  setopt(CURLOPT_HEADERFUNCTION, &Request::headerData);
  setopt(CURLOPT_HEADERDATA, this);
  setopt(CURLOPT_PRIVATE, this);
  setopt(CURLOPT_USERAGENT, "curl");
  // set useragent
  LOG_DEBUG << curl_ << " " << url;
  curl_multi_add_handle(owner_->getCurlm(), curl_);
}

Request::~Request()
{
  assert(!channel_ || channel_->isNoneEvent());
  curl_multi_remove_handle(owner_->getCurlm(), curl_);
  curl_easy_cleanup(curl_);
}

// NOT implemented yet
//
// void Request::allowRedirect(int redirects)
// {
//   setopt(CURLOPT_FOLLOWLOCATION, 1);
//   setopt(CURLOPT_MAXREDIRS, redirects);
// }

void Request::headerOnly()
{
  setopt(CURLOPT_NOBODY, 1);
}

void Request::setRange(const StringArg range)
{
  setopt(CURLOPT_RANGE, range.c_str());
}

const char* Request::getEffectiveUrl()
{
  const char* p = NULL;
  curl_easy_getinfo(curl_, CURLINFO_EFFECTIVE_URL, &p);
  return p;
}

const char* Request::getRedirectUrl()
{
  const char* p = NULL;
  curl_easy_getinfo(curl_, CURLINFO_REDIRECT_URL, &p);
  return p;
}

int Request::getResponseCode()
{
  long code = 0;
  curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, &code);
  return static_cast<int>(code);
}

Channel* Request::setChannel(int fd)
{
  assert(channel_.get() == NULL);
  channel_.reset(new Channel(owner_->getLoop(), fd));
  channel_->tie(shared_from_this());
  return get_pointer(channel_);
}

void Request::removeChannel()
{
  channel_->disableAll();
  channel_->remove();
  owner_->getLoop()->queueInLoop(std::bind(dummy, channel_));
  channel_.reset();
}

void Request::done(int code)
{
  if (doneCb_)
  {
    doneCb_(this, code);
  }
}

void Request::dataCallback(const char* buffer, int len)
{
  if (dataCb_)
  {
    dataCb_(buffer, len);
  }
}

void Request::headerCallback(const char* buffer, int len)
{
  if (headerCb_)
  {
    headerCb_(buffer, len);
  }
}

size_t Request::writeData(char* buffer, size_t size, size_t nmemb, void* userp)
{
  assert(size == 1);
  Request* req = static_cast<Request*>(userp);
  req->dataCallback(buffer, static_cast<int>(nmemb));
  return nmemb;
}

size_t Request::headerData(char* buffer, size_t size, size_t nmemb, void* userp)
{
  assert(size == 1);
  Request* req = static_cast<Request*>(userp);
  req->headerCallback(buffer, static_cast<int>(nmemb));
  return nmemb;
}

// ==================================================================

void Curl::initialize(Option opt)
{
  curl_global_init(opt == kCURLnossl ? CURL_GLOBAL_NOTHING : CURL_GLOBAL_SSL);
}

int Curl::socketCallback(CURL* c, int fd, int what, void* userp, void* socketp)
{
  Curl* curl = static_cast<Curl*>(userp);
  const char *whatstr[]={ "none", "IN", "OUT", "INOUT", "REMOVE" };
  LOG_DEBUG << "Curl::socketCallback [" << curl << "] - fd = " << fd
            << " what = " << whatstr[what];
  Request* req = NULL;
  curl_easy_getinfo(c, CURLINFO_PRIVATE, &req);
  assert(req->getCurl() == c);
  if (what == CURL_POLL_REMOVE)
  {
    muduo::net::Channel* ch = static_cast<Channel*>(socketp);
    assert(req->getChannel() == ch);
    req->removeChannel();
    ch = NULL;
    curl_multi_assign(curl->curlm_, fd, ch);
  }
  else
  {
    muduo::net::Channel* ch = static_cast<Channel*>(socketp);
    if (!ch)
    {
      ch = req->setChannel(fd);
      ch->setReadCallback(std::bind(&Curl::onRead, curl, fd));
      ch->setWriteCallback(std::bind(&Curl::onWrite, curl, fd));
      ch->enableReading();
      curl_multi_assign(curl->curlm_, fd, ch);
      LOG_TRACE << "new channel for fd=" << fd;
    }
    assert(req->getChannel() == ch);
    // update
    if (what & CURL_POLL_OUT)
    {
      ch->enableWriting();
    }
    else
    {
      ch->disableWriting();
    }
  }
  return 0;
}

int Curl::timerCallback(CURLM* curlm, long ms, void* userp)
{
  Curl* curl = static_cast<Curl*>(userp);
  LOG_DEBUG << curl << " " << ms << " ms";
  curl->loop_->runAfter(static_cast<int>(ms)/1000.0, std::bind(&Curl::onTimer, curl));
  return 0;
}

Curl::Curl(EventLoop* loop)
  : loop_(loop),
    curlm_(CHECK_NOTNULL(curl_multi_init())),
    runningHandles_(0),
    prevRunningHandles_(0)
{
  curl_multi_setopt(curlm_, CURLMOPT_SOCKETFUNCTION, &Curl::socketCallback);
  curl_multi_setopt(curlm_, CURLMOPT_SOCKETDATA, this);
  curl_multi_setopt(curlm_, CURLMOPT_TIMERFUNCTION, &Curl::timerCallback);
  curl_multi_setopt(curlm_, CURLMOPT_TIMERDATA, this);
}

Curl::~Curl()
{
  curl_multi_cleanup(curlm_);
}

RequestPtr Curl::getUrl(StringArg url)
{
  RequestPtr req(new Request(this, url.c_str()));
  return req;
}

void Curl::onTimer()
{
  CURLMcode rc = CURLM_OK;
  do {
    LOG_TRACE;
    rc = curl_multi_socket_action(curlm_, CURL_SOCKET_TIMEOUT, 0, &runningHandles_);
    LOG_TRACE << rc << " " << runningHandles_;
  } while (rc == CURLM_CALL_MULTI_PERFORM);
  checkFinish();
}

void Curl::onRead(int fd)
{
  CURLMcode rc = CURLM_OK;
  do {
    LOG_TRACE << fd;
    rc = curl_multi_socket_action(curlm_, fd, CURL_POLL_IN, &runningHandles_);
    LOG_TRACE << fd << " " << rc << " " << runningHandles_;
  } while (rc == CURLM_CALL_MULTI_PERFORM);
  checkFinish();
}

void Curl::onWrite(int fd)
{
  CURLMcode rc = CURLM_OK;
  do {
    LOG_TRACE << fd;
    rc = curl_multi_socket_action(curlm_, fd, CURL_POLL_OUT, &runningHandles_);
    LOG_TRACE << fd << " " << rc << " " << runningHandles_;
  } while (rc == CURLM_CALL_MULTI_PERFORM);
  checkFinish();
}

void Curl::checkFinish()
{
  if (prevRunningHandles_ > runningHandles_ || runningHandles_ == 0)
  {
    CURLMsg* msg = NULL;
    int left = 0;
    while ( (msg = curl_multi_info_read(curlm_, &left)) != NULL)
    {
      if (msg->msg == CURLMSG_DONE)
      {
        CURL* c = msg->easy_handle;
        CURLcode res = msg->data.result;
        Request* req = NULL;
        curl_easy_getinfo(c, CURLINFO_PRIVATE, &req);
        assert(req->getCurl() == c);
        LOG_TRACE << req << " done";
        req->done(res);
      }
    }
  }
  prevRunningHandles_ = runningHandles_;
}


================================================
FILE: examples/curl/Curl.h
================================================
#ifndef MUDUO_EXAMPLES_CURL_CURL_H
#define MUDUO_EXAMPLES_CURL_CURL_H

#include "muduo/base/noncopyable.h"
#include "muduo/base/StringPiece.h"

#include "muduo/net/Callbacks.h"

extern "C"
{
typedef void CURLM;
typedef void CURL;
}

namespace muduo
{
namespace net
{
class Channel;
class EventLoop;
}
}

namespace curl
{

class Curl;

class Request : public std::enable_shared_from_this<Request>,
                muduo::noncopyable
{
 public:
  typedef std::function<void(const char*, int)> DataCallback;
  typedef std::function<void(Request*, int)> DoneCallback;

  Request(Curl*, const char* url);
  ~Request();

  void setDataCallback(const DataCallback& cb)
  { dataCb_ = cb; }

  void setDoneCallback(const DoneCallback& cb)
  { doneCb_ = cb; }

  void setHeaderCallback(const DataCallback& cb)
  { headerCb_ = cb; }

  // void allowRedirect(int redirects);
  void headerOnly();
  void setRange(const muduo::StringArg range);

  template<typename OPT>
  int setopt(OPT opt, long p)
  {
    return curl_easy_setopt(curl_, opt, p);
  }

  template<typename OPT>
  int setopt(OPT opt, const char* p)
  {
    return curl_easy_setopt(curl_, opt, p);
  }

  template<typename OPT>
  int setopt(OPT opt, void* p)
  {
    return curl_easy_setopt(curl_, opt, p);
  }

  template<typename OPT>
  int setopt(OPT opt, size_t (*p)(char *, size_t , size_t , void *))
  {
    return curl_easy_setopt(curl_, opt, p);
  }

  const char* getEffectiveUrl();
  const char* getRedirectUrl();
  int getResponseCode();

  // internal
  muduo::net::Channel* setChannel(int fd);
  void removeChannel();
  void done(int code);
  CURL* getCurl() { return curl_; }
  muduo::net::Channel* getChannel() { return muduo::get_pointer(channel_); }

 private:

  void dataCallback(const char* buffer, int len);
  void headerCallback(const char* buffer, int len);
  static size_t writeData(char *buffer, size_t size, size_t nmemb, void *userp);
  static size_t headerData(char *buffer, size_t size, size_t nmemb, void *userp);
  void doneCallback();

  class Curl* owner_;
  CURL* curl_;
  std::shared_ptr<muduo::net::Channel> channel_;
  DataCallback dataCb_;
  DataCallback headerCb_;
  DoneCallback doneCb_;
};

typedef std::shared_ptr<Request> RequestPtr;

class Curl : muduo::noncopyable
{
 public:

  enum Option
  {
    kCURLnossl = 0,
    kCURLssl   = 1,
  };

  explicit Curl(muduo::net::EventLoop* loop);
  ~Curl();

  RequestPtr getUrl(muduo::StringArg url);

  static void initialize(Option opt = kCURLnossl);

  // internal
  CURLM* getCurlm() { return curlm_; }
  muduo::net::EventLoop* getLoop() { return loop_; }

 private:
  void onTimer();
  void onRead(int fd);
  void onWrite(int fd);
  void checkFinish();

  static int socketCallback(CURL*, int, int, void*, void*);
  static int timerCallback(CURLM*, long, void*);

  muduo::net::EventLoop* loop_;
  CURLM* curlm_;
  int runningHandles_;
  int prevRunningHandles_;
};

}  // namespace curl

#endif  // MUDUO_EXAMPLES_CURL_CURL_H


================================================
FILE: examples/curl/README
================================================
This is a proof-of-concept implementation of muduo-curl bridge.
It demostrates the simplest use case of curl with muduo.

Note:
1. DNS resolving could be blocking, if your curl is not built with c-ares.
2. Request object should survive doneCallback.


================================================
FILE: examples/curl/download.cc
================================================
// Concurrent downloading one file from HTTP

#include "examples/curl/Curl.h"
#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"
#include <stdio.h>
#include <sstream>

using namespace muduo;
using namespace muduo::net;

typedef std::shared_ptr<FILE> FilePtr;

template<int N>
bool startWith(const string& str, const char (&prefix)[N])
{
  return str.size() >= N-1 && std::equal(prefix, prefix+N-1, str.begin());
}

class Piece : noncopyable
{
 public:
  Piece(const curl::RequestPtr& req,
        const FilePtr& out,
        const muduo::string& range,
        std::function<void()> done)
    : req_(req),
      out_(out),
      range_(range),
      doneCb_(std::move(done))
  {
    LOG_INFO << "range: " << range;
    req->setRange(range);
    req_->setDataCallback(
        std::bind(&Piece::onData, this, _1, _2));
    req_->setDoneCallback(
        std::bind(&Piece::onDone, this, _1, _2));
  }
 private:
  void onData(const char* data, int len)
  {
    ::fwrite(data, 1, len, get_pointer(out_));
  }

  void onDone(curl::Request* c, int code)
  {
    LOG_INFO << "[" << range_ << "] is done";
    req_.reset();
    out_.reset();
    doneCb_();
  }

  curl::RequestPtr req_;
  FilePtr out_;
  muduo::string range_;
  std::function<void()> doneCb_;
};

class Downloader : noncopyable
{
 public:
  Downloader(EventLoop* loop, const string& url)
    : loop_(loop),
      curl_(loop_),
      url_(url),
      req_(curl_.getUrl(url_)),
      found_(false),
      acceptRanges_(false),
      length_(0),
      pieces_(kConcurrent),
      concurrent_(0)
  {
    req_->setHeaderCallback(
        std::bind(&Downloader::onHeader, this, _1, _2));
    req_->setDoneCallback(
        std::bind(&Downloader::onHeaderDone, this, _1, _2));
    req_->headerOnly();
  }

 private:
  void onHeader(const char* data, int len)
  {
    string line(data, len);
    if (startWith(line, "HTTP/1.1 200") || startWith(line, "HTTP/1.0 200"))
    {
      found_ = true;
    }
    if (line == "Accept-Ranges: bytes\r\n")
    {
      acceptRanges_ = true;
      LOG_DEBUG << "Accept-Ranges";
    }
    else if (startWith(line, "Content-Length:"))
    {
      length_ = atoll(line.c_str() + strlen("Content-Length:"));
      LOG_INFO << "Content-Length: " << length_;
    }
  }

  void onHeaderDone(curl::Request* c, int code)
  {
    LOG_DEBUG << code;
    if (acceptRanges_ && length_ >= kConcurrent * 4096)
    {
      LOG_INFO << "Downloading with " << kConcurrent << " connections";
      concurrent_ = kConcurrent;
      concurrentDownload();
    }
    else if (found_)
    {
      LOG_WARN << "Single connection download";
      FILE* fp = ::fopen("output", "wb");
      if (fp)
      {
        FilePtr(fp, ::fclose).swap(out_);
        req_.reset();
        req2_ = curl_.getUrl(url_);
        req2_->setDataCallback(
            std::bind(&Downloader::onData, this, _1, _2));
        req2_->setDoneCallback(
            std::bind(&Downloader::onDownloadDone, this));
        concurrent_ = 1;
      }
      else
      {
        LOG_ERROR << "Can not create output file";
        loop_->quit();
      }
    }
    else
    {
      LOG_ERROR << "File not found";
      loop_->quit();
    }
  }

  void concurrentDownload()
  {
    const int64_t pieceLen = length_ / kConcurrent;
    for (int i = 0; i < kConcurrent; ++i)
    {
      char buf[256];
      snprintf(buf, sizeof buf, "output-%05d-of-%05d", i, kConcurrent);
      FILE* fp = ::fopen(buf, "wb");
      if (fp)
      {
        FilePtr out(fp, ::fclose);
        curl::RequestPtr req = curl_.getUrl(url_);

        std::ostringstream range;
        if (i < kConcurrent - 1)
        {
          range << i * pieceLen << "-" << (i+1) * pieceLen - 1;
        }
        else
        {
          range << i * pieceLen << "-" << length_ - 1;
        }
        pieces_[i].reset(new Piece(req,
                                   out,
                                   range.str(),
                                   std::bind(&Downloader::onDownloadDone, this)));
      }
      else
      {
        LOG_ERROR << "Can not create output file: " << buf;
        loop_->quit();
      }
    }
  }

  void onData(const char* data, int len)
  {
    ::fwrite(data, 1, len, get_pointer(out_));
  }

  void onDownloadDone()
  {
    if (--concurrent_ <= 0)
    {
      loop_->quit();
    }
  }

  EventLoop* loop_;
  curl::Curl curl_;
  string url_;
  curl::RequestPtr req_;
  curl::RequestPtr req2_;
  bool found_;
  bool acceptRanges_;
  int64_t length_;
  FilePtr out_;
  std::vector<std::unique_ptr<Piece>> pieces_;
  int concurrent_;

  const static int kConcurrent = 4;
};

int main(int argc, char* argv[])
{
  EventLoop loop;
  curl::Curl::initialize(curl::Curl::kCURLssl);
  string url = argc > 1 ? argv[1] : "https://chenshuo-public.s3.amazonaws.com/pdf/allinone.pdf";
  Downloader d(&loop, url);
  loop.loop();
}


================================================
FILE: examples/curl/mcurl.cc
================================================
#include "examples/curl/Curl.h"
#include "muduo/net/EventLoop.h"
#include <stdio.h>

using namespace muduo::net;

EventLoop* g_loop = NULL;

void onData(const char* data, int len)
{
  printf("len %d\n", len);
}

void done(curl::Request* c, int code)
{
  printf("done %p %s %d\n", c, c->getEffectiveUrl(), code);
}

void done2(curl::Request* c, int code)
{
  printf("done2 %p %s %d %d\n", c, c->getRedirectUrl(), c->getResponseCode(), code);
  // g_loop->quit();
}

int main(int argc, char* argv[])
{
  EventLoop loop;
  g_loop = &loop;
  loop.runAfter(30.0, std::bind(&EventLoop::quit, &loop));
  curl::Curl::initialize(curl::Curl::kCURLssl);
  curl::Curl curl(&loop);

  curl::RequestPtr req = curl.getUrl("http://chenshuo.com");
  req->setDataCallback(onData);
  req->setDoneCallback(done);

  curl::RequestPtr req2 = curl.getUrl("https://github.com");
  // req2->allowRedirect(5);
  req2->setDataCallback(onData);
  req2->setDoneCallback(done);

  curl::RequestPtr req3 = curl.getUrl("http://example.com");
  // req3->allowRedirect(5);
  req3->setDataCallback(onData);
  req3->setDoneCallback(done2);

  loop.loop();
}


================================================
FILE: examples/fastcgi/CMakeLists.txt
================================================
add_executable(fastcgi_test fastcgi.cc fastcgi_test.cc ../sudoku/sudoku.cc)
target_link_libraries(fastcgi_test muduo_net)



================================================
FILE: examples/fastcgi/fastcgi.cc
================================================
#include "examples/fastcgi/fastcgi.h"
#include "muduo/base/Logging.h"
#include "muduo/net/Endian.h"

struct FastCgiCodec::RecordHeader
{
  uint8_t version;
  uint8_t type;
  uint16_t id;
  uint16_t length;
  uint8_t padding;
  uint8_t unused;
};

const unsigned FastCgiCodec::kRecordHeader = static_cast<unsigned>(sizeof(FastCgiCodec::RecordHeader));

enum FcgiType
{
  kFcgiInvalid = 0,
  kFcgiBeginRequest = 1,
  kFcgiAbortRequest = 2,
  kFcgiEndRequest = 3,
  kFcgiParams = 4,
  kFcgiStdin = 5,
  kFcgiStdout = 6,
  kFcgiStderr = 7,
  kFcgiData = 8,
  kFcgiGetValues = 9,
  kFcgiGetValuesResult = 10,
};

enum FcgiRole
{
  // kFcgiInvalid = 0,
  kFcgiResponder = 1,
  kFcgiAuthorizer = 2,
};

enum FcgiConstant
{
  kFcgiKeepConn = 1,
};

using namespace muduo::net;

bool FastCgiCodec::onParams(const char* content, uint16_t length)
{
  if (length > 0)
  {
    paramsStream_.append(content, length);
  }
  else if (!parseAllParams())
  {
    LOG_ERROR << "parseAllParams() failed";
    return false;
  }
  return true;
}

void FastCgiCodec::onStdin(const char* content, uint16_t length)
{
  if (length > 0)
  {
    stdin_.append(content, length);
  }
  else
  {
    gotRequest_ = true;
  }
}

bool FastCgiCodec::parseAllParams()
{
  while (paramsStream_.readableBytes() > 0)
  {
    uint32_t nameLen = readLen();
    if (nameLen == static_cast<uint32_t>(-1))
      return false;
    uint32_t valueLen = readLen();
    if (valueLen == static_cast<uint32_t>(-1))
      return false;
    if (paramsStream_.readableBytes() >= nameLen+valueLen)
    {
      std::string name = paramsStream_.retrieveAsString(nameLen);
      params_[name] = paramsStream_.retrieveAsString(valueLen);
    }
    else
    {
      return false;
    }
  }
  return true;
}

uint32_t FastCgiCodec::readLen()
{
  if (paramsStream_.readableBytes() >= 1)
  {
    uint8_t byte = paramsStream_.peekInt8();
    if (byte & 0x80)
    {
      if (paramsStream_.readableBytes() >= sizeof(uint32_t))
      {
        return paramsStream_.readInt32() & 0x7fffffff;
      }
      else
      {
        return -1;
      }
    }
    else
    {
      return paramsStream_.readInt8();
    }
  }
  else
  {
    return -1;
  }
}

using muduo::net::Buffer;

void FastCgiCodec::endStdout(Buffer* buf)
{
  RecordHeader header =
  {
    1,
    kFcgiStdout,
    sockets::hostToNetwork16(1),
    0,
    0,
    0,
  };
  buf->append(&header, kRecordHeader);
}

void FastCgiCodec::endRequest(Buffer* buf)
{
  RecordHeader header =
  {
    1,
    kFcgiEndRequest,
    sockets::hostToNetwork16(1),
    sockets::hostToNetwork16(kRecordHeader),
    0,
    0,
  };
  buf->append(&header, kRecordHeader);
  buf->appendInt32(0);
  buf->appendInt32(0);
}

void FastCgiCodec::respond(Buffer* response)
{
  if (response->readableBytes() < 65536
      && response->prependableBytes() >= kRecordHeader)
  {
    RecordHeader header =
    {
      1,
      kFcgiStdout,
      sockets::hostToNetwork16(1),
      sockets::hostToNetwork16(static_cast<uint16_t>(response->readableBytes())),
      static_cast<uint8_t>(-response->readableBytes() & 7),
      0,
    };
    response->prepend(&header, kRecordHeader);
    response->append("\0\0\0\0\0\0\0\0", header.padding);
  }
  else
  {
    // FIXME:
  }

  endStdout(response);
  endRequest(response);
}

bool FastCgiCodec::parseRequest(Buffer* buf)
{
  while (buf->readableBytes() >= kRecordHeader)
  {
    RecordHeader header;
    memcpy(&header, buf->peek(), kRecordHeader);
    header.id = sockets::networkToHost16(header.id);
    header.length = sockets::networkToHost16(header.length);
    size_t total = kRecordHeader + header.length + header.padding;
    if (buf->readableBytes() >= total)
    {
      switch (header.type)
      {
        case kFcgiBeginRequest:
          onBeginRequest(header, buf);
          // FIXME: check
          break;
        case kFcgiParams:
          onParams(buf->peek() + kRecordHeader, header.length);
          // FIXME: check
          break;
        case kFcgiStdin:
          onStdin(buf->peek() + kRecordHeader, header.length);
          break;
        case kFcgiData:
          // FIXME:
          break;
        case kFcgiGetValues:
          // FIXME:
          break;
        default:
          // FIXME:
          break;
      }
      buf->retrieve(total);
    }
    else
    {
      break;
    }
  }
  return true;
}

uint16_t readInt16(const void* p)
{
  uint16_t be16 = 0;
  ::memcpy(&be16, p, sizeof be16);
  return sockets::networkToHost16(be16);
}

bool FastCgiCodec::onBeginRequest(const RecordHeader& header, const Buffer* buf)
{
  assert(buf->readableBytes() >= header.length);
  assert(header.type == kFcgiBeginRequest);

  if (header.length >= kRecordHeader)
  {
    uint16_t role = readInt16(buf->peek()+kRecordHeader);
    uint8_t flags = buf->peek()[kRecordHeader + sizeof(int16_t)];
    if (role == kFcgiResponder)
    {
      keepConn_ = flags == kFcgiKeepConn;
      return true;
    }
  }
  return false;
}


================================================
FILE: examples/fastcgi/fastcgi.h
================================================
#ifndef MUDUO_EXAMPLES_FASTCGI_FASTCGI_H
#define MUDUO_EXAMPLES_FASTCGI_FASTCGI_H

#include "muduo/net/TcpConnection.h"
#include <map>

// one FastCgiCodec per TcpConnection
// both lighttpd and nginx do not implement multiplexing,
// so there is no concurrent requests of one connection.
class FastCgiCodec : muduo::noncopyable
{
 public:
  typedef std::map<std::string, std::string> ParamMap;
  typedef std::function<void (const muduo::net::TcpConnectionPtr& conn,
                                ParamMap&,
                                muduo::net::Buffer*)> Callback;

  explicit FastCgiCodec(const Callback& cb)
    : cb_(cb),
      gotRequest_(false),
      keepConn_(false)
  {
  }

  void onMessage(const muduo::net::TcpConnectionPtr& conn,
                 muduo::net::Buffer* buf,
                 muduo::Timestamp receiveTime)
  {
    parseRequest(buf);
    if (gotRequest_)
    {
      cb_(conn, params_, &stdin_);
      stdin_.retrieveAll();
      paramsStream_.retrieveAll();
      params_.clear();
      gotRequest_ = false;
      if (!keepConn_)
      {
        conn->shutdown();
      }
    }
  }

  static void respond(muduo::net::Buffer* response);

 private:
  struct RecordHeader;
  bool parseRequest(muduo::net::Buffer* buf);
  bool onBeginRequest(const RecordHeader& header, const muduo::net::Buffer* buf);
  void onStdin(const char* content, uint16_t length);
  bool onParams(const char* content, uint16_t length);
  bool parseAllParams();
  uint32_t readLen();

  static void endStdout(muduo::net::Buffer* buf);
  static void endRequest(muduo::net::Buffer* buf);

  Callback cb_;
  bool gotRequest_;
  bool keepConn_;
  muduo::net::Buffer stdin_;
  muduo::net::Buffer paramsStream_;
  ParamMap params_;

  const static unsigned kRecordHeader;
};

#endif  // MUDUO_EXAMPLES_FASTCGI_FASTCGI_H


================================================
FILE: examples/fastcgi/fastcgi_test.cc
================================================
#include "examples/fastcgi/fastcgi.h"
#include "examples/sudoku/sudoku.h"

#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/TcpServer.h"

using namespace muduo;
using namespace muduo::net;

const string kPath = "/sudoku/";

void onRequest(const TcpConnectionPtr& conn,
               FastCgiCodec::ParamMap& params,
               Buffer* in)
{
  string uri = params["REQUEST_URI"];
  LOG_INFO << conn->name() << ": " << uri;

  for (FastCgiCodec::ParamMap::const_iterator it = params.begin();
       it != params.end(); ++it)
  {
    LOG_DEBUG << it->first << " = " << it->second;
  }
  if (in->readableBytes() > 0)
    LOG_DEBUG << "stdin " << in->retrieveAllAsString();
  Buffer response;
  response.append("Context-Type: text/plain\r\n\r\n");
  if (uri.size() == kCells + kPath.size() && uri.find(kPath) == 0)
  {
    response.append(solveSudoku(uri.substr(kPath.size())));
  }
  else
  {
    // FIXME: set http status code 400
    response.append("bad request");
  }

  FastCgiCodec::respond(&response);
  conn->send(&response);
}

void onConnection(const TcpConnectionPtr& conn)
{
  if (conn->connected())
  {
    typedef std::shared_ptr<FastCgiCodec> CodecPtr;
    CodecPtr codec(new FastCgiCodec(onRequest));
    conn->setContext(codec);
    conn->setMessageCallback(
        std::bind(&FastCgiCodec::onMessage, codec, _1, _2, _3));
    conn->setTcpNoDelay(true);
  }
}

int main(int argc, char* argv[])
{
  int port = 19981;
  int threads = 0;
  if (argc > 1)
    port = atoi(argv[1]);
  if (argc > 2)
    threads = atoi(argv[2]);
  InetAddress addr(static_cast<uint16_t>(port));
  LOG_INFO << "Sudoku FastCGI listens on " << addr.toIpPort()
           << " threads " << threads;
  muduo::net::EventLoop loop;
  TcpServer server(&loop, addr, "FastCGI");
  server.setConnectionCallback(onConnection);
  server.setThreadNum(threads);
  server.start();
  loop.loop();
}


================================================
FILE: examples/fastcgi/nginx.conf
================================================

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

events {
    worker_connections  1024;
}

http {
    #include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;
    access_log      off;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    upstream muduo_backend {
        server localhost:19981;
        #server localhost:19982;
        keepalive 32;
    }

    server {
        listen       10080;
        server_name  localhost;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # pass /sudoku/ to muduo FastCGI server listening on 127.0.0.1:19981
        #
        location /sudoku/  {
            fastcgi_keep_conn   on;
            fastcgi_pass        muduo_backend;
            #include             fastcgi_params;
            #fastcgi_param  QUERY_STRING       $query_string;
            #fastcgi_param  REQUEST_METHOD     $request_method;
            #fastcgi_param  CONTENT_TYPE       $content_type;
            #fastcgi_param  CONTENT_LENGTH     $content_length;

            #fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
            fastcgi_param  REQUEST_URI        $request_uri;
            #fastcgi_param  DOCUMENT_URI       $document_uri;
            #fastcgi_param  DOCUMENT_ROOT      $document_root;
            #fastcgi_param  SERVER_PROTOCOL    $server_protocol;
            #fastcgi_param  HTTPS              $https if_not_empty;

            #fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
            #fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

            #fastcgi_param  REMOTE_ADDR        $remote_addr;
            #fastcgi_param  REMOTE_PORT        $remote_port;
            #fastcgi_param  SERVER_ADDR        $server_addr;
            #fastcgi_param  SERVER_PORT        $server_port;
            #fastcgi_param  SERVER_NAME        $server_name;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }
}


================================================
FILE: examples/filetransfer/CMakeLists.txt
================================================
add_executable(filetransfer_download download.cc)
target_link_libraries(filetransfer_download muduo_net)

add_executable(filetransfer_download2 download2.cc)
target_link_libraries(filetransfer_download2 muduo_net)

add_executable(filetransfer_download3 download3.cc)
target_link_libraries(filetransfer_download3 muduo_net)



================================================
FILE: examples/filetransfer/download.cc
================================================
#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/TcpServer.h"

#include <stdio.h>
#include <unistd.h>

using namespace muduo;
using namespace muduo::net;

const char* g_file = NULL;

// FIXME: use FileUtil::readFile()
string readFile(const char* filename)
{
  string content;
  FILE* fp = ::fopen(filename, "rb");
  if (fp)
  {
    // inefficient!!!
    const int kBufSize = 1024*1024;
    char iobuf[kBufSize];
    ::setbuffer(fp, iobuf, sizeof iobuf);

    char buf[kBufSize];
    size_t nread = 0;
    while ( (nread = ::fread(buf, 1, sizeof buf, fp)) > 0)
    {
      content.append(buf, nread);
    }
    ::fclose(fp);
  }
  return content;
}

void onHighWaterMark(const TcpConnectionPtr& conn, size_t len)
{
  LOG_INFO << "HighWaterMark " << len;
}

void onConnection(const TcpConnectionPtr& conn)
{
  LOG_INFO << "FileServer - " << conn->peerAddress().toIpPort() << " -> "
           << conn->localAddress().toIpPort() << " is "
           << (conn->connected() ? "UP" : "DOWN");
  if (conn->connected())
  {
    LOG_INFO << "FileServer - Sending file " << g_file
             << " to " << conn->peerAddress().toIpPort();
    conn->setHighWaterMarkCallback(onHighWaterMark, 64*1024);
    string fileContent = readFile(g_file);
    conn->send(fileContent);
    conn->shutdown();
    LOG_INFO << "FileServer - done";
  }
}

int main(int argc, char* argv[])
{
  LOG_INFO << "pid = " << getpid();
  if (argc > 1)
  {
    g_file = argv[1];

    EventLoop loop;
    InetAddress listenAddr(2021);
    TcpServer server(&loop, listenAddr, "FileServer");
    server.setConnectionCallback(onConnection);
    server.start();
    loop.loop();
  }
  else
  {
    fprintf(stderr, "Usage: %s file_for_downloading\n", argv[0]);
  }
}



================================================
FILE: examples/filetransfer/download2.cc
================================================
#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/TcpServer.h"

#include <stdio.h>
#include <unistd.h>

using namespace muduo;
using namespace muduo::net;

void onHighWaterMark(const TcpConnectionPtr& conn, size_t len)
{
  LOG_INFO << "HighWaterMark " << len;
}

const int kBufSize = 64*1024;
const char* g_file = NULL;

void onConnection(const TcpConnectionPtr& conn)
{
  LOG_INFO << "FileServer - " << conn->peerAddress().toIpPort() << " -> "
           << conn->localAddress().toIpPort() << " is "
           << (conn->connected() ? "UP" : "DOWN");
  if (conn->connected())
  {
    LOG_INFO << "FileServer - Sending file " << g_file
             << " to " << conn->peerAddress().toIpPort();
    conn->setHighWaterMarkCallback(onHighWaterMark, kBufSize+1);

    FILE* fp = ::fopen(g_file, "rb");
    if (fp)
    {
      conn->setContext(fp);
      char buf[kBufSize];
      size_t nread = ::fread(buf, 1, sizeof buf, fp);
      conn->send(buf, static_cast<int>(nread));
    }
    else
    {
      conn->shutdown();
      LOG_INFO << "FileServer - no such file";
    }
  }
  else
  {
    if (!conn->getContext().empty())
    {
      FILE* fp = boost::any_cast<FILE*>(conn->getContext());
      if (fp)
      {
        ::fclose(fp);
      }
    }
  }
}

void onWriteComplete(const TcpConnectionPtr& conn)
{
  FILE* fp = boost::any_cast<FILE*>(conn->getContext());
  char buf[kBufSize];
  size_t nread = ::fread(buf, 1, sizeof buf, fp);
  if (nread > 0)
  {
    conn->send(buf, static_cast<int>(nread));
  }
  else
  {
    ::fclose(fp);
    fp = NULL;
    conn->setContext(fp);
    conn->shutdown();
    LOG_INFO << "FileServer - done";
  }
}

int main(int argc, char* argv[])
{
  LOG_INFO << "pid = " << getpid();
  if (argc > 1)
  {
    g_file = argv[1];

    EventLoop loop;
    InetAddress listenAddr(2021);
    TcpServer server(&loop, listenAddr, "FileServer");
    server.setConnectionCallback(onConnection);
    server.setWriteCompleteCallback(onWriteComplete);
    server.start();
    loop.loop();
  }
  else
  {
    fprintf(stderr, "Usage: %s file_for_downloading\n", argv[0]);
  }
}



================================================
FILE: examples/filetransfer/download3.cc
================================================
#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/TcpServer.h"

#include <stdio.h>
#include <unistd.h>

using namespace muduo;
using namespace muduo::net;

void onHighWaterMark(const TcpConnectionPtr& conn, size_t len)
{
  LOG_INFO << "HighWaterMark " << len;
}

const int kBufSize = 64*1024;
const char* g_file = NULL;
typedef std::shared_ptr<FILE> FilePtr;

void onConnection(const TcpConnectionPtr& conn)
{
  LOG_INFO << "FileServer - " << conn->peerAddress().toIpPort() << " -> "
           << conn->localAddress().toIpPort() << " is "
           << (conn->connected() ? "UP" : "DOWN");
  if (conn->connected())
  {
    LOG_INFO << "FileServer - Sending file " << g_file
             << " to " << conn->peerAddress().toIpPort();
    conn->setHighWaterMarkCallback(onHighWaterMark, kBufSize+1);

    FILE* fp = ::fopen(g_file, "rb");
    if (fp)
    {
      FilePtr ctx(fp, ::fclose);
      conn->setContext(ctx);
      char buf[kBufSize];
      size_t nread = ::fread(buf, 1, sizeof buf, fp);
      conn->send(buf, static_cast<int>(nread));
    }
    else
    {
      conn->shutdown();
      LOG_INFO << "FileServer - no such file";
    }
  }
}

void onWriteComplete(const TcpConnectionPtr& conn)
{
  const FilePtr& fp = boost::any_cast<const FilePtr&>(conn->getContext());
  char buf[kBufSize];
  size_t nread = ::fread(buf, 1, sizeof buf, get_pointer(fp));
  if (nread > 0)
  {
    conn->send(buf, static_cast<int>(nread));
  }
  else
  {
    conn->shutdown();
    LOG_INFO << "FileServer - done";
  }
}

int main(int argc, char* argv[])
{
  LOG_INFO << "pid = " << getpid();
  if (argc > 1)
  {
    g_file = argv[1];

    EventLoop loop;
    InetAddress listenAddr(2021);
    TcpServer server(&loop, listenAddr, "FileServer");
    server.setConnectionCallback(onConnection);
    server.setWriteCompleteCallback(onWriteComplete);
    server.start();
    loop.loop();
  }
  else
  {
    fprintf(stderr, "Usage: %s file_for_downloading\n", argv[0]);
  }
}



================================================
FILE: examples/filetransfer/loadtest/Client.java
================================================
import java.net.InetSocketAddress;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;

public class Client {

    private static final class PipelineFactory implements ChannelPipelineFactory {
        private final int kMinLength;
        private final int kMaxLength;
        private final CountDownLatch latch;
        Random random = new Random();

        private PipelineFactory(int kMinLength, int kMaxLength, CountDownLatch latch) {
            this.kMinLength = kMinLength;
            this.kMaxLength = kMaxLength;
            this.latch = latch;
            assert kMinLength <= kMaxLength;
        }

        @Override
        public ChannelPipeline getPipeline() throws Exception {
            int variance = random.nextInt(kMaxLength - kMinLength + 1);
            int maxLength = kMinLength + variance;
            return Channels.pipeline(new Handler(maxLength, latch));
        }
    }

    static final int kClients = 500;
    static final int kMB = 1024 * 1024;
    static final int kMinLength = 1 * kMB;
    static final int kMaxLength = 6 * kMB;

    public static void main(String[] args) throws Exception {
        ChannelFactory channelFactory = new NioClientSocketChannelFactory(
                Executors.newCachedThreadPool(),
                Executors.newCachedThreadPool());
        long start = System.currentTimeMillis();

        final CountDownLatch latch = new CountDownLatch(kClients);
        ChannelPipelineFactory pipelineFactory = new PipelineFactory(kMinLength, kMaxLength, latch);
        for (int i = 0; i < kClients; ++i) {
            ClientBootstrap bootstrap = new ClientBootstrap(channelFactory);
            bootstrap.setPipelineFactory(pipelineFactory);
            bootstrap.connect(new InetSocketAddress(args[0], 2021));
        }

        latch.await();

        System.out.println(Thread.currentThread().getId() + " All done. "
                + (System.currentTimeMillis() - start));
        System.exit(0);
    }

}


================================================
FILE: examples/filetransfer/loadtest/Handler.java
================================================
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.concurrent.CountDownLatch;

import org.jboss.netty.buffer.BigEndianHeapChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;

public class Handler extends SimpleChannelUpstreamHandler {

    private static int created = 0;
    private int received = 0;
    private final int maxLength;
    private int id;
    private CountDownLatch latch;
    private MessageDigest digest;

    public Handler(int maxLength, CountDownLatch latch) throws Exception {
        this.id = created++;
        this.maxLength = maxLength;
        this.latch = latch;
        this.digest = MessageDigest.getInstance("MD5");
        System.out.println("Handler tid=" + Thread.currentThread().getId() + " " + id);
    }

    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
            throws Exception {
        System.out.println("channelConnected tid=" + Thread.currentThread().getId() + " " + id);
    }

    @Override
    public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e)
            throws Exception {
        byte[] md5 = digest.digest();
        BigInteger bigInt = new BigInteger(1, md5);
        System.out.println("channelDisconnected tid=" + Thread.currentThread().getId() + " " + id
                + " got "
                + received + " " + bigInt.toString(16));
        latch.countDown();
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        BigEndianHeapChannelBuffer message = (BigEndianHeapChannelBuffer) e.getMessage();
        // System.out.println("messageReceived " + ctx.getChannel() + message.readableBytes());
        received += message.readableBytes();
        digest.update(message.array(), message.readerIndex(), message.readableBytes());
        if (received > maxLength) {
            System.out.println("messageReceived tid=" + Thread.currentThread().getId()
                    + " " + id + " got " + received);
            ctx.getChannel().close();
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
        e.getCause().printStackTrace();

        Channel ch = e.getChannel();
        ch.close();
        latch.countDown();
    }
}


================================================
FILE: examples/hub/CMakeLists.txt
================================================
add_executable(hub hub.cc codec.cc)
target_link_libraries(hub muduo_inspect)

add_library(muduo_pubsub pubsub.cc codec.cc)
target_link_libraries(muduo_pubsub muduo_net)

add_executable(pub pub.cc)
target_link_libraries(pub muduo_pubsub)

add_executable(sub sub.cc)
target_link_libraries(sub muduo_pubsub)



================================================
FILE: examples/hub/README
================================================
hub - a server for broadcasting
pubsub - a client library of hub
pub - a command line tool for publishing content on a topic
sub - a demo tool for subscribing a topic



================================================
FILE: examples/hub/codec.cc
================================================
#include "examples/hub/codec.h"

using namespace muduo;
using namespace muduo::net;
using namespace pubsub;

ParseResult pubsub::parseMessage(Buffer* buf,
                                 string* cmd,
                                 string* topic,
                                 string* content)
{
  ParseResult result = kError;
  const char* crlf = buf->findCRLF();
  if (crlf)
  {
    const char* space = std::find(buf->peek(), crlf, ' ');
    if (space != crlf)
    {
      cmd->assign(buf->peek(), space);
      topic->assign(space+1, crlf);
      if (*cmd == "pub")
      {
        const char* start = crlf + 2;
        crlf = buf->findCRLF(start);
        if (crlf)
        {
          content->assign(start, crlf);
          buf->retrieveUntil(crlf+2);
          result = kSuccess;
        }
        else
        {
          result = kContinue;
        }
      }
      else
      {
        buf->retrieveUntil(crlf+2);
        result = kSuccess;
      }
    }
    else
    {
      result = kError;
    }
  }
  else
  {
    result = kContinue;
  }
  return result;
}



================================================
FILE: examples/hub/codec.h
================================================
#ifndef MUDUO_EXAMPLES_HUB_CODEC_H
#define MUDUO_EXAMPLES_HUB_CODEC_H

// internal header file

#include "muduo/base/Types.h"
#include "muduo/net/Buffer.h"

namespace pubsub
{
using muduo::string;

enum ParseResult
{
  kError,
  kSuccess,
  kContinue,
};

ParseResult parseMessage(muduo::net::Buffer* buf,
                         string* cmd,
                         string* topic,
                         string* content);
}  // namespace pubsub

#endif  // MUDUO_EXAMPLES_HUB_CODEC_H



================================================
FILE: examples/hub/hub.cc
================================================
#include "examples/hub/codec.h"

#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/TcpServer.h"

#include <map>
#include <set>
#include <stdio.h>

using namespace muduo;
using namespace muduo::net;

namespace pubsub
{

typedef std::set<string> ConnectionSubscription;

class Topic : public muduo::copyable
{
 public:
  Topic(const string& topic)
    : topic_(topic)
  {
  }

  void add(const TcpConnectionPtr& conn)
  {
    audiences_.insert(conn);
    if (lastPubTime_.valid())
    {
      conn->send(makeMessage());
    }
  }

  void remove(const TcpConnectionPtr& conn)
  {
    audiences_.erase(conn);
  }

  void publish(const string& content, Timestamp time)
  {
    content_ = content;
    lastPubTime_ = time;
    string message = makeMessage();
    for (std::set<TcpConnectionPtr>::iterator it = audiences_.begin();
         it != audiences_.end();
         ++it)
    {
      (*it)->send(message);
    }
  }

 private:

  string makeMessage()
  {
    return "pub " + topic_ + "\r\n" + content_ + "\r\n";
  }

  string topic_;
  string content_;
  Timestamp lastPubTime_;
  std::set<TcpConnectionPtr> audiences_;
};

class PubSubServer : noncopyable
{
 public:
  PubSubServer(muduo::net::EventLoop* loop,
               const muduo::net::InetAddress& listenAddr)
    : loop_(loop),
      server_(loop, listenAddr, "PubSubServer")
  {
    server_.setConnectionCallback(
        std::bind(&PubSubServer::onConnection, this, _1));
    server_.setMessageCallback(
        std::bind(&PubSubServer::onMessage, this, _1, _2, _3));
    loop_->runEvery(1.0, std::bind(&PubSubServer::timePublish, this));
  }

  void start()
  {
    server_.start();
  }

 private:
  void onConnection(const TcpConnectionPtr& conn)
  {
    if (conn->connected())
    {
      conn->setContext(ConnectionSubscription());
    }
    else
    {
      const ConnectionSubscription& connSub
        = boost::any_cast<const ConnectionSubscription&>(conn->getContext());
      // subtle: doUnsubscribe will erase *it, so increase before calling.
      for (ConnectionSubscription::const_iterator it = connSub.begin();
           it != connSub.end();)
      {
        doUnsubscribe(conn, *it++);
      }
    }
  }

  void onMessage(const TcpConnectionPtr& conn,
                 Buffer* buf,
                 Timestamp receiveTime)
  {
    ParseResult result = kSuccess;
    while (result == kSuccess)
    {
      string cmd;
      string topic;
      string content;
      result = parseMessage(buf, &cmd, &topic, &content);
      if (result == kSuccess)
      {
        if (cmd == "pub")
        {
          doPublish(conn->name(), topic, content, receiveTime);
        }
        else if (cmd == "sub")
        {
          LOG_INFO << conn->name() << " subscribes " << topic;
          doSubscribe(conn, topic);
        }
        else if (cmd == "unsub")
        {
          doUnsubscribe(conn, topic);
        }
        else
        {
          conn->shutdown();
          result = kError;
        }
      }
      else if (result == kError)
      {
        conn->shutdown();
      }
    }
  }

  void timePublish()
  {
    Timestamp now = Timestamp::now();
    doPublish("internal", "utc_time", now.toFormattedString(), now);
  }

  void doSubscribe(const TcpConnectionPtr& conn,
                   const string& topic)
  {
    ConnectionSubscription* connSub
      = boost::any_cast<ConnectionSubscription>(conn->getMutableContext());

    connSub->insert(topic);
    getTopic(topic).add(conn);
  }

  void doUnsubscribe(const TcpConnectionPtr& conn,
                     const string& topic)
  {
    LOG_INFO << conn->name() << " unsubscribes " << topic;
    getTopic(topic).remove(conn);
    // topic could be the one to be destroyed, so don't use it after erasing.
    ConnectionSubscription* connSub
      = boost::any_cast<ConnectionSubscription>(conn->getMutableContext());
    connSub->erase(topic);
  }

  void doPublish(const string& source,
                 const string& topic,
                 const string& content,
                 Timestamp time)
  {
    getTopic(topic).publish(content, time);
  }

  Topic& getTopic(const string& topic)
  {
    std::map<string, Topic>::iterator it = topics_.find(topic);
    if (it == topics_.end())
    {
      it = topics_.insert(make_pair(topic, Topic(topic))).first;
    }
    return it->second;
  }

  EventLoop* loop_;
  TcpServer server_;
  std::map<string, Topic> topics_;
};

}  // namespace pubsub

int main(int argc, char* argv[])
{
  if (argc > 1)
  {
    uint16_t port = static_cast<uint16_t>(atoi(argv[1]));
    EventLoop loop;
    if (argc > 2)
    {
      //int inspectPort = atoi(argv[2]);
    }
    pubsub::PubSubServer server(&loop, InetAddress(port));
    server.start();
    loop.loop();
  }
  else
  {
    printf("Usage: %s pubsub_port [inspect_port]\n", argv[0]);
  }
}



================================================
FILE: examples/hub/pub.cc
================================================
#include "examples/hub/pubsub.h"
#include "muduo/base/ProcessInfo.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/EventLoopThread.h"

#include <iostream>
#include <stdio.h>

using namespace muduo;
using namespace muduo::net;
using namespace pubsub;

EventLoop* g_loop = NULL;
string g_topic;
string g_content;

void connection(PubSubClient* client)
{
  if (client->connected())
  {
    client->publish(g_topic, g_content);
    client->stop();
  }
  else
  {
    g_loop->quit();
  }
}

int main(int argc, char* argv[])
{
  if (argc == 4)
  {
    string hostport = argv[1];
    size_t colon = hostport.find(':');
    if (colon != string::npos)
    {
      string hostip = hostport.substr(0, colon);
      uint16_t port = static_cast<uint16_t>(atoi(hostport.c_str()+colon+1));
      g_topic = argv[2];
      g_content = argv[3];

      string name = ProcessInfo::username()+"@"+ProcessInfo::hostname();
      name += ":" + ProcessInfo::pidString();

      if (g_content == "-")
      {
        EventLoopThread loopThread;
        g_loop = loopThread.startLoop();
        PubSubClient client(g_loop, InetAddress(hostip, port), name);
        client.start();

        string line;
        while (getline(std::cin, line))
        {
          client.publish(g_topic, line);
        }
        client.stop();
        CurrentThread::sleepUsec(1000*1000);
      }
      else
      {
        EventLoop loop;
        g_loop = &loop;
        PubSubClient client(g_loop, InetAddress(hostip, port), name);
        client.setConnectionCallback(connection);
        client.start();
        loop.loop();
      }
    }
    else
    {
      printf("Usage: %s hub_ip:port topic content\n", argv[0]);
    }
  }
  else
  {
    printf("Usage: %s hub_ip:port topic content\n"
           "Read contents from stdin:\n"
           "  %s hub_ip:port topic -\n", argv[0], argv[0]);
  }
}


================================================
FILE: examples/hub/pubsub.cc
================================================
#include "examples/hub/pubsub.h"
#include "examples/hub/codec.h"

using namespace muduo;
using namespace muduo::net;
using namespace pubsub;

PubSubClient::PubSubClient(EventLoop* loop,
                           const InetAddress& hubAddr,
                           const string& name)
  : client_(loop, hubAddr, name)
{
  // FIXME: dtor is not thread safe
  client_.setConnectionCallback(
      std::bind(&PubSubClient::onConnection, this, _1));
  client_.setMessageCallback(
      std::bind(&PubSubClient::onMessage, this, _1, _2, _3));
}

void PubSubClient::start()
{
  client_.connect();
}

void PubSubClient::stop()
{
  client_.disconnect();
}

bool PubSubClient::connected() const
{
  return conn_ && conn_->connected();
}

bool PubSubClient::subscribe(const string& topic, const SubscribeCallback& cb)
{
  string message = "sub " + topic + "\r\n";
  subscribeCallback_ = cb;
  return send(message);
}

void PubSubClient::unsubscribe(const string& topic)
{
  string message = "unsub " + topic + "\r\n";
  send(message);
}


bool PubSubClient::publish(const string& topic, const string& content)
{
  string message = "pub " + topic + "\r\n" + content + "\r\n";
  return send(message);
}

void PubSubClient::onConnection(const TcpConnectionPtr& conn)
{
  if (conn->connected())
  {
    conn_ = conn;
    // FIXME: re-sub
  }
  else
  {
    conn_.reset();
  }
  if (connectionCallback_)
  {
    connectionCallback_(this);
  }
}

void PubSubClient::onMessage(const TcpConnectionPtr& conn,
                             Buffer* buf,
                             Timestamp receiveTime)
{
  ParseResult result = kSuccess;
  while (result == kSuccess)
  {
    string cmd;
    string topic;
    string content;
    result = parseMessage(buf, &cmd, &topic, &content);
    if (result == kSuccess)
    {
      if (cmd == "pub" && subscribeCallback_)
      {
        subscribeCallback_(topic, content, receiveTime);
      }
    }
    else if (result == kError)
    {
      conn->shutdown();
    }
  }
}

bool PubSubClient::send(const string& message)
{
  bool succeed = false;
  if (conn_ && conn_->connected())
  {
    conn_->send(message);
    succeed = true;
  }
  return succeed;
}


================================================
FILE: examples/hub/pubsub.h
================================================
#ifndef MUDUO_EXAMPLES_HUB_PUBSUB_H
#define MUDUO_EXAMPLES_HUB_PUBSUB_H

#include "muduo/net/TcpClient.h"

namespace pubsub
{
using muduo::string;

// FIXME: dtor is not thread safe
class PubSubClient : muduo::noncopyable
{
 public:
  typedef std::function<void (PubSubClient*)> ConnectionCallback;
  typedef std::function<void (const string& topic,
                              const string& content,
                              muduo::Timestamp)> SubscribeCallback;

  PubSubClient(muduo::net::EventLoop* loop,
               const muduo::net::InetAddress& hubAddr,
               const string& name);
  void start();
  void stop();
  bool connected() const;

  void setConnectionCallback(const ConnectionCallback& cb)
  { connectionCallback_ = cb; }

  bool subscribe(const string& topic, const SubscribeCallback& cb);
  void unsubscribe(const string& topic);
  bool publish(const string& topic, const string& content);

 private:
  void onConnection(const muduo::net::TcpConnectionPtr& conn);
  void onMessage(const muduo::net::TcpConnectionPtr& conn,
                 muduo::net::Buffer* buf,
                 muduo::Timestamp receiveTime);
  bool send(const string& message);

  muduo::net::TcpClient client_;
  muduo::net::TcpConnectionPtr conn_;
  ConnectionCallback connectionCallback_;
  SubscribeCallback subscribeCallback_;
};
}  // namespace pubsub

#endif  // MUDUO_EXAMPLES_HUB_PUBSUB_H


================================================
FILE: examples/hub/sub.cc
================================================
#include "examples/hub/pubsub.h"
#include "muduo/base/ProcessInfo.h"
#include "muduo/net/EventLoop.h"

#include <vector>
#include <stdio.h>

using namespace muduo;
using namespace muduo::net;
using namespace pubsub;

EventLoop* g_loop = NULL;
std::vector<string> g_topics;

void subscription(const string& topic, const string& content, Timestamp)
{
  printf("%s: %s\n", topic.c_str(), content.c_str());
}

void connection(PubSubClient* client)
{
  if (client->connected())
  {
    for (std::vector<string>::iterator it = g_topics.begin();
        it != g_topics.end(); ++it)
    {
      client->subscribe(*it, subscription);
    }
  }
  else
  {
    g_loop->quit();
  }
}

int main(int argc, char* argv[])
{
  if (argc > 2)
  {
    string hostport = argv[1];
    size_t colon = hostport.find(':');
    if (colon != string::npos)
    {
      string hostip = hostport.substr(0, colon);
      uint16_t port = static_cast<uint16_t>(atoi(hostport.c_str()+colon+1));
      for (int i = 2; i < argc; ++i)
      {
        g_topics.push_back(argv[i]);
      }

      EventLoop loop;
      g_loop = &loop;
      string name = ProcessInfo::username()+"@"+ProcessInfo::hostname();
      name += ":" + ProcessInfo::pidString();
      PubSubClient client(&loop, InetAddress(hostip, port), name);
      client.setConnectionCallback(connection);
      client.start();
      loop.loop();
    }
    else
    {
      printf("Usage: %s hub_ip:port topic [topic ...]\n", argv[0]);
    }
  }
  else
  {
    printf("Usage: %s hub_ip:port topic [topic ...]\n", argv[0]);
  }
}


================================================
FILE: examples/idleconnection/CMakeLists.txt
================================================
add_executable(idleconnection_echo echo.cc main.cc)
target_link_libraries(idleconnection_echo muduo_net)

add_executable(idleconnection_echo2 sortedlist.cc)
target_link_libraries(idleconnection_echo2 muduo_net)


================================================
FILE: examples/idleconnection/echo.cc
================================================
#include "examples/idleconnection/echo.h"

#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"

#include <assert.h>
#include <stdio.h>

using namespace muduo;
using namespace muduo::net;


EchoServer::EchoServer(EventLoop* loop,
                       const InetAddress& listenAddr,
                       int idleSeconds)
  : server_(loop, listenAddr, "EchoServer"),
    connectionBuckets_(idleSeconds)
{
  server_.setConnectionCallback(
      std::bind(&EchoServer::onConnection, this, _1));
  server_.setMessageCallback(
      std::bind(&EchoServer::onMessage, this, _1, _2, _3));
  loop->runEvery(1.0, std::bind(&EchoServer::onTimer, this));
  connectionBuckets_.resize(idleSeconds);
  dumpConnectionBuckets();
}

void EchoServer::start()
{
  server_.start();
}

void EchoServer::onConnection(const TcpConnectionPtr& conn)
{
  LOG_INFO << "EchoServer - " << conn->peerAddress().toIpPort() << " -> "
           << conn->localAddress().toIpPort() << " is "
           << (conn->connected() ? "UP" : "DOWN");

  if (conn->connected())
  {
    EntryPtr entry(new Entry(conn));
    connectionBuckets_.back().insert(entry);
    dumpConnectionBuckets();
    WeakEntryPtr weakEntry(entry);
    conn->setContext(weakEntry);
  }
  else
  {
    assert(!conn->getContext().empty());
    WeakEntryPtr weakEntry(boost::any_cast<WeakEntryPtr>(conn->getContext()));
    LOG_DEBUG << "Entry use_count = " << weakEntry.use_count();
  }
}

void EchoServer::onMessage(const TcpConnectionPtr& conn,
                           Buffer* buf,
                           Timestamp time)
{
  string msg(buf->retrieveAllAsString());
  LOG_INFO << conn->name() << " echo " << msg.size()
           << " bytes at " << time.toString();
  conn->send(msg);

  assert(!conn->getContext().empty());
  WeakEntryPtr weakEntry(boost::any_cast<WeakEntryPtr>(conn->getContext()));
  EntryPtr entry(weakEntry.lock());
  if (entry)
  {
    connectionBuckets_.back().insert(entry);
    dumpConnectionBuckets();
  }
}

void EchoServer::onTimer()
{
  connectionBuckets_.push_back(Bucket());
  dumpConnectionBuckets();
}

void EchoServer::dumpConnectionBuckets() const
{
  LOG_INFO << "size = " << connectionBuckets_.size();
  int idx = 0;
  for (WeakConnectionList::const_iterator bucketI = connectionBuckets_.begin();
      bucketI != connectionBuckets_.end();
      ++bucketI, ++idx)
  {
    const Bucket& bucket = *bucketI;
    printf("[%d] len = %zd : ", idx, bucket.size());
    for (const auto& it : bucket)
    {
      bool connectionDead = it->weakConn_.expired();
      printf("%p(%ld)%s, ", get_pointer(it), it.use_count(),
          connectionDead ? " DEAD" : "");
    }
    puts("");
  }
}



================================================
FILE: examples/idleconnection/echo.h
================================================
#ifndef MUDUO_EXAMPLES_IDLECONNECTION_ECHO_H
#define MUDUO_EXAMPLES_IDLECONNECTION_ECHO_H

#include "muduo/net/TcpServer.h"
//#include <muduo/base/Types.h>

#include <unordered_set>

#include <boost/circular_buffer.hpp>

// RFC 862
class EchoServer
{
 public:
  EchoServer(muduo::net::EventLoop* loop,
             const muduo::net::InetAddress& listenAddr,
             int idleSeconds);

  void start();

 private:
  void onConnection(const muduo::net::TcpConnectionPtr& conn);

  void onMessage(const muduo::net::TcpConnectionPtr& conn,
                 muduo::net::Buffer* buf,
                 muduo::Timestamp time);

  void onTimer();

  void dumpConnectionBuckets() const;

  typedef std::weak_ptr<muduo::net::TcpConnection> WeakTcpConnectionPtr;

  struct Entry : public muduo::copyable
  {
    explicit Entry(const WeakTcpConnectionPtr& weakConn)
      : weakConn_(weakConn)
    {
    }

    ~Entry()
    {
      muduo::net::TcpConnectionPtr conn = weakConn_.lock();
      if (conn)
      {
        conn->shutdown();
      }
    }

    WeakTcpConnectionPtr weakConn_;
  };
  typedef std::shared_ptr<Entry> EntryPtr;
  typedef std::weak_ptr<Entry> WeakEntryPtr;
  typedef std::unordered_set<EntryPtr> Bucket;
  typedef boost::circular_buffer<Bucket> WeakConnectionList;

  muduo::net::TcpServer server_;
  WeakConnectionList connectionBuckets_;
};

#endif  // MUDUO_EXAMPLES_IDLECONNECTION_ECHO_H


================================================
FILE: examples/idleconnection/main.cc
================================================
#include "examples/idleconnection/echo.h"
#include <stdio.h>

#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"

using namespace muduo;
using namespace muduo::net;

/*
void testHash()
{
  boost::hash<std::shared_ptr<int> > h;
  std::shared_ptr<int> x1(new int(10));
  std::shared_ptr<int> x2(new int(10));
  h(x1);
  assert(h(x1) != h(x2));
  x1 = x2;
  assert(h(x1) == h(x2));
  x1.reset();
  assert(h(x1) != h(x2));
  x2.reset();
  assert(h(x1) == h(x2));
}
*/

int main(int argc, char* argv[])
{
  // testHash();
  EventLoop loop;
  InetAddress listenAddr(2007);
  int idleSeconds = 10;
  if (argc > 1)
  {
    idleSeconds = atoi(argv[1]);
  }
  LOG_INFO << "pid = " << getpid() << ", idle seconds = " << idleSeconds;
  EchoServer server(&loop, listenAddr, idleSeconds);
  server.start();
  loop.loop();
}



================================================
FILE: examples/idleconnection/sortedlist.cc
================================================
#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/TcpServer.h"
#include <list>
#include <stdio.h>
#include <unistd.h>

using namespace muduo;
using namespace muduo::net;

// RFC 862
class EchoServer
{
 public:
  EchoServer(EventLoop* loop,
             const InetAddress& listenAddr,
             int idleSeconds);

  void start()
  {
    server_.start();
  }

 private:
  void onConnection(const TcpConnectionPtr& conn);

  void onMessage(const TcpConnectionPtr& conn,
                 Buffer* buf,
                 Timestamp time);

  void onTimer();

  void dumpConnectionList() const;

  typedef std::weak_ptr<TcpConnection> WeakTcpConnectionPtr;
  typedef std::list<WeakTcpConnectionPtr> WeakConnectionList;

  struct Node : public muduo::copyable
  {
    Timestamp lastReceiveTime;
    WeakConnectionList::iterator position;
  };

  TcpServer server_;
  int idleSeconds_;
  WeakConnectionList connectionList_;
};

EchoServer::EchoServer(EventLoop* loop,
                       const InetAddress& listenAddr,
                       int idleSeconds)
  : server_(loop, listenAddr, "EchoServer"),
    idleSeconds_(idleSeconds)
{
  server_.setConnectionCallback(
      std::bind(&EchoServer::onConnection, this, _1));
  server_.setMessageCallback(
      std::bind(&EchoServer::onMessage, this, _1, _2, _3));
  loop->runEvery(1.0, std::bind(&EchoServer::onTimer, this));
  dumpConnectionList();
}

void EchoServer::onConnection(const TcpConnectionPtr& conn)
{
  LOG_INFO << "EchoServer - " << conn->peerAddress().toIpPort() << " -> "
           << conn->localAddress().toIpPort() << " is "
           << (conn->connected() ? "UP" : "DOWN");

  if (conn->connected())
  {
    Node node;
    node.lastReceiveTime = Timestamp::now();
    connectionList_.push_back(conn);
    node.position = --connectionList_.end();
    conn->setContext(node);
  }
  else
  {
    assert(!conn->getContext().empty());
    const Node& node = boost::any_cast<const Node&>(conn->getContext());
    connectionList_.erase(node.position);
  }
  dumpConnectionList();
}

void EchoServer::onMessage(const TcpConnectionPtr& conn,
                           Buffer* buf,
                           Timestamp time)
{
  string msg(buf->retrieveAllAsString());
  LOG_INFO << conn->name() << " echo " << msg.size()
           << " bytes at " << time.toString();
  conn->send(msg);

  assert(!conn->getContext().empty());
  Node* node = boost::any_cast<Node>(conn->getMutableContext());
  node->lastReceiveTime = time;
  connectionList_.splice(connectionList_.end(), connectionList_, node->position);
  assert(node->position == --connectionList_.end());

  dumpConnectionList();
}

void EchoServer::onTimer()
{
  dumpConnectionList();
  Timestamp now = Timestamp::now();
  for (WeakConnectionList::iterator it = connectionList_.begin();
      it != connectionList_.end();)
  {
    TcpConnectionPtr conn = it->lock();
    if (conn)
    {
      Node* n = boost::any_cast<Node>(conn->getMutableContext());
      double age = timeDifference(now, n->lastReceiveTime);
      if (age > idleSeconds_)
      {
        if (conn->connected())
        {
          conn->shutdown();
          LOG_INFO << "shutting down " << conn->name();
          conn->forceCloseWithDelay(3.5);  // > round trip of the whole Internet.
        }
      }
      else if (age < 0)
      {
        LOG_WARN << "Time jump";
        n->lastReceiveTime = now;
      }
      else
      {
        break;
      }
      ++it;
    }
    else
    {
      LOG_WARN << "Expired";
      it = connectionList_.erase(it);
    }
  }
}

void EchoServer::dumpConnectionList() const
{
  LOG_INFO << "size = " << connectionList_.size();

  for (WeakConnectionList::const_iterator it = connectionList_.begin();
      it != connectionList_.end(); ++it)
  {
    TcpConnectionPtr conn = it->lock();
    if (conn)
    {
      printf("conn %p\n", get_pointer(conn));
      const Node& n = boost::any_cast<const Node&>(conn->getContext());
      printf("    time %s\n", n.lastReceiveTime.toString().c_str());
    }
    else
    {
      printf("expired\n");
    }
  }
}

int main(int argc, char* argv[])
{
  EventLoop loop;
  InetAddress listenAddr(2007);
  int idleSeconds = 10;
  if (argc > 1)
  {
    idleSeconds = atoi(argv[1]);
  }
  LOG_INFO << "pid = " << getpid() << ", idle seconds = " << idleSeconds;
  EchoServer server(&loop, listenAddr, idleSeconds);
  server.start();
  loop.loop();
}



================================================
FILE: examples/maxconnection/CMakeLists.txt
================================================
add_executable(maxconnection_echo echo.cc main.cc)
target_link_libraries(maxconnection_echo muduo_net)


================================================
FILE: examples/maxconnection/echo.cc
================================================
#include "examples/maxconnection/echo.h"

#include "muduo/base/Logging.h"

using namespace muduo;
using namespace muduo::net;

EchoServer::EchoServer(EventLoop* loop,
                       const InetAddress& listenAddr,
                       int maxConnections)
  : server_(loop, listenAddr, "EchoServer"),
    numConnected_(0),
    kMaxConnections_(maxConnections)
{
  server_.setConnectionCallback(
      std::bind(&EchoServer::onConnection, this, _1));
  server_.setMessageCallback(
      std::bind(&EchoServer::onMessage, this, _1, _2, _3));
}

void EchoServer::start()
{
  server_.start();
}

void EchoServer::onConnection(const TcpConnectionPtr& conn)
{
  LOG_INFO << "EchoServer - " << conn->peerAddress().toIpPort() << " -> "
           << conn->localAddress().toIpPort() << " is "
           << (conn->connected() ? "UP" : "DOWN");

  if (conn->connected())
  {
    ++numConnected_;
    if (numConnected_ > kMaxConnections_)
    {
      conn->shutdown();
      conn->forceCloseWithDelay(3.0);  // > round trip of the whole Internet.
    }
  }
  else
  {
    --numConnected_;
  }
  LOG_INFO << "numConnected = " << numConnected_;
}

void EchoServer::onMessage(const TcpConnectionPtr& conn,
                           Buffer* buf,
                           Timestamp time)
{
  string msg(buf->retrieveAllAsString());
  LOG_INFO << conn->name() << " echo " << msg.size() << " bytes at " << time.toString();
  conn->send(msg);
}



================================================
FILE: examples/maxconnection/echo.h
================================================
#ifndef MUDUO_EXAMPLES_MAXCONNECTION_ECHO_H
#define MUDUO_EXAMPLES_MAXCONNECTION_ECHO_H

#include "muduo/net/TcpServer.h"

// RFC 862
class EchoServer
{
 public:
  EchoServer(muduo::net::EventLoop* loop,
             const muduo::net::InetAddress& listenAddr,
             int maxConnections);

  void start();

 private:
  void onConnection(const muduo::net::TcpConnectionPtr& conn);

  void onMessage(const muduo::net::TcpConnectionPtr& conn,
                 muduo::net::Buffer* buf,
                 muduo::Timestamp time);

  muduo::net::TcpServer server_;
  int numConnected_; // should be atomic_int
  const int kMaxConnections_;
};

#endif  // MUDUO_EXAMPLES_MAXCONNECTION_ECHO_H


================================================
FILE: examples/maxconnection/main.cc
================================================
#include "examples/maxconnection/echo.h"

#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"

#include <unistd.h>

using namespace muduo;
using namespace muduo::net;

int main(int argc, char* argv[])
{
  LOG_INFO << "pid = " << getpid();
  EventLoop loop;
  InetAddress listenAddr(2007);
  int maxConnections = 5;
  if (argc > 1)
  {
    maxConnections = atoi(argv[1]);
  }
  LOG_INFO << "maxConnections = " << maxConnections;
  EchoServer server(&loop, listenAddr, maxConnections);
  server.start();
  loop.loop();
}



================================================
FILE: examples/memcached/README
================================================
Simple implementation of memcached protocol for both server and client side.
Not meant to replace memcached, but just sample code of network programming with muduo.

Server limits:
 - The memory management is not customized, just uses (tc)malloc.
 - It doesn't control the memory footprint
 - Unix domain socket is not supported
 - Only listen on one TCP port

Server goals:
 - Pass as many feature tests as possible
 - Prefer simplicity over performance

TODO:
 - incr/decr
 - UDP
 - Binary protocol
 - expiration
 - LRU


================================================
FILE: examples/memcached/client/CMakeLists.txt
================================================
if(BOOSTPO_LIBRARY)
  add_executable(memcached_bench bench.cc)
  target_link_libraries(memcached_bench muduo_net boost_program_options)
endif()


================================================
FILE: examples/memcached/client/bench.cc
================================================
#include "muduo/base/CountDownLatch.h"
#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/EventLoopThreadPool.h"
#include "muduo/net/TcpClient.h"

#include <boost/program_options.hpp>
#include <iostream>

#include <stdio.h>

namespace po = boost::program_options;
using namespace muduo;
using namespace muduo::net;

class Client : noncopyable
{
 public:
  enum Operation
  {
    kGet,
    kSet,
  };

  Client(const string& name,
         EventLoop* loop,
         const InetAddress& serverAddr,
         Operation op,
         int requests,
         int keys,
         int valuelen,
         CountDownLatch* connected,
         CountDownLatch* finished)
    : name_(name),
      client_(loop, serverAddr, name),
      op_(op),
      sent_(0),
      acked_(0),
      requests_(requests),
      keys_(keys),
      valuelen_(valuelen),
      value_(valuelen_, 'a'),
      connected_(connected),
      finished_(finished)
  {
    value_ += "\r\n";
    client_.setConnectionCallback(std::bind(&Client::onConnection, this, _1));
    client_.setMessageCallback(std::bind(&Client::onMessage, this, _1, _2, _3));
    client_.connect();
  }

  void send()
  {
    Buffer buf;
    fill(&buf);
    conn_->send(&buf);
  }

 private:

  void onConnection(const TcpConnectionPtr& conn)
  {
    if (conn->connected())
    {
      conn_ = conn;
      connected_->countDown();
    }
    else
    {
      conn_.reset();
      client_.getLoop()->queueInLoop(std::bind(&CountDownLatch::countDown, finished_));
    }
  }

  void onMessage(const TcpConnectionPtr& conn,
                 Buffer* buffer,
                 Timestamp receiveTime)
  {
    if (op_ == kSet)
    {
      while (buffer->readableBytes() > 0)
      {
        const char* crlf = buffer->findCRLF();
        if (crlf)
        {
          buffer->retrieveUntil(crlf+2);
          ++acked_;
          if (sent_ < requests_)
          {
            send();
          }
        }
        else
        {
          break;
        }
      }
    }
    else
    {
      while (buffer->readableBytes() > 0)
      {
        const char* end = static_cast<const char*>(memmem(buffer->peek(),
                                                          buffer->readableBytes(),
                                                          "END\r\n", 5));
        if (end)
        {
          buffer->retrieveUntil(end+5);
          ++acked_;
          if (sent_ < requests_)
          {
            send();
          }
        }
        else
        {
          break;
        }
      }
    }
    
Download .txt
gitextract_80xohvuq/

├── .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
Download .txt
SYMBOL INDEX (1371 symbols across 299 files)

FILE: contrib/hiredis/Hiredis.cc
  function dummy (line 14) | static void dummy(const std::shared_ptr<Channel>&)
  function Hiredis (line 112) | Hiredis* Hiredis::getHiredis(const redisAsyncContext* ac)

FILE: contrib/hiredis/Hiredis.h
  type redisAsyncContext (line 12) | struct redisAsyncContext
  function namespace (line 14) | namespace muduo
  function namespace (line 23) | namespace hiredis

FILE: contrib/hiredis/mrediscli.cc
  function string (line 11) | string toString(long long value)
  function string (line 18) | string redisReplyToString(const redisReply* reply)
  function connectCallback (line 53) | void connectCallback(hiredis::Hiredis* c, int status)
  function disconnectCallback (line 65) | void disconnectCallback(hiredis::Hiredis* c, int status)
  function timeCallback (line 77) | void timeCallback(hiredis::Hiredis* c, redisReply* reply)
  function echoCallback (line 82) | void echoCallback(hiredis::Hiredis* c, redisReply* reply, string* echo)
  function dbsizeCallback (line 88) | void dbsizeCallback(hiredis::Hiredis* c, redisReply* reply)
  function selectCallback (line 93) | void selectCallback(hiredis::Hiredis* c, redisReply* reply, uint16_t* in...
  function authCallback (line 98) | void authCallback(hiredis::Hiredis* c, redisReply* reply, string* password)
  function echo (line 103) | void echo(hiredis::Hiredis* c, string* s)
  function main (line 108) | int main(int argc, char** argv)

FILE: contrib/thrift/ThriftConnection.h
  type State (line 60) | enum State
  type boost (line 64) | typedef boost::shared_ptr<ThriftConnection> ThriftConnectionPtr;

FILE: contrib/thrift/ThriftServer.h
  function setThreadNum (line 182) | void setThreadNum(int numThreads)
  function setWorkerThreadNum (line 187) | void setWorkerThreadNum(int numWorkerThreads)

FILE: contrib/thrift/tests/echo/EchoServer.cc
  class EchoHandler (line 15) | class EchoHandler : virtual public EchoIf
    method EchoHandler (line 18) | EchoHandler()
    method echo (line 22) | void echo(std::string& str, const std::string& s)
  function NumCPU (line 30) | int NumCPU()
  function main (line 35) | int main(int argc, char **argv)

FILE: contrib/thrift/tests/echo/echoclient.py
  function echo (line 11) | def echo(s):
  function main (line 23) | def main():

FILE: contrib/thrift/tests/ping/PingServer.cc
  class PingHandler (line 17) | class PingHandler : virtual public PingIf
    method PingHandler (line 20) | PingHandler()
    method ping (line 24) | void ping()
  function main (line 31) | int main(int argc, char **argv)

FILE: contrib/thrift/tests/ping/pingclient.py
  function ping (line 11) | def ping():
  function main (line 21) | def main():

FILE: examples/ace/logging/client.cc
  type logging (line 19) | namespace logging
    class LogClient (line 25) | class LogClient : noncopyable
      method LogClient (line 28) | LogClient(EventLoop* loop, const InetAddress& serverAddr)
      method connect (line 39) | void connect()
      method disconnect (line 44) | void disconnect()
      method write (line 49) | void write(const StringPiece& message)
      method onConnection (line 64) | void onConnection(const TcpConnectionPtr& conn)
      method onMessage (line 91) | void onMessage(const TcpConnectionPtr&,
      method REQUIRES (line 100) | REQUIRES(mutex_)
  function main (line 118) | int main(int argc, char* argv[])

FILE: examples/ace/logging/server.cc
  type logging (line 15) | namespace logging
    class Session (line 20) | class Session : noncopyable
      method Session (line 23) | explicit Session(const TcpConnectionPtr& conn)
      method string (line 35) | string getFileName(const TcpConnectionPtr& conn)
      method onMessage (line 56) | void onMessage(const TcpConnectionPtr& conn,
    class LogServer (line 80) | class LogServer : noncopyable
      method LogServer (line 83) | LogServer(EventLoop* loop, const InetAddress& listenAddr, int numThr...
      method start (line 95) | void start()
      method onConnection (line 101) | void onConnection(const TcpConnectionPtr& conn)
  function main (line 120) | int main(int argc, char* argv[])

FILE: examples/ace/ttcp/common.cc
  function parseCommandLine (line 13) | bool parseCommandLine(int argc, char* argv[], Options* opt)
  function resolveOrDie (line 60) | struct sockaddr_in resolveOrDie(const char* host, uint16_t port)

FILE: examples/ace/ttcp/common.h
  type sockaddr_in (line 21) | struct sockaddr_in
  type SessionMessage (line 23) | struct SessionMessage
  type PayloadMessage (line 29) | struct PayloadMessage

FILE: examples/ace/ttcp/main.cc
  function main (line 5) | int main(int argc, char* argv[])

FILE: examples/ace/ttcp/ttcp.cc
  type Context (line 15) | struct Context
    method Context (line 22) | Context()
  type trans (line 35) | namespace trans
    function onConnection (line 38) | void onConnection(const Options& opt, const TcpConnectionPtr& conn)
    function onMessage (line 72) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp time)
  function transmit (line 102) | void transmit(const Options& opt)
  type receiving (line 128) | namespace receiving
    function onConnection (line 131) | void onConnection(const TcpConnectionPtr& conn)
    function onMessage (line 146) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp time)
  function receive (line 202) | void receive(const Options& opt)

FILE: examples/ace/ttcp/ttcp_asio_async.cc
  function transmit (line 9) | void transmit(const Options& opt)
  function TtcpServerConnection (line 28) | TtcpServerConnection(const tcp::socket::executor_type& executor)
  function start (line 43) | void start()
  function doReadSession (line 52) | void doReadSession()
  function doReadLength (line 76) | void doReadLength()
  function doReadPayload (line 96) | void doReadPayload()
  function doWriteAck (line 115) | void doWriteAck()
  type SessionMessage (line 143) | struct SessionMessage
  type PayloadMessage (line 144) | struct PayloadMessage
  function doAccept (line 149) | void doAccept(tcp::acceptor& acceptor)
  function receive (line 169) | void receive(const Options& opt)

FILE: examples/ace/ttcp/ttcp_asio_sync.cc
  function transmit (line 9) | void transmit(const Options& opt)
  function receive (line 20) | void receive(const Options& opt)

FILE: examples/ace/ttcp/ttcp_blocking.cc
  function acceptOrDie (line 15) | static int acceptOrDie(uint16_t port)
  function write_n (line 57) | static int write_n(int sockfd, const void* buf, int length)
  function read_n (line 80) | static int read_n(int sockfd, void* buf, int length)
  function transmit (line 103) | void transmit(const Options& opt)
  function receive (line 160) | void receive(const Options& opt)

FILE: examples/asio/chat/client.cc
  class ChatClient (line 15) | class ChatClient : noncopyable
    method ChatClient (line 18) | ChatClient(EventLoop* loop, const InetAddress& serverAddr)
    method connect (line 29) | void connect()
    method disconnect (line 34) | void disconnect()
    method write (line 39) | void write(const StringPiece& message)
    method onConnection (line 49) | void onConnection(const TcpConnectionPtr& conn)
    method onStringMessage (line 66) | void onStringMessage(const TcpConnectionPtr&,
  function main (line 79) | int main(int argc, char* argv[])

FILE: examples/asio/chat/codec.h
  function class (line 9) | class LengthHeaderCodec : muduo::noncopyable

FILE: examples/asio/chat/loadtest.cc
  class ChatClient (line 24) | class ChatClient : noncopyable
    method ChatClient (line 27) | ChatClient(EventLoop* loop, const InetAddress& serverAddr)
    method connect (line 39) | void connect()
    method disconnect (line 44) | void disconnect()
    method Timestamp (line 49) | Timestamp receiveTime() const { return receiveTime_; }
    method onConnection (line 52) | void onConnection(const TcpConnectionPtr& conn)
    method onStringMessage (line 73) | void onStringMessage(const TcpConnectionPtr&,
    method send (line 93) | void send()
  function statistic (line 107) | void statistic(const std::vector<std::unique_ptr<ChatClient>>& clients)
  function main (line 128) | int main(int argc, char* argv[])

FILE: examples/asio/chat/server.cc
  class ChatServer (line 15) | class ChatServer : noncopyable
    method ChatServer (line 18) | ChatServer(EventLoop* loop,
    method start (line 29) | void start()
    method onConnection (line 35) | void onConnection(const TcpConnectionPtr& conn)
    method onStringMessage (line 51) | void onStringMessage(const TcpConnectionPtr&,
  function main (line 69) | int main(int argc, char* argv[])

FILE: examples/asio/chat/server_threaded.cc
  class ChatServer (line 15) | class ChatServer : noncopyable
    method ChatServer (line 18) | ChatServer(EventLoop* loop,
    method setThreadNum (line 29) | void setThreadNum(int numThreads)
    method start (line 34) | void start()
    method onConnection (line 40) | void onConnection(const TcpConnectionPtr& conn)
    method onStringMessage (line 57) | void onStringMessage(const TcpConnectionPtr&,
  function main (line 77) | int main(int argc, char* argv[])

FILE: examples/asio/chat/server_threaded_efficient.cc
  class ChatServer (line 15) | class ChatServer : noncopyable
    method ChatServer (line 18) | ChatServer(EventLoop* loop,
    method setThreadNum (line 30) | void setThreadNum(int numThreads)
    method start (line 35) | void start()
    method onConnection (line 41) | void onConnection(const TcpConnectionPtr& conn)
    method onStringMessage (line 67) | void onStringMessage(const TcpConnectionPtr&,
    method ConnectionListPtr (line 80) | ConnectionListPtr getConnectionList()
  function main (line 92) | int main(int argc, char* argv[])

FILE: examples/asio/chat/server_threaded_highperformance.cc
  class ChatServer (line 16) | class ChatServer : noncopyable
    method ChatServer (line 19) | ChatServer(EventLoop* loop,
    method setThreadNum (line 30) | void setThreadNum(int numThreads)
    method start (line 35) | void start()
    method onConnection (line 42) | void onConnection(const TcpConnectionPtr& conn)
    method onStringMessage (line 58) | void onStringMessage(const TcpConnectionPtr&,
    method distributeMessage (line 77) | void distributeMessage(const string& message)
    method threadInit (line 89) | void threadInit(EventLoop* loop)
  function main (line 106) | int main(int argc, char* argv[])

FILE: examples/asio/tutorial/timer2/timer.cc
  function print (line 5) | void print()
  function main (line 10) | int main()

FILE: examples/asio/tutorial/timer3/timer.cc
  function print (line 5) | void print(muduo::net::EventLoop* loop, int* count)
  function main (line 20) | int main()

FILE: examples/asio/tutorial/timer4/timer.cc
  class Printer (line 5) | class Printer : muduo::noncopyable
    method Printer (line 8) | Printer(muduo::net::EventLoop* loop)
    method print (line 21) | void print()
  function main (line 41) | int main()

FILE: examples/asio/tutorial/timer5/timer.cc
  class Printer (line 7) | class Printer : muduo::noncopyable
    method Printer (line 10) | Printer(muduo::net::EventLoop* loop1, muduo::net::EventLoop* loop2)
    method print1 (line 24) | void print1()
    method print2 (line 40) | void print2()
  function main (line 64) | int main()

FILE: examples/asio/tutorial/timer6/timer.cc
  class Printer (line 11) | class Printer : muduo::noncopyable
    method Printer (line 14) | Printer(muduo::net::EventLoop* loop1, muduo::net::EventLoop* loop2)
    method print1 (line 30) | void print1()
    method print2 (line 63) | void print2()
  function main (line 104) | int main()

FILE: examples/cdns/Resolver.cc
  function getSeconds (line 22) | double getSeconds(struct timeval* tv)
  type ares_options (line 49) | struct ares_options
  type timeval (line 84) | struct timeval
  type timeval (line 85) | struct timeval
  type timeval (line 106) | struct timeval
  type timeval (line 107) | struct timeval
  type hostent (line 121) | struct hostent
  type sockaddr_in (line 124) | struct sockaddr_in
  type hostent (line 181) | struct hostent

FILE: examples/cdns/Resolver.h
  type hostent (line 15) | struct hostent
  type ares_channeldata (line 16) | struct ares_channeldata
  type ares_channeldata (line 17) | struct ares_channeldata
  function namespace (line 20) | namespace muduo
  function class (line 32) | class Resolver : muduo::noncopyable

FILE: examples/cdns/dns.cc
  function quit (line 13) | void quit()
  function resolveCallback (line 18) | void resolveCallback(const string& host, const InetAddress& addr)
  function resolve (line 25) | void resolve(Resolver* res, const string& host)
  function main (line 30) | int main(int argc, char* argv[])

FILE: examples/curl/Curl.cc
  function dummy (line 13) | static void dummy(const std::shared_ptr<Channel>&)
  function Channel (line 79) | Channel* Request::setChannel(int fd)
  function RequestPtr (line 210) | RequestPtr Curl::getUrl(StringArg url)

FILE: examples/curl/Curl.h
  type CURLM (line 11) | typedef void CURLM;
  type CURL (line 12) | typedef void CURL;
  function namespace (line 15) | namespace muduo
  function namespace (line 24) | namespace curl
  type std (line 103) | typedef std::shared_ptr<Request> RequestPtr;
  function class (line 105) | class Curl : muduo::noncopyable

FILE: examples/curl/download.cc
  function startWith (line 15) | bool startWith(const string& str, const char (&prefix)[N])
  class Piece (line 20) | class Piece : noncopyable
    method Piece (line 23) | Piece(const curl::RequestPtr& req,
    method onData (line 40) | void onData(const char* data, int len)
    method onDone (line 45) | void onDone(curl::Request* c, int code)
  class Downloader (line 59) | class Downloader : noncopyable
    method Downloader (line 62) | Downloader(EventLoop* loop, const string& url)
    method onHeader (line 81) | void onHeader(const char* data, int len)
    method onHeaderDone (line 100) | void onHeaderDone(curl::Request* c, int code)
    method concurrentDownload (line 137) | void concurrentDownload()
    method onData (line 172) | void onData(const char* data, int len)
    method onDownloadDone (line 177) | void onDownloadDone()
  function main (line 200) | int main(int argc, char* argv[])

FILE: examples/curl/mcurl.cc
  function onData (line 9) | void onData(const char* data, int len)
  function done (line 14) | void done(curl::Request* c, int code)
  function done2 (line 19) | void done2(curl::Request* c, int code)
  function main (line 25) | int main(int argc, char* argv[])

FILE: examples/fastcgi/fastcgi.cc
  type FastCgiCodec::RecordHeader (line 5) | struct FastCgiCodec::RecordHeader
  type FcgiType (line 17) | enum FcgiType
  type FcgiRole (line 32) | enum FcgiRole
  type FcgiConstant (line 39) | enum FcgiConstant
  function readInt16 (line 224) | uint16_t readInt16(const void* p)

FILE: examples/fastcgi/fastcgi.h
  function class (line 10) | class FastCgiCodec : muduo::noncopyable
  type RecordHeader (line 47) | struct RecordHeader

FILE: examples/fastcgi/fastcgi_test.cc
  function onRequest (line 13) | void onRequest(const TcpConnectionPtr& conn,
  function onConnection (line 43) | void onConnection(const TcpConnectionPtr& conn)
  function main (line 56) | int main(int argc, char* argv[])

FILE: examples/filetransfer/download.cc
  function string (line 14) | string readFile(const char* filename)
  function onHighWaterMark (line 36) | void onHighWaterMark(const TcpConnectionPtr& conn, size_t len)
  function onConnection (line 41) | void onConnection(const TcpConnectionPtr& conn)
  function main (line 58) | int main(int argc, char* argv[])

FILE: examples/filetransfer/download2.cc
  function onHighWaterMark (line 11) | void onHighWaterMark(const TcpConnectionPtr& conn, size_t len)
  function onConnection (line 19) | void onConnection(const TcpConnectionPtr& conn)
  function onWriteComplete (line 57) | void onWriteComplete(const TcpConnectionPtr& conn)
  function main (line 76) | int main(int argc, char* argv[])

FILE: examples/filetransfer/download3.cc
  function onHighWaterMark (line 11) | void onHighWaterMark(const TcpConnectionPtr& conn, size_t len)
  function onConnection (line 20) | void onConnection(const TcpConnectionPtr& conn)
  function onWriteComplete (line 48) | void onWriteComplete(const TcpConnectionPtr& conn)
  function main (line 64) | int main(int argc, char* argv[])

FILE: examples/filetransfer/loadtest/Client.java
  class Client (line 13) | public class Client {
    class PipelineFactory (line 15) | private static final class PipelineFactory implements ChannelPipelineF...
      method PipelineFactory (line 21) | private PipelineFactory(int kMinLength, int kMaxLength, CountDownLat...
      method getPipeline (line 28) | @Override
    method main (line 41) | public static void main(String[] args) throws Exception {

FILE: examples/filetransfer/loadtest/Handler.java
  class Handler (line 13) | public class Handler extends SimpleChannelUpstreamHandler {
    method Handler (line 22) | public Handler(int maxLength, CountDownLatch latch) throws Exception {
    method channelConnected (line 30) | @Override
    method channelDisconnected (line 36) | @Override
    method messageReceived (line 47) | @Override
    method exceptionCaught (line 60) | @Override

FILE: examples/hub/codec.cc
  function ParseResult (line 7) | ParseResult pubsub::parseMessage(Buffer* buf,

FILE: examples/hub/codec.h
  function namespace (line 9) | namespace pubsub

FILE: examples/hub/hub.cc
  type pubsub (line 14) | namespace pubsub
    class Topic (line 19) | class Topic : public muduo::copyable
      method Topic (line 22) | Topic(const string& topic)
      method add (line 27) | void add(const TcpConnectionPtr& conn)
      method remove (line 36) | void remove(const TcpConnectionPtr& conn)
      method publish (line 41) | void publish(const string& content, Timestamp time)
      method string (line 56) | string makeMessage()
    class PubSubServer (line 67) | class PubSubServer : noncopyable
      method PubSubServer (line 70) | PubSubServer(muduo::net::EventLoop* loop,
      method start (line 82) | void start()
      method onConnection (line 88) | void onConnection(const TcpConnectionPtr& conn)
      method onMessage (line 107) | void onMessage(const TcpConnectionPtr& conn,
      method timePublish (line 146) | void timePublish()
      method doSubscribe (line 152) | void doSubscribe(const TcpConnectionPtr& conn,
      method doUnsubscribe (line 162) | void doUnsubscribe(const TcpConnectionPtr& conn,
      method doPublish (line 173) | void doPublish(const string& source,
      method Topic (line 181) | Topic& getTopic(const string& topic)
  function main (line 198) | int main(int argc, char* argv[])

FILE: examples/hub/pub.cc
  function connection (line 17) | void connection(PubSubClient* client)
  function main (line 30) | int main(int argc, char* argv[])

FILE: examples/hub/pubsub.h
  function namespace (line 6) | namespace pubsub

FILE: examples/hub/sub.cc
  function subscription (line 15) | void subscription(const string& topic, const string& content, Timestamp)
  function connection (line 20) | void connection(PubSubClient* client)
  function main (line 36) | int main(int argc, char* argv[])

FILE: examples/idleconnection/echo.h
  function class (line 12) | class EchoServer

FILE: examples/idleconnection/main.cc
  function main (line 27) | int main(int argc, char* argv[])

FILE: examples/idleconnection/sortedlist.cc
  class EchoServer (line 12) | class EchoServer
    method start (line 19) | void start()
    type Node (line 38) | struct Node : public muduo::copyable
  function main (line 165) | int main(int argc, char* argv[])

FILE: examples/maxconnection/echo.h
  function class (line 7) | class EchoServer

FILE: examples/maxconnection/main.cc
  function main (line 11) | int main(int argc, char* argv[])

FILE: examples/memcached/client/bench.cc
  class Client (line 16) | class Client : noncopyable
    type Operation (line 19) | enum Operation
    method Client (line 25) | Client(const string& name,
    method send (line 52) | void send()
    method onConnection (line 61) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 75) | void onMessage(const TcpConnectionPtr& conn,
    method fill (line 127) | void fill(Buffer* buf)
  function main (line 159) | int main(int argc, char* argv[])

FILE: examples/memcached/server/Item.h
  function namespace (line 10) | namespace muduo
  type std (line 19) | typedef std::shared_ptr<Item> ItemPtr;
  type std (line 20) | typedef std::shared_ptr<const Item> ConstItemPtr;
  function class (line 23) | class Item : muduo::noncopyable
  function setCas (line 93) | void setCas(uint64_t casArg)

FILE: examples/memcached/server/MemcacheServer.cc
  type MemcacheServer::Stats (line 17) | struct MemcacheServer::Stats
  function ConstItemPtr (line 140) | ConstItemPtr MemcacheServer::getItem(const ConstItemPtr& key) const

FILE: examples/memcached/server/MemcacheServer.h
  function class (line 15) | class MemcacheServer : muduo::noncopyable

FILE: examples/memcached/server/Session.cc
  function isBinaryProtocol (line 11) | static bool isBinaryProtocol(uint8_t firstByte)
  type Session::Reader (line 44) | struct Session::Reader
    method Reader (line 46) | Reader(Tokenizer::iterator& beg, Tokenizer::iterator end)
    method read (line 53) | bool read(T* val)

FILE: examples/memcached/server/Session.h
  type State (line 48) | enum State
  type Protocol (line 55) | enum Protocol
  type SpaceSeparator (line 76) | struct SpaceSeparator
  type boost (line 83) | typedef boost::tokenizer<SpaceSeparator,
  type Reader (line 86) | struct Reader
  type std (line 112) | typedef std::shared_ptr<Session> SessionPtr;

FILE: examples/memcached/server/footprint_test.cc
  function main (line 13) | int main(int argc, char* argv[])

FILE: examples/memcached/server/server.cc
  function parseCommandLine (line 12) | bool parseCommandLine(int argc, char* argv[], MemcacheServer::Options* o...
  function main (line 39) | int main(int argc, char* argv[])

FILE: examples/multiplexer/demux.cc
  type Entry (line 26) | struct Entry
  class DemuxServer (line 34) | class DemuxServer : noncopyable
    method DemuxServer (line 37) | DemuxServer(EventLoop* loop, const InetAddress& listenAddr, const Inet...
    method start (line 48) | void start()
    method onServerConnection (line 53) | void onServerConnection(const TcpConnectionPtr& conn)
    method onServerMessage (line 79) | void onServerMessage(const TcpConnectionPtr& conn, Buffer* buf, Timest...
    method doCommand (line 117) | void doCommand(const string& cmd)
    method onSocksConnection (line 155) | void onSocksConnection(int connId, const TcpConnectionPtr& conn)
    method onSocksMessage (line 184) | void onSocksMessage(int connId, const TcpConnectionPtr& conn, Buffer* ...
    method sendServerPacket (line 200) | void sendServerPacket(int connId, Buffer* buf)
  function main (line 224) | int main(int argc, char* argv[])

FILE: examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/DataEvent.java
  class DataEvent (line 7) | public class DataEvent extends Event {
    method DataEvent (line 13) | public DataEvent(EventSource source, int whichClient, ChannelBuffer da...
    method getString (line 19) | public String getString() {

FILE: examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/Event.java
  class Event (line 3) | public class Event {

FILE: examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/EventQueue.java
  class EventQueue (line 7) | public class EventQueue {
    method put (line 10) | public void put(Event e) {
    method take (line 14) | public Event take() {
    method isEmpty (line 22) | public boolean isEmpty() {

FILE: examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/EventSource.java
  type EventSource (line 3) | public enum EventSource {

FILE: examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/MockBackendServer.java
  class MockBackendServer (line 27) | public class MockBackendServer {
    class Handler (line 30) | private class Handler extends SimpleChannelHandler {
      method channelConnected (line 32) | @Override
      method channelDisconnected (line 41) | @Override
      method messageReceived (line 49) | @Override
      method exceptionCaught (line 62) | @Override
    method MockBackendServer (line 77) | public MockBackendServer(EventQueue queue, int listeningPort, Executor...
    method start (line 86) | public void start() {
    method sendToClient (line 92) | public void sendToClient(int whichClient, ChannelBuffer data) {
    method sendToClient (line 99) | public ChannelBuffer sendToClient(int whichClient, String str) {
    method stop (line 106) | public void stop() {
    method getBootstrap (line 110) | private ServerBootstrap getBootstrap() {

FILE: examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/MockClient.java
  class MockClient (line 28) | public class MockClient {
    class Handler (line 31) | private class Handler extends SimpleChannelHandler {
      method channelConnected (line 33) | @Override
      method channelDisconnected (line 43) | @Override
      method messageReceived (line 51) | @Override
      method exceptionCaught (line 59) | @Override
      method reconnect (line 66) | @SuppressWarnings("unused")
    method MockClient (line 89) | public MockClient(EventQueue queue, InetSocketAddress remoteAddress, E...
    method connect (line 99) | public ChannelFuture connect() {
    method connectAndWait (line 117) | public void connectAndWait() {
    method send (line 124) | public void send(ChannelBuffer buf) {
    method send (line 128) | public ChannelBuffer send(String str) {
    method disconnect (line 135) | public void disconnect() {
    method setId (line 139) | public void setId(int connId) {

FILE: examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/MultiplexerTest.java
  class MultiplexerTest (line 21) | public class MultiplexerTest {
    method MultiplexerTest (line 38) | public MultiplexerTest(String multiplexerHost) {
    method main (line 48) | public static void main(String[] args) {
    method addTestCase (line 64) | private void addTestCase(TestCase testCase) {
    method run (line 69) | private void run() {
    method newClient (line 84) | public MockClient newClient() {
    method getEventQueue (line 90) | public EventQueue getEventQueue() {
    method getBackend (line 94) | public MockBackendServer getBackend() {
    method sleep (line 98) | public void sleep(int millis) {

FILE: examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/MyCountDownLatch.java
  class MyCountDownLatch (line 6) | public class MyCountDownLatch extends CountDownLatch {
    method MyCountDownLatch (line 8) | public MyCountDownLatch(int count) {
    method awaitUninterruptibly (line 12) | public void awaitUninterruptibly() {
    method awaitUninterruptibly (line 19) | public void awaitUninterruptibly(int millis) {

FILE: examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/TestCase.java
  class TestCase (line 5) | public abstract class TestCase {
    method setOwner (line 12) | public void setOwner(MultiplexerTest god) {
    method test (line 18) | public void test() {
    method assertEquals (line 33) | protected void assertEquals(Object expected, Object actual) {
    method assertTrue (line 38) | protected void assertTrue(boolean yes) {
    method fail (line 43) | protected void fail(String message) {
    method run (line 47) | public abstract void run();

FILE: examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/TestFailedException.java
  class TestFailedException (line 3) | public class TestFailedException extends RuntimeException {
    method TestFailedException (line 6) | public TestFailedException(String message) {

FILE: examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/testcase/TestOneClientBackendSend.java
  class TestOneClientBackendSend (line 14) | public class TestOneClientBackendSend extends TestCase {
    method run (line 16) | @Override

FILE: examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/testcase/TestOneClientBothSend.java
  class TestOneClientBothSend (line 14) | public class TestOneClientBothSend extends TestCase {
    method run (line 16) | @Override

FILE: examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/testcase/TestOneClientNoData.java
  class TestOneClientNoData (line 11) | public class TestOneClientNoData extends TestCase {
    method run (line 13) | @Override

FILE: examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/testcase/TestOneClientSend.java
  class TestOneClientSend (line 14) | public class TestOneClientSend extends TestCase {
    method run (line 16) | @Override

FILE: examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/testcase/TestTwoClients.java
  class TestTwoClients (line 14) | public class TestTwoClients extends TestCase {
    method run (line 16) | @Override

FILE: examples/multiplexer/multiplexer.cc
  class MultiplexServer (line 27) | class MultiplexServer
    method MultiplexServer (line 30) | MultiplexServer(EventLoop* loop,
    method start (line 56) | void start()
    method sendBackendPacket (line 64) | void sendBackendPacket(int id, Buffer* buf)
    method sendBackendString (line 85) | void sendBackendString(int id, const string& msg)
    method sendBackendBuffer (line 93) | void sendBackendBuffer(int id, Buffer* buf)
    method sendToClient (line 108) | void sendToClient(Buffer* buf)
    method onClientConnection (line 140) | void onClientConnection(const TcpConnectionPtr& conn)
    method onClientMessage (line 197) | void onClientMessage(const TcpConnectionPtr& conn, Buffer* buf, Timest...
    method onBackendConnection (line 215) | void onBackendConnection(const TcpConnectionPtr& conn)
    method onBackendMessage (line 257) | void onBackendMessage(const TcpConnectionPtr& conn, Buffer* buf, Times...
    method printStatistics (line 265) | void printStatistics()
  function main (line 294) | int main(int argc, char* argv[])

FILE: examples/multiplexer/multiplexer_simple.cc
  class MultiplexServer (line 24) | class MultiplexServer : noncopyable
    method MultiplexServer (line 27) | MultiplexServer(EventLoop* loop, const InetAddress& listenAddr, const ...
    method start (line 42) | void start()
    method onClientConnection (line 50) | void onClientConnection(const TcpConnectionPtr& conn)
    method sendBackendString (line 105) | void sendBackendString(int id, const string& msg)
    method onClientMessage (line 113) | void onClientMessage(const TcpConnectionPtr& conn, Buffer* buf, Timest...
    method sendBackendBuffer (line 127) | void sendBackendBuffer(int id, Buffer* buf)
    method sendBackendPacket (line 142) | void sendBackendPacket(int id, Buffer* buf)
    method onBackendConnection (line 159) | void onBackendConnection(const TcpConnectionPtr& conn)
    method onBackendMessage (line 191) | void onBackendMessage(const TcpConnectionPtr& conn, Buffer* buf, Times...
    method sendToClient (line 196) | void sendToClient(Buffer* buf)
    method doCommand (line 229) | void doCommand(const string& cmd)
  function main (line 253) | int main(int argc, char* argv[])

FILE: examples/netty/discard/client.cc
  class DiscardClient (line 16) | class DiscardClient : noncopyable
    method DiscardClient (line 19) | DiscardClient(EventLoop* loop, const InetAddress& listenAddr, int size)
    method connect (line 33) | void connect()
    method onConnection (line 39) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 56) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp time)
    method onWriteComplete (line 61) | void onWriteComplete(const TcpConnectionPtr& conn)
  function main (line 72) | int main(int argc, char* argv[])

FILE: examples/netty/discard/server.cc
  class DiscardServer (line 19) | class DiscardServer
    method DiscardServer (line 22) | DiscardServer(EventLoop* loop, const InetAddress& listenAddr)
    method start (line 35) | void start()
    method onConnection (line 42) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 49) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp)
    method printThroughput (line 57) | void printThroughput()
  function main (line 81) | int main(int argc, char* argv[])

FILE: examples/netty/echo/client.cc
  class EchoClient (line 16) | class EchoClient : noncopyable
    method EchoClient (line 19) | EchoClient(EventLoop* loop, const InetAddress& listenAddr, int size)
    method connect (line 31) | void connect()
    method onConnection (line 37) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 54) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp time)
  function main (line 64) | int main(int argc, char* argv[])

FILE: examples/netty/echo/server.cc
  class EchoServer (line 19) | class EchoServer
    method EchoServer (line 22) | EchoServer(EventLoop* loop, const InetAddress& listenAddr)
    method start (line 35) | void start()
    method onConnection (line 42) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 50) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp)
    method printThroughput (line 58) | void printThroughput()
  function main (line 81) | int main(int argc, char* argv[])

FILE: examples/netty/echo/server2.cc
  class EchoServer (line 21) | class EchoServer
    method EchoServer (line 24) | EchoServer(EventLoop* loop, const InetAddress& listenAddr)
    method start (line 36) | void start()
    method onConnection (line 43) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 59) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp)
    method printThroughput (line 67) | void printThroughput()
    method printConnection (line 84) | void printConnection()
    method getLong (line 103) | long getLong(const string& procStatus, const char* key)
  function main (line 121) | int main(int argc, char* argv[])

FILE: examples/netty/uptime/uptime.cc
  class UptimeClient (line 16) | class UptimeClient : noncopyable
    method UptimeClient (line 19) | UptimeClient(EventLoop* loop, const InetAddress& listenAddr)
    method connect (line 29) | void connect()
    method onConnection (line 35) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 42) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp time)
  function main (line 49) | int main(int argc, char* argv[])

FILE: examples/pingpong/bench.cc
  function readCallback (line 26) | void readCallback(Timestamp, int fd, int idx)
  function runOnce (line 48) | std::pair<int, int> runOnce()
  function main (line 78) | int main(int argc, char* argv[])

FILE: examples/pingpong/client.cc
  class Client (line 17) | class Client
    method Client (line 80) | Client(EventLoop* loop,
    method string (line 113) | const string& message() const
    method onConnect (line 118) | void onConnect()
    method onDisconnect (line 126) | void onDisconnect(const TcpConnectionPtr& conn)
    method quit (line 151) | void quit()
    method handleTimeout (line 156) | void handleTimeout()
  class Session (line 19) | class Session : noncopyable
    method Session (line 22) | Session(EventLoop* loop,
    method start (line 38) | void start()
    method stop (line 43) | void stop()
    method bytesRead (line 48) | int64_t bytesRead() const
    method messagesRead (line 53) | int64_t messagesRead() const
    method onMessage (line 62) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp)
  class Client (line 77) | class Client : noncopyable
    method Client (line 80) | Client(EventLoop* loop,
    method string (line 113) | const string& message() const
    method onConnect (line 118) | void onConnect()
    method onDisconnect (line 126) | void onDisconnect(const TcpConnectionPtr& conn)
    method quit (line 151) | void quit()
    method handleTimeout (line 156) | void handleTimeout()
  function main (line 188) | int main(int argc, char* argv[])

FILE: examples/pingpong/server.cc
  function onConnection (line 17) | void onConnection(const TcpConnectionPtr& conn)
  function onMessage (line 25) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp)
  function main (line 30) | int main(int argc, char* argv[])

FILE: examples/procmon/dummyload.cc
  function busy (line 22) | double busy(int cycles)
  function getSeconds (line 32) | double getSeconds(int cycles)
  function findCycles (line 39) | void findCycles()
  function threadFunc (line 47) | void threadFunc()
  function load (line 62) | void load(int percent)
  function fixed (line 97) | void fixed()
  function cosine (line 105) | void cosine()
  function sawtooth (line 115) | void sawtooth()
  function main (line 125) | int main(int argc, char* argv[])

FILE: examples/procmon/plot.cc
  type Plot::MyGdFont (line 9) | struct Plot::MyGdFont : public gdFont {}

FILE: examples/procmon/plot.h
  type gdImageStruct (line 6) | struct gdImageStruct
  function class (line 8) | class Plot : muduo::noncopyable

FILE: examples/procmon/plot_test.cc
  function main (line 7) | int main()

FILE: examples/procmon/procmon.cc
  type StatData (line 32) | struct StatData
    method parse (line 34) | void parse(const char* startAtState, int kbPerPage)
  class Procmon (line 89) | class Procmon : noncopyable
    method Procmon (line 92) | Procmon(EventLoop* loop, pid_t pid, uint16_t port, const char* procname)
    method start (line 126) | void start()
    method string (line 135) | string getName() const
    method onRequest (line 142) | void onRequest(const HttpRequest& req, HttpResponse* resp)
    method fillOverview (line 222) | void fillOverview(const string& query)
    method fillRefresh (line 285) | void fillRefresh(const string& query)
    method dirFilter (line 298) | static int dirFilter(const struct dirent* d)
    method getDirType (line 303) | static char getDirType(char d_type)
    method listFiles (line 314) | void listFiles()
    method listThreads (line 345) | void listThreads()
    method string (line 351) | string readProcFile(const char* basename)
    method string (line 360) | string readLink(const char* basename)
    method appendTableRow (line 376) | void appendTableRow(const char* name, long value)
    method appendTableRowFloat (line 381) | void appendTableRowFloat(const char* name, double value)
    method appendTableRow (line 386) | void appendTableRow(const char* name, StringArg value)
    method string (line 391) | string getCmdLine()
    method string (line 396) | string getEnviron()
    method Timestamp (line 401) | Timestamp getStartTime(long starttime)
    method getSeconds (line 407) | double getSeconds(long ticks)
    method tick (line 412) | void tick()
    method getLong (line 457) | static long getLong(const string& status, const char* key)
    method getBootTime (line 468) | static long getBootTime()
    type CpuTime (line 475) | struct CpuTime
      method cpuUsage (line 479) | double cpuUsage(double kPeriod, double kClockTicksPerSecond) const
  function processExists (line 515) | bool processExists(pid_t pid)
  function main (line 522) | int main(int argc, char* argv[])

FILE: examples/protobuf/codec/client.cc
  class QueryClient (line 21) | class QueryClient : noncopyable
    method QueryClient (line 24) | QueryClient(EventLoop* loop,
    method connect (line 41) | void connect()
    method onConnection (line 48) | void onConnection(const TcpConnectionPtr& conn)
    method onUnknownMessage (line 64) | void onUnknownMessage(const TcpConnectionPtr&,
    method onAnswer (line 71) | void onAnswer(const muduo::net::TcpConnectionPtr&,
    method onEmpty (line 78) | void onEmpty(const muduo::net::TcpConnectionPtr&,
  function main (line 91) | int main(int argc, char* argv[])

FILE: examples/protobuf/codec/codec.cc
  function string (line 95) | const string& ProtobufCodec::errorCodeToString(ErrorCode errorCode)
  function asInt32 (line 128) | int32_t asInt32(const char* buf)
  function MessagePtr (line 186) | MessagePtr ProtobufCodec::parse(const char* buf, int len, ErrorCode* error)

FILE: examples/protobuf/codec/codec.h
  type std (line 26) | typedef std::shared_ptr<google::protobuf::Message> MessagePtr;
  function class (line 31) | class ProtobufCodec : muduo::noncopyable

FILE: examples/protobuf/codec/codec_test.cc
  function print (line 11) | void print(const Buffer& buf)
  function testQuery (line 22) | void testQuery()
  function testAnswer (line 47) | void testAnswer()
  function testEmpty (line 74) | void testEmpty()
  function redoCheckSum (line 92) | void redoCheckSum(string& data, int len)
  function testBadBuffer (line 104) | void testBadBuffer()
  function onMessage (line 195) | void onMessage(const muduo::net::TcpConnectionPtr& conn,
  function testOnMessage (line 202) | void testOnMessage()
  function main (line 245) | int main()

FILE: examples/protobuf/codec/dispatcher.h
  type std (line 21) | typedef std::shared_ptr<google::protobuf::Message> MessagePtr;
  function class (line 23) | class Callback : muduo::noncopyable
  function callback_ (line 42) | CallbackT(const ProtobufMessageTCallback& callback)
  function onMessage (line 47) | void onMessage(const muduo::net::TcpConnectionPtr& conn,
  function class (line 60) | class ProtobufDispatcher

FILE: examples/protobuf/codec/dispatcher_lite.h
  type std (line 19) | typedef std::shared_ptr<google::protobuf::Message> MessagePtr;
  function class (line 21) | class ProtobufDispatcherLite : muduo::noncopyable

FILE: examples/protobuf/codec/dispatcher_lite_test.cc
  function onUnknownMessageType (line 10) | void onUnknownMessageType(const muduo::net::TcpConnectionPtr&,
  function onQuery (line 17) | void onQuery(const muduo::net::TcpConnectionPtr&,
  function onAnswer (line 26) | void onAnswer(const muduo::net::TcpConnectionPtr&,
  function main (line 35) | int main()

FILE: examples/protobuf/codec/dispatcher_test.cc
  function test_down_pointer_cast (line 13) | void test_down_pointer_cast()
  function onQuery (line 24) | void onQuery(const muduo::net::TcpConnectionPtr&,
  function onAnswer (line 31) | void onAnswer(const muduo::net::TcpConnectionPtr&,
  function onUnknownMessageType (line 38) | void onUnknownMessageType(const muduo::net::TcpConnectionPtr&,
  function main (line 45) | int main()

FILE: examples/protobuf/codec/server.cc
  class QueryServer (line 19) | class QueryServer : noncopyable
    method QueryServer (line 22) | QueryServer(EventLoop* loop,
    method start (line 38) | void start()
    method onConnection (line 44) | void onConnection(const TcpConnectionPtr& conn)
    method onUnknownMessage (line 51) | void onUnknownMessage(const TcpConnectionPtr& conn,
    method onQuery (line 59) | void onQuery(const muduo::net::TcpConnectionPtr& conn,
    method onAnswer (line 75) | void onAnswer(const muduo::net::TcpConnectionPtr& conn,
  function main (line 88) | int main(int argc, char* argv[])

FILE: examples/protobuf/resolver/client.cc
  class RpcClient (line 18) | class RpcClient : noncopyable
    method RpcClient (line 21) | RpcClient(EventLoop* loop, const InetAddress& serverAddr)
    method connect (line 36) | void connect()
    method onConnection (line 42) | void onConnection(const TcpConnectionPtr& conn)
    method resolve (line 60) | void resolve(const std::string& host)
    method resolved (line 70) | void resolved(resolver::ResolveResponse* resp, std::string host) // pa...
  function main (line 100) | int main(int argc, char* argv[])

FILE: examples/protobuf/resolver/server.cc
  type resolver (line 13) | namespace resolver
    class ResolverServiceImpl (line 16) | class ResolverServiceImpl : public ResolverService
      method ResolverServiceImpl (line 19) | ResolverServiceImpl(EventLoop* loop)
      method Resolve (line 24) | virtual void Resolve(::google::protobuf::RpcController* controller,
      method doneCallback (line 47) | void doneCallback(const std::string& host,
  function main (line 73) | int main()

FILE: examples/protobuf/rpc/client.cc
  class RpcClient (line 16) | class RpcClient : noncopyable
    method RpcClient (line 19) | RpcClient(EventLoop* loop, const InetAddress& serverAddr)
    method connect (line 32) | void connect()
    method onConnection (line 38) | void onConnection(const TcpConnectionPtr& conn)
    method solved (line 56) | void solved(sudoku::SudokuResponse* resp)
  function main (line 68) | int main(int argc, char* argv[])

FILE: examples/protobuf/rpc/server.cc
  type sudoku (line 12) | namespace sudoku
    class SudokuServiceImpl (line 15) | class SudokuServiceImpl : public SudokuService
      method Solve (line 18) | virtual void Solve(::google::protobuf::RpcController* controller,
  function main (line 32) | int main()

FILE: examples/protobuf/rpcbalancer/balancer.cc
  class BackendSession (line 16) | class BackendSession : noncopyable
    method BackendSession (line 19) | BackendSession(EventLoop* loop, const InetAddress& backendAddr, const ...
    method connect (line 32) | void connect()
    method send (line 38) | bool send(RpcMessage& msg, const TcpConnectionPtr& clientConn)
    method onConnection (line 58) | void onConnection(const TcpConnectionPtr& conn)
    method onRpcMessage (line 76) | void onRpcMessage(const TcpConnectionPtr&,
    type Request (line 102) | struct Request
  class Balancer (line 116) | class Balancer : noncopyable
    method Balancer (line 119) | Balancer(EventLoop* loop,
    method setThreadNum (line 139) | void setThreadNum(int numThreads)
    method start (line 144) | void start()
    type PerThread (line 150) | struct PerThread
      method PerThread (line 154) | PerThread() : current(0) { }
    method initPerThread (line 157) | void initPerThread(EventLoop* ioLoop)
    method onConnection (line 173) | void onConnection(const TcpConnectionPtr& conn)
    method onRpcMessage (line 185) | void onRpcMessage(const TcpConnectionPtr& conn,
  function main (line 209) | int main(int argc, char* argv[])

FILE: examples/protobuf/rpcbalancer/balancer_raw.cc
  type RawMessage (line 19) | struct RawMessage
    method RawMessage (line 21) | RawMessage(StringPiece m)
    method id (line 25) | uint64_t id() const { return id_; }
    method set_id (line 26) | void set_id(uint64_t x) { id_ = x; }
    method parse (line 28) | bool parse(const string& tag)
    method updateId (line 52) | void updateId()
  class BackendSession (line 71) | class BackendSession : noncopyable
    method BackendSession (line 74) | BackendSession(EventLoop* loop, const InetAddress& backendAddr, const ...
    method connect (line 88) | void connect()
    method send (line 95) | bool send(MSG& msg, const TcpConnectionPtr& clientConn)
    method sendTo (line 115) | void sendTo(const TcpConnectionPtr& conn, const RpcMessage& msg)
    method sendTo (line 120) | void sendTo(const TcpConnectionPtr& conn, RawMessage& msg)
    method onConnection (line 126) | void onConnection(const TcpConnectionPtr& conn)
    method onRpcMessage (line 144) | void onRpcMessage(const TcpConnectionPtr&,
    method onRawMessage (line 151) | bool onRawMessage(const TcpConnectionPtr&,
    method onMessageT (line 166) | void onMessageT(MSG& msg)
    type Request (line 190) | struct Request
  class Balancer (line 204) | class Balancer : noncopyable
    method Balancer (line 207) | Balancer(EventLoop* loop,
    method setThreadNum (line 228) | void setThreadNum(int numThreads)
    method start (line 233) | void start()
    type PerThread (line 239) | struct PerThread
      method PerThread (line 243) | PerThread() : current(0) { }
    method initPerThread (line 246) | void initPerThread(EventLoop* ioLoop)
    method onConnection (line 262) | void onConnection(const TcpConnectionPtr& conn)
    method onRawMessage (line 274) | bool onRawMessage(const TcpConnectionPtr& conn,
    method onRpcMessage (line 288) | void onRpcMessage(const TcpConnectionPtr& conn,
    method onMessageT (line 296) | bool onMessageT(const TcpConnectionPtr& conn, MSG& msg)
  function main (line 319) | int main(int argc, char* argv[])

FILE: examples/protobuf/rpcbench/client.cc
  class RpcClient (line 20) | class RpcClient : noncopyable
    method RpcClient (line 24) | RpcClient(EventLoop* loop,
    method connect (line 43) | void connect()
    method sendRequest (line 48) | void sendRequest()
    method onConnection (line 57) | void onConnection(const TcpConnectionPtr& conn)
    method replied (line 68) | void replied(echo::EchoResponse* resp)
  function main (line 93) | int main(int argc, char* argv[])

FILE: examples/protobuf/rpcbench/server.cc
  type echo (line 12) | namespace echo
    class EchoServiceImpl (line 15) | class EchoServiceImpl : public EchoService
      method Echo (line 18) | virtual void Echo(::google::protobuf::RpcController* controller,
  function main (line 31) | int main(int argc, char* argv[])

FILE: examples/roundtrip/roundtrip.cc
  function serverConnectionCallback (line 13) | void serverConnectionCallback(const TcpConnectionPtr& conn)
  function serverMessageCallback (line 27) | void serverMessageCallback(const TcpConnectionPtr& conn,
  function runServer (line 41) | void runServer(uint16_t port)
  function clientConnectionCallback (line 53) | void clientConnectionCallback(const TcpConnectionPtr& conn)
  function clientMessageCallback (line 69) | void clientMessageCallback(const TcpConnectionPtr&,
  function sendMyTime (line 87) | void sendMyTime()
  function runClient (line 97) | void runClient(const char* ip, uint16_t port)
  function main (line 109) | int main(int argc, char* argv[])

FILE: examples/roundtrip/roundtrip_udp.cc
  function createNonblockingUDP (line 16) | int createNonblockingUDP()
  function serverReadCallback (line 28) | void serverReadCallback(int sockfd, muduo::Timestamp receiveTime)
  function runServer (line 63) | void runServer(uint16_t port)
  function clientReadCallback (line 76) | void clientReadCallback(int sockfd, muduo::Timestamp receiveTime)
  function sendMyTime (line 100) | void sendMyTime(int sockfd)
  function runClient (line 115) | void runClient(const char* ip, uint16_t port)
  function main (line 132) | int main(int argc, char* argv[])

FILE: examples/shorturl/shorturl.cc
  function onRequest (line 20) | void onRequest(const HttpRequest& req, HttpResponse* resp)
  function main (line 78) | int main(int argc, char* argv[])

FILE: examples/simple/allinone/allinone.cc
  function main (line 15) | int main()

FILE: examples/simple/chargen/chargen.h
  function class (line 7) | class ChargenServer

FILE: examples/simple/chargen/main.cc
  function main (line 11) | int main()

FILE: examples/simple/chargenclient/chargenclient.cc
  class ChargenClient (line 14) | class ChargenClient : noncopyable
    method ChargenClient (line 17) | ChargenClient(EventLoop* loop, const InetAddress& listenAddr)
    method connect (line 28) | void connect()
    method onConnection (line 34) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 44) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp re...
  function main (line 53) | int main(int argc, char* argv[])

FILE: examples/simple/daytime/daytime.h
  function class (line 7) | class DaytimeServer

FILE: examples/simple/daytime/main.cc
  function main (line 11) | int main()

FILE: examples/simple/discard/discard.h
  function class (line 7) | class DiscardServer

FILE: examples/simple/discard/main.cc
  function main (line 11) | int main()

FILE: examples/simple/echo/echo.h
  function class (line 7) | class EchoServer

FILE: examples/simple/echo/main.cc
  function main (line 11) | int main()

FILE: examples/simple/time/main.cc
  function main (line 11) | int main()

FILE: examples/simple/time/time.h
  function class (line 7) | class TimeServer

FILE: examples/simple/timeclient/timeclient.cc
  class TimeClient (line 15) | class TimeClient : noncopyable
    method TimeClient (line 18) | TimeClient(EventLoop* loop, const InetAddress& serverAddr)
    method connect (line 29) | void connect()
    method onConnection (line 39) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 51) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp re...
  function main (line 70) | int main(int argc, char* argv[])

FILE: examples/socks4a/balancer.cc
  function onServerConnection (line 14) | void onServerConnection(const TcpConnectionPtr& conn)
  function onServerMessage (line 44) | void onServerMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp)
  function main (line 54) | int main(int argc, char* argv[])

FILE: examples/socks4a/socks4a.cc
  function onServerConnection (line 14) | void onServerConnection(const TcpConnectionPtr& conn)
  function onServerMessage (line 32) | void onServerMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp)
  function main (line 116) | int main(int argc, char* argv[])

FILE: examples/socks4a/tcprelay.cc
  function onServerConnection (line 15) | void onServerConnection(const TcpConnectionPtr& conn)
  function onServerMessage (line 35) | void onServerMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp)
  function memstat (line 46) | void memstat()
  function main (line 51) | int main(int argc, char* argv[])

FILE: examples/socks4a/tunnel.h
  function setup (line 29) | void setup()
  function connect (line 45) | void connect()
  function disconnect (line 50) | void disconnect()
  function onClientConnection (line 69) | void onClientConnection(const muduo::net::TcpConnectionPtr& conn)
  function onClientMessage (line 96) | void onClientMessage(const muduo::net::TcpConnectionPtr& conn,
  type ServerClient (line 112) | enum ServerClient
  function onHighWaterMark (line 117) | void onHighWaterMark(ServerClient which,
  function onHighWaterMarkWeak (line 149) | static void onHighWaterMarkWeak(const std::weak_ptr<Tunnel>& wkTunnel,
  function onWriteComplete (line 161) | void onWriteComplete(ServerClient which, const muduo::net::TcpConnection...
  function onWriteCompleteWeak (line 177) | static void onWriteCompleteWeak(const std::weak_ptr<Tunnel>& wkTunnel,
  type std (line 193) | typedef std::shared_ptr<Tunnel> TunnelPtr;

FILE: examples/sudoku/batch.cc
  function verify (line 14) | bool verify(const string& result)
  function runLocal (line 19) | void runLocal(std::istream& in)
  function InputPtr (line 43) | InputPtr readInput(std::istream& in)
  class SudokuClient (line 59) | class SudokuClient : noncopyable
    method SudokuClient (line 62) | SudokuClient(EventLoop* loop,
    method connect (line 80) | void connect()
    method onConnection (line 86) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 106) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp)
  function done (line 161) | void done(const string& name, double elapsed, int count)
  function runClient (line 176) | void runClient(std::istream& in, const InetAddress& serverAddr, int conn)
  function main (line 196) | int main(int argc, char* argv[])

FILE: examples/sudoku/loadtest.cc
  function InputPtr (line 22) | InputPtr readInput(std::istream& in)
  class SudokuClient (line 36) | class SudokuClient : noncopyable
    method SudokuClient (line 39) | SudokuClient(EventLoop* loop,
    method connect (line 56) | void connect()
    method send (line 61) | void send(int n)
    method report (line 82) | void report(std::vector<int>* latency, int* infly)
    method onConnection (line 90) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 107) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp re...
    method verify (line 138) | bool verify(const string& response, Timestamp recvTime)
  class SudokuLoadtest (line 175) | class SudokuLoadtest : noncopyable
    method SudokuLoadtest (line 178) | SudokuLoadtest()
    method runClient (line 185) | void runClient(const InputPtr& input, const InetAddress& serverAddr, i...
    method tick (line 203) | void tick(int rps)
    method tock (line 218) | void tock()
  function main (line 242) | int main(int argc, char* argv[])

FILE: examples/sudoku/percentile.h
  function class (line 4) | class Percentile
  function save (line 35) | void save(const std::vector<int>& latencies, muduo::StringArg name) const

FILE: examples/sudoku/pipeline.cc
  class SudokuClient (line 22) | class SudokuClient : noncopyable
    method SudokuClient (line 25) | SudokuClient(EventLoop* loop,
    method connect (line 44) | void connect()
    method report (line 49) | void report(std::vector<int>* latency, int* infly)
    method onConnection (line 57) | void onConnection(const TcpConnectionPtr& conn)
    method send (line 75) | void send(int n)
    method onMessage (line 93) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp re...
    method verify (line 128) | bool verify(const string& response, Timestamp recvTime)
  function report (line 165) | void report(const std::vector<std::unique_ptr<SudokuClient>>& clients)
  function InputPtr (line 184) | InputPtr readInput(std::istream& in)
  function runClient (line 198) | void runClient(const InputPtr& input,
  function main (line 218) | int main(int argc, char* argv[])

FILE: examples/sudoku/server_basic.cc
  class SudokuServer (line 18) | class SudokuServer
    method SudokuServer (line 21) | SudokuServer(EventLoop* loop, const InetAddress& listenAddr)
    method start (line 31) | void start()
    method onConnection (line 37) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 44) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp)
    method processRequest (line 76) | bool processRequest(const TcpConnectionPtr& conn, const string& request)
  function main (line 117) | int main(int argc, char* argv[])

FILE: examples/sudoku/server_hybrid.cc
  class SudokuServer (line 23) | class SudokuServer : noncopyable
    method SudokuServer (line 26) | SudokuServer(EventLoop* loop,
    method start (line 55) | void start()
    method onConnection (line 63) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 72) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp re...
    type Request (line 107) | struct Request
    method processRequest (line 114) | bool processRequest(const TcpConnectionPtr& conn, const string& reques...
    method solve (line 141) | void solve(const TcpConnectionPtr& conn, const Request& req)
  function main (line 167) | int main(int argc, char* argv[])

FILE: examples/sudoku/server_multiloop.cc
  class SudokuServer (line 18) | class SudokuServer
    method SudokuServer (line 21) | SudokuServer(EventLoop* loop, const InetAddress& listenAddr, int numTh...
    method start (line 33) | void start()
    method onConnection (line 40) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 47) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp)
    method processRequest (line 79) | bool processRequest(const TcpConnectionPtr& conn, const string& request)
  function main (line 121) | int main(int argc, char* argv[])

FILE: examples/sudoku/server_prod.cc
  class SudokuServer (line 23) | class SudokuServer : noncopyable
    method SudokuServer (line 26) | SudokuServer(EventLoop* loop,
    method start (line 55) | void start()
    method onConnection (line 63) | void onConnection(const TcpConnectionPtr& conn)
    method highWaterMark (line 79) | void highWaterMark(const TcpConnectionPtr& conn, size_t tosend)
    method writeComplete (line 98) | void writeComplete(const TcpConnectionPtr& conn)
    method onMessage (line 108) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp re...
    type Request (line 142) | struct Request
    method processRequest (line 149) | bool processRequest(const TcpConnectionPtr& conn, const string& reques...
    method solve (line 192) | void solve(const TcpConnectionPtr& conn, const Request& req)
  function main (line 218) | int main(int argc, char* argv[])

FILE: examples/sudoku/server_threadpool.cc
  class SudokuServer (line 19) | class SudokuServer
    method SudokuServer (line 22) | SudokuServer(EventLoop* loop, const InetAddress& listenAddr, int numTh...
    method start (line 33) | void start()
    method onConnection (line 41) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 48) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp)
    method processRequest (line 80) | bool processRequest(const TcpConnectionPtr& conn, const string& request)
    method solve (line 108) | static void solve(const TcpConnectionPtr& conn,
  function main (line 130) | int main(int argc, char* argv[])

FILE: examples/sudoku/stat.h
  function class (line 3) | class SudokuStat : muduo::noncopyable
  function string (line 68) | string reset()
  function recordResponse (line 85) | void recordResponse(Timestamp now, Timestamp receive, bool solved)
  function recordRequest (line 162) | void recordRequest()
  function recordBadRequest (line 168) | void recordBadRequest()
  function recordDroppedRequest (line 174) | void recordDroppedRequest()

FILE: examples/sudoku/stat_unittest.cc
  function BOOST_AUTO_TEST_CASE (line 16) | BOOST_AUTO_TEST_CASE(testSudokuStatSameSecond)
  function BOOST_AUTO_TEST_CASE (line 31) | BOOST_AUTO_TEST_CASE(testSudokuStatNextSecond)
  function BOOST_AUTO_TEST_CASE (line 48) | BOOST_AUTO_TEST_CASE(testSudokuStatFuzz)
  function BOOST_AUTO_TEST_CASE (line 66) | BOOST_AUTO_TEST_CASE(testSudokuStatJumpAhead5)
  function BOOST_AUTO_TEST_CASE (line 82) | BOOST_AUTO_TEST_CASE(testSudokuStatJumpAhead59)
  function BOOST_AUTO_TEST_CASE (line 98) | BOOST_AUTO_TEST_CASE(testSudokuStatJumpAhead60)
  function BOOST_AUTO_TEST_CASE (line 114) | BOOST_AUTO_TEST_CASE(testSudokuStatJumpBack3)

FILE: examples/sudoku/sudoku.cc
  type Node (line 12) | struct Node
  type Node (line 14) | struct Node
  class SudokuSolver (line 30) | class SudokuSolver
    method SudokuSolver (line 33) | SudokuSolver(int board[kCells])
    method solve (line 95) | bool solve()
    method Column (line 144) | Column* new_column(int n = 0)
    method append_column (line 158) | void append_column(int n)
    method Node (line 167) | Node* new_row(int col)
    method get_row_col (line 186) | int get_row_col(int row, int val)
    method get_col_col (line 191) | int get_col_col(int col, int val)
    method get_box_col (line 196) | int get_box_col(int box, int val)
    method Column (line 201) | Column* get_min_column()
    method cover (line 218) | void cover(Column* c)
    method uncover (line 231) | void uncover(Column* c)
    method put_left (line 244) | void put_left(Column* old, Column* nnew)
    method put_up (line 252) | void put_up(Column* old, Node* nnew)
  function string (line 263) | string solveSudoku(const StringPiece& puzzle)

FILE: examples/twisted/finger/finger01.cc
  function main (line 6) | int main()

FILE: examples/twisted/finger/finger02.cc
  function main (line 7) | int main()

FILE: examples/twisted/finger/finger03.cc
  function onConnection (line 7) | void onConnection(const TcpConnectionPtr& conn)
  function main (line 15) | int main()

FILE: examples/twisted/finger/finger04.cc
  function onMessage (line 7) | void onMessage(const TcpConnectionPtr& conn,
  function main (line 17) | int main()

FILE: examples/twisted/finger/finger05.cc
  function onMessage (line 7) | void onMessage(const TcpConnectionPtr& conn,
  function main (line 18) | int main()

FILE: examples/twisted/finger/finger06.cc
  function string (line 12) | string getUser(const string& user)
  function onMessage (line 23) | void onMessage(const TcpConnectionPtr& conn,
  function main (line 37) | int main()

FILE: examples/twisted/finger/finger07.cc
  function string (line 12) | string getUser(const string& user)
  function onMessage (line 23) | void onMessage(const TcpConnectionPtr& conn,
  function main (line 37) | int main()

FILE: examples/wordcount/hash.h
  type std (line 6) | typedef std::unordered_map<muduo::string, int64_t> WordCountMap;

FILE: examples/wordcount/hasher.cc
  class SendThrottler (line 23) | class SendThrottler : muduo::noncopyable
    method SendThrottler (line 26) | SendThrottler(EventLoop* loop, const InetAddress& addr)
    method connect (line 38) | void connect()
    method disconnect (line 44) | void disconnect()
    method send (line 55) | void send(const string& word, int64_t count)
    method onConnection (line 71) | void onConnection(const TcpConnectionPtr& conn)
    method onHighWaterMark (line 90) | void onHighWaterMark()
    method onWriteComplete (line 96) | void onWriteComplete()
    method throttle (line 107) | void throttle()
  class WordCountSender (line 128) | class WordCountSender : muduo::noncopyable
    method connectAll (line 133) | void connectAll()
    method disconnectAll (line 142) | void disconnectAll()
  function main (line 214) | int main(int argc, char* argv[])

FILE: examples/wordcount/receiver.cc
  class WordCountReceiver (line 14) | class WordCountReceiver : muduo::noncopyable
    method WordCountReceiver (line 17) | WordCountReceiver(EventLoop* loop, const InetAddress& listenAddr)
    method start (line 28) | void start(int senders)
    method onConnection (line 37) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 52) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp)
    method output (line 75) | void output()
  function main (line 92) | int main(int argc, char* argv[])

FILE: examples/zeromq/local_lat.cc
  function onConnection (line 16) | void onConnection(const muduo::net::TcpConnectionPtr& conn)
  function onStringMessage (line 24) | void onStringMessage(LengthHeaderCodec* codec,
  function main (line 32) | int main(int argc, char* argv[])

FILE: examples/zeromq/remote_lat.cc
  function onConnection (line 20) | void onConnection(LengthHeaderCodec* codec, const muduo::net::TcpConnect...
  function onStringMessage (line 36) | void onStringMessage(LengthHeaderCodec* codec,
  function main (line 69) | int main(int argc, char* argv[])

FILE: muduo/base/AsyncLogging.h
  function namespace (line 19) | namespace muduo

FILE: muduo/base/Atomic.h
  function namespace (line 13) | namespace muduo

FILE: muduo/base/BlockingQueue.h
  function namespace (line 15) | namespace muduo

FILE: muduo/base/BoundedBlockingQueue.h
  function namespace (line 15) | namespace muduo

FILE: muduo/base/Condition.cc
  type timespec (line 13) | struct timespec

FILE: muduo/base/Condition.h
  function namespace (line 13) | namespace muduo

FILE: muduo/base/CountDownLatch.h
  function namespace (line 12) | namespace muduo

FILE: muduo/base/CurrentThread.cc
  type muduo (line 12) | namespace muduo
    type CurrentThread (line 14) | namespace CurrentThread
      function string (line 22) | string stackTrace(bool demangle)

FILE: muduo/base/CurrentThread.h
  function namespace (line 11) | namespace muduo

FILE: muduo/base/Date.cc
  type muduo (line 10) | namespace muduo
    type detail (line 12) | namespace detail
      function getJulianDayNumber (line 21) | int getJulianDayNumber(int year, int month, int day)
      function getYearMonthDay (line 30) | struct Date::YearMonthDay getYearMonthDay(int julianDayNumber)
  type tm (line 56) | struct tm
  function string (line 64) | string Date::toIsoString() const

FILE: muduo/base/Date.h
  type tm (line 12) | struct tm
  type YearMonthDay (line 29) | struct YearMonthDay
  function explicit (line 55) | explicit Date(int julianDayNum)
  type tm (line 62) | struct tm
  function swap (line 66) | void swap(Date& that)
  function string (line 76) | string toIsoString() const;

FILE: muduo/base/Exception.cc
  type muduo (line 9) | namespace muduo

FILE: muduo/base/Exception.h
  function namespace (line 12) | namespace muduo

FILE: muduo/base/FileUtil.cc
  type stat (line 102) | struct stat

FILE: muduo/base/FileUtil.h
  function namespace (line 15) | namespace muduo

FILE: muduo/base/GzipFile.h
  function namespace (line 12) | namespace muduo

FILE: muduo/base/LogFile.cc
  function string (line 110) | string LogFile::getLogFileName(const string& basename, time_t* now)

FILE: muduo/base/LogFile.h
  function namespace (line 14) | namespace muduo

FILE: muduo/base/LogStream.cc
  type muduo (line 33) | namespace muduo
    type detail (line 35) | namespace detail
      function convert (line 47) | size_t convert(char buf[], T value)
      function convertHex (line 69) | size_t convertHex(char buf[], uintptr_t value)
      class FixedBuffer<kSmallBuffer> (line 87) | class FixedBuffer<kSmallBuffer>
      class FixedBuffer<kLargeBuffer> (line 88) | class FixedBuffer<kLargeBuffer>
    function formatSI (line 102) | std::string formatSI(int64_t s)
    function formatIEC (line 150) | std::string formatIEC(int64_t s)
  function LogStream (line 246) | LogStream& LogStream::operator<<(short v)
  function LogStream (line 252) | LogStream& LogStream::operator<<(unsigned short v)
  function LogStream (line 258) | LogStream& LogStream::operator<<(int v)
  function LogStream (line 264) | LogStream& LogStream::operator<<(unsigned int v)
  function LogStream (line 270) | LogStream& LogStream::operator<<(long v)
  function LogStream (line 276) | LogStream& LogStream::operator<<(unsigned long v)
  function LogStream (line 282) | LogStream& LogStream::operator<<(long long v)
  function LogStream (line 288) | LogStream& LogStream::operator<<(unsigned long long v)
  function LogStream (line 294) | LogStream& LogStream::operator<<(const void* p)
  function LogStream (line 309) | LogStream& LogStream::operator<<(double v)

FILE: muduo/base/LogStream.h
  function namespace (line 15) | namespace muduo
  function append (line 156) | void append(const char* data, int len) { buffer_.append(data, len); }
  function resetBuffer (line 158) | void resetBuffer() { buffer_.reset(); }
  function class (line 171) | class Fmt // : noncopyable

FILE: muduo/base/Logging.cc
  type muduo (line 18) | namespace muduo
    function initLogLevel (line 47) | Logger::LogLevel initLogLevel()
    class T (line 70) | class T
      method T (line 73) | T(const char* str, unsigned len)
    function LogStream (line 84) | inline LogStream& operator<<(LogStream& s, T v)
    function LogStream (line 90) | inline LogStream& operator<<(LogStream& s, const Logger::SourceFile& v)
    function defaultOutput (line 96) | void defaultOutput(const char* msg, int len)
    function defaultFlush (line 103) | void defaultFlush()
  type DateTime (line 141) | struct DateTime

FILE: muduo/base/Logging.h
  function namespace (line 12) | namespace muduo

FILE: muduo/base/Mutex.h
  function namespace (line 107) | namespace muduo

FILE: muduo/base/ProcessInfo.cc
  type muduo (line 21) | namespace muduo
    type detail (line 23) | namespace detail
      function fdDirFilter (line 26) | int fdDirFilter(const struct dirent* d)
      function taskDirFilter (line 36) | int taskDirFilter(const struct dirent* d)
      function scanDir (line 45) | int scanDir(const char *dirpath, int (*filter)(const struct dirent *))
  function pid_t (line 63) | pid_t ProcessInfo::pid()
  function string (line 68) | string ProcessInfo::pidString()
  function uid_t (line 75) | uid_t ProcessInfo::uid()
  function string (line 80) | string ProcessInfo::username()
  function uid_t (line 95) | uid_t ProcessInfo::euid()
  function Timestamp (line 100) | Timestamp ProcessInfo::startTime()
  function string (line 124) | string ProcessInfo::hostname()
  function string (line 140) | string ProcessInfo::procname()
  function StringPiece (line 145) | StringPiece ProcessInfo::procname(const string& stat)
  function string (line 157) | string ProcessInfo::procStatus()
  function string (line 164) | string ProcessInfo::procStat()
  function string (line 171) | string ProcessInfo::threadStat()
  function string (line 180) | string ProcessInfo::exePath()
  type rlimit (line 201) | struct rlimit
  type tms (line 215) | struct tms

FILE: muduo/base/ProcessInfo.h
  function namespace (line 20) | namespace ProcessInfo

FILE: muduo/base/Singleton.h
  function namespace (line 15) | namespace muduo

FILE: muduo/base/StringPiece.h
  function namespace (line 48) | namespace muduo
  function StringPiece (line 177) | struct __type_traits<muduo::StringPiece> {

FILE: muduo/base/Thread.cc
  type muduo (line 21) | namespace muduo
    type detail (line 23) | namespace detail
      function pid_t (line 26) | pid_t gettid()
      function afterFork (line 31) | void afterFork()
      class ThreadNameInitializer (line 39) | class ThreadNameInitializer
        method ThreadNameInitializer (line 42) | ThreadNameInitializer()
      type ThreadData (line 52) | struct ThreadData
        method ThreadData (line 60) | ThreadData(ThreadFunc func,
        method runInThread (line 70) | void runInThread()
    type timespec (line 134) | struct timespec

FILE: muduo/base/Thread.h
  function namespace (line 17) | namespace muduo

FILE: muduo/base/ThreadLocal.h
  function namespace (line 14) | namespace muduo

FILE: muduo/base/ThreadLocalSingleton.h
  function namespace (line 14) | namespace muduo

FILE: muduo/base/ThreadPool.h
  function namespace (line 17) | namespace muduo

FILE: muduo/base/TimeZone.cc
  type TimeZone::Data (line 25) | struct TimeZone::Data
    type Transition (line 27) | struct Transition
      method Transition (line 33) | Transition(int64_t t, int64_t l, int localIdx)
    type LocalTime (line 38) | struct LocalTime
      method LocalTime (line 44) | LocalTime(int32_t offset, bool dst, int idx)
    method addLocalTime (line 49) | void addLocalTime(int32_t utcOffset, bool isDst, int desigIdx)
    method addTransition (line 54) | void addTransition(int64_t utcTime, int localtimeIdx)
    type DateTime (line 61) | struct DateTime
    type CompareUtcTime (line 63) | struct CompareUtcTime
    type CompareLocalTime (line 71) | struct CompareLocalTime
  type muduo (line 85) | namespace muduo
    type detail (line 90) | namespace detail
      class File (line 93) | class File : noncopyable
        method File (line 96) | File(const char* file)
        method valid (line 109) | bool valid() const { return fp_; }
        method string (line 111) | string readBytes(int n)
        method string (line 120) | string readToEnd()
        method readInt64 (line 132) | int64_t readInt64()
        method readInt32 (line 141) | int32_t readInt32()
        method readUInt8 (line 150) | uint8_t readUInt8()
        method off_t (line 159) | off_t skip(ssize_t bytes)
      function readDataBlock (line 169) | bool readDataBlock(File& f, struct TimeZone::Data* data, bool v1)
      function readTimeZoneFile (line 238) | bool readTimeZoneFile(const char* zonefile, struct TimeZone::Data* d...
      function fillHMS (line 285) | inline void fillHMS(unsigned seconds, struct DateTime* dt)
      function DateTime (line 293) | DateTime BreakTime(int64_t t)
  type DateTime (line 359) | struct DateTime
  function TimeZone (line 433) | TimeZone TimeZone::UTC()
  function TimeZone (line 439) | TimeZone TimeZone::loadZoneFile(const char* zonefile)
  type DateTime (line 461) | struct DateTime
  type DateTime (line 463) | struct DateTime
  type DateTime (line 480) | struct DateTime
  function DateTime (line 493) | DateTime TimeZone::toUtcTime(int64_t secondsSinceEpoch)
  type tm (line 507) | struct tm
  function string (line 513) | string DateTime::toIsoString() const

FILE: muduo/base/TimeZone.h
  function namespace (line 14) | namespace muduo

FILE: muduo/base/Timestamp.cc
  function string (line 22) | string Timestamp::toString() const
  function string (line 31) | string Timestamp::toFormattedString(bool showMicroseconds) const
  function Timestamp (line 55) | Timestamp Timestamp::now()

FILE: muduo/base/Timestamp.h
  function namespace (line 14) | namespace muduo
  function string (line 52) | string toString() const;
  function Timestamp (line 66) | static Timestamp invalid()
  function Timestamp (line 71) | static Timestamp fromUnixTime(time_t t)
  function Timestamp (line 76) | static Timestamp fromUnixTime(time_t t, int microseconds)
  function timeDifference (line 104) | inline double timeDifference(Timestamp high, Timestamp low)
  function Timestamp (line 115) | inline Timestamp addTime(Timestamp timestamp, double seconds)

FILE: muduo/base/Types.h
  function namespace (line 15) | namespace muduo

FILE: muduo/base/WeakCallback.h
  function namespace (line 12) | namespace muduo

FILE: muduo/base/copyable.h
  function namespace (line 4) | namespace muduo

FILE: muduo/base/noncopyable.h
  function namespace (line 4) | namespace muduo

FILE: muduo/base/tests/AsyncLogging_test.cc
  function asyncOutput (line 13) | void asyncOutput(const char* msg, int len)
  function bench (line 18) | void bench(bool longLog)
  function main (line 45) | int main(int argc, char* argv[])

FILE: muduo/base/tests/Atomic_unittest.cc
  function main (line 4) | int main()

FILE: muduo/base/tests/BlockingQueue_bench.cc
  class Bench (line 16) | class Bench
    method Bench (line 19) | Bench(int numThreads)
    method run (line 36) | void run(int times)
    method joinAll (line 51) | void joinAll()
    method threadFunc (line 67) | void threadFunc()
  function main (line 113) | int main(int argc, char* argv[])

FILE: muduo/base/tests/BlockingQueue_bench2.cc
  class Bench (line 14) | class Bench
    method Bench (line 17) | Bench(int numThreads)
    method Start (line 34) | void Start()
    method Run (line 47) | void Run()
    method Stop (line 59) | void Stop()
    method threadFunc (line 77) | void threadFunc(int id)
  function main (line 112) | int main(int argc, char* argv[])

FILE: muduo/base/tests/BlockingQueue_test.cc
  class Test (line 11) | class Test
    method Test (line 14) | Test(int numThreads)
    method run (line 30) | void run(int times)
    method joinAll (line 44) | void joinAll()
    method threadFunc (line 59) | void threadFunc()
  function testMove (line 84) | void testMove()
  function main (line 96) | int main()

FILE: muduo/base/tests/BoundedBlockingQueue_test.cc
  class Test (line 11) | class Test
    method Test (line 14) | Test(int numThreads)
    method run (line 32) | void run(int times)
    method joinAll (line 46) | void joinAll()
    method threadFunc (line 61) | void threadFunc()
  function testMove (line 86) | void testMove()
  function main (line 101) | int main()

FILE: muduo/base/tests/Date_unittest.cc
  function isLeapYear (line 10) | int isLeapYear(int year)
  function daysOfMonth (line 22) | int daysOfMonth(int year, int month)
  function passByConstReference (line 32) | void passByConstReference(const Date& x)
  function passByValue (line 37) | void passByValue(Date x)
  function main (line 42) | int main()

FILE: muduo/base/tests/Exception_test.cc
  class Bar (line 7) | class Bar
    method test (line 10) | void test(std::vector<std::string> names = {})
    method callback (line 28) | void callback()
  function foo (line 34) | void foo()
  function main (line 40) | int main()

FILE: muduo/base/tests/FileUtil_test.cc
  function main (line 9) | int main()

FILE: muduo/base/tests/Fork_test.cc
  function print (line 12) | void print()
  function main (line 17) | int main()

FILE: muduo/base/tests/GzipFile_test.cc
  function main (line 5) | int main()

FILE: muduo/base/tests/LogFile_test.cc
  function outputFunc (line 8) | void outputFunc(const char* msg, int len)
  function flushFunc (line 13) | void flushFunc()
  function main (line 18) | int main(int argc, char* argv[])

FILE: muduo/base/tests/LogStream_bench.cc
  function benchPrintf (line 16) | void benchPrintf(const char* fmt)
  function benchStringStream (line 28) | void benchStringStream()
  function benchLogStream (line 44) | void benchLogStream()
  function main (line 58) | int main()

FILE: muduo/base/tests/LogStream_test.cc
  function BOOST_AUTO_TEST_CASE (line 13) | BOOST_AUTO_TEST_CASE(testLogStreamBooleans)
  function BOOST_AUTO_TEST_CASE (line 26) | BOOST_AUTO_TEST_CASE(testLogStreamIntegers)
  function BOOST_AUTO_TEST_CASE (line 43) | BOOST_AUTO_TEST_CASE(testLogStreamIntegerLimits)
  function BOOST_AUTO_TEST_CASE (line 113) | BOOST_AUTO_TEST_CASE(testLogStreamFloats)
  function BOOST_AUTO_TEST_CASE (line 172) | BOOST_AUTO_TEST_CASE(testLogStreamVoid)
  function BOOST_AUTO_TEST_CASE (line 186) | BOOST_AUTO_TEST_CASE(testLogStreamStrings)
  function BOOST_AUTO_TEST_CASE (line 199) | BOOST_AUTO_TEST_CASE(testLogStreamFmts)
  function BOOST_AUTO_TEST_CASE (line 217) | BOOST_AUTO_TEST_CASE(testLogStreamLong)
  function BOOST_AUTO_TEST_CASE (line 237) | BOOST_AUTO_TEST_CASE(testFormatSI)
  function BOOST_AUTO_TEST_CASE (line 263) | BOOST_AUTO_TEST_CASE(testFormatIEC)

FILE: muduo/base/tests/Logging_test.cc
  function dummyOutput (line 13) | void dummyOutput(const char* msg, int len)
  function bench (line 26) | void bench(const char* type)
  function logInThread (line 49) | void logInThread()
  function main (line 55) | int main()

FILE: muduo/base/tests/Mutex_test.cc
  function threadFunc (line 16) | void threadFunc()
  function foo (line 28) | int foo()
  function main (line 41) | int main()

FILE: muduo/base/tests/ProcessInfo_test.cc
  function main (line 6) | int main()

FILE: muduo/base/tests/SingletonThreadLocal_test.cc
  class Test (line 9) | class Test : muduo::noncopyable
    method Test (line 12) | Test()
    method setName (line 23) | void setName(const muduo::string& n) { name_ = n; }
  function print (line 31) | void print()
  function threadFunc (line 39) | void threadFunc(const char* changeTo)
  function main (line 47) | int main()

FILE: muduo/base/tests/Singleton_test.cc
  class Test (line 7) | class Test : muduo::noncopyable
    method Test (line 10) | Test()
    method setName (line 21) | void setName(const muduo::string& n) { name_ = n; }
  class TestNoDestroy (line 27) | class TestNoDestroy : muduo::noncopyable
    method TestNoDestroy (line 33) | TestNoDestroy()
  function threadFunc (line 44) | void threadFunc()
  function main (line 53) | int main()

FILE: muduo/base/tests/ThreadLocalSingleton_test.cc
  class Test (line 7) | class Test : muduo::noncopyable
    method Test (line 10) | Test()
    method setName (line 21) | void setName(const muduo::string& n) { name_ = n; }
  function threadFunc (line 27) | void threadFunc(const char* changeTo)
  function main (line 43) | int main()

FILE: muduo/base/tests/ThreadLocal_test.cc
  class Test (line 7) | class Test : muduo::noncopyable
    method Test (line 10) | Test()
    method setName (line 21) | void setName(const muduo::string& n) { name_ = n; }
  function print (line 30) | void print()
  function threadFunc (line 42) | void threadFunc()
  function main (line 50) | int main()

FILE: muduo/base/tests/ThreadPool_test.cc
  function print (line 9) | void print()
  function printString (line 14) | void printString(const std::string& str)
  function test (line 20) | void test(int maxSize)
  function longTask (line 57) | void longTask(int num)
  function test2 (line 63) | void test2()
  function main (line 89) | int main()

FILE: muduo/base/tests/Thread_bench.cc
  function threadFunc (line 21) | void threadFunc()
  function threadFunc2 (line 27) | void threadFunc2(muduo::Timestamp start)
  function forkBench (line 35) | void forkBench()
  class Bench (line 61) | class Bench
    method Bench (line 64) | Bench(int numThreads)
    method Start (line 79) | void Start()
    method Stop (line 105) | void Stop()
    method threadFunc (line 129) | void threadFunc()
  function main (line 144) | int main(int argc, char* argv[])

FILE: muduo/base/tests/Thread_test.cc
  function mysleep (line 8) | void mysleep(int seconds)
  function threadFunc (line 14) | void threadFunc()
  function threadFunc2 (line 19) | void threadFunc2(int x)
  function threadFunc3 (line 24) | void threadFunc3()
  class Foo (line 30) | class Foo
    method Foo (line 33) | explicit Foo(double x)
    method memberFunc (line 38) | void memberFunc()
    method memberFunc2 (line 43) | void memberFunc2(const std::string& text)
  function main (line 52) | int main()

FILE: muduo/base/tests/TimeZone_unittest.cc
  function getTm (line 11) | struct tm getTm(int year, int month, int day,
  function getTm (line 25) | struct tm getTm(const char* str)
  function time_t (line 33) | time_t getGmt(int year, int month, int day,
  function time_t (line 40) | time_t getGmt(const char* str)
  type TestCase (line 46) | struct TestCase
  function test (line 55) | void test(const TimeZone& tz, TestCase tc)
  function testNewYork (line 92) | void testNewYork()
  function testLondon (line 168) | void testLondon()
  function testHongKong (line 212) | void testHongKong()
  function testSydney (line 235) | void testSydney()
  function testUtc (line 267) | void testUtc()
  function testFixedTimezone (line 306) | void testFixedTimezone()
  type LocalToUtcTestCase (line 327) | struct LocalToUtcTestCase
  function testLosAngeles (line 334) | void testLosAngeles()
  function main (line 426) | int main()

FILE: muduo/base/tests/TimeZone_util.cc
  function printUtcAndLocal (line 16) | void printUtcAndLocal(int64_t utc, TimeZone local)
  function main (line 25) | int main(int argc, char* argv[])

FILE: muduo/base/tests/Timestamp_unittest.cc
  function passByConstReference (line 7) | void passByConstReference(const Timestamp& x)
  function passByValue (line 12) | void passByValue(Timestamp x)
  function benchmark (line 17) | void benchmark()
  function main (line 58) | int main()

FILE: muduo/net/Acceptor.h
  function namespace (line 19) | namespace muduo

FILE: muduo/net/Buffer.cc
  type iovec (line 29) | struct iovec

FILE: muduo/net/Buffer.h
  function namespace (line 27) | namespace muduo

FILE: muduo/net/Callbacks.h
  function namespace (line 19) | namespace muduo

FILE: muduo/net/Channel.cc
  function string (line 116) | string Channel::reventsToString() const
  function string (line 121) | string Channel::eventsToString() const
  function string (line 126) | string Channel::eventsToString(int fd, int ev)

FILE: muduo/net/Channel.h
  function namespace (line 20) | namespace muduo

FILE: muduo/net/Connector.h
  function namespace (line 20) | namespace muduo

FILE: muduo/net/Endian.h
  function namespace (line 17) | namespace muduo

FILE: muduo/net/EventLoop.cc
  function createEventfd (line 33) | int createEventfd()
  class IgnoreSigPipe (line 45) | class IgnoreSigPipe
    method IgnoreSigPipe (line 48) | IgnoreSigPipe()
  function EventLoop (line 59) | EventLoop* EventLoop::getEventLoopOfCurrentThread()
  function TimerId (line 179) | TimerId EventLoop::runAt(Timestamp time, TimerCallback cb)
  function TimerId (line 184) | TimerId EventLoop::runAfter(double delay, TimerCallback cb)
  function TimerId (line 190) | TimerId EventLoop::runEvery(double interval, TimerCallback cb)

FILE: muduo/net/EventLoop.h
  function namespace (line 26) | namespace muduo

FILE: muduo/net/EventLoopThread.cc
  function EventLoop (line 39) | EventLoop* EventLoopThread::startLoop()

FILE: muduo/net/EventLoopThread.h
  function namespace (line 18) | namespace muduo

FILE: muduo/net/EventLoopThreadPool.cc
  function EventLoop (line 54) | EventLoop* EventLoopThreadPool::getNextLoop()
  function EventLoop (line 73) | EventLoop* EventLoopThreadPool::getLoopForHash(size_t hashCode)

FILE: muduo/net/EventLoopThreadPool.h
  function namespace (line 21) | namespace muduo

FILE: muduo/net/InetAddress.cc
  type sockaddr_in6 (line 48) | struct sockaddr_in6
  function string (line 91) | string InetAddress::toIpPort() const
  function string (line 98) | string InetAddress::toIp() const
  type hostent (line 121) | struct hostent
  type hostent (line 122) | struct hostent
  type in_addr (line 130) | struct in_addr

FILE: muduo/net/InetAddress.h
  function namespace (line 19) | namespace muduo

FILE: muduo/net/Poller.h
  function namespace (line 20) | namespace muduo

FILE: muduo/net/Socket.cc
  type tcp_info (line 27) | struct tcp_info
  type tcp_info (line 36) | struct tcp_info
  type sockaddr_in6 (line 72) | struct sockaddr_in6

FILE: muduo/net/Socket.h
  type tcp_info (line 17) | struct tcp_info
  function namespace (line 19) | namespace muduo

FILE: muduo/net/SocketsOps.cc
  type sockaddr (line 28) | struct sockaddr
  function setNonBlockAndCloseOnExec (line 32) | void setNonBlockAndCloseOnExec(int sockfd)
  type sockaddr (line 52) | struct sockaddr
  type sockaddr_in6 (line 52) | struct sockaddr_in6
  type sockaddr (line 54) | struct sockaddr
  type sockaddr (line 57) | struct sockaddr
  type sockaddr_in6 (line 57) | struct sockaddr_in6
  type sockaddr (line 59) | struct sockaddr
  type sockaddr (line 62) | struct sockaddr
  type sockaddr_in (line 62) | struct sockaddr_in
  type sockaddr (line 64) | struct sockaddr
  type sockaddr_in (line 67) | struct sockaddr_in
  type sockaddr (line 67) | struct sockaddr
  type sockaddr_in (line 69) | struct sockaddr_in
  type sockaddr_in6 (line 72) | struct sockaddr_in6
  type sockaddr (line 72) | struct sockaddr
  type sockaddr_in6 (line 74) | struct sockaddr_in6
  type sockaddr (line 97) | struct sockaddr
  type sockaddr_in6 (line 99) | struct sockaddr_in6
  type sockaddr_in6 (line 115) | struct sockaddr_in6
  type sockaddr (line 159) | struct sockaddr
  type sockaddr_in6 (line 161) | struct sockaddr_in6
  type iovec (line 169) | struct iovec
  type sockaddr (line 196) | struct sockaddr
  type sockaddr_in6 (line 203) | struct sockaddr_in6
  type sockaddr_in (line 211) | struct sockaddr_in
  type sockaddr (line 218) | struct sockaddr
  type sockaddr_in (line 223) | struct sockaddr_in
  type sockaddr_in6 (line 229) | struct sockaddr_in6
  type sockaddr_in (line 235) | struct sockaddr_in
  type sockaddr_in6 (line 246) | struct sockaddr_in6
  type sockaddr_in6 (line 271) | struct sockaddr_in6
  type sockaddr_in6 (line 273) | struct sockaddr_in6
  type sockaddr_in6 (line 283) | struct sockaddr_in6
  type sockaddr_in6 (line 285) | struct sockaddr_in6
  type sockaddr_in6 (line 297) | struct sockaddr_in6
  type sockaddr_in6 (line 298) | struct sockaddr_in6
  type sockaddr_in (line 301) | struct sockaddr_in
  type sockaddr_in (line 301) | struct sockaddr_in
  type sockaddr_in (line 302) | struct sockaddr_in
  type sockaddr_in (line 302) | struct sockaddr_in

FILE: muduo/net/SocketsOps.h
  function namespace (line 16) | namespace muduo

FILE: muduo/net/TcpClient.cc
  type muduo (line 33) | namespace muduo
    type net (line 35) | namespace net
      type detail (line 37) | namespace detail
        function removeConnection (line 40) | void removeConnection(EventLoop* loop, const TcpConnectionPtr& conn)
        function removeConnector (line 45) | void removeConnector(const ConnectorPtr& connector)

FILE: muduo/net/TcpClient.h
  function namespace (line 17) | namespace muduo

FILE: muduo/net/TcpConnection.cc
  type tcp_info (line 74) | struct tcp_info
  function string (line 79) | string TcpConnection::getTcpInfoString() const

FILE: muduo/net/TcpConnection.h
  type tcp_info (line 26) | struct tcp_info
  function namespace (line 28) | namespace muduo

FILE: muduo/net/TcpServer.h
  function namespace (line 20) | namespace muduo

FILE: muduo/net/Timer.h
  function namespace (line 18) | namespace muduo

FILE: muduo/net/TimerId.h
  function namespace (line 16) | namespace muduo

FILE: muduo/net/TimerQueue.cc
  type muduo (line 23) | namespace muduo
    type net (line 25) | namespace net
      type detail (line 27) | namespace detail
        function createTimerfd (line 30) | int createTimerfd()
        function howMuchTimeFromNow (line 41) | struct timespec howMuchTimeFromNow(Timestamp when)
        function readTimerfd (line 57) | void readTimerfd(int timerfd, Timestamp now)
        function resetTimerfd (line 68) | void resetTimerfd(int timerfd, Timestamp expiration)
  function TimerId (line 116) | TimerId TimerQueue::addTimer(TimerCallback cb,

FILE: muduo/net/TimerQueue.h
  function namespace (line 22) | namespace muduo

FILE: muduo/net/ZlibStream.h
  function namespace (line 8) | namespace muduo

FILE: muduo/net/boilerplate.h
  function namespace (line 17) | namespace muduo

FILE: muduo/net/http/HttpContext.h
  function namespace (line 18) | namespace muduo

FILE: muduo/net/http/HttpRequest.h
  function namespace (line 22) | namespace muduo

FILE: muduo/net/http/HttpResponse.h
  function namespace (line 19) | namespace muduo

FILE: muduo/net/http/HttpServer.cc
  type muduo (line 20) | namespace muduo
    type net (line 22) | namespace net
      type detail (line 24) | namespace detail
        function defaultHttpCallback (line 27) | void defaultHttpCallback(const HttpRequest&, HttpResponse* resp)

FILE: muduo/net/http/HttpServer.h
  function namespace (line 16) | namespace muduo

FILE: muduo/net/http/tests/HttpRequest_unittest.cc
  function BOOST_AUTO_TEST_CASE (line 15) | BOOST_AUTO_TEST_CASE(testParseRequestAllInOne)
  function BOOST_AUTO_TEST_CASE (line 33) | BOOST_AUTO_TEST_CASE(testParseRequestInTwoPieces)
  function BOOST_AUTO_TEST_CASE (line 60) | BOOST_AUTO_TEST_CASE(testParseRequestEmptyHeaderValue)

FILE: muduo/net/http/tests/HttpServer_test.cc
  function onRequest (line 16) | void onRequest(const HttpRequest& req, HttpResponse* resp)
  function main (line 62) | int main(int argc, char* argv[])

FILE: muduo/net/inspect/Inspector.cc
  function split (line 35) | std::vector<string> split(const string& str)

FILE: muduo/net/inspect/Inspector.h
  function namespace (line 20) | namespace muduo

FILE: muduo/net/inspect/PerformanceInspector.cc
  function string (line 36) | string PerformanceInspector::heap(HttpRequest::Method, const Inspector::...
  function string (line 43) | string PerformanceInspector::growth(HttpRequest::Method, const Inspector...
  function string (line 50) | string PerformanceInspector::profile(HttpRequest::Method, const Inspecto...
  function string (line 71) | string PerformanceInspector::cmdline(HttpRequest::Method, const Inspecto...
  function string (line 76) | string PerformanceInspector::memstats(HttpRequest::Method, const Inspect...
  function string (line 83) | string PerformanceInspector::memhistogram(HttpRequest::Method, const Ins...
  function string (line 97) | string PerformanceInspector::releaseFreeMemory(HttpRequest::Method, cons...

FILE: muduo/net/inspect/PerformanceInspector.h
  function namespace (line 16) | namespace muduo

FILE: muduo/net/inspect/ProcessInspector.cc
  type muduo (line 21) | namespace muduo
    type inspect (line 23) | namespace inspect
      function string (line 26) | string uptime(Timestamp now, Timestamp start, bool showMicroseconds)
      function getLong (line 48) | long getLong(const string& procStatus, const char* key)
      function string (line 59) | string getProcessName(const string& procStatus)
      function StringPiece (line 76) | StringPiece next(StringPiece data)
      function getCpuTime (line 87) | ProcessInfo::CpuTime getCpuTime(StringPiece data)
      function stringPrintf (line 106) | int stringPrintf(string* out, const char* fmt, ...)
  function string (line 133) | string ProcessInspector::overview(HttpRequest::Method, const Inspector::...
  function string (line 193) | string ProcessInspector::pid(HttpRequest::Method, const Inspector::ArgLi...
  function string (line 200) | string ProcessInspector::procStatus(HttpRequest::Method, const Inspector...
  function string (line 205) | string ProcessInspector::openedFiles(HttpRequest::Method, const Inspecto...
  function string (line 212) | string ProcessInspector::threads(HttpRequest::Method, const Inspector::A...

FILE: muduo/net/inspect/ProcessInspector.h
  function namespace (line 16) | namespace muduo

FILE: muduo/net/inspect/SystemInspector.cc
  type muduo (line 18) | namespace muduo
    type inspect (line 20) | namespace inspect
  function string (line 40) | string SystemInspector::loadavg(HttpRequest::Method, const Inspector::Ar...
  function string (line 47) | string SystemInspector::version(HttpRequest::Method, const Inspector::Ar...
  function string (line 54) | string SystemInspector::cpuinfo(HttpRequest::Method, const Inspector::Ar...
  function string (line 61) | string SystemInspector::meminfo(HttpRequest::Method, const Inspector::Ar...
  function string (line 68) | string SystemInspector::stat(HttpRequest::Method, const Inspector::ArgLi...
  function string (line 75) | string SystemInspector::overview(HttpRequest::Method, const Inspector::A...

FILE: muduo/net/inspect/SystemInspector.h
  function namespace (line 16) | namespace muduo

FILE: muduo/net/inspect/tests/Inspector_test.cc
  function main (line 8) | int main()

FILE: muduo/net/poller/DefaultPoller.cc
  function Poller (line 17) | Poller* Poller::newDefaultPoller(EventLoop* loop)

FILE: muduo/net/poller/EPollPoller.cc
  function Timestamp (line 55) | Timestamp EPollPoller::poll(int timeoutMs, ChannelList* activeChannels)
  type epoll_event (line 174) | struct epoll_event

FILE: muduo/net/poller/EPollPoller.h
  type epoll_event (line 18) | struct epoll_event
  function namespace (line 20) | namespace muduo

FILE: muduo/net/poller/PollPoller.cc
  function Timestamp (line 29) | Timestamp PollPoller::poll(int timeoutMs, ChannelList* activeChannels)
  type pollfd (line 83) | struct pollfd
  type pollfd (line 99) | struct pollfd
  type pollfd (line 121) | struct pollfd

FILE: muduo/net/poller/PollPoller.h
  type pollfd (line 18) | struct pollfd
  function namespace (line 20) | namespace muduo

FILE: muduo/net/protobuf/BufferStream.h
  function namespace (line 12) | namespace muduo

FILE: muduo/net/protobuf/ProtobufCodecLite.cc
  function ProtobufVersionCheck (line 25) | int ProtobufVersionCheck()
  function string (line 155) | const string& ProtobufCodecLite::errorCodeToString(ErrorCode errorCode)

FILE: muduo/net/protobuf/ProtobufCodecLite.h
  function namespace (line 25) | namespace google
  function namespace (line 33) | namespace muduo

FILE: muduo/net/protorpc/RpcChannel.h
  function namespace (line 59) | namespace google {
  function namespace (line 77) | namespace muduo

FILE: muduo/net/protorpc/RpcCodec.cc
  function ProtobufVersionCheck (line 23) | int ProtobufVersionCheck()
  type muduo (line 31) | namespace muduo
    type net (line 33) | namespace net

FILE: muduo/net/protorpc/RpcCodec.h
  function namespace (line 17) | namespace muduo

FILE: muduo/net/protorpc/RpcCodec_test.cc
  function rpcMessageCallback (line 12) | void rpcMessageCallback(const TcpConnectionPtr&,
  function messageCallback (line 19) | void messageCallback(const TcpConnectionPtr&,
  function print (line 26) | void print(const Buffer& buf)
  function main (line 39) | int main()

FILE: muduo/net/protorpc/RpcServer.h
  function namespace (line 16) | namespace google {
  function namespace (line 24) | namespace muduo

FILE: muduo/net/protorpc/google-inl.h
  function ByteSizeConsistencyError (line 47) | inline
  function std (line 61) | inline

FILE: muduo/net/tests/Buffer_unittest.cc
  function BOOST_AUTO_TEST_CASE (line 11) | BOOST_AUTO_TEST_CASE(testBufferAppendRetrieve)
  function BOOST_AUTO_TEST_CASE (line 44) | BOOST_AUTO_TEST_CASE(testBufferGrow)
  function BOOST_AUTO_TEST_CASE (line 67) | BOOST_AUTO_TEST_CASE(testBufferInsideGrow)
  function BOOST_AUTO_TEST_CASE (line 85) | BOOST_AUTO_TEST_CASE(testBufferShrink)
  function BOOST_AUTO_TEST_CASE (line 105) | BOOST_AUTO_TEST_CASE(testBufferPrepend)
  function BOOST_AUTO_TEST_CASE (line 120) | BOOST_AUTO_TEST_CASE(testBufferReadInt)
  function BOOST_AUTO_TEST_CASE (line 146) | BOOST_AUTO_TEST_CASE(testBufferFindEOL)
  function output (line 155) | void output(Buffer&& buf, const void* inner)
  function BOOST_AUTO_TEST_CASE (line 163) | BOOST_AUTO_TEST_CASE(testMove)

FILE: muduo/net/tests/Channel_test.cc
  function print (line 15) | void print(const char* msg)
  type muduo (line 25) | namespace muduo
    type net (line 27) | namespace net
      type detail (line 29) | namespace detail
  class PeriodicTimer (line 38) | class PeriodicTimer
    method PeriodicTimer (line 41) | PeriodicTimer(EventLoop* loop, double interval, const TimerCallback& cb)
    method start (line 53) | void start()
    method handleRead (line 74) | void handleRead()
    method toTimeSpec (line 82) | static struct timespec toTimeSpec(double seconds)
  function main (line 103) | int main(int argc, char* argv[])

FILE: muduo/net/tests/EchoClient_unittest.cc
  class EchoClient (line 17) | class EchoClient
    method EchoClient (line 24) | EchoClient(EventLoop* loop, const InetAddress& listenAddr, const strin...
    method connect (line 35) | void connect()
    method onConnection (line 42) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 60) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp time)
  class EchoClient (line 21) | class EchoClient : noncopyable
    method EchoClient (line 24) | EchoClient(EventLoop* loop, const InetAddress& listenAddr, const strin...
    method connect (line 35) | void connect()
    method onConnection (line 42) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 60) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp time)
  function main (line 83) | int main(int argc, char* argv[])

FILE: muduo/net/tests/EchoServer_unittest.cc
  class EchoServer (line 18) | class EchoServer
    method EchoServer (line 21) | EchoServer(EventLoop* loop, const InetAddress& listenAddr)
    method start (line 32) | void start()
    method onConnection (line 39) | void onConnection(const TcpConnectionPtr& conn)
    method onMessage (line 49) | void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp time)
  function main (line 69) | int main(int argc, char* argv[])

FILE: muduo/net/tests/EventLoopThreadPool_unittest.cc
  function print (line 11) | void print(EventLoop* p = NULL)
  function init (line 17) | void init(EventLoop* p)
  function main (line 23) | int main()

FILE: muduo/net/tests/EventLoopThread_unittest.cc
  function print (line 12) | void print(EventLoop* p = NULL)
  function quit (line 18) | void quit(EventLoop* p)
  function main (line 24) | int main()

FILE: muduo/net/tests/EventLoop_unittest.cc
  function callback (line 13) | void callback()
  function threadFunc (line 19) | void threadFunc()
  function main (line 30) | int main()

FILE: muduo/net/tests/InetAddress_unittest.cc
  function BOOST_AUTO_TEST_CASE (line 13) | BOOST_AUTO_TEST_CASE(testInetAddress)
  function BOOST_AUTO_TEST_CASE (line 36) | BOOST_AUTO_TEST_CASE(testInet6Address)
  function BOOST_AUTO_TEST_CASE (line 59) | BOOST_AUTO_TEST_CASE(testInetAddressResolve)

FILE: muduo/net/tests/TcpClient_reg1.cc
  function timeout (line 12) | void timeout()
  function main (line 18) | int main(int argc, char* argv[])

FILE: muduo/net/tests/TcpClient_reg2.cc
  function threadFunc (line 11) | void threadFunc(EventLoop* loop)
  function main (line 21) | int main(int argc, char* argv[])

FILE: muduo/net/tests/TcpClient_reg3.cc
  function main (line 10) | int main(int argc, char* argv[])

FILE: muduo/net/tests/TimerQueue_unittest.cc
  function printTid (line 14) | void printTid()
  function print (line 20) | void print(const char* msg)
  function cancel (line 29) | void cancel(TimerId timer)
  function main (line 35) | int main()

FILE: muduo/net/tests/ZlibStream_unittest.cc
  function BOOST_AUTO_TEST_CASE (line 11) | BOOST_AUTO_TEST_CASE(testZlibOutputStream)
  function BOOST_AUTO_TEST_CASE (line 21) | BOOST_AUTO_TEST_CASE(testZlibOutputStream1)
  function BOOST_AUTO_TEST_CASE (line 30) | BOOST_AUTO_TEST_CASE(testZlibOutputStream2)
  function BOOST_AUTO_TEST_CASE (line 41) | BOOST_AUTO_TEST_CASE(testZlibOutputStream3)
  function BOOST_AUTO_TEST_CASE (line 55) | BOOST_AUTO_TEST_CASE(testZlibOutputStream4)
  function BOOST_AUTO_TEST_CASE (line 75) | BOOST_AUTO_TEST_CASE(testZlibOutputStream5)
Condensed preview — 418 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,063K chars).
[
  {
    "path": ".clang-tidy",
    "chars": 586,
    "preview": "---\n# Only run a few checks for now.\nChecks:          'performance-*'\nWarningsAsErrors: ''\nHeaderFilterRegex: ''\nAnalyze"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 993,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\nDELETE FROM HERE"
  },
  {
    "path": ".github/issue_template.md",
    "chars": 890,
    "preview": "DELETE FROM HERE TO LINE 18 BEFORE OPEN AN ISSUE.\n\nGitHub issues are for tracking bugs, not for general discussing like "
  },
  {
    "path": ".gitignore",
    "chars": 36,
    "preview": "*.swp\nbazel-*\ncompile_commands.json\n"
  },
  {
    "path": ".travis.yml",
    "chars": 485,
    "preview": "language: cpp\nsudo: required\ncompiler:\n  - gcc\n  - clang\nos:\n  - linux\ninstall:\n  - sudo apt-get install libboost-dev\n  "
  },
  {
    "path": "BUILD.bazel",
    "chars": 87,
    "preview": "# See https://github.com/chenshuo/muduo-tutorial for how to use muduo in your project.\n"
  },
  {
    "path": "CMakeLists.txt",
    "chars": 3061,
    "preview": "cmake_minimum_required(VERSION 2.6)\n\nproject(muduo C CXX)\n\nenable_testing()\n\nif(NOT CMAKE_BUILD_TYPE)\n  set(CMAKE_BUILD_"
  },
  {
    "path": "ChangeLog",
    "chars": 13010,
    "preview": "2018-10-22   Shuo Chen  <chenshuo@chenshuo.com>\n  * Last version in C++98/03, next version will use C++11\n  * Enable Cla"
  },
  {
    "path": "ChangeLog2",
    "chars": 640,
    "preview": "2018-10-24   Shuo Chen  <chenshuo@chenshuo.com>\n  * First release of C++11 version of muduo.\n  * Forked after v1.0.9, e6"
  },
  {
    "path": "License",
    "chars": 1641,
    "preview": "// Muduo - A reactor-based C++ network library for Linux\n// Copyright (c) 2010, Shuo Chen.  All rights reserved.\n// http"
  },
  {
    "path": "README",
    "chars": 972,
    "preview": "Muduo is a multithreaded C++ network library based on\nthe reactor pattern.\n\nhttp://github.com/chenshuo/muduo\n\nCopyright "
  },
  {
    "path": "WORKSPACE",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "build.sh",
    "chars": 673,
    "preview": "#!/bin/sh\n\nset -x\n\nSOURCE_DIR=`pwd`\nBUILD_DIR=${BUILD_DIR:-../build}\nBUILD_TYPE=${BUILD_TYPE:-release}\nINSTALL_DIR=${INS"
  },
  {
    "path": "contrib/CMakeLists.txt",
    "chars": 281,
    "preview": "if(HIREDIS_INCLUDE_DIR AND HIREDIS_LIBRARY)\n  add_subdirectory(hiredis)\nelse()\n  add_subdirectory(hiredis EXCLUDE_FROM_A"
  },
  {
    "path": "contrib/hiredis/CMakeLists.txt",
    "chars": 101,
    "preview": "add_executable(mrediscli Hiredis.cc mrediscli.cc)\ntarget_link_libraries(mrediscli muduo_net hiredis)\n"
  },
  {
    "path": "contrib/hiredis/Hiredis.cc",
    "chars": 5117,
    "preview": "#include \"contrib/hiredis/Hiredis.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/Channel.h\"\n#include \"muduo/net"
  },
  {
    "path": "contrib/hiredis/Hiredis.h",
    "chars": 2515,
    "preview": "#ifndef MUDUO_CONTRIB_HIREDIS_HIREDIS_H\n#define MUDUO_CONTRIB_HIREDIS_HIREDIS_H\n\n#include \"muduo/base/noncopyable.h\"\n#in"
  },
  {
    "path": "contrib/hiredis/README.md",
    "chars": 127,
    "preview": "# Hiredis\n\nThe version of hiredis must be 0.11.0 or greater\n\nSee also issue [#92](https://github.com/chenshuo/muduo/issu"
  },
  {
    "path": "contrib/hiredis/mrediscli.cc",
    "chars": 3309,
    "preview": "#include \"contrib/hiredis/Hiredis.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n\n#include <string"
  },
  {
    "path": "contrib/thrift/CMakeLists.txt",
    "chars": 320,
    "preview": "set(MUDUO_THRIFT_SRCS\n    ThriftConnection.cc\n    ThriftServer.cc\n    )\nadd_library(muduo_thrift ${MUDUO_THRIFT_SRCS})\nt"
  },
  {
    "path": "contrib/thrift/ThriftConnection.cc",
    "chars": 3307,
    "preview": "#include \"contrib/thrift/ThriftConnection.h\"\n\n#include <functional>\n\n#include \"muduo/base/Logging.h\"\n\n#include <thrift/t"
  },
  {
    "path": "contrib/thrift/ThriftConnection.h",
    "chars": 1779,
    "preview": "#ifndef MUDUO_CONTRIB_THRIFT_THRIFTCONNECTION_H\n#define MUDUO_CONTRIB_THRIFT_THRIFTCONNECTION_H\n\n#include <boost/enable_"
  },
  {
    "path": "contrib/thrift/ThriftServer.cc",
    "chars": 1085,
    "preview": "#include \"contrib/thrift/ThriftServer.h\"\n\n#include <functional>\n\n#include \"muduo/net/EventLoop.h\"\n\nusing muduo::MutexLoc"
  },
  {
    "path": "contrib/thrift/ThriftServer.h",
    "chars": 7694,
    "preview": "#ifndef MUDUO_CONTRIB_THRIFT_THRIFTSERVER_H\n#define MUDUO_CONTRIB_THRIFT_THRIFTSERVER_H\n\n#include <functional>\n#include "
  },
  {
    "path": "contrib/thrift/tests/.gitignore",
    "chars": 15,
    "preview": "gen-cpp\ngen-py\n"
  },
  {
    "path": "contrib/thrift/tests/CMakeLists.txt",
    "chars": 46,
    "preview": "add_subdirectory(echo)\nadd_subdirectory(ping)\n"
  },
  {
    "path": "contrib/thrift/tests/echo/CMakeLists.txt",
    "chars": 584,
    "preview": "include_directories(gen-cpp)\nset(ECHO_THRIFT echo.thrift)\nexecute_process(COMMAND ${THRIFT_COMPILER} --gen cpp ${ECHO_TH"
  },
  {
    "path": "contrib/thrift/tests/echo/EchoServer.cc",
    "chars": 897,
    "preview": "#include <unistd.h>\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n\n#include \"ThriftServer.h\"\n\n#inclu"
  },
  {
    "path": "contrib/thrift/tests/echo/echo.thrift",
    "chars": 86,
    "preview": "namespace cpp echo\nnamespace py echo\n\nservice Echo\n{\n  string echo(1: string arg);\n}\n\n"
  },
  {
    "path": "contrib/thrift/tests/echo/echoclient.py",
    "chars": 548,
    "preview": "import sys\nsys.path.append('gen-py')\n\nfrom thrift.transport import TSocket\nfrom thrift.transport import TTransport\nfrom "
  },
  {
    "path": "contrib/thrift/tests/ping/CMakeLists.txt",
    "chars": 584,
    "preview": "include_directories(gen-cpp)\nset(PING_THRIFT ping.thrift)\nexecute_process(COMMAND ${THRIFT_COMPILER} --gen cpp ${PING_TH"
  },
  {
    "path": "contrib/thrift/tests/ping/PingServer.cc",
    "chars": 893,
    "preview": "#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n\n#include <thrift/protocol/TCompactProtocol.h>\n\n#includ"
  },
  {
    "path": "contrib/thrift/tests/ping/ping.thrift",
    "chars": 71,
    "preview": "namespace cpp ping\nnamespace py ping\n\nservice Ping\n{\n  void ping();\n}\n\n"
  },
  {
    "path": "contrib/thrift/tests/ping/pingclient.py",
    "chars": 520,
    "preview": "import sys\nsys.path.append('gen-py')\n\nfrom thrift.transport import TSocket\nfrom thrift.transport import TTransport\nfrom "
  },
  {
    "path": "examples/CMakeLists.txt",
    "chars": 1202,
    "preview": "add_subdirectory(ace/ttcp)\nadd_subdirectory(asio/chat)\nadd_subdirectory(asio/tutorial)\nadd_subdirectory(fastcgi)\nadd_sub"
  },
  {
    "path": "examples/ace/logging/CMakeLists.txt",
    "chars": 884,
    "preview": "add_custom_command(OUTPUT logrecord.pb.cc logrecord.pb.h\n  COMMAND protoc\n  ARGS --cpp_out . ${CMAKE_CURRENT_SOURCE_DIR}"
  },
  {
    "path": "examples/ace/logging/client.cc",
    "chars": 3729,
    "preview": "#include \"examples/ace/logging/logrecord.pb.h\"\n\n#include \"muduo/base/Mutex.h\"\n#include \"muduo/base/Logging.h\"\n#include \""
  },
  {
    "path": "examples/ace/logging/logrecord.proto",
    "chars": 730,
    "preview": "package logging;\n\nmessage LogRecord {\n  // must present in first message\n  message Heartbeat {\n    required string hostn"
  },
  {
    "path": "examples/ace/logging/server.cc",
    "chars": 3047,
    "preview": "#include \"examples/ace/logging/logrecord.pb.h\"\n\n#include \"muduo/base/Atomic.h\"\n#include \"muduo/base/FileUtil.h\"\n#include"
  },
  {
    "path": "examples/ace/ttcp/CMakeLists.txt",
    "chars": 765,
    "preview": "if(BOOSTPO_LIBRARY)\n  add_executable(ttcp_blocking ttcp_blocking.cc common.cc main.cc)\n  target_link_libraries(ttcp_bloc"
  },
  {
    "path": "examples/ace/ttcp/common.cc",
    "chars": 1924,
    "preview": "#include \"examples/ace/ttcp/common.h\"\n#include \"muduo/base/Types.h\"\n\n#include <boost/program_options.hpp>\n\n#include <ios"
  },
  {
    "path": "examples/ace/ttcp/common.h",
    "chars": 638,
    "preview": "#pragma once\n\n#include <string>\n#include <stdint.h>\n\nstruct Options\n{\n  uint16_t port;\n  int length;\n  int number;\n  boo"
  },
  {
    "path": "examples/ace/ttcp/main.cc",
    "chars": 338,
    "preview": "#include \"examples/ace/ttcp/common.h\"\n\n#include <assert.h>\n\nint main(int argc, char* argv[])\n{\n  Options options;\n  if ("
  },
  {
    "path": "examples/ace/ttcp/ttcp.cc",
    "chars": 5255,
    "preview": "#include \"examples/ace/ttcp/common.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/"
  },
  {
    "path": "examples/ace/ttcp/ttcp_asio_async.cc",
    "chars": 4828,
    "preview": "#include \"examples/ace/ttcp/common.h\"\n\n#include \"muduo/base/Logging.h\"\n#include <boost/asio.hpp>\n#include <stdio.h>\n\nusi"
  },
  {
    "path": "examples/ace/ttcp/ttcp_asio_sync.cc",
    "chars": 2635,
    "preview": "#include \"examples/ace/ttcp/common.h\"\n\n#include \"muduo/base/Logging.h\"\n#include <boost/asio.hpp>\n#include <stdio.h>\n\nusi"
  },
  {
    "path": "examples/ace/ttcp/ttcp_blocking.cc",
    "chars": 5055,
    "preview": "#include \"examples/ace/ttcp/common.h\"\n#include \"muduo/base/Timestamp.h\"\n#include \"muduo/base/Types.h\"\n\n#undef NDEBUG\n\n#i"
  },
  {
    "path": "examples/asio/chat/CMakeLists.txt",
    "chars": 729,
    "preview": "add_executable(asio_chat_client client.cc)\ntarget_link_libraries(asio_chat_client muduo_net)\n\nadd_executable(asio_chat_l"
  },
  {
    "path": "examples/asio/chat/client.cc",
    "chars": 2295,
    "preview": "#include \"examples/asio/chat/codec.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/base/Mutex.h\"\n#include \"muduo/net"
  },
  {
    "path": "examples/asio/chat/codec.h",
    "chars": 2002,
    "preview": "#ifndef MUDUO_EXAMPLES_ASIO_CHAT_CODEC_H\n#define MUDUO_EXAMPLES_ASIO_CHAT_CODEC_H\n\n#include \"muduo/base/Logging.h\"\n#incl"
  },
  {
    "path": "examples/asio/chat/loadtest.cc",
    "chars": 4223,
    "preview": "#include \"examples/asio/chat/codec.h\"\n\n#include \"muduo/base/Atomic.h\"\n#include \"muduo/base/Logging.h\"\n#include \"muduo/ba"
  },
  {
    "path": "examples/asio/chat/server.cc",
    "chars": 1905,
    "preview": "#include \"examples/asio/chat/codec.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/base/Mutex.h\"\n#include \"muduo/net"
  },
  {
    "path": "examples/asio/chat/server_threaded.cc",
    "chars": 2168,
    "preview": "#include \"examples/asio/chat/codec.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/base/Mutex.h\"\n#include \"muduo/net"
  },
  {
    "path": "examples/asio/chat/server_threaded_efficient.cc",
    "chars": 2545,
    "preview": "#include \"examples/asio/chat/codec.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/base/Mutex.h\"\n#include \"muduo/net"
  },
  {
    "path": "examples/asio/chat/server_threaded_highperformance.cc",
    "chars": 3004,
    "preview": "#include \"examples/asio/chat/codec.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/base/Mutex.h\"\n#include \"muduo/bas"
  },
  {
    "path": "examples/asio/echo_see_simple",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "examples/asio/tutorial/CMakeLists.txt",
    "chars": 540,
    "preview": "add_executable(asio_tutorial_timer2 timer2/timer.cc)\ntarget_link_libraries(asio_tutorial_timer2 muduo_net)\n\nadd_executab"
  },
  {
    "path": "examples/asio/tutorial/daytime_see_simple",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "examples/asio/tutorial/there_is_no_timer1",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "examples/asio/tutorial/timer2/timer.cc",
    "chars": 195,
    "preview": "#include \"muduo/net/EventLoop.h\"\n\n#include <iostream>\n\nvoid print()\n{\n  std::cout << \"Hello, world!\\n\";\n}\n\nint main()\n{\n"
  },
  {
    "path": "examples/asio/tutorial/timer3/timer.cc",
    "chars": 513,
    "preview": "#include \"muduo/net/EventLoop.h\"\n\n#include <iostream>\n\nvoid print(muduo::net::EventLoop* loop, int* count)\n{\n  if (*coun"
  },
  {
    "path": "examples/asio/tutorial/timer4/timer.cc",
    "chars": 732,
    "preview": "#include \"muduo/net/EventLoop.h\"\n\n#include <iostream>\n\nclass Printer : muduo::noncopyable\n{\n public:\n  Printer(muduo::ne"
  },
  {
    "path": "examples/asio/tutorial/timer5/timer.cc",
    "chars": 1648,
    "preview": "#include \"muduo/base/Mutex.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/net/EventLoopThread.h\"\n\n#include <iostrea"
  },
  {
    "path": "examples/asio/tutorial/timer6/timer.cc",
    "chars": 2324,
    "preview": "#include \"muduo/base/Mutex.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/net/EventLoopThread.h\"\n\n#include <stdio.h"
  },
  {
    "path": "examples/cdns/CMakeLists.txt",
    "chars": 291,
    "preview": "add_library(muduo_cdns Resolver.cc)\ntarget_link_libraries(muduo_cdns muduo_net)\ntarget_link_libraries(muduo_cdns cares)\n"
  },
  {
    "path": "examples/cdns/Resolver.cc",
    "chars": 5031,
    "preview": "#include \"examples/cdns/Resolver.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/Channel.h\"\n#include \"muduo/net/"
  },
  {
    "path": "examples/cdns/Resolver.h",
    "chars": 1736,
    "preview": "#ifndef MUDUO_EXAMPLES_CDNS_RESOLVER_H\n#define MUDUO_EXAMPLES_CDNS_RESOLVER_H\n\n#include \"muduo/base/noncopyable.h\"\n#incl"
  },
  {
    "path": "examples/cdns/dns.cc",
    "chars": 1045,
    "preview": "#include \"examples/cdns/Resolver.h\"\n#include \"muduo/net/EventLoop.h\"\n#include <stdio.h>\n\nusing namespace muduo;\nusing na"
  },
  {
    "path": "examples/curl/CMakeLists.txt",
    "chars": 377,
    "preview": "add_library(muduo_curl Curl.cc)\ntarget_link_libraries(muduo_curl muduo_net)\ntarget_link_libraries(muduo_curl curl)\n\ninst"
  },
  {
    "path": "examples/curl/Curl.cc",
    "chars": 6437,
    "preview": "#include \"examples/curl/Curl.h\"\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/Channel.h\"\n#include \"muduo/net/Event"
  },
  {
    "path": "examples/curl/Curl.h",
    "chars": 2970,
    "preview": "#ifndef MUDUO_EXAMPLES_CURL_CURL_H\n#define MUDUO_EXAMPLES_CURL_CURL_H\n\n#include \"muduo/base/noncopyable.h\"\n#include \"mud"
  },
  {
    "path": "examples/curl/README",
    "chars": 250,
    "preview": "This is a proof-of-concept implementation of muduo-curl bridge.\nIt demostrates the simplest use case of curl with muduo."
  },
  {
    "path": "examples/curl/download.cc",
    "chars": 4856,
    "preview": "// Concurrent downloading one file from HTTP\n\n#include \"examples/curl/Curl.h\"\n#include \"muduo/base/Logging.h\"\n#include \""
  },
  {
    "path": "examples/curl/mcurl.cc",
    "chars": 1122,
    "preview": "#include \"examples/curl/Curl.h\"\n#include \"muduo/net/EventLoop.h\"\n#include <stdio.h>\n\nusing namespace muduo::net;\n\nEventL"
  },
  {
    "path": "examples/fastcgi/CMakeLists.txt",
    "chars": 123,
    "preview": "add_executable(fastcgi_test fastcgi.cc fastcgi_test.cc ../sudoku/sudoku.cc)\ntarget_link_libraries(fastcgi_test muduo_net"
  },
  {
    "path": "examples/fastcgi/fastcgi.cc",
    "chars": 4952,
    "preview": "#include \"examples/fastcgi/fastcgi.h\"\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/Endian.h\"\n\nstruct FastCgiCodec"
  },
  {
    "path": "examples/fastcgi/fastcgi.h",
    "chars": 1818,
    "preview": "#ifndef MUDUO_EXAMPLES_FASTCGI_FASTCGI_H\n#define MUDUO_EXAMPLES_FASTCGI_FASTCGI_H\n\n#include \"muduo/net/TcpConnection.h\"\n"
  },
  {
    "path": "examples/fastcgi/fastcgi_test.cc",
    "chars": 1912,
    "preview": "#include \"examples/fastcgi/fastcgi.h\"\n#include \"examples/sudoku/sudoku.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"mud"
  },
  {
    "path": "examples/fastcgi/nginx.conf",
    "chars": 3296,
    "preview": "\n#user  nobody;\nworker_processes  1;\n\n#error_log  logs/error.log;\n#error_log  logs/error.log  notice;\n#error_log  logs/e"
  },
  {
    "path": "examples/filetransfer/CMakeLists.txt",
    "chars": 324,
    "preview": "add_executable(filetransfer_download download.cc)\ntarget_link_libraries(filetransfer_download muduo_net)\n\nadd_executable"
  },
  {
    "path": "examples/filetransfer/download.cc",
    "chars": 1761,
    "preview": "#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/net/TcpServer.h\"\n\n#include <stdio.h>\n#i"
  },
  {
    "path": "examples/filetransfer/download2.cc",
    "chars": 2128,
    "preview": "#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/net/TcpServer.h\"\n\n#include <stdio.h>\n#i"
  },
  {
    "path": "examples/filetransfer/download3.cc",
    "chars": 1996,
    "preview": "#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/net/TcpServer.h\"\n\n#include <stdio.h>\n#i"
  },
  {
    "path": "examples/filetransfer/loadtest/Client.java",
    "chars": 2342,
    "preview": "import java.net.InetSocketAddress;\nimport java.util.Random;\nimport java.util.concurrent.CountDownLatch;\nimport java.util"
  },
  {
    "path": "examples/filetransfer/loadtest/Handler.java",
    "chars": 2600,
    "preview": "import java.math.BigInteger;\nimport java.security.MessageDigest;\nimport java.util.concurrent.CountDownLatch;\n\nimport org"
  },
  {
    "path": "examples/hub/CMakeLists.txt",
    "chars": 306,
    "preview": "add_executable(hub hub.cc codec.cc)\ntarget_link_libraries(hub muduo_inspect)\n\nadd_library(muduo_pubsub pubsub.cc codec.c"
  },
  {
    "path": "examples/hub/README",
    "chars": 168,
    "preview": "hub - a server for broadcasting\npubsub - a client library of hub\npub - a command line tool for publishing content on a t"
  },
  {
    "path": "examples/hub/codec.cc",
    "chars": 1076,
    "preview": "#include \"examples/hub/codec.h\"\n\nusing namespace muduo;\nusing namespace muduo::net;\nusing namespace pubsub;\n\nParseResult"
  },
  {
    "path": "examples/hub/codec.h",
    "chars": 490,
    "preview": "#ifndef MUDUO_EXAMPLES_HUB_CODEC_H\n#define MUDUO_EXAMPLES_HUB_CODEC_H\n\n// internal header file\n\n#include \"muduo/base/Typ"
  },
  {
    "path": "examples/hub/hub.cc",
    "chars": 4854,
    "preview": "#include \"examples/hub/codec.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/net/Tc"
  },
  {
    "path": "examples/hub/pub.cc",
    "chars": 1865,
    "preview": "#include \"examples/hub/pubsub.h\"\n#include \"muduo/base/ProcessInfo.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/ne"
  },
  {
    "path": "examples/hub/pubsub.cc",
    "chars": 2180,
    "preview": "#include \"examples/hub/pubsub.h\"\n#include \"examples/hub/codec.h\"\n\nusing namespace muduo;\nusing namespace muduo::net;\nusi"
  },
  {
    "path": "examples/hub/pubsub.h",
    "chars": 1405,
    "preview": "#ifndef MUDUO_EXAMPLES_HUB_PUBSUB_H\n#define MUDUO_EXAMPLES_HUB_PUBSUB_H\n\n#include \"muduo/net/TcpClient.h\"\n\nnamespace pub"
  },
  {
    "path": "examples/hub/sub.cc",
    "chars": 1553,
    "preview": "#include \"examples/hub/pubsub.h\"\n#include \"muduo/base/ProcessInfo.h\"\n#include \"muduo/net/EventLoop.h\"\n\n#include <vector>"
  },
  {
    "path": "examples/idleconnection/CMakeLists.txt",
    "chars": 211,
    "preview": "add_executable(idleconnection_echo echo.cc main.cc)\ntarget_link_libraries(idleconnection_echo muduo_net)\n\nadd_executable"
  },
  {
    "path": "examples/idleconnection/echo.cc",
    "chars": 2675,
    "preview": "#include \"examples/idleconnection/echo.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n\n#include <a"
  },
  {
    "path": "examples/idleconnection/echo.h",
    "chars": 1406,
    "preview": "#ifndef MUDUO_EXAMPLES_IDLECONNECTION_ECHO_H\n#define MUDUO_EXAMPLES_IDLECONNECTION_ECHO_H\n\n#include \"muduo/net/TcpServer"
  },
  {
    "path": "examples/idleconnection/main.cc",
    "chars": 825,
    "preview": "#include \"examples/idleconnection/echo.h\"\n#include <stdio.h>\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventL"
  },
  {
    "path": "examples/idleconnection/sortedlist.cc",
    "chars": 4439,
    "preview": "#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/net/TcpServer.h\"\n#include <list>\n#inclu"
  },
  {
    "path": "examples/maxconnection/CMakeLists.txt",
    "chars": 103,
    "preview": "add_executable(maxconnection_echo echo.cc main.cc)\ntarget_link_libraries(maxconnection_echo muduo_net)\n"
  },
  {
    "path": "examples/maxconnection/echo.cc",
    "chars": 1438,
    "preview": "#include \"examples/maxconnection/echo.h\"\n\n#include \"muduo/base/Logging.h\"\n\nusing namespace muduo;\nusing namespace muduo:"
  },
  {
    "path": "examples/maxconnection/echo.h",
    "chars": 688,
    "preview": "#ifndef MUDUO_EXAMPLES_MAXCONNECTION_ECHO_H\n#define MUDUO_EXAMPLES_MAXCONNECTION_ECHO_H\n\n#include \"muduo/net/TcpServer.h"
  },
  {
    "path": "examples/maxconnection/main.cc",
    "chars": 533,
    "preview": "#include \"examples/maxconnection/echo.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n\n#include <un"
  },
  {
    "path": "examples/memcached/README",
    "chars": 522,
    "preview": "Simple implementation of memcached protocol for both server and client side.\nNot meant to replace memcached, but just sa"
  },
  {
    "path": "examples/memcached/client/CMakeLists.txt",
    "chars": 144,
    "preview": "if(BOOSTPO_LIBRARY)\n  add_executable(memcached_bench bench.cc)\n  target_link_libraries(memcached_bench muduo_net boost_p"
  },
  {
    "path": "examples/memcached/client/bench.cc",
    "chars": 5757,
    "preview": "#include \"muduo/base/CountDownLatch.h\"\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/"
  },
  {
    "path": "examples/memcached/server/CMakeLists.txt",
    "chars": 617,
    "preview": "if(BOOSTPO_LIBRARY)\n  add_executable(memcached_debug Item.cc MemcacheServer.cc Session.cc server.cc)\n  target_link_libra"
  },
  {
    "path": "examples/memcached/server/Item.cc",
    "chars": 1493,
    "preview": "#include \"examples/memcached/server/Item.h\"\n\n#include \"muduo/base/LogStream.h\"\n#include \"muduo/net/Buffer.h\"\n\n#include <"
  },
  {
    "path": "examples/memcached/server/Item.h",
    "chars": 2421,
    "preview": "#ifndef MUDUO_EXAMPLES_MEMCACHED_SERVER_ITEM_H\n#define MUDUO_EXAMPLES_MEMCACHED_SERVER_ITEM_H\n\n#include \"muduo/base/Atom"
  },
  {
    "path": "examples/memcached/server/MemcacheServer.cc",
    "chars": 4354,
    "preview": "#include \"examples/memcached/server/MemcacheServer.h\"\n\n#include \"muduo/base/Atomic.h\"\n#include \"muduo/base/Logging.h\"\n#i"
  },
  {
    "path": "examples/memcached/server/MemcacheServer.h",
    "chars": 2037,
    "preview": "#ifndef MUDUO_EXAMPLES_MEMCACHED_SERVER_MEMCACHESERVER_H\n#define MUDUO_EXAMPLES_MEMCACHED_SERVER_MEMCACHESERVER_H\n\n#incl"
  },
  {
    "path": "examples/memcached/server/Session.cc",
    "chars": 9161,
    "preview": "#include \"examples/memcached/server/Session.h\"\n#include \"examples/memcached/server/MemcacheServer.h\"\n\n#ifdef HAVE_TCMALL"
  },
  {
    "path": "examples/memcached/server/Session.h",
    "chars": 2807,
    "preview": "#ifndef MUDUO_EXAMPLES_MEMCACHED_SERVER_SESSION_H\n#define MUDUO_EXAMPLES_MEMCACHED_SERVER_SESSION_H\n\n#include \"examples/"
  },
  {
    "path": "examples/memcached/server/footprint_test.cc",
    "chars": 1985,
    "preview": "#include \"examples/memcached/server/MemcacheServer.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/net/inspect/Proce"
  },
  {
    "path": "examples/memcached/server/server.cc",
    "chars": 1498,
    "preview": "#include \"examples/memcached/server/MemcacheServer.h\"\n\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/net/EventLoopThr"
  },
  {
    "path": "examples/multiplexer/CMakeLists.txt",
    "chars": 310,
    "preview": "add_executable(multiplex_server multiplexer.cc)\ntarget_link_libraries(multiplex_server muduo_net)\n\nadd_executable(multip"
  },
  {
    "path": "examples/multiplexer/demux.cc",
    "chars": 5828,
    "preview": "#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/net/InetAddress.h\"\n#include \"muduo/net/"
  },
  {
    "path": "examples/multiplexer/harness/run.sh",
    "chars": 367,
    "preview": "#!/bin/sh\n\nCLASSPATH=lib/netty-3.2.4.Final.jar:lib/slf4j-api-1.6.1.jar:lib/slf4j-simple-1.6.1.jar:./bin\n\nexport CLASSPAT"
  },
  {
    "path": "examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/DataEvent.java",
    "chars": 557,
    "preview": "package com.chenshuo.muduo.example.multiplexer;\n\nimport java.nio.charset.Charset;\n\nimport org.jboss.netty.buffer.Channel"
  },
  {
    "path": "examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/Event.java",
    "chars": 73,
    "preview": "package com.chenshuo.muduo.example.multiplexer;\n\npublic class Event {\n\n}\n"
  },
  {
    "path": "examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/EventQueue.java",
    "chars": 602,
    "preview": "package com.chenshuo.muduo.example.multiplexer;\n\nimport java.util.concurrent.BlockingDeque;\nimport java.util.concurrent."
  },
  {
    "path": "examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/EventSource.java",
    "chars": 99,
    "preview": "package com.chenshuo.muduo.example.multiplexer;\n\npublic enum EventSource {\n    kBackend, kClient\n}\n"
  },
  {
    "path": "examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/MockBackendServer.java",
    "chars": 4785,
    "preview": "package com.chenshuo.muduo.example.multiplexer;\n\nimport static org.jboss.netty.buffer.ChannelBuffers.wrappedBuffer;\n\nimp"
  },
  {
    "path": "examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/MockClient.java",
    "chars": 4733,
    "preview": "package com.chenshuo.muduo.example.multiplexer;\n\nimport java.net.InetSocketAddress;\nimport java.util.concurrent.Executor"
  },
  {
    "path": "examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/MultiplexerTest.java",
    "chars": 3685,
    "preview": "package com.chenshuo.muduo.example.multiplexer;\n\nimport java.net.InetSocketAddress;\nimport java.nio.ByteOrder;\nimport ja"
  },
  {
    "path": "examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/MyCountDownLatch.java",
    "chars": 571,
    "preview": "package com.chenshuo.muduo.example.multiplexer;\n\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent"
  },
  {
    "path": "examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/TestCase.java",
    "chars": 1407,
    "preview": "package com.chenshuo.muduo.example.multiplexer;\n\nimport org.jboss.netty.buffer.ChannelBufferFactory;\n\npublic abstract cl"
  },
  {
    "path": "examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/TestFailedException.java",
    "chars": 247,
    "preview": "package com.chenshuo.muduo.example.multiplexer;\n\npublic class TestFailedException extends RuntimeException {\n    private"
  },
  {
    "path": "examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/testcase/TestOneClientBackendSend.java",
    "chars": 2527,
    "preview": "package com.chenshuo.muduo.example.multiplexer.testcase;\n\nimport java.nio.charset.Charset;\nimport java.util.regex.Matche"
  },
  {
    "path": "examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/testcase/TestOneClientBothSend.java",
    "chars": 2157,
    "preview": "package com.chenshuo.muduo.example.multiplexer.testcase;\n\nimport java.nio.charset.Charset;\nimport java.util.regex.Matche"
  },
  {
    "path": "examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/testcase/TestOneClientNoData.java",
    "chars": 1437,
    "preview": "package com.chenshuo.muduo.example.multiplexer.testcase;\n\nimport java.util.regex.Matcher;\n\nimport com.chenshuo.muduo.exa"
  },
  {
    "path": "examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/testcase/TestOneClientSend.java",
    "chars": 2677,
    "preview": "package com.chenshuo.muduo.example.multiplexer.testcase;\n\nimport java.nio.charset.Charset;\nimport java.util.regex.Matche"
  },
  {
    "path": "examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/testcase/TestTwoClients.java",
    "chars": 2990,
    "preview": "package com.chenshuo.muduo.example.multiplexer.testcase;\n\nimport java.nio.charset.Charset;\nimport java.util.regex.Matche"
  },
  {
    "path": "examples/multiplexer/multiplexer.cc",
    "chars": 8114,
    "preview": "#include \"muduo/base/Atomic.h\"\n#include \"muduo/base/Logging.h\"\n#include \"muduo/base/Mutex.h\"\n#include \"muduo/base/Thread"
  },
  {
    "path": "examples/multiplexer/multiplexer_simple.cc",
    "chars": 6604,
    "preview": "#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/net/InetAddress.h\"\n#include \"muduo/net/"
  },
  {
    "path": "examples/netty/discard/CMakeLists.txt",
    "chars": 204,
    "preview": "add_executable(netty_discard_client client.cc)\ntarget_link_libraries(netty_discard_client muduo_net)\n\nadd_executable(net"
  },
  {
    "path": "examples/netty/discard/client.cc",
    "chars": 1997,
    "preview": "#include \"muduo/net/TcpClient.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/base/Thread.h\"\n#include \"muduo/net/Eve"
  },
  {
    "path": "examples/netty/discard/server.cc",
    "chars": 2383,
    "preview": "#include \"muduo/net/TcpServer.h\"\n\n#include \"muduo/base/Atomic.h\"\n#include \"muduo/base/Logging.h\"\n#include \"muduo/base/Th"
  },
  {
    "path": "examples/netty/echo/CMakeLists.txt",
    "chars": 291,
    "preview": "add_executable(netty_echo_client client.cc)\ntarget_link_libraries(netty_echo_client muduo_net)\n\nadd_executable(netty_ech"
  },
  {
    "path": "examples/netty/echo/client.cc",
    "chars": 1733,
    "preview": "#include \"muduo/net/TcpClient.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/base/Thread.h\"\n#include \"muduo/net/Eve"
  },
  {
    "path": "examples/netty/echo/server.cc",
    "chars": 2383,
    "preview": "#include \"muduo/net/TcpServer.h\"\n\n#include \"muduo/base/Atomic.h\"\n#include \"muduo/base/Logging.h\"\n#include \"muduo/base/Th"
  },
  {
    "path": "examples/netty/echo/server2.cc",
    "chars": 3595,
    "preview": "#include \"muduo/net/TcpServer.h\"\n\n#include \"muduo/base/Atomic.h\"\n#include \"muduo/base/FileUtil.h\"\n#include \"muduo/base/L"
  },
  {
    "path": "examples/netty/uptime/CMakeLists.txt",
    "chars": 86,
    "preview": "add_executable(netty_uptime uptime.cc)\ntarget_link_libraries(netty_uptime muduo_net)\n\n"
  },
  {
    "path": "examples/netty/uptime/uptime.cc",
    "chars": 1453,
    "preview": "#include \"muduo/net/TcpClient.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/base/Thread.h\"\n#include \"muduo/net/Eve"
  },
  {
    "path": "examples/pingpong/CMakeLists.txt",
    "chars": 273,
    "preview": "add_executable(pingpong_client client.cc)\ntarget_link_libraries(pingpong_client muduo_net)\n\nadd_executable(pingpong_serv"
  },
  {
    "path": "examples/pingpong/bench.cc",
    "chars": 3025,
    "preview": "// Benchmark inspired by libevent/test/bench.c\n// See also: http://libev.schmorp.de/bench.html\n\n#include \"muduo/base/Log"
  },
  {
    "path": "examples/pingpong/client.cc",
    "chars": 4700,
    "preview": "#include \"muduo/net/TcpClient.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/base/Thread.h\"\n#include \"muduo/net/Eve"
  },
  {
    "path": "examples/pingpong/server.cc",
    "chars": 1225,
    "preview": "#include \"muduo/net/TcpServer.h\"\n\n#include \"muduo/base/Atomic.h\"\n#include \"muduo/base/Logging.h\"\n#include \"muduo/base/Th"
  },
  {
    "path": "examples/procmon/CMakeLists.txt",
    "chars": 266,
    "preview": "add_executable(procmon procmon.cc plot.cc)\ntarget_link_libraries(procmon muduo_http gd)\n\nadd_executable(plot_test plot_t"
  },
  {
    "path": "examples/procmon/dummyload.cc",
    "chars": 3014,
    "preview": "#include \"muduo/base/Atomic.h\"\n#include \"muduo/base/Condition.h\"\n#include \"muduo/base/CurrentThread.h\"\n#include \"muduo/b"
  },
  {
    "path": "examples/procmon/plot.cc",
    "chars": 3378,
    "preview": "#include \"examples/procmon/plot.h\"\n#include <algorithm>\n\n#include <math.h>\n\n#include <gd.h>\n#include <gdfonts.h>\n\nstruct"
  },
  {
    "path": "examples/procmon/plot.h",
    "chars": 1180,
    "preview": "#include \"muduo/base/noncopyable.h\"\n#include \"muduo/base/Types.h\"\n#include <vector>\n#include <stdlib.h> // ssize_t\n\ntype"
  },
  {
    "path": "examples/procmon/plot_test.cc",
    "chars": 842,
    "preview": "#include \"examples/procmon/plot.h\"\n#include \"muduo/base/Timestamp.h\"\n#include <vector>\n#include <math.h>\n#include <stdio"
  },
  {
    "path": "examples/procmon/procmon.cc",
    "chars": 14551,
    "preview": "#include \"examples/procmon/plot.h\"\n\n#include \"muduo/base/FileUtil.h\"\n#include \"muduo/base/Logging.h\"\n#include \"muduo/bas"
  },
  {
    "path": "examples/protobuf/CMakeLists.txt",
    "chars": 234,
    "preview": "add_subdirectory(codec)\nadd_subdirectory(rpc)\nadd_subdirectory(rpcbalancer)\nadd_subdirectory(rpcbench)\n\nif(CARES_INCLUDE"
  },
  {
    "path": "examples/protobuf/codec/CMakeLists.txt",
    "chars": 1852,
    "preview": "add_library(protobuf_codec codec.cc)\ntarget_link_libraries(protobuf_codec protobuf muduo_net z)\n\nadd_custom_command(OUTP"
  },
  {
    "path": "examples/protobuf/codec/client.cc",
    "chars": 3033,
    "preview": "#include \"examples/protobuf/codec/dispatcher.h\"\n#include \"examples/protobuf/codec/codec.h\"\n#include \"examples/protobuf/c"
  },
  {
    "path": "examples/protobuf/codec/codec.cc",
    "chars": 7026,
    "preview": "// Copyright 2011, Shuo Chen.  All rights reserved.\n// http://code.google.com/p/muduo/\n//\n// Use of this source code is "
  },
  {
    "path": "examples/protobuf/codec/codec.h",
    "chars": 3096,
    "preview": "// Copyright 2011, Shuo Chen.  All rights reserved.\n// http://code.google.com/p/muduo/\n//\n// Use of this source code is "
  },
  {
    "path": "examples/protobuf/codec/codec_test.cc",
    "chars": 7290,
    "preview": "#include \"examples/protobuf/codec/codec.h\"\n#include \"muduo/net/Endian.h\"\n#include \"examples/protobuf/codec/query.pb.h\"\n\n"
  },
  {
    "path": "examples/protobuf/codec/dispatcher.h",
    "chars": 2950,
    "preview": "// Copyright 2011, Shuo Chen.  All rights reserved.\n// http://code.google.com/p/muduo/\n//\n// Use of this source code is "
  },
  {
    "path": "examples/protobuf/codec/dispatcher_lite.h",
    "chars": 2070,
    "preview": "// Copyright 2011, Shuo Chen.  All rights reserved.\n// http://code.google.com/p/muduo/\n//\n// Use of this source code is "
  },
  {
    "path": "examples/protobuf/codec/dispatcher_lite_test.cc",
    "chars": 1684,
    "preview": "#include \"examples/protobuf/codec/dispatcher_lite.h\"\n\n#include \"examples/protobuf/codec/query.pb.h\"\n\n#include <iostream>"
  },
  {
    "path": "examples/protobuf/codec/dispatcher_test.cc",
    "chars": 1789,
    "preview": "#include \"examples/protobuf/codec/dispatcher.h\"\n\n#include \"examples/protobuf/codec/query.pb.h\"\n\n#include <iostream>\n\nusi"
  },
  {
    "path": "examples/protobuf/codec/query.proto",
    "chars": 402,
    "preview": "package muduo;\noption java_package = \"muduo.codec.tests\";\noption java_outer_classname = \"QueryProtos\";\n\nmessage Query {\n"
  },
  {
    "path": "examples/protobuf/codec/server.cc",
    "chars": 2856,
    "preview": "#include \"examples/protobuf/codec/codec.h\"\n#include \"examples/protobuf/codec/dispatcher.h\"\n#include \"examples/protobuf/c"
  },
  {
    "path": "examples/protobuf/resolver/CMakeLists.txt",
    "chars": 913,
    "preview": "add_custom_command(OUTPUT resolver.pb.cc resolver.pb.h\n  COMMAND protoc\n  ARGS --cpp_out . ${CMAKE_CURRENT_SOURCE_DIR}/r"
  },
  {
    "path": "examples/protobuf/resolver/client.cc",
    "chars": 2584,
    "preview": "#include \"examples/protobuf/resolver/resolver.pb.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n#i"
  },
  {
    "path": "examples/protobuf/resolver/resolver.proto",
    "chars": 401,
    "preview": "package resolver;\noption cc_generic_services = true;\noption java_generic_services = true;\noption py_generic_services = t"
  },
  {
    "path": "examples/protobuf/resolver/server.cc",
    "chars": 2174,
    "preview": "#include \"examples/protobuf/resolver/resolver.pb.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n#i"
  },
  {
    "path": "examples/protobuf/rpc/CMakeLists.txt",
    "chars": 1399,
    "preview": "add_custom_command(OUTPUT sudoku.pb.cc sudoku.pb.h\n  COMMAND protoc\n  ARGS --cpp_out . ${CMAKE_CURRENT_SOURCE_DIR}/sudok"
  },
  {
    "path": "examples/protobuf/rpc/client.cc",
    "chars": 1944,
    "preview": "#include \"examples/protobuf/rpc/sudoku.pb.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n#include "
  },
  {
    "path": "examples/protobuf/rpc/server.cc",
    "chars": 1013,
    "preview": "#include \"examples/protobuf/rpc/sudoku.pb.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n#include "
  },
  {
    "path": "examples/protobuf/rpc/sudoku.proto",
    "chars": 376,
    "preview": "package sudoku;\noption cc_generic_services = true;\noption java_generic_services = true;\noption py_generic_services = tru"
  },
  {
    "path": "examples/protobuf/rpcbalancer/CMakeLists.txt",
    "chars": 461,
    "preview": "include_directories(${PROJECT_BINARY_DIR})\n\nadd_executable(protobuf_rpc_balancer balancer.cc)\nset_target_properties(prot"
  },
  {
    "path": "examples/protobuf/rpcbalancer/balancer.cc",
    "chars": 6283,
    "preview": "#include \"muduo/base/Logging.h\"\n#include \"muduo/base/ThreadLocal.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/net"
  },
  {
    "path": "examples/protobuf/rpcbalancer/balancer_raw.cc",
    "chars": 9207,
    "preview": "#include \"muduo/base/Logging.h\"\n#include \"muduo/base/ThreadLocal.h\"\n#include \"muduo/net/EventLoop.h\"\n//#include <muduo/n"
  },
  {
    "path": "examples/protobuf/rpcbench/CMakeLists.txt",
    "chars": 838,
    "preview": "add_custom_command(OUTPUT echo.pb.cc echo.pb.h\n  COMMAND protoc\n  ARGS --cpp_out . ${CMAKE_CURRENT_SOURCE_DIR}/echo.prot"
  },
  {
    "path": "examples/protobuf/rpcbench/client.cc",
    "chars": 3480,
    "preview": "#include \"examples/protobuf/rpcbench/echo.pb.h\"\n\n#include \"muduo/base/CountDownLatch.h\"\n#include \"muduo/base/Logging.h\"\n"
  },
  {
    "path": "examples/protobuf/rpcbench/echo.proto",
    "chars": 384,
    "preview": "package echo;\n//option py_generic_services = true;\noption cc_generic_services = true;\noption java_generic_services = tru"
  },
  {
    "path": "examples/protobuf/rpcbench/server.cc",
    "chars": 1112,
    "preview": "#include \"examples/protobuf/rpcbench/echo.pb.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n#inclu"
  },
  {
    "path": "examples/roundtrip/CMakeLists.txt",
    "chars": 178,
    "preview": "add_executable(roundtrip roundtrip.cc)\ntarget_link_libraries(roundtrip muduo_net)\n\nadd_executable(roundtrip_udp roundtri"
  },
  {
    "path": "examples/roundtrip/roundtrip.cc",
    "chars": 3063,
    "preview": "#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/net/TcpClient.h\"\n#include \"muduo/net/Tc"
  },
  {
    "path": "examples/roundtrip/roundtrip_udp.cc",
    "chars": 3732,
    "preview": "#include \"muduo/base/Logging.h\"\n#include \"muduo/net/Channel.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/net/Sock"
  },
  {
    "path": "examples/shorturl/CMakeLists.txt",
    "chars": 81,
    "preview": "add_executable(shorturl shorturl.cc)\ntarget_link_libraries(shorturl muduo_http)\n\n"
  },
  {
    "path": "examples/shorturl/shorturl.cc",
    "chars": 7477,
    "preview": "#include \"muduo/net/http/HttpServer.h\"\n#include \"muduo/net/http/HttpRequest.h\"\n#include \"muduo/net/http/HttpResponse.h\"\n"
  },
  {
    "path": "examples/simple/CMakeLists.txt",
    "chars": 980,
    "preview": "add_executable(simple_chargen chargen/chargen.cc chargen/main.cc)\ntarget_link_libraries(simple_chargen muduo_net)\n\nadd_e"
  },
  {
    "path": "examples/simple/allinone/allinone.cc",
    "chars": 876,
    "preview": "#include \"examples/simple/chargen/chargen.h\"\n#include \"examples/simple/daytime/daytime.h\"\n#include \"examples/simple/disc"
  },
  {
    "path": "examples/simple/chargen/chargen.cc",
    "chars": 2097,
    "preview": "#include \"examples/simple/chargen/chargen.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n\n#include"
  },
  {
    "path": "examples/simple/chargen/chargen.h",
    "chars": 812,
    "preview": "#ifndef MUDUO_EXAMPLES_SIMPLE_CHARGEN_CHARGEN_H\n#define MUDUO_EXAMPLES_SIMPLE_CHARGEN_CHARGEN_H\n\n#include \"muduo/net/Tcp"
  },
  {
    "path": "examples/simple/chargen/main.cc",
    "chars": 369,
    "preview": "#include \"examples/simple/chargen/chargen.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n\n#include"
  },
  {
    "path": "examples/simple/chargenclient/chargenclient.cc",
    "chars": 1470,
    "preview": "#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n#include \"muduo/net/InetAddress.h\"\n#include \"muduo/net/"
  },
  {
    "path": "examples/simple/daytime/daytime.cc",
    "chars": 1235,
    "preview": "#include \"examples/simple/daytime/daytime.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n\nusing na"
  },
  {
    "path": "examples/simple/daytime/daytime.h",
    "chars": 601,
    "preview": "#ifndef MUDUO_EXAMPLES_SIMPLE_DAYTIME_DAYTIME_H\n#define MUDUO_EXAMPLES_SIMPLE_DAYTIME_DAYTIME_H\n\n#include \"muduo/net/Tcp"
  },
  {
    "path": "examples/simple/daytime/main.cc",
    "chars": 363,
    "preview": "#include \"examples/simple/daytime/daytime.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n\n#include"
  },
  {
    "path": "examples/simple/discard/discard.cc",
    "chars": 1086,
    "preview": "#include \"examples/simple/discard/discard.h\"\n\n#include \"muduo/base/Logging.h\"\n\nusing namespace muduo;\nusing namespace mu"
  },
  {
    "path": "examples/simple/discard/discard.h",
    "chars": 601,
    "preview": "#ifndef MUDUO_EXAMPLES_SIMPLE_DISCARD_DISCARD_H\n#define MUDUO_EXAMPLES_SIMPLE_DISCARD_DISCARD_H\n\n#include \"muduo/net/Tcp"
  },
  {
    "path": "examples/simple/discard/main.cc",
    "chars": 363,
    "preview": "#include \"examples/simple/discard/discard.h\"\n\n#include \"muduo/base/Logging.h\"\n#include \"muduo/net/EventLoop.h\"\n\n#include"
  },
  {
    "path": "examples/simple/echo/echo.cc",
    "chars": 1236,
    "preview": "#include \"examples/simple/echo/echo.h\"\n\n#include \"muduo/base/Logging.h\"\n\nusing std::placeholders::_1;\nusing std::placeho"
  },
  {
    "path": "examples/simple/echo/echo.h",
    "chars": 601,
    "preview": "#ifndef MUDUO_EXAMPLES_SIMPLE_ECHO_ECHO_H\n#define MUDUO_EXAMPLES_SIMPLE_ECHO_ECHO_H\n\n#include \"muduo/net/TcpServer.h\"\n\n/"
  }
]

// ... and 218 more files (download for full content)

About this extraction

This page contains the full source code of the chenshuo/muduo GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 418 files (964.8 KB), approximately 287.0k tokens, and a symbol index with 1371 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!