├── .gitignore ├── LICENSE ├── README ├── algorithm ├── combination.cc ├── iprange.cc ├── mergeMaps.cc ├── mergeN.cc ├── partition.cc ├── permutation.cc ├── permutation2.cc ├── removeContinuousSpaces.cc └── select.cc ├── basic ├── bench.cc ├── build.sh ├── combination.cc ├── counted_ptr.h ├── counted_ptr_test.cc ├── exact.cc ├── factorial.cc ├── fibonacci.cc ├── int128.h ├── numheaps.cc ├── partitions.cc ├── test.cc ├── tutorial │ ├── build.sh │ ├── factorial.cc │ └── sieve.cc ├── uint.cc └── uint.h ├── benchmark ├── .gitignore ├── BUILD.bazel ├── WORKSPACE ├── bench_dd.py ├── bm_compress.cc ├── bm_containers.cc ├── bm_fileio.cc ├── bm_ipc.cc ├── bm_memory.cc ├── external │ ├── lz4.BUILD │ ├── zlib.BUILD │ └── zstd.BUILD ├── format.cc ├── format.h ├── format_bench.cc └── format_test.cc ├── datetime ├── .gitignore ├── Date.cc ├── Date.h ├── Date_test.cc ├── Date_unittest.cc ├── License ├── Makefile ├── TimeZone.cc ├── TimeZone.h ├── TimeZone_dump.cc ├── TimeZone_unittest.cc ├── Timestamp.cc ├── Timestamp.h ├── Timestamp_unittest.cc ├── build.sh ├── copyable.h ├── formula_cumdays.tex ├── formula_cycles.tex ├── formula_floors.tex ├── formula_linear_reg.tex ├── formula_phases.tex ├── formula_shift.tex ├── linear_regression.mp ├── regress.m ├── shift_month.pic ├── shift_month_cumsum.pic └── time_benchmark.c ├── digest ├── DigestEVP.h ├── DigestEVP2.h ├── DigestOOP.cc ├── DigestOOP.h ├── DigestOOP2.cc ├── DigestTMP.cc ├── bench.cc ├── build.sh ├── test_evp.cc ├── test_evp2.cc └── test_oop.cc ├── esort ├── README ├── build.sh ├── sort00.cc ├── sort01.cc ├── sort02.cc ├── sort03.cc ├── sort04.cc ├── sort10.cc ├── sort11.cc └── sort12.cc ├── faketcp ├── Makefile ├── README ├── acceptall.cc ├── connectmany.cc ├── discardall.cc ├── discardall2.cc ├── echoall.cc ├── echoall2.cc ├── faketcp.cc ├── faketcp.h ├── icmpecho.cc ├── net.pic ├── rejectall.cc └── tun.pic ├── java ├── bankqueue │ ├── Bank.java │ ├── WindowType.java │ ├── customer │ │ ├── Customer.java │ │ ├── CustomerFactory.java │ │ ├── CustomerType.java │ │ ├── FastCustomer.java │ │ ├── NormalCustomer.java │ │ └── VipCustomer.java │ ├── event │ │ ├── CustomerArriveEvent.java │ │ ├── CustomerLeaveEvent.java │ │ ├── Event.java │ │ └── EventSimulator.java │ └── tests │ │ ├── BankTest.java │ │ └── EventTest.java ├── billing │ ├── BillCalculator.java │ ├── DataFields.java │ ├── DefaultRule.java │ ├── Money.java │ ├── Rule.java │ ├── RuleFactory.java │ ├── Slip.java │ ├── UserMonthUsage.java │ └── test │ │ ├── NormalCustomerTest.java │ │ └── VipCustomerTest.java ├── groovy │ └── billing │ │ ├── base_internet.groovy │ │ ├── base_phone_call.groovy │ │ ├── base_short_message.groovy │ │ ├── normal_user.groovy │ │ ├── normal_user_internet.groovy │ │ ├── normal_user_newjoiner.groovy │ │ ├── normal_user_phone_call.groovy │ │ ├── normal_user_short_message.groovy │ │ ├── package_internet.groovy │ │ ├── package_phone_call.groovy │ │ ├── package_short_message.groovy │ │ ├── root.groovy │ │ ├── vip_user.groovy │ │ ├── vip_user_newjoiner.groovy │ │ ├── vip_user_nopackage.groovy │ │ ├── vip_user_package1.groovy │ │ └── vip_user_package2.groovy ├── pdf │ └── com │ │ └── chenshuo │ │ └── pdf │ │ └── PdfHack.java └── run.sh ├── logging ├── AsyncLoggingDoubleBuffering.h ├── AsyncLoggingQueue.h ├── AsyncLogging_test.cc ├── LogFile.cc ├── LogFile.h ├── LogFile_test.cc ├── LogStream.cc ├── LogStream.h ├── LogStream_bench.cc ├── LogStream_test.cc ├── Logging.cc ├── Logging.h ├── Logging_test.cc ├── README └── build.sh ├── pingpong ├── asio │ ├── LICENSE_1_0.txt │ ├── README │ ├── asio.hpp │ ├── build.sh │ ├── client.cpp │ ├── handler_allocator.hpp │ ├── multiple_thread.sh │ ├── server.cpp │ └── single_thread.sh ├── libevent │ ├── Makefile │ ├── bench.c │ ├── client.c │ ├── run_bench.sh │ ├── server-half-close.c │ ├── server-line-echo.c │ ├── server.c │ └── single_thread.sh └── muduo │ ├── README │ ├── multiple_thread.sh │ └── single_thread.sh ├── protobuf ├── Makefile ├── codec.h ├── codec_test.cc ├── descriptor_test.cc ├── dispatcher.cc ├── dispatcher_lite.cc └── query.proto ├── protorpc ├── README ├── build.sh ├── echo.proto ├── echo │ ├── EchoClient.java │ ├── EchoProto.java │ └── EchoServer.java ├── muduo │ ├── codec │ │ ├── ProtobufDecoder.java │ │ ├── ProtobufEncoder.java │ │ └── tests │ │ │ ├── CodecTest.java │ │ │ └── QueryProtos.java │ └── rpc │ │ ├── NewChannelCallback.java │ │ ├── RpcChannel.java │ │ ├── RpcChannelPiplineFactory.java │ │ ├── RpcClient.java │ │ ├── RpcDecoder.java │ │ ├── RpcEncoder.java │ │ ├── RpcMessageHandler.java │ │ ├── RpcPeer.java │ │ ├── RpcServer.java │ │ ├── proto │ │ └── RpcProto.java │ │ └── test │ │ ├── MockChannel.java │ │ └── RpcTest.java ├── rpc.proto ├── run_client.sh ├── run_server.sh ├── sudoku.proto └── sudoku │ ├── Client.java │ ├── Server.java │ ├── Sudoku.java │ └── SudokuImpl.java ├── puzzle ├── Einstein.java ├── buysell.cc ├── dance.cc ├── f100.pic ├── fib.py ├── fibonacci.cc ├── huarong.cc ├── latin_square.cc ├── nbody.c ├── nbody.cc ├── nqueens.cc ├── nqueens_dl.cc ├── nqueens_mt.cc ├── nqueens_opt.cc ├── nqueens_opt_mt.cc ├── poker │ ├── bench.py │ ├── generate.py │ ├── poker.cc │ ├── poker.py │ ├── poker2.py │ └── poker_test.py ├── query_freq.cc ├── seven.pic ├── typoglycemia.cc └── waterpour.cc ├── python ├── chargen.py ├── chat-poll.py ├── chat-reactor.py ├── echo-fork.py ├── echo-iterative.py ├── echo-poll.py ├── echo-reactor.py ├── echo-single.py ├── echo-thread.py ├── logviewer.py ├── netcat-nonblock.py ├── netcat.py ├── nqueens.py ├── self-connect.py ├── sockopt.py ├── tcprelay.py ├── tcprelay2.py ├── throughput-bidi.py ├── throughput.py └── ttcp.py ├── reactor ├── .gitignore ├── License ├── Makefile ├── README ├── mkdiff.sh ├── reactor.mk ├── reactor_lib.mk ├── s00 │ ├── EventLoop.cc │ ├── EventLoop.h │ ├── Makefile │ ├── test1.cc │ └── test2.cc ├── s01-s00-EventLoop.cc.diff ├── s01-s00-EventLoop.h.diff ├── s01 │ ├── Channel.cc │ ├── Channel.h │ ├── EventLoop.cc │ ├── EventLoop.h │ ├── Makefile │ ├── Poller.cc │ ├── Poller.h │ ├── test1.cc │ ├── test2.cc │ └── test3.cc ├── s02-s01-EventLoop.cc.diff ├── s02-s01-EventLoop.h.diff ├── s02 │ ├── Callbacks.h │ ├── Channel.cc │ ├── Channel.h │ ├── EventLoop.cc │ ├── EventLoop.h │ ├── Makefile │ ├── Poller.cc │ ├── Poller.h │ ├── Timer.cc │ ├── Timer.h │ ├── TimerId.h │ ├── TimerQueue.cc │ ├── TimerQueue.h │ ├── test1.cc │ ├── test2.cc │ ├── test3.cc │ └── test4.cc ├── s03-s02-EventLoop.cc.diff ├── s03-s02-EventLoop.h.diff ├── s03-s02-TimerQueue.cc.diff ├── s03-s02-TimerQueue.h.diff ├── s03 │ ├── Callbacks.h │ ├── Channel.cc │ ├── Channel.h │ ├── EventLoop.cc │ ├── EventLoop.h │ ├── EventLoopThread.cc │ ├── EventLoopThread.h │ ├── Makefile │ ├── Poller.cc │ ├── Poller.h │ ├── Timer.cc │ ├── Timer.h │ ├── TimerId.h │ ├── TimerQueue.cc │ ├── TimerQueue.h │ ├── test1.cc │ ├── test2.cc │ ├── test3.cc │ ├── test4.cc │ ├── test5.cc │ └── test6.cc ├── s04 │ ├── Acceptor.cc │ ├── Acceptor.h │ ├── Callbacks.h │ ├── Channel.cc │ ├── Channel.h │ ├── EventLoop.cc │ ├── EventLoop.h │ ├── EventLoopThread.cc │ ├── EventLoopThread.h │ ├── InetAddress.cc │ ├── InetAddress.h │ ├── Makefile │ ├── Poller.cc │ ├── Poller.h │ ├── Socket.cc │ ├── Socket.h │ ├── SocketsOps.cc │ ├── SocketsOps.h │ ├── Timer.cc │ ├── Timer.h │ ├── TimerId.h │ ├── TimerQueue.cc │ ├── TimerQueue.h │ ├── test1.cc │ ├── test2.cc │ ├── test3.cc │ ├── test4.cc │ ├── test5.cc │ ├── test6.cc │ └── test7.cc ├── s05-s04-Callbacks.h.diff ├── s05-s04-SocketsOps.cc.diff ├── s05-s04-SocketsOps.h.diff ├── s05 │ ├── Acceptor.cc │ ├── Acceptor.h │ ├── Callbacks.h │ ├── Channel.cc │ ├── Channel.h │ ├── EventLoop.cc │ ├── EventLoop.h │ ├── EventLoopThread.cc │ ├── EventLoopThread.h │ ├── InetAddress.cc │ ├── InetAddress.h │ ├── Makefile │ ├── Poller.cc │ ├── Poller.h │ ├── Socket.cc │ ├── Socket.h │ ├── SocketsOps.cc │ ├── SocketsOps.h │ ├── TcpConnection.cc │ ├── TcpConnection.h │ ├── TcpServer.cc │ ├── TcpServer.h │ ├── Timer.cc │ ├── Timer.h │ ├── TimerId.h │ ├── TimerQueue.cc │ ├── TimerQueue.h │ ├── test1.cc │ ├── test2.cc │ ├── test3.cc │ ├── test4.cc │ ├── test5.cc │ ├── test6.cc │ ├── test7.cc │ └── test8.cc ├── s06-s05-Callbacks.h.diff ├── s06-s05-Channel.cc.diff ├── s06-s05-Channel.h.diff ├── s06-s05-EventLoop.cc.diff ├── s06-s05-EventLoop.h.diff ├── s06-s05-Poller.cc.diff ├── s06-s05-Poller.h.diff ├── s06-s05-SocketsOps.cc.diff ├── s06-s05-SocketsOps.h.diff ├── s06-s05-TcpConnection.cc.diff ├── s06-s05-TcpConnection.h.diff ├── s06-s05-TcpServer.cc.diff ├── s06-s05-TcpServer.h.diff ├── s06 │ ├── Acceptor.cc │ ├── Acceptor.h │ ├── Callbacks.h │ ├── Channel.cc │ ├── Channel.h │ ├── EventLoop.cc │ ├── EventLoop.h │ ├── EventLoopThread.cc │ ├── EventLoopThread.h │ ├── InetAddress.cc │ ├── InetAddress.h │ ├── Makefile │ ├── Poller.cc │ ├── Poller.h │ ├── Socket.cc │ ├── Socket.h │ ├── SocketsOps.cc │ ├── SocketsOps.h │ ├── TcpConnection.cc │ ├── TcpConnection.h │ ├── TcpServer.cc │ ├── TcpServer.h │ ├── Timer.cc │ ├── Timer.h │ ├── TimerId.h │ ├── TimerQueue.cc │ ├── TimerQueue.h │ ├── test1.cc │ ├── test2.cc │ ├── test3.cc │ ├── test4.cc │ ├── test5.cc │ ├── test6.cc │ ├── test7.cc │ └── test8.cc ├── s07-s06-Callbacks.h.diff ├── s07-s06-Channel.cc.diff ├── s07-s06-Channel.h.diff ├── s07-s06-EventLoop.cc.diff ├── s07-s06-TcpConnection.cc.diff ├── s07-s06-TcpConnection.h.diff ├── s07-s06-test3.cc.diff ├── s07-s06-test8.cc.diff ├── s07 │ ├── Acceptor.cc │ ├── Acceptor.h │ ├── Buffer.cc │ ├── Buffer.h │ ├── Callbacks.h │ ├── Channel.cc │ ├── Channel.h │ ├── EventLoop.cc │ ├── EventLoop.h │ ├── EventLoopThread.cc │ ├── EventLoopThread.h │ ├── InetAddress.cc │ ├── InetAddress.h │ ├── Makefile │ ├── Poller.cc │ ├── Poller.h │ ├── Socket.cc │ ├── Socket.h │ ├── SocketsOps.cc │ ├── SocketsOps.h │ ├── TcpConnection.cc │ ├── TcpConnection.h │ ├── TcpServer.cc │ ├── TcpServer.h │ ├── Timer.cc │ ├── Timer.h │ ├── TimerId.h │ ├── TimerQueue.cc │ ├── TimerQueue.h │ ├── test1.cc │ ├── test2.cc │ ├── test3.cc │ ├── test4.cc │ ├── test5.cc │ ├── test6.cc │ ├── test7.cc │ └── test8.cc ├── s08-s07-Channel.h.diff ├── s08-s07-Socket.cc.diff ├── s08-s07-Socket.h.diff ├── s08-s07-SocketsOps.cc.diff ├── s08-s07-SocketsOps.h.diff ├── s08-s07-TcpConnection.cc.diff ├── s08-s07-TcpConnection.h.diff ├── s08 │ ├── Acceptor.cc │ ├── Acceptor.h │ ├── Buffer.cc │ ├── Buffer.h │ ├── Callbacks.h │ ├── Channel.cc │ ├── Channel.h │ ├── EventLoop.cc │ ├── EventLoop.h │ ├── EventLoopThread.cc │ ├── EventLoopThread.h │ ├── InetAddress.cc │ ├── InetAddress.h │ ├── Makefile │ ├── Poller.cc │ ├── Poller.h │ ├── Socket.cc │ ├── Socket.h │ ├── SocketsOps.cc │ ├── SocketsOps.h │ ├── TcpConnection.cc │ ├── TcpConnection.h │ ├── TcpServer.cc │ ├── TcpServer.h │ ├── Timer.cc │ ├── Timer.h │ ├── TimerId.h │ ├── TimerQueue.cc │ ├── TimerQueue.h │ ├── test1.cc │ ├── test10.cc │ ├── test2.cc │ ├── test3.cc │ ├── test4.cc │ ├── test5.cc │ ├── test6.cc │ ├── test7.cc │ ├── test8.cc │ └── test9.cc ├── s09-s08-Callbacks.h.diff ├── s09-s08-EventLoop.cc.diff ├── s09-s08-Socket.cc.diff ├── s09-s08-Socket.h.diff ├── s09-s08-TcpConnection.cc.diff ├── s09-s08-TcpConnection.h.diff ├── s09-s08-TcpServer.cc.diff ├── s09-s08-TcpServer.h.diff ├── s09-s08-test10.cc.diff ├── s09 │ ├── Acceptor.cc │ ├── Acceptor.h │ ├── Buffer.cc │ ├── Buffer.h │ ├── Callbacks.h │ ├── Channel.cc │ ├── Channel.h │ ├── EventLoop.cc │ ├── EventLoop.h │ ├── EventLoopThread.cc │ ├── EventLoopThread.h │ ├── InetAddress.cc │ ├── InetAddress.h │ ├── Makefile │ ├── Poller.cc │ ├── Poller.h │ ├── Socket.cc │ ├── Socket.h │ ├── SocketsOps.cc │ ├── SocketsOps.h │ ├── TcpConnection.cc │ ├── TcpConnection.h │ ├── TcpServer.cc │ ├── TcpServer.h │ ├── Timer.cc │ ├── Timer.h │ ├── TimerId.h │ ├── TimerQueue.cc │ ├── TimerQueue.h │ ├── test1.cc │ ├── test10.cc │ ├── test11.cc │ ├── test2.cc │ ├── test3.cc │ ├── test4.cc │ ├── test5.cc │ ├── test6.cc │ ├── test7.cc │ ├── test8.cc │ └── test9.cc ├── s10-s09-TcpServer.cc.diff ├── s10-s09-TcpServer.h.diff ├── s10-s09-test10.cc.diff ├── s10-s09-test11.cc.diff ├── s10-s09-test8.cc.diff ├── s10-s09-test9.cc.diff ├── s10 │ ├── Acceptor.cc │ ├── Acceptor.h │ ├── Buffer.cc │ ├── Buffer.h │ ├── Callbacks.h │ ├── Channel.cc │ ├── Channel.h │ ├── EventLoop.cc │ ├── EventLoop.h │ ├── EventLoopThread.cc │ ├── EventLoopThread.h │ ├── EventLoopThreadPool.cc │ ├── EventLoopThreadPool.h │ ├── InetAddress.cc │ ├── InetAddress.h │ ├── Makefile │ ├── Poller.cc │ ├── Poller.h │ ├── Socket.cc │ ├── Socket.h │ ├── SocketsOps.cc │ ├── SocketsOps.h │ ├── TcpConnection.cc │ ├── TcpConnection.h │ ├── TcpServer.cc │ ├── TcpServer.h │ ├── Timer.cc │ ├── Timer.h │ ├── TimerId.h │ ├── TimerQueue.cc │ ├── TimerQueue.h │ ├── test1.cc │ ├── test10.cc │ ├── test11.cc │ ├── test2.cc │ ├── test3.cc │ ├── test4.cc │ ├── test5.cc │ ├── test6.cc │ ├── test7.cc │ ├── test8.cc │ └── test9.cc ├── s11-s10-EventLoop.cc.diff ├── s11-s10-EventLoop.h.diff ├── s11-s10-SocketsOps.cc.diff ├── s11-s10-SocketsOps.h.diff ├── s11-s10-Timer.cc.diff ├── s11-s10-Timer.h.diff ├── s11-s10-TimerId.h.diff ├── s11-s10-TimerQueue.cc.diff ├── s11-s10-TimerQueue.h.diff ├── s11-s10-test4.cc.diff ├── s11 │ ├── Acceptor.cc │ ├── Acceptor.h │ ├── Buffer.cc │ ├── Buffer.h │ ├── Callbacks.h │ ├── Channel.cc │ ├── Channel.h │ ├── Connector.cc │ ├── Connector.h │ ├── EventLoop.cc │ ├── EventLoop.h │ ├── EventLoopThread.cc │ ├── EventLoopThread.h │ ├── EventLoopThreadPool.cc │ ├── EventLoopThreadPool.h │ ├── InetAddress.cc │ ├── InetAddress.h │ ├── Makefile │ ├── Poller.cc │ ├── Poller.h │ ├── Socket.cc │ ├── Socket.h │ ├── SocketsOps.cc │ ├── SocketsOps.h │ ├── TcpConnection.cc │ ├── TcpConnection.h │ ├── TcpServer.cc │ ├── TcpServer.h │ ├── Timer.cc │ ├── Timer.h │ ├── TimerId.h │ ├── TimerQueue.cc │ ├── TimerQueue.h │ ├── test1.cc │ ├── test10.cc │ ├── test11.cc │ ├── test12.cc │ ├── test2.cc │ ├── test3.cc │ ├── test4.cc │ ├── test5.cc │ ├── test6.cc │ ├── test7.cc │ ├── test8.cc │ └── test9.cc ├── s12 │ ├── Acceptor.cc │ ├── Acceptor.h │ ├── Buffer.cc │ ├── Buffer.h │ ├── Callbacks.h │ ├── Channel.cc │ ├── Channel.h │ ├── Connector.cc │ ├── Connector.h │ ├── EventLoop.cc │ ├── EventLoop.h │ ├── EventLoopThread.cc │ ├── EventLoopThread.h │ ├── EventLoopThreadPool.cc │ ├── EventLoopThreadPool.h │ ├── InetAddress.cc │ ├── InetAddress.h │ ├── Makefile │ ├── 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 │ ├── test1.cc │ ├── test10.cc │ ├── test11.cc │ ├── test12.cc │ ├── test13.cc │ ├── test2.cc │ ├── test3.cc │ ├── test4.cc │ ├── test5.cc │ ├── test6.cc │ ├── test7.cc │ ├── test8.cc │ └── test9.cc ├── s13-s12-EventLoop.cc.diff ├── s13-s12-EventLoop.h.diff └── s13 │ ├── Acceptor.cc │ ├── Acceptor.h │ ├── Buffer.cc │ ├── Buffer.h │ ├── Callbacks.h │ ├── Channel.cc │ ├── Channel.h │ ├── Connector.cc │ ├── Connector.h │ ├── EPoller.cc │ ├── EPoller.h │ ├── EventLoop.cc │ ├── EventLoop.h │ ├── EventLoopThread.cc │ ├── EventLoopThread.h │ ├── EventLoopThreadPool.cc │ ├── EventLoopThreadPool.h │ ├── InetAddress.cc │ ├── InetAddress.h │ ├── Makefile │ ├── 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 │ ├── test1.cc │ ├── test10.cc │ ├── test11.cc │ ├── test12.cc │ ├── test13.cc │ ├── test2.cc │ ├── test3.cc │ ├── test4.cc │ ├── test5.cc │ ├── test6.cc │ ├── test7.cc │ ├── test8.cc │ └── test9.cc ├── ssl ├── .gitignore ├── TlsAcceptor.cc ├── TlsAcceptor.h ├── TlsConfig.cc ├── TlsConfig.h ├── TlsContext.h ├── TlsStream.cc ├── TlsStream.h ├── benchmark-libressl.cc ├── benchmark-openssl.cc ├── benchmark-polarssl.cc ├── build.sh ├── client.cc ├── footprint-openssl.cc ├── footprint-openssl2.cc ├── hook.py ├── loop-libressl.cc ├── loop-polarssl.cc ├── server.cc └── timer.h ├── string ├── StringEager.cc ├── StringEager.h ├── StringSso.h ├── StringTrivial.h ├── StringTrivialTest.cc ├── build.sh ├── main.cc ├── test.cc └── test.sh ├── sudoku ├── Makefile ├── README ├── main.cc ├── neighbor.cc ├── sudoku.h ├── sudoku_basic.cc ├── sudoku_dancing_links.cc ├── sudoku_min_arity.cc ├── sudoku_min_arity_cache.cc ├── test1 └── test1000 ├── thread ├── Atomic.h ├── BlockingQueue.h ├── BoundedBlockingQueue.h ├── Condition.h ├── CountDownLatch.h ├── Exception.cc ├── Exception.h ├── License ├── Makefile ├── Mutex.h ├── README ├── SignalSlot.h ├── SignalSlotTrivial.h ├── Singleton.h ├── Thread.cc ├── Thread.h ├── ThreadLocal.h ├── ThreadLocalSingleton.h ├── ThreadPool.cc ├── ThreadPool.h ├── WeakCallback.h └── test │ ├── Atomic_unittest.cc │ ├── BlockingQueue_test.cc │ ├── BoundedBlockingQueue_test.cc │ ├── CopyOnWrite_test.cc │ ├── Counter.cc │ ├── Customer.cc │ ├── Exception_test.cc │ ├── ExitDeadLock.cc │ ├── Factory.cc │ ├── Factory_deadlock.cc │ ├── Factory_new_racecondition.cc │ ├── Factory_racecondition.cc │ ├── Fork_test.cc │ ├── MutualDeadLock.cc │ ├── NonRecursiveMutex_test.cc │ ├── Observer.cc │ ├── Observer_safe.cc │ ├── RequestInventory_test.cc │ ├── RequestInventory_test2.cc │ ├── SelfDeadLock.cc │ ├── SignalSlot_test.cc │ ├── SingletonThreadLocal_test.cc │ ├── Singleton_test.cc │ ├── ThreadLocalSingleton_test.cc │ ├── ThreadLocal_test.cc │ ├── ThreadPool_test.cc │ ├── Thread_bench.cc │ ├── Thread_test.cc │ ├── Waiter_test.cc │ ├── WeakCallback_test.cc │ └── destruct.cc ├── topk ├── .gitignore ├── BUILD.bazel ├── Makefile ├── WORKSPACE ├── benchmark.cc ├── file.h ├── gen.cc ├── gen.py ├── gen_count.py ├── input.h ├── merge.h ├── merger.cc ├── sender.cc ├── sha1all.cc ├── split.cc ├── timer.h ├── word_freq.cc ├── word_freq_shards.cc ├── word_freq_shards_basic.cc ├── word_freq_sort.cc └── word_freq_sort_basic.cc ├── tpc ├── Makefile ├── README ├── bin │ ├── .gitignore │ ├── chargen.cc │ ├── discard.cc │ ├── echo.cc │ ├── echo_client.cc │ ├── footprint.cc │ ├── footprint.py │ ├── netcat.cc │ ├── nodelay.cc │ ├── nodelay_server.cc │ ├── roundtrip_tcp.cc │ ├── roundtrip_udp.cc │ ├── sender.cc │ ├── sendoob.cc │ ├── sudoku_stress.cc │ ├── tcpperf.cc │ └── ttcp.cc ├── include │ ├── Acceptor.h │ ├── Common.h │ ├── InetAddress.h │ ├── Socket.h │ └── TcpStream.h ├── lib │ ├── Acceptor.cc │ ├── InetAddress.cc │ ├── Socket.cc │ └── TcpStream.cc └── ttcp.pic └── utility ├── Makefile ├── codesize.py └── cwc.cc /.gitignore: -------------------------------------------------------------------------------- 1 | *.a 2 | *.o 3 | *.swp 4 | *.out 5 | profile*.pb.gz 6 | core 7 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenshuo/recipes/c418129499e98b43358340751cdd7b082b7ed122/README -------------------------------------------------------------------------------- /algorithm/combination.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() 8 | { 9 | int values[] = { 1, 2, 3, 4, 5, 6, 7 }; 10 | int elements[] = { 1, 1, 1, 0, 0, 0, 0 }; 11 | const size_t N = sizeof(elements)/sizeof(elements[0]); 12 | assert(N == sizeof(values)/sizeof(values[0])); 13 | std::vector selectors(elements, elements + N); 14 | 15 | int count = 0; 16 | do 17 | { 18 | std::cout << ++count << ": "; 19 | for (size_t i = 0; i < selectors.size(); ++i) 20 | { 21 | if (selectors[i]) 22 | { 23 | std::cout << values[i] << ", "; 24 | } 25 | } 26 | std::cout << std::endl; 27 | } while (prev_permutation(selectors.begin(), selectors.end())); 28 | } 29 | -------------------------------------------------------------------------------- /algorithm/partition.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | bool isOdd(int x) 6 | { 7 | return x % 2 != 0; // x % 2 == 1 is WRONG 8 | } 9 | 10 | void moveOddsBeforeEvens() 11 | { 12 | int oddeven[] = { 1, 2, 3, 4, 5, 6 }; 13 | std::partition(oddeven, oddeven+6, &isOdd); 14 | std::copy(oddeven, oddeven+6, std::ostream_iterator(std::cout, ", ")); 15 | std::cout << std::endl; 16 | } 17 | 18 | int main() 19 | { 20 | moveOddsBeforeEvens(); 21 | 22 | int oddeven[] = { 1, 2, 3, 4, 5, 6 }; 23 | std::stable_partition(oddeven, oddeven+6, &isOdd); 24 | std::copy(oddeven, oddeven+6, std::ostream_iterator(std::cout, ", ")); 25 | std::cout << std::endl; 26 | } 27 | -------------------------------------------------------------------------------- /algorithm/permutation.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | int elements[] = { 1, 2, 3, 4 }; 9 | const size_t N = sizeof(elements)/sizeof(elements[0]); 10 | std::vector vec(elements, elements + N); 11 | 12 | int count = 0; 13 | do 14 | { 15 | std::cout << ++count << ": "; 16 | std::copy(vec.begin(), vec.end(), 17 | std::ostream_iterator(std::cout, ", ")); 18 | std::cout << std::endl; 19 | } while (next_permutation(vec.begin(), vec.end())); 20 | } 21 | -------------------------------------------------------------------------------- /algorithm/permutation2.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | char elements[] = { 'a', 'a', 'b', 'b', 'b' }; 9 | const size_t N = sizeof(elements)/sizeof(elements[0]); 10 | std::vector vec(elements, elements + N); 11 | 12 | int count = 0; 13 | do 14 | { 15 | std::cout << ++count << ": "; 16 | std::copy(vec.begin(), vec.end(), 17 | std::ostream_iterator(std::cout, ", ")); 18 | std::cout << std::endl; 19 | } while (next_permutation(vec.begin(), vec.end())); 20 | } 21 | -------------------------------------------------------------------------------- /basic/bench.cc: -------------------------------------------------------------------------------- 1 | #include "uint.h" 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | void reserve() 11 | { 12 | const double b = log10(2.0); 13 | for (int i = 0; i <= 100000; ++i) 14 | { 15 | int d = ceil(i*32*b); 16 | int r = 9*i + 7*i/11 + 1; 17 | printf("%6d %7d %7d %3d %f\n", i, d, r, r-d, double(r-d)/d); 18 | if (d > r) 19 | break; 20 | } 21 | } 22 | 23 | int main() 24 | { 25 | UnsignedInt u0; 26 | u0.setValue(100, -1); 27 | cout << u0.toDec() << endl; 28 | u0.setValue(1000, -1); 29 | cout << u0.toDec() << endl; 30 | reserve(); 31 | u0.setValue(1, 2); 32 | u0.power(1024); 33 | cout << u0.toDec() << endl; 34 | u0.setValue(1, 5); 35 | u0.power(1022); 36 | cout << u0.toDec() << endl; 37 | } 38 | -------------------------------------------------------------------------------- /basic/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -x 4 | 5 | mkdir -p bin 6 | g++ test.cc uint.cc -o bin/test-dbg -Wall -Wextra -g -O0 \ 7 | -DBOOST_TEST_DYN_LINK -lboost_unit_test_framework 8 | g++ test.cc uint.cc -o bin/test-opt -Wall -Wextra -g -O2 -DNDEBUG \ 9 | -DBOOST_TEST_DYN_LINK -lboost_unit_test_framework 10 | 11 | g++ bench.cc uint.cc -o bin/bench-dbg -Wall -Wextra -g -O0 12 | g++ bench.cc uint.cc -o bin/bench-opt -Wall -Wextra -g -O2 -DNDEBUG 13 | 14 | g++ exact.cc uint.cc -o bin/exact-dbg -Wall -Wextra -g -O0 15 | 16 | g++ factorial.cc uint.cc -o bin/factorial-opt -Wall -Wextra -g -O2 -DNDEBUG 17 | g++ fibonacci.cc uint.cc -o bin/fibonacci-opt -Wall -Wextra -g -O2 -DNDEBUG 18 | g++ combination.cc uint.cc -o bin/combination-opt -Wall -Wextra -g -O2 -DNDEBUG 19 | g++ partitions.cc uint.cc -o bin/partition-opt -Wall -Wextra -g -O2 -DNDEBUG 20 | g++ numheaps.cc uint.cc -o bin/numheaps-opt -std=c++0x -Wall -Wextra -g -O2 -DNDEBUG 21 | -------------------------------------------------------------------------------- /basic/combination.cc: -------------------------------------------------------------------------------- 1 | #include "uint.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char* argv[]) 8 | { 9 | if (argc > 2) 10 | { 11 | int M = atoi(argv[1]); 12 | const int N = atoi(argv[2]); 13 | assert(0 <= M && M <= N); 14 | if (M > N/2) 15 | M = N - M; 16 | UnsignedInt result(1); 17 | for (int i = 1; i <= M; ++i) 18 | { 19 | result.multiply(N - i + 1); 20 | int r = result.devide(i); 21 | assert(r == 0); 22 | if (r != 0) 23 | abort(); 24 | } 25 | printf("%s\n", result.toDec().c_str()); 26 | } 27 | else 28 | { 29 | printf("Usage: %s M N\n", argv[0]); 30 | printf("Choose M elements out of N.\n"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /basic/counted_ptr_test.cc: -------------------------------------------------------------------------------- 1 | #include "counted_ptr.h" 2 | 3 | #include 4 | 5 | #include 6 | 7 | counted_ptr foo() 8 | { 9 | counted_ptr sp(new int(123)); 10 | return sp; 11 | } 12 | 13 | void bar(counted_ptr x) 14 | { 15 | printf("%d\n", x.use_count()); 16 | } 17 | 18 | class Zoo; 19 | struct Age 20 | { 21 | int value; 22 | }; 23 | 24 | int main() 25 | { 26 | counted_ptr sp1; 27 | counted_ptr sp2(new int); 28 | sp1 = sp2; 29 | counted_ptr sp3(sp2); 30 | { 31 | counted_ptr sp4(sp2); 32 | counted_ptr sp5(sp1); 33 | printf("%d\n", sp5.use_count()); 34 | bar(std::move(sp5)); 35 | } 36 | counted_ptr sp6(foo()); 37 | 38 | printf("%d\n", *sp6); 39 | counted_ptr sp7(new Age); 40 | sp7->value = 43; 41 | printf("%d\n", sp7->value); 42 | 43 | std::vector> vec; 44 | vec.push_back(sp1); 45 | vec.push_back(sp2); 46 | vec.push_back(sp3); 47 | vec.push_back(sp6); 48 | 49 | if (sp2) 50 | printf("%p\n", sp2.get()); 51 | // counted_ptr x; 52 | } 53 | -------------------------------------------------------------------------------- /basic/factorial.cc: -------------------------------------------------------------------------------- 1 | #include "uint.h" 2 | 3 | #include 4 | #include 5 | 6 | int main(int argc, char* argv[]) 7 | { 8 | if (argc > 1) 9 | { 10 | const int N = atoi(argv[1]); 11 | UnsignedInt result(1); 12 | for (int i = 1; i <= N; ++i) 13 | { 14 | result.multiply(i); 15 | } 16 | printf("%s\n", result.toDec().c_str()); 17 | } 18 | else 19 | { 20 | printf("Usage: %s number\n", argv[0]); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /basic/tutorial/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | g++ -std=c++0x -O2 -Wall -g factorial.cc -o factorial 4 | g++ -std=c++0x -O2 -Wall -g sieve.cc -o sieve 5 | -------------------------------------------------------------------------------- /basic/tutorial/sieve.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char* argv[]) 6 | { 7 | size_t N = argc > 1 ? atol(argv[1]) : 100; 8 | int count = 1; 9 | std::vector sieve(N, true); 10 | printf("2\n"); 11 | for (size_t i = 1; i < sieve.size(); ++i) 12 | { 13 | if (sieve[i]) 14 | { 15 | size_t p = 2*i + 1; 16 | ++count; 17 | printf("%zd\n", p); 18 | size_t q = 3 * p; 19 | size_t j = (q-1) / 2; 20 | while (j < sieve.size()) 21 | { 22 | sieve[j] = false; 23 | q += 2 * p; 24 | j = (q-1) / 2; 25 | } 26 | } 27 | } 28 | //printf("count = %d\n", count); 29 | } 30 | -------------------------------------------------------------------------------- /benchmark/.gitignore: -------------------------------------------------------------------------------- 1 | bazel-* 2 | -------------------------------------------------------------------------------- /benchmark/external/lz4.BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "lz4", 3 | srcs = ["lib/lz4.c"], 4 | hdrs = ["lib/lz4.h"], 5 | includes = ["lib"], 6 | visibility = ["//visibility:public"], 7 | ) 8 | -------------------------------------------------------------------------------- /benchmark/external/zlib.BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "zlib", 3 | srcs = glob(["*.c"]), 4 | hdrs = glob(["*.h"]), 5 | copts = ["-DHAVE_UNISTD_H"], 6 | includes = ["."], 7 | visibility = ["//visibility:public"], 8 | ) 9 | -------------------------------------------------------------------------------- /benchmark/external/zstd.BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "zstd", 3 | srcs = glob(["lib/common/*.c", "lib/compress/*.c"]), 4 | hdrs = glob(["lib/common/*.h", "lib/compress/*.h"]) + ["lib/zstd.h"], 5 | includes = ["lib", "lib/common"], 6 | visibility = ["//visibility:public"], 7 | ) 8 | -------------------------------------------------------------------------------- /benchmark/format.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | std::string formatSI(size_t n); 4 | std::string formatIEC(size_t n); 5 | -------------------------------------------------------------------------------- /benchmark/format_bench.cc: -------------------------------------------------------------------------------- 1 | #include "format.h" 2 | #include "benchmark/benchmark.h" 3 | #include 4 | 5 | static void BM_formatSI(benchmark::State& state) 6 | { 7 | std::mt19937_64 gen(43); 8 | for (auto _ : state) 9 | { 10 | formatSI(gen()); 11 | } 12 | state.SetItemsProcessed(state.iterations()); 13 | } 14 | BENCHMARK(BM_formatSI); 15 | 16 | static void BM_formatIEC(benchmark::State& state) 17 | { 18 | std::mt19937_64 gen(43); 19 | for (auto _ : state) 20 | { 21 | formatIEC(gen()); 22 | } 23 | state.SetItemsProcessed(state.iterations()); 24 | } 25 | BENCHMARK(BM_formatIEC); 26 | -------------------------------------------------------------------------------- /datetime/.gitignore: -------------------------------------------------------------------------------- 1 | *.aux 2 | *.dvi 3 | *.eps 4 | *.log 5 | *.mps 6 | *.mpx 7 | *.png 8 | *.ps 9 | *.swp 10 | -------------------------------------------------------------------------------- /datetime/Date_test.cc: -------------------------------------------------------------------------------- 1 | #include "Date.h" 2 | #include 3 | #include 4 | 5 | using muduo::Date; 6 | 7 | int main(int argc, char* argv[]) 8 | { 9 | if (argc == 2) 10 | { 11 | int jdn = atoi(argv[1]); 12 | Date date(jdn); 13 | printf("%s\n", date.toIsoString().c_str()); 14 | } 15 | else if (argc == 4) 16 | { 17 | int year = atoi(argv[1]); 18 | int month = atoi(argv[2]); 19 | int day = atoi(argv[3]); 20 | Date date(year, month, day); 21 | printf("%d\n", date.julianDayNumber()); 22 | } 23 | else 24 | { 25 | printf("Usage: %s [julian_day_number | year month day]\n", argv[0]); 26 | } 27 | } 28 | 29 | 30 | -------------------------------------------------------------------------------- /datetime/TimeZone_dump.cc: -------------------------------------------------------------------------------- 1 | #include "TimeZone.h" 2 | #include 3 | 4 | using muduo::TimeZone; 5 | 6 | int main(int argc, char* argv[]) 7 | { 8 | const char* zonefile = argc == 1 ? "/etc/localtime" : argv[1]; 9 | TimeZone tz(zonefile); 10 | } 11 | -------------------------------------------------------------------------------- /datetime/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | gpic shift_month.pic | groff | ps2eps --loose --gsbbox > shift_month.eps 4 | eps2png --pnggray -resolution 144 shift_month.eps 5 | 6 | gpic shift_month_cumsum.pic | groff | ps2eps --loose --gsbbox > shift_month_cumsum.eps 7 | eps2png --png16m -resolution 144 shift_month_cumsum.eps 8 | 9 | mpost linear_regression.mp 10 | ps2eps --loose --gsbbox < linear_regression-1.mps > linear_regression-1.eps 11 | eps2png --png16m -resolution 300 linear_regression-1.eps 12 | ps2eps --loose --gsbbox < linear_regression-2.mps > linear_regression-2.eps 13 | eps2png --png16m -resolution 300 linear_regression-2.eps 14 | 15 | latex formula_shift.tex 16 | dvips formula_shift 17 | ps2eps --loose --gsbbox < formula_shift.ps > formula_shift.eps 18 | eps2png --pnggray -resolution 300 formula_shift.eps 19 | -------------------------------------------------------------------------------- /datetime/copyable.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (giantchen at gmail dot com) 7 | 8 | #ifndef MUDUO_BASE_COPYABLE_H 9 | #define MUDUO_BASE_COPYABLE_H 10 | 11 | namespace muduo 12 | { 13 | 14 | /// A tag class emphasises the objects are copyable. 15 | /// The empty base class optimization applies. 16 | /// Any derived class of copyable should be a value type. 17 | class copyable 18 | { 19 | }; 20 | 21 | }; 22 | 23 | #endif // MUDUO_BASE_COPYABLE_H 24 | -------------------------------------------------------------------------------- /datetime/formula_cumdays.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{amsmath} 3 | \begin{document} 4 | \pagestyle{empty} 5 | \[ 6 | \left\lfloor\frac{153m+2}{5}\right\rfloor 7 | \] 8 | \end{document} 9 | -------------------------------------------------------------------------------- /datetime/formula_cycles.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{amsmath} 3 | \begin{document} 4 | \pagestyle{empty} 5 | \[ 6 | p = \left\lfloor\frac{4x+3}{4n+1}\right\rfloor \quad 7 | b = \left\lfloor \frac{p(4n+1)}{4} \right\rfloor \quad 8 | d = x-b 9 | \] 10 | \end{document} 11 | -------------------------------------------------------------------------------- /datetime/formula_floors.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{amsmath} 3 | \begin{document} 4 | \pagestyle{empty} 5 | \[ 6 | \begin{array}{lcc} 7 | \lfloor f(0) \rfloor = 0 &\Rightarrow & 0 \le f(0) < 1 \\[1mm] 8 | \lfloor f(1) \rfloor = 31 &\Rightarrow & 31 \le f(1) < 32 \\[1mm] 9 | \lfloor f(2) \rfloor = 61 &\Rightarrow & 61 \le f(2) < 62 \\[1mm] 10 | \lfloor f(3) \rfloor = 92 &\Rightarrow & 92 \le f(3) < 93 \\ 11 | & \vdots & \\ 12 | \lfloor f(11) \rfloor = 337 &\Rightarrow & 337 \le f(11) < 338 13 | \end{array} 14 | \] 15 | \end{document} 16 | -------------------------------------------------------------------------------- /datetime/formula_linear_reg.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{amsmath} 3 | \begin{document} 4 | \pagestyle{empty} 5 | \begin{eqnarray*} 6 | \hat{a} &=& \frac{\sum_{i=1}^{n}(x_i-\bar{x})(y_i-\bar{y})}{\sum_{i=1}^{n}(x_i-\bar{x})^2} 7 | =\frac{n\sum_{i=1}^{n}x_i y_i - \sum_{i=1}^{n}x_i \sum_{i=1}^{n}y_i} 8 | {n\sum_{i=1}^{n}\left(x_i^2\right) - \big(\sum_{i=1}^{n}x_i\big)^2}\\ 9 | \hat{b} &=& \bar{y} - \hat{a}\bar{x} 10 | \end{eqnarray*} 11 | \end{document} 12 | -------------------------------------------------------------------------------- /datetime/formula_phases.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{amsmath} 3 | \begin{document} 4 | \pagestyle{empty} 5 | \begin{alignat*}{2} 6 | p&=0 &\hspace{65pt} 0 \le x & 4 | #include 5 | #ifdef __cpp_lib_string_view 6 | #include 7 | #endif 8 | 9 | namespace oop 10 | { 11 | 12 | class Digest 13 | { 14 | public: 15 | virtual ~Digest() {} 16 | virtual void update(const void* data, int len) = 0; 17 | #ifdef __cpp_lib_string_view 18 | void update(std::string_view str) 19 | { 20 | update(str.data(), str.length()); 21 | } 22 | #endif 23 | virtual std::string digest() = 0; 24 | virtual int length() const = 0; 25 | 26 | enum Type 27 | { 28 | SHA1 = 1, 29 | SHA256 = 2, 30 | MD5 = 5, 31 | }; 32 | static std::unique_ptr create(Type t); 33 | 34 | protected: 35 | Digest() {} 36 | 37 | private: 38 | Digest(const Digest&) = delete; 39 | void operator=(const Digest&) = delete; 40 | }; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /digest/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -x 4 | 5 | g++ DigestOOP.cc test_oop.cc -std=c++17 -lcrypto -o oop 6 | g++ DigestOOP2.cc test_oop.cc -std=c++17 -lcrypto -o oop2 7 | g++ DigestTMP.cc test_oop.cc -std=c++17 -lcrypto -o tmp 8 | g++ test_evp.cc -std=c++17 -lcrypto -o evp 9 | g++ test_evp2.cc -std=c++17 -lcrypto -o evp2 10 | g++ bench.cc DigestOOP.cc -std=c++17 -lbenchmark -lpthread -lcrypto -O2 -o bench 11 | 12 | -------------------------------------------------------------------------------- /digest/test_evp.cc: -------------------------------------------------------------------------------- 1 | #include "DigestEVP.h" 2 | 3 | void print(const std::string& d) 4 | { 5 | for (int i = 0; i < d.size(); ++i) 6 | { 7 | printf("%02x", (unsigned char)d[i]); 8 | } 9 | printf("\n"); 10 | } 11 | 12 | evp::Digest getDefaultDigest() 13 | { 14 | return evp::Digest(evp::Digest::SHA1); 15 | } 16 | 17 | int main(int argc, char* argv[]) 18 | { 19 | OpenSSL_add_all_digests(); 20 | 21 | evp::Digest md5(evp::Digest::MD5); 22 | print(md5.digest()); 23 | evp::Digest sha1(evp::Digest::SHA1); 24 | print(sha1.digest()); 25 | evp::Digest sha256(evp::Digest::SHA256); 26 | print(sha256.digest()); 27 | 28 | evp::Digest md = getDefaultDigest(); 29 | md.update("hello\n", 6); 30 | print(md.digest()); 31 | md = getDefaultDigest(); 32 | md = std::move(md); 33 | 34 | EVP_cleanup(); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /digest/test_oop.cc: -------------------------------------------------------------------------------- 1 | #include "DigestOOP.h" 2 | 3 | void print(const std::string& d) 4 | { 5 | for (int i = 0; i < d.size(); ++i) 6 | { 7 | printf("%02x", (unsigned char)d[i]); 8 | } 9 | printf("\n"); 10 | } 11 | 12 | int main(int argc, char* argv[]) 13 | { 14 | auto md5 = oop::Digest::create(oop::Digest::MD5); 15 | print(md5->digest()); 16 | auto sha1 = oop::Digest::create(oop::Digest::SHA1); 17 | print(sha1->digest()); 18 | auto sha256 = oop::Digest::create(oop::Digest::SHA256); 19 | print(sha256->digest()); 20 | } 21 | -------------------------------------------------------------------------------- /esort/README: -------------------------------------------------------------------------------- 1 | 2 | External sorting experiments 3 | 4 | sort00 ~ sort04, the standard sort benchmark, 10-byte key with 90-byte value, 100-byte per record. 5 | 6 | sort10 ~ sort12, sort 64-bit integers or doubles. 7 | 8 | 9 | -------------------------------------------------------------------------------- /esort/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -x 4 | 5 | CXXFLAGS="-O2 -g -Wall" 6 | export CXXFLAGS 7 | g++ -I .. $CXXFLAGS -o sort00 sort00.cc ../datetime/Timestamp.cc 8 | g++ -I .. $CXXFLAGS -o sort01 sort01.cc ../datetime/Timestamp.cc 9 | g++ -I .. $CXXFLAGS -o sort02 sort02.cc ../datetime/Timestamp.cc 10 | g++ -I .. $CXXFLAGS -o sort03 sort03.cc ../datetime/Timestamp.cc ../thread/Thread.cc ../thread/ThreadPool.cc ../thread/Exception.cc -lpthread 11 | g++ -I .. $CXXFLAGS -o sort04 sort04.cc ../datetime/Timestamp.cc ../thread/Thread.cc ../thread/ThreadPool.cc ../thread/Exception.cc -lpthread 12 | 13 | g++ -I .. $CXXFLAGS -o sort10 sort10.cc ../datetime/Timestamp.cc 14 | g++ -I .. $CXXFLAGS -o sort11 sort11.cc ../datetime/Timestamp.cc ../thread/Thread.cc ../thread/ThreadPool.cc ../thread/Exception.cc -lpthread 15 | g++ -I .. $CXXFLAGS -o sort12 sort12.cc ../datetime/Timestamp.cc ../thread/Thread.cc ../thread/ThreadPool.cc ../thread/Exception.cc -lpthread 16 | -------------------------------------------------------------------------------- /faketcp/Makefile: -------------------------------------------------------------------------------- 1 | CXXFLAGS=-g -Wall -pthread 2 | 3 | BINARIES=icmpecho rejectall acceptall discardall discardall2 echoall echoall2 connectmany 4 | 5 | all: $(BINARIES) 6 | 7 | icmpecho: icmpecho.cc faketcp.cc 8 | rejectall: rejectall.cc faketcp.cc 9 | acceptall: acceptall.cc faketcp.cc 10 | discardall: discardall.cc faketcp.cc 11 | discardall2: discardall2.cc faketcp.cc 12 | discardall2: CXXFLAGS += -std=c++0x 13 | echoall: echoall.cc faketcp.cc 14 | echoall2: echoall2.cc faketcp.cc 15 | echoall2: CXXFLAGS += -std=c++0x 16 | connectmany: connectmany.cc faketcp.cc 17 | 18 | $(BINARIES): 19 | g++ $(CXXFLAGS) $(LDFLAGS) $(filter %.cc,$^) -o $@ 20 | 21 | clean: 22 | rm -f $(BINARIES) 23 | 24 | -------------------------------------------------------------------------------- /faketcp/faketcp.h: -------------------------------------------------------------------------------- 1 | #include // std::swap 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include // inet_ntop 9 | #include 10 | 11 | struct SocketAddr 12 | { 13 | uint32_t saddr, daddr; 14 | uint16_t sport, dport; 15 | 16 | bool operator==(const SocketAddr& rhs) const 17 | { 18 | return saddr == rhs.saddr && daddr == rhs.daddr && sport == rhs.sport && dport == rhs.dport; 19 | } 20 | 21 | bool operator<(const SocketAddr& rhs) const 22 | { 23 | BOOST_STATIC_ASSERT(sizeof(SocketAddr) == 12); 24 | return memcmp(this, &rhs, sizeof(rhs)) < 0; 25 | } 26 | }; 27 | 28 | int tun_alloc(char dev[IFNAMSIZ], bool offload = false); 29 | uint16_t in_checksum(const void* buf, int len); 30 | 31 | void icmp_input(int fd, const void* input, const void* payload, int len); 32 | -------------------------------------------------------------------------------- /faketcp/net.pic: -------------------------------------------------------------------------------- 1 | .PS 2 | 3 | R: box "\fCrouter\fR" 4 | move 5 | A: box "\fCatom\fR" 6 | circle rad 0.02 at R.s filled 1 7 | circle rad 0.02 at A.s filled 1 8 | line from R.s down 0.4 "" ".1 " rjust 9 | line from A.s down 0.4 "" ".2 " rjust 10 | linethick = 2 11 | E: line from R.sw - (0.2, 0.4) to A.se - (-0.2, 0.4) "" "" "Ethernet" 12 | "10.0.0.0/24 " rjust at E.w 13 | .PE 14 | -------------------------------------------------------------------------------- /faketcp/tun.pic: -------------------------------------------------------------------------------- 1 | .PS 2 | 3 | R: box "\fCrouter\fR" 4 | move 5 | A: box "\fCatom\fR" 6 | F: box "\fIfaketcp\fR" at last box + (0, 1) 7 | 8 | circle rad 0.02 at R.s filled 1 9 | circle rad 0.02 at A.s filled 1 10 | line from R.s down 0.4 "" ".1 " rjust 11 | line from A.s down 0.4 "" ".2 " rjust 12 | 13 | circle rad 0.02 at F.e filled 1 14 | circle rad 0.02 at A.e filled 1 15 | line from F.e right 0.4 "" ".\fIX\fR " rjust 16 | line from A.e right 0.4 "" ".1 " rjust 17 | 18 | linethick = 2 19 | E: line from R.sw - (0.2, 0.4) to A.se - (-0.2, 0.4) "" "" "Ethernet" 20 | "10.0.0.0/24 " rjust at E.w 21 | T: line from F.ne + (0.4, 0.2) to A.se + (0.4, -0.2) " TUN" ljust 22 | "192.168.0.0/24" "" at T.n 23 | .PE 24 | -------------------------------------------------------------------------------- /java/bankqueue/WindowType.java: -------------------------------------------------------------------------------- 1 | package bankqueue; 2 | 3 | public enum WindowType { 4 | kNormal, kFast, kVip, kNumWindows 5 | } 6 | -------------------------------------------------------------------------------- /java/bankqueue/customer/Customer.java: -------------------------------------------------------------------------------- 1 | package bankqueue.customer; 2 | 3 | import bankqueue.Bank; 4 | 5 | public abstract class Customer { 6 | 7 | public final int id; 8 | public final int serviceTime; 9 | 10 | protected Customer(int id, int serviceTime) { 11 | this.id = id; 12 | this.serviceTime = serviceTime; 13 | } 14 | 15 | public String getTypeName() { 16 | return getClass().getSimpleName(); 17 | } 18 | 19 | public abstract boolean findSpareWindow(Bank bank); 20 | public abstract void gotoWindow(Bank bank); 21 | } 22 | -------------------------------------------------------------------------------- /java/bankqueue/customer/CustomerType.java: -------------------------------------------------------------------------------- 1 | package bankqueue.customer; 2 | 3 | public enum CustomerType { 4 | kNormal, kFast, kVip 5 | } 6 | -------------------------------------------------------------------------------- /java/bankqueue/customer/FastCustomer.java: -------------------------------------------------------------------------------- 1 | package bankqueue.customer; 2 | 3 | import bankqueue.Bank; 4 | import bankqueue.WindowType; 5 | 6 | public class FastCustomer extends Customer { 7 | 8 | public FastCustomer(int id, int serviceTime) { 9 | super(id, serviceTime); 10 | } 11 | 12 | @Override 13 | public boolean findSpareWindow(Bank bank) { 14 | return bank.hasSpareWindow(WindowType.kFast); 15 | } 16 | 17 | @Override 18 | public void gotoWindow(Bank bank) { 19 | assert bank.hasSpareWindow(WindowType.kFast); 20 | bank.serveAtWindow(this, WindowType.kFast); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /java/bankqueue/customer/NormalCustomer.java: -------------------------------------------------------------------------------- 1 | package bankqueue.customer; 2 | 3 | import bankqueue.Bank; 4 | import bankqueue.WindowType; 5 | 6 | public class NormalCustomer extends Customer { 7 | 8 | public NormalCustomer(int id, int serviceTime) { 9 | super(id, serviceTime); 10 | } 11 | 12 | @Override 13 | public boolean findSpareWindow(Bank bank) { 14 | return bank.hasAnySpareWindow(); 15 | } 16 | 17 | @Override 18 | public void gotoWindow(Bank bank) { 19 | if (bank.hasSpareWindow(WindowType.kNormal)) { 20 | bank.serveAtWindow(this, WindowType.kNormal); 21 | } else if (bank.hasSpareWindow(WindowType.kFast)) { 22 | bank.serveAtWindow(this, WindowType.kFast); 23 | } else if (bank.hasSpareWindow(WindowType.kVip)) { 24 | bank.serveAtWindow(this, WindowType.kVip); 25 | } else { 26 | assert false; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /java/bankqueue/customer/VipCustomer.java: -------------------------------------------------------------------------------- 1 | package bankqueue.customer; 2 | 3 | import bankqueue.Bank; 4 | import bankqueue.WindowType; 5 | 6 | public class VipCustomer extends Customer { 7 | 8 | public VipCustomer(int id, int serviceTime) { 9 | super(id, serviceTime); 10 | } 11 | 12 | @Override 13 | public boolean findSpareWindow(Bank bank) { 14 | return bank.hasSpareWindow(WindowType.kVip); 15 | } 16 | 17 | @Override 18 | public void gotoWindow(Bank bank) { 19 | assert bank.hasSpareWindow(WindowType.kVip); 20 | bank.serveAtWindow(this, WindowType.kVip); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /java/bankqueue/event/CustomerArriveEvent.java: -------------------------------------------------------------------------------- 1 | package bankqueue.event; 2 | 3 | import bankqueue.Bank; 4 | import bankqueue.customer.Customer; 5 | 6 | public class CustomerArriveEvent extends Event { 7 | 8 | private final Customer customer; 9 | private final Bank bank; 10 | 11 | public CustomerArriveEvent(int time, Customer customer, Bank bank) { 12 | super(time); 13 | this.customer = customer; 14 | this.bank = bank; 15 | } 16 | 17 | @Override 18 | public void happen(EventSimulator simulator) { 19 | assert simulator.getNow() == scheduledTime; 20 | 21 | bank.arrive(simulator.getNow(), customer); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /java/bankqueue/event/CustomerLeaveEvent.java: -------------------------------------------------------------------------------- 1 | package bankqueue.event; 2 | 3 | import bankqueue.Bank; 4 | import bankqueue.WindowType; 5 | import bankqueue.customer.Customer; 6 | 7 | public class CustomerLeaveEvent extends Event { 8 | 9 | private final Customer customer; 10 | private final Bank bank; 11 | private final WindowType type; 12 | 13 | public CustomerLeaveEvent(int time, Customer customer, Bank bank, WindowType type) { 14 | super(time); 15 | this.customer = customer; 16 | this.bank = bank; 17 | this.type = type; 18 | } 19 | 20 | @Override 21 | public void happen(EventSimulator simulator) { 22 | assert simulator.getNow() == scheduledTime; 23 | 24 | bank.leave(simulator.getNow(), customer, type); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /java/bankqueue/event/Event.java: -------------------------------------------------------------------------------- 1 | package bankqueue.event; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | public abstract class Event implements Comparable { 6 | 7 | private static AtomicInteger numEventsCreated = new AtomicInteger(); 8 | 9 | public final int scheduledTime; 10 | public final int tieBreaker; 11 | 12 | public Event(int time) { 13 | this.scheduledTime = time; 14 | this.tieBreaker = numEventsCreated.getAndIncrement(); 15 | } 16 | 17 | public int compareTo(Event rhs) { 18 | if (scheduledTime != rhs.scheduledTime) 19 | return scheduledTime - rhs.scheduledTime; 20 | else 21 | return tieBreaker - rhs.tieBreaker; 22 | } 23 | 24 | public abstract void happen(EventSimulator simulator); 25 | } 26 | -------------------------------------------------------------------------------- /java/bankqueue/event/EventSimulator.java: -------------------------------------------------------------------------------- 1 | package bankqueue.event; 2 | 3 | import java.util.PriorityQueue; 4 | 5 | public class EventSimulator { 6 | 7 | private int now = 0; 8 | private PriorityQueue queue = new PriorityQueue(); 9 | 10 | public int getNow() { 11 | return now; 12 | } 13 | 14 | public void addEvent(Event e) { 15 | queue.add(e); 16 | } 17 | 18 | public void run() { 19 | Event ev = queue.poll(); 20 | while (ev != null) { 21 | assert ev.scheduledTime >= now; 22 | now = ev.scheduledTime; 23 | ev.happen(this); 24 | ev = queue.poll(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /java/billing/BillCalculator.java: -------------------------------------------------------------------------------- 1 | package billing; 2 | 3 | public class BillCalculator { 4 | private final RuleFactory factory; 5 | 6 | public BillCalculator(String rulePath) { 7 | factory = new RuleFactory(rulePath); 8 | } 9 | 10 | public Money calculate(UserMonthUsage input) { 11 | Rule rule = factory.create("root"); 12 | return new Money(rule.getMoneyInPips(input)); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /java/billing/DataFields.java: -------------------------------------------------------------------------------- 1 | package billing; 2 | 3 | // FIXME: should be in groovy 4 | public class DataFields { 5 | 6 | public static enum UserField { 7 | kUserType, 8 | kJoinTime, 9 | kIsNewUser, 10 | kPackages, 11 | kSlips, 12 | kDaysServed, 13 | } 14 | 15 | public static enum SlipType { 16 | kPhoneCall, 17 | kShortMessage, 18 | kInternet, 19 | } 20 | 21 | public static enum UserType { 22 | kNormal, 23 | kVip; 24 | 25 | public String getRuleName() { 26 | return name().substring(1).toLowerCase() + "_user"; 27 | } 28 | } 29 | 30 | public static enum PackageType { 31 | kNormalUserPhoneCall, 32 | kNormalUserShortMessage, 33 | kNormalUserInternet, 34 | 35 | kVipUserPackage1, 36 | kVipUserPackage2, 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /java/billing/DefaultRule.java: -------------------------------------------------------------------------------- 1 | package billing; 2 | 3 | public class DefaultRule extends Rule { 4 | 5 | private final String name; 6 | 7 | public DefaultRule(String name) { 8 | this.name = name; 9 | } 10 | 11 | @Override 12 | public long getMoneyInPips(UserMonthUsage input) { 13 | throw new RuntimeException("Rule " + name + " not implemented"); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /java/billing/Rule.java: -------------------------------------------------------------------------------- 1 | package billing; 2 | 3 | public abstract class Rule implements Cloneable { 4 | 5 | protected RuleFactory factory; 6 | protected Object state; 7 | 8 | public void setFactory(RuleFactory factory) { 9 | this.factory = factory; 10 | } 11 | 12 | public void setState(Object state) { 13 | this.state = state; 14 | } 15 | 16 | @Override 17 | protected Object clone() { 18 | Class clazz = getClass(); 19 | Rule newRule = null; 20 | try { 21 | newRule = clazz.newInstance(); 22 | newRule.setFactory(factory); 23 | } catch (Exception e) { 24 | e.printStackTrace(); 25 | } 26 | return newRule; 27 | } 28 | 29 | public abstract long getMoneyInPips(UserMonthUsage input); 30 | } 31 | -------------------------------------------------------------------------------- /java/billing/Slip.java: -------------------------------------------------------------------------------- 1 | package billing; 2 | 3 | import org.joda.time.LocalDateTime; 4 | 5 | import billing.DataFields.SlipType; 6 | 7 | public class Slip { 8 | public final SlipType type; 9 | public final LocalDateTime time; 10 | // DateTimeZone zone; 11 | // Map data 12 | long data; 13 | 14 | public Slip(SlipType type, LocalDateTime time, long data) { 15 | this.type = type; 16 | this.time = time; 17 | this.data = data; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /java/groovy/billing/base_internet.groovy: -------------------------------------------------------------------------------- 1 | package billing; 2 | 3 | import static billing.DataFields.*; 4 | 5 | public class ShortMessageRule extends Rule { 6 | 7 | @Override 8 | long getMoneyInPips(UserMonthUsage input) { 9 | final long pipsPerKiloBytes = (Long)state; 10 | 11 | long result = 0; 12 | List slips = (List)input.get(UserField.kSlips); 13 | for (Slip slip : slips) { 14 | if (slip.type == SlipType.kInternet) { 15 | result += slip.data * pipsPerKiloBytes; 16 | } 17 | } 18 | 19 | return result; 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /java/groovy/billing/base_phone_call.groovy: -------------------------------------------------------------------------------- 1 | package billing; 2 | 3 | import static billing.DataFields.*; 4 | 5 | public class PhoneCallRule extends Rule { 6 | 7 | @Override 8 | long getMoneyInPips(UserMonthUsage input) { 9 | final long pipsPerMinute = (Long)state; 10 | 11 | long result = 0; 12 | List slips = (List)input.get(UserField.kSlips); 13 | for (Slip slip : slips) { 14 | if (slip.type == SlipType.kPhoneCall) { 15 | result += slip.data * pipsPerMinute; 16 | } 17 | } 18 | 19 | return result; 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /java/groovy/billing/base_short_message.groovy: -------------------------------------------------------------------------------- 1 | package billing; 2 | 3 | import static billing.DataFields.*; 4 | 5 | public class ShortMessageRule extends Rule { 6 | 7 | @Override 8 | long getMoneyInPips(UserMonthUsage input) { 9 | final long pipsPerMessage = (Long)state; 10 | 11 | long result = 0; 12 | List slips = (List)input.get(UserField.kSlips); 13 | for (Slip slip : slips) { 14 | if (slip.type == SlipType.kShortMessage) { 15 | result += slip.data * pipsPerMessage; 16 | } 17 | } 18 | 19 | return result; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /java/groovy/billing/normal_user.groovy: -------------------------------------------------------------------------------- 1 | package billing; 2 | 3 | import static billing.DataFields.*; 4 | 5 | public class NormalUserRule extends Rule { 6 | 7 | @Override 8 | long getMoneyInPips(UserMonthUsage input) { 9 | UserType type = (UserType)input.get(UserField.kUserType); 10 | assert type == UserType.kNormal; 11 | boolean isNew = input.getBoolean(UserField.kIsNewUser); 12 | if (isNew) { 13 | Rule newUser = factory.create(type.getRuleName()+"_newjoiner"); 14 | return newUser.getMoneyInPips(input); 15 | } else { 16 | Rule phoneCall = factory.create(type.getRuleName()+"_phone_call", 0L); 17 | Rule shortMessage = factory.create(type.getRuleName()+"_short_message", 0L); 18 | Rule internet = factory.create(type.getRuleName()+"_internet", 0L); 19 | long total = phoneCall.getMoneyInPips(input) + 20 | shortMessage.getMoneyInPips(input) + 21 | internet.getMoneyInPips(input); 22 | return total; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /java/groovy/billing/package_internet.groovy: -------------------------------------------------------------------------------- 1 | package billing; 2 | 3 | import static billing.DataFields.*; 4 | 5 | public class PackageInternetRule extends Rule { 6 | 7 | @Override 8 | long getMoneyInPips(UserMonthUsage input) { 9 | long[] parameters = (long[])state; 10 | long packagePips = parameters[0]; 11 | long noChargeKiloBytes = parameters[1]; 12 | long pipsPerKiloByte = parameters[2]; 13 | return calc(input, packagePips, noChargeKiloBytes, pipsPerKiloByte); 14 | } 15 | 16 | long calc(UserMonthUsage input, long packagePips, long noChargeKiloBytes, long pipsPerKiloByte) { 17 | Rule internet = factory.create("base_internet", pipsPerKiloByte); 18 | long fee = internet.getMoneyInPips(input); 19 | fee -= noChargeKiloBytes*pipsPerKiloByte; 20 | if (fee < 0) { 21 | fee = 0; 22 | } 23 | return fee + packagePips; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /java/groovy/billing/package_phone_call.groovy: -------------------------------------------------------------------------------- 1 | package billing; 2 | 3 | import static billing.DataFields.*; 4 | 5 | public class PackagePhoneCallRule extends Rule { 6 | 7 | @Override 8 | long getMoneyInPips(UserMonthUsage input) { 9 | long[] parameters = (long[])state; 10 | long packagePips = parameters[0]; 11 | long noChargeMinutes = parameters[1]; 12 | long pipsPhoneCallPerMinute = parameters[2]; 13 | return calc(input, packagePips, noChargeMinutes, pipsPhoneCallPerMinute); 14 | } 15 | 16 | long calc(UserMonthUsage input, long packagePips, long noChargeMinutes, long pipsPerMinute) { 17 | Rule phoneCall = factory.create("base_phone_call", pipsPerMinute); 18 | long fee = phoneCall.getMoneyInPips(input); 19 | fee -= noChargeMinutes*pipsPerMinute; 20 | if (fee < 0) { 21 | fee = 0; 22 | } 23 | return fee + packagePips; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /java/groovy/billing/package_short_message.groovy: -------------------------------------------------------------------------------- 1 | package billing; 2 | 3 | import static billing.DataFields.*; 4 | 5 | public class PackageShortMessageRule extends Rule { 6 | 7 | @Override 8 | long getMoneyInPips(UserMonthUsage input) { 9 | long[] parameters = (long[])state; 10 | long packagePips = parameters[0]; 11 | long noChargeMessages = parameters[1]; 12 | long pipsPerMessage = parameters[2]; 13 | return calc(input, packagePips, noChargeMessages, pipsPerMessage); 14 | } 15 | 16 | long calc(UserMonthUsage input, long packagePips, long noChargeMessages, long pipsPerMessage) { 17 | Rule messageRule = factory.create("base_short_message", pipsPerMessage); 18 | long fee = messageRule.getMoneyInPips(input); 19 | fee -= noChargeMessages*pipsPerMessage; 20 | if (fee < 0) { 21 | fee = 0; 22 | } 23 | return fee + packagePips; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /java/groovy/billing/root.groovy: -------------------------------------------------------------------------------- 1 | package billing; 2 | 3 | import static billing.DataFields.*; 4 | 5 | public class RootRule extends Rule { 6 | 7 | long getMoneyInPips(UserMonthUsage input) { 8 | UserType type = (UserType)input.get(UserField.kUserType); 9 | Rule rule = factory.create(type.getRuleName()); 10 | return rule.getMoneyInPips(input); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /java/groovy/billing/vip_user_newjoiner.groovy: -------------------------------------------------------------------------------- 1 | package billing; 2 | 3 | import static billing.DataFields.*; 4 | 5 | public class VipUserNewJoinRule extends Rule { 6 | public static final long kFreePhoneCallMinutes = 200; 7 | public static final long kFreeShortMessages = 200; 8 | public static final long kFreeInternetKiloBytes = 100*1000L; 9 | 10 | @Override 11 | long getMoneyInPips(UserMonthUsage input) { 12 | UserType type = (UserType)input.get(UserField.kUserType); 13 | assert type == UserType.kVip; 14 | boolean isNew = input.getBoolean(UserField.kIsNewUser); 15 | assert isNew; 16 | List packages = input.getPackages(); 17 | assert packages.isEmpty(); 18 | 19 | Rule rule = factory.create("vip_user_nopackage", 20 | [ kFreePhoneCallMinutes, kFreeShortMessages, kFreeInternetKiloBytes ]); 21 | return rule.getMoneyInPips(input); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /java/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | CLASSPATH=lib/junit-4.8.2.jar:\ 4 | lib/joda-time-1.6.2.jar:\ 5 | lib/groovy-1.7.10.jar:\ 6 | lib/asm-3.2.jar:\ 7 | lib/antlr-2.7.7.jar:\ 8 | ./bin 9 | 10 | export CLASSPATH 11 | mkdir bin 12 | javac -d bin billing/*.java billing/test/*.java 13 | java -ea org.junit.runner.JUnitCore billing.test.VipCustomerTest billing.test.NormalCustomerTest 14 | -------------------------------------------------------------------------------- /logging/LogFile_test.cc: -------------------------------------------------------------------------------- 1 | #include "LogFile.h" 2 | #include "Logging.h" 3 | 4 | boost::scoped_ptr g_logFile; 5 | 6 | void outputFunc(const char* msg, int len) 7 | { 8 | g_logFile->append(msg, len); 9 | } 10 | 11 | void flushFunc() 12 | { 13 | g_logFile->flush(); 14 | } 15 | 16 | int main(int argc, char* argv[]) 17 | { 18 | char name[256]; 19 | strncpy(name, argv[0], 256); 20 | g_logFile.reset(new muduo::LogFile(::basename(name), 256*1024)); 21 | muduo::Logger::setOutput(outputFunc); 22 | muduo::Logger::setFlush(flushFunc); 23 | 24 | muduo::string line = "1234567890 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 25 | 26 | for (int i = 0; i < 10000; ++i) 27 | { 28 | LOG_INFO << line; 29 | 30 | usleep(1000); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /logging/README: -------------------------------------------------------------------------------- 1 | This is an old & experimental version of logging library, 2 | please use the version in muduo/base. 3 | 4 | http://github.com/chenshuo/muduo -------------------------------------------------------------------------------- /pingpong/asio/README: -------------------------------------------------------------------------------- 1 | 2 | The following files are retrieved from 3 | http://asio.cvs.sourceforge.net/viewvc/asio/asio/src/tests/performance/ 4 | 5 | client.cpp 6 | server.cpp 7 | handler_allocator.hpp 8 | 9 | The author of them is Christopher M. Kohlhoff (chris at kohlhoff dot com). 10 | 11 | -------------------------------------------------------------------------------- /pingpong/asio/asio.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace asio 5 | { 6 | using namespace boost::asio; 7 | using boost::system::error_code; 8 | using boost::thread; 9 | } 10 | -------------------------------------------------------------------------------- /pingpong/asio/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | g++ -O2 -finline-limit=1000 server.cpp -o server -lpthread -lboost_thread -lboost_system 3 | g++ -O2 -finline-limit=1000 client.cpp -o client -lpthread -lboost_thread -lboost_system 4 | # g++ -O2 -finline-limit=1000 -I../asio-1.4.5/include server.cpp -o server145 -lpthread 5 | # g++ -O2 -finline-limit=1000 -I../asio-1.4.5/include client.cpp -o client145 -lpthread 6 | -------------------------------------------------------------------------------- /pingpong/asio/multiple_thread.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | killall server 4 | timeout=${timeout:-100} 5 | bufsize=${bufsize:-16384} 6 | 7 | for nosessions in 100 1000; do 8 | for nothreads in 1 2 3 4; do 9 | sleep 5 10 | echo "Bufsize: $bufsize Threads: $nothreads Sessions: $nosessions" 11 | ./server 0.0.0.0 55555 $nothreads $bufsize & srvpid=$! 12 | sleep 1 13 | ./client 127.0.0.1 55555 $nothreads $bufsize $nosessions $timeout 14 | kill -9 $srvpid 15 | done 16 | done 17 | -------------------------------------------------------------------------------- /pingpong/asio/single_thread.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | killall server 4 | timeout=${timeout:-100} 5 | bufsize=${bufsize:-16384} 6 | nothreads=1 7 | 8 | for nosessions in 1 10 100 1000 10000; do 9 | sleep 5 10 | echo "Bufsize: $bufsize Threads: $nothreads Sessions: $nosessions" 11 | taskset -c 1 ./server 0.0.0.0 55555 $nothreads $bufsize & srvpid=$! 12 | sleep 1 13 | taskset -c 2 ./client 127.0.0.1 55555 $nothreads $bufsize $nosessions $timeout 14 | kill -9 $srvpid 15 | done 16 | 17 | -------------------------------------------------------------------------------- /pingpong/libevent/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS+=-g -Wall -O2 2 | LDLIBS=-levent_core -Wl,--rpath -Wl,/usr/local/lib 3 | 4 | all: client server bench server-line-echo server-half-close 5 | 6 | clean: 7 | rm -f client server bench server-line-echo server-half-close 8 | 9 | .PHONY: all clean 10 | 11 | -------------------------------------------------------------------------------- /pingpong/libevent/single_thread.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | killall server 4 | timeout=${timeout:-100} 5 | bufsize=${bufsize:-16384} 6 | nothreads=1 7 | 8 | for nosessions in 1 10 100 1000 10000; do 9 | sleep 5 10 | echo "Bufsize: $bufsize Threads: $nothreads Sessions: $nosessions" 11 | taskset -c 1 ./server 2> /dev/null & srvpid=$! 12 | sleep 1 13 | taskset -c 2 ./client 9876 $bufsize $nosessions $timeout 14 | kill -9 $srvpid 15 | done 16 | 17 | -------------------------------------------------------------------------------- /pingpong/muduo/README: -------------------------------------------------------------------------------- 1 | Start scripts of ping pong test. 2 | 3 | Copy *.sh to muduo/../build/release, and run. 4 | -------------------------------------------------------------------------------- /pingpong/muduo/multiple_thread.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | killall pingpong_server 4 | timeout=${timeout:-100} 5 | bufsize=${bufsize:-16384} 6 | 7 | for nosessions in 100 1000; do 8 | for nothreads in 1 2 3 4; do 9 | sleep 5 10 | echo "Bufsize: $bufsize Threads: $nothreads Sessions: $nosessions" 11 | bin/pingpong_server 0.0.0.0 55555 $nothreads $bufsize & srvpid=$! 12 | sleep 1 13 | bin/pingpong_client 127.0.0.1 55555 $nothreads $bufsize $nosessions $timeout 14 | kill -9 $srvpid 15 | done 16 | done 17 | -------------------------------------------------------------------------------- /pingpong/muduo/single_thread.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | killall pingpong_server 4 | timeout=${timeout:-100} 5 | bufsize=${bufsize:-16384} 6 | nothreads=1 7 | 8 | for nosessions in 1 10 100 1000 10000; do 9 | sleep 5 10 | echo "Bufsize: $bufsize Threads: $nothreads Sessions: $nosessions" 11 | taskset -c 1 bin/pingpong_server 0.0.0.0 33333 $nothreads $bufsize & srvpid=$! 12 | sleep 1 13 | taskset -c 2 bin/pingpong_client 127.0.0.1 33333 $nothreads $bufsize $nosessions $timeout 14 | kill -9 $srvpid 15 | done 16 | 17 | -------------------------------------------------------------------------------- /protobuf/Makefile: -------------------------------------------------------------------------------- 1 | LIBDIR=/usr/local/lib 2 | 3 | CXXFLAGS=-g -Wall -O0 -pthread 4 | LDFLAGS=-lprotobuf -lz -lpthread -Wl,-rpath -Wl,$(LIBDIR) 5 | 6 | BINARIES=codec_test descriptor_test dispatcher_lite dispatcher 7 | TARGETS=$(BINARIES) 8 | 9 | # comment out following line if you have boost installed 10 | TARGETS=codec_test descriptor_test 11 | 12 | all: $(TARGETS) 13 | 14 | whole: $(BINARIES) 15 | 16 | codec_test: query.pb.h query.pb.cc codec.h codec_test.cc 17 | 18 | descriptor_test: query.pb.h query.pb.cc codec.h descriptor_test.cc 19 | 20 | dispatcher_lite: query.pb.h query.pb.cc dispatcher_lite.cc 21 | 22 | dispatcher: query.pb.h query.pb.cc dispatcher.cc 23 | 24 | $(BINARIES): 25 | g++ $(CXXFLAGS) $(filter %.cc,$^) -o $@ $(LDFLAGS) 26 | 27 | query.pb.h query.pb.cc: query.proto 28 | protoc --cpp_out . $< 29 | 30 | test: codec_test 31 | ./codec_test 32 | 33 | clean: 34 | rm -f query.pb.* 35 | rm -f $(BINARIES) 36 | 37 | -------------------------------------------------------------------------------- /protobuf/query.proto: -------------------------------------------------------------------------------- 1 | package muduo; 2 | 3 | option java_package = "muduo.codec.tests"; 4 | option java_outer_classname = "QueryProtos"; 5 | 6 | message Query { 7 | required int64 id = 1; 8 | required string questioner = 2; 9 | 10 | repeated string question = 3; 11 | } 12 | 13 | message Answer { 14 | required int64 id = 1; 15 | required string questioner = 2; 16 | required string answerer = 3; 17 | 18 | repeated string solution = 4; 19 | } 20 | 21 | message Empty { 22 | optional int32 id = 1; 23 | } 24 | -------------------------------------------------------------------------------- /protorpc/README: -------------------------------------------------------------------------------- 1 | Muduo Protorpc for Java has moved to 2 | http://github.com/chenshuo/muduo-protorpc 3 | -------------------------------------------------------------------------------- /protorpc/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | mkdir -p bin 3 | javac -extdirs lib -d bin echo/*.java 4 | -------------------------------------------------------------------------------- /protorpc/echo.proto: -------------------------------------------------------------------------------- 1 | package echo; 2 | //option py_generic_services = true; 3 | //option cc_generic_services = true; 4 | option java_generic_services = true; 5 | option java_package = "echo"; 6 | option java_outer_classname = "EchoProto"; 7 | 8 | message EchoRequest { 9 | required string payload = 1; 10 | } 11 | 12 | message EchoResponse { 13 | required string payload = 2; 14 | } 15 | 16 | service EchoService { 17 | rpc Echo (EchoRequest) returns (EchoResponse); 18 | } 19 | 20 | -------------------------------------------------------------------------------- /protorpc/echo/EchoServer.java: -------------------------------------------------------------------------------- 1 | package echo; 2 | 3 | import com.google.protobuf.RpcCallback; 4 | import com.google.protobuf.RpcController; 5 | 6 | import echo.EchoProto.EchoRequest; 7 | import echo.EchoProto.EchoResponse; 8 | import echo.EchoProto.EchoService.Interface; 9 | import muduo.rpc.RpcServer; 10 | 11 | public class EchoServer { 12 | 13 | public static void main(String[] args) { 14 | RpcServer server = new RpcServer(); 15 | server.registerService(EchoProto.EchoService.newReflectiveService(new Interface() { 16 | @Override 17 | public void echo(RpcController controller, EchoRequest request, RpcCallback done) { 18 | done.run(EchoResponse.newBuilder().setPayload(request.getPayload()).build()); 19 | } 20 | })); 21 | server.start(8888); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /protorpc/muduo/rpc/NewChannelCallback.java: -------------------------------------------------------------------------------- 1 | package muduo.rpc; 2 | 3 | public interface NewChannelCallback { 4 | 5 | public abstract void run(RpcChannel channel); 6 | } 7 | -------------------------------------------------------------------------------- /protorpc/rpc.proto: -------------------------------------------------------------------------------- 1 | package muduo; 2 | option java_package = "muduo.rpc.proto"; 3 | option java_outer_classname = "RpcProto"; 4 | 5 | enum MessageType 6 | { 7 | REQUEST = 1; 8 | RESPONSE = 2; 9 | ERROR = 3; 10 | } 11 | 12 | enum ErrorCode 13 | { 14 | WRONG_PROTO = 1; 15 | NO_SERVICE = 2; 16 | NO_METHOD = 3; 17 | INVALID_REQUEST = 4; 18 | INVALID_RESPONSE = 5; 19 | } 20 | 21 | message RpcMessage 22 | { 23 | required MessageType type = 1; 24 | required fixed64 id = 2; 25 | 26 | optional string service = 3; 27 | optional string method = 4; 28 | optional bytes request = 5; 29 | 30 | optional bytes response = 6; 31 | 32 | optional ErrorCode error = 7; 33 | } 34 | -------------------------------------------------------------------------------- /protorpc/run_client.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | java -ea -server -Djava.ext.dirs=lib -cp bin echo.EchoClient $1 3 | -------------------------------------------------------------------------------- /protorpc/run_server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | java -ea -server -Djava.ext.dirs=lib -cp bin echo.EchoServer 3 | -------------------------------------------------------------------------------- /protorpc/sudoku.proto: -------------------------------------------------------------------------------- 1 | package sudoku; 2 | option cc_generic_services = true; 3 | option java_generic_services = true; 4 | option py_generic_services = true; 5 | 6 | message SudokuRequest { 7 | required string checkerboard = 1; 8 | } 9 | 10 | message SudokuResponse { 11 | optional bool solved = 1 [default=false]; 12 | optional string checkerboard = 2; 13 | } 14 | 15 | service SudokuService { 16 | rpc Solve (SudokuRequest) returns (SudokuResponse); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /protorpc/sudoku/Server.java: -------------------------------------------------------------------------------- 1 | package sudoku; 2 | 3 | import muduo.rpc.NewChannelCallback; 4 | import muduo.rpc.RpcChannel; 5 | import muduo.rpc.RpcServer; 6 | 7 | public class Server { 8 | 9 | public static void main(String[] args) { 10 | RpcServer server = new RpcServer(); 11 | server.registerService(Sudoku.SudokuService.newReflectiveService(new SudokuImpl())); 12 | server.setNewChannelCallback(new NewChannelCallback() { 13 | 14 | @Override 15 | public void run(RpcChannel channel) { 16 | // TODO call client 17 | 18 | } 19 | }); 20 | server.start(9981); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /protorpc/sudoku/SudokuImpl.java: -------------------------------------------------------------------------------- 1 | package sudoku; 2 | 3 | import sudoku.Sudoku.SudokuRequest; 4 | import sudoku.Sudoku.SudokuResponse; 5 | import sudoku.Sudoku.SudokuService.Interface; 6 | 7 | import com.google.protobuf.RpcCallback; 8 | import com.google.protobuf.RpcController; 9 | 10 | public class SudokuImpl implements Interface { 11 | 12 | @Override 13 | public void solve(RpcController controller, SudokuRequest request, 14 | RpcCallback done) { 15 | SudokuResponse resp = SudokuResponse.newBuilder() 16 | .setSolved(true).setCheckerboard("12345").build(); 17 | done.run(resp); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /puzzle/poker/bench.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import time 4 | import poker, poker2, generate 5 | 6 | if __name__ == '__main__': 7 | 8 | start = time.time() 9 | max1 = max(generate.gen(5)) 10 | elapsed = time.time() - start 11 | print ("%.4f" % (elapsed)), max1 12 | 13 | start = time.time() 14 | max2 = max(generate.gen(5), key=poker.score) 15 | elapsed = time.time() - start 16 | print ("%.4f" % (elapsed)), max2 17 | 18 | start = time.time() 19 | max3 = max(generate.gen(5), key=poker2.score2) 20 | elapsed = time.time() - start 21 | print ("%.4f" % (elapsed)), max3 22 | 23 | -------------------------------------------------------------------------------- /puzzle/poker/generate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import itertools 4 | import poker 5 | 6 | def gen(num): 7 | cards = [] 8 | ranks = '23456789TJQKA' 9 | for rank in reversed(ranks): 10 | for suit in 'SHDC': 11 | cards.append(rank + suit) 12 | return itertools.combinations(cards, num) 13 | 14 | if __name__ == '__main__': 15 | scores = [] 16 | for hand in gen(5): 17 | scores.append((poker.score(hand), " ".join(hand))) 18 | scores.sort(reverse=True) 19 | for s in scores: 20 | print s 21 | -------------------------------------------------------------------------------- /python/echo-fork.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from SocketServer import BaseRequestHandler, TCPServer 4 | from SocketServer import ForkingTCPServer, ThreadingTCPServer 5 | 6 | class EchoHandler(BaseRequestHandler): 7 | def handle(self): 8 | print "got connection from", self.client_address 9 | while True: 10 | data = self.request.recv(4096) 11 | if data: 12 | sent = self.request.send(data) # sendall? 13 | else: 14 | print "disconnect", self.client_address 15 | self.request.close() 16 | break 17 | 18 | if __name__ == "__main__": 19 | listen_address = ("0.0.0.0", 2007) 20 | server = ForkingTCPServer(listen_address, EchoHandler) 21 | server.serve_forever() 22 | -------------------------------------------------------------------------------- /python/echo-iterative.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import socket 4 | 5 | def handle(client_socket, client_address): 6 | while True: 7 | data = client_socket.recv(4096) 8 | if data: 9 | sent = client_socket.send(data) # sendall? 10 | else: 11 | print "disconnect", client_address 12 | client_socket.close() 13 | break 14 | 15 | if __name__ == "__main__": 16 | listen_address = ("0.0.0.0", 2007) 17 | server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 18 | server_socket.bind(listen_address) 19 | server_socket.listen(5) 20 | 21 | while True: 22 | (client_socket, client_address) = server_socket.accept() 23 | print "got connection from", client_address 24 | handle(client_socket, client_address) 25 | -------------------------------------------------------------------------------- /python/echo-single.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from SocketServer import BaseRequestHandler, TCPServer 4 | from SocketServer import ForkingTCPServer, ThreadingTCPServer 5 | 6 | class EchoHandler(BaseRequestHandler): 7 | def handle(self): 8 | print "got connection from", self.client_address 9 | while True: 10 | data = self.request.recv(4096) 11 | if data: 12 | sent = self.request.send(data) # sendall? 13 | else: 14 | print "disconnect", self.client_address 15 | self.request.close() 16 | break 17 | 18 | if __name__ == "__main__": 19 | listen_address = ("0.0.0.0", 2007) 20 | server = TCPServer(listen_address, EchoHandler) 21 | server.serve_forever() 22 | -------------------------------------------------------------------------------- /python/echo-thread.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from SocketServer import BaseRequestHandler, TCPServer 4 | from SocketServer import ForkingTCPServer, ThreadingTCPServer 5 | 6 | class EchoHandler(BaseRequestHandler): 7 | def handle(self): 8 | print "got connection from", self.client_address 9 | while True: 10 | data = self.request.recv(4096) 11 | if data: 12 | sent = self.request.send(data) # sendall? 13 | else: 14 | print "disconnect", self.client_address 15 | self.request.close() 16 | break 17 | 18 | if __name__ == "__main__": 19 | listen_address = ("0.0.0.0", 2007) 20 | server = ThreadingTCPServer(listen_address, EchoHandler) 21 | server.serve_forever() 22 | -------------------------------------------------------------------------------- /python/nqueens.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # http://code.activestate.com/recipes/576647-eight-queens-six-lines/ 4 | 5 | from itertools import permutations 6 | 7 | N = 8 8 | for rows in permutations(range(N)): 9 | if (N == len(set(rows[i]-i for i in range(N))) # Diagonal 10 | == len(set(rows[i]+i for i in range(N)))): # Anti-diagonal 11 | print rows 12 | -------------------------------------------------------------------------------- /python/self-connect.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import errno 4 | import socket 5 | import sys 6 | import time 7 | 8 | if len(sys.argv) < 2: 9 | print "Usage: %s port" % sys.argv[0] 10 | print "port should in net.ipv4.ip_local_port_range" 11 | else: 12 | port = int(sys.argv[1]) 13 | for i in range(65536): 14 | try: 15 | sock = socket.create_connection(('localhost', port)) 16 | print "connected", sock.getsockname(), sock.getpeername() 17 | time.sleep(60*60) 18 | except socket.error, e: 19 | if e.errno != errno.ECONNREFUSED: 20 | break 21 | 22 | 23 | -------------------------------------------------------------------------------- /reactor/.gitignore: -------------------------------------------------------------------------------- 1 | test[1-9] 2 | test[1-9][0-9] 3 | -------------------------------------------------------------------------------- /reactor/Makefile: -------------------------------------------------------------------------------- 1 | SUBDIRS = s00 s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 2 | 3 | all: $(SUBDIRS) 4 | 5 | clean: 6 | for d in $(SUBDIRS); do cd $$d && make clean && cd ..; done 7 | 8 | $(SUBDIRS): 9 | cd $@ && make 10 | 11 | .PHONY: all clean $(SUBDIRS) 12 | -------------------------------------------------------------------------------- /reactor/mkdiff.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | diff_a_file() 4 | { 5 | diff $1 $2 -q |grep differ |grep -v Makefile|awk '{\ 6 | split($2, old, "/"); \ 7 | split($4, new, "/"); \ 8 | print "diff -U200", $2, $4, "| awk \" NR>3 {print}\" >", new[1]"-"old[1]"-"new[2]".diff"}' 9 | echo 10 | } 11 | 12 | diff_a_file s00 s01 13 | diff_a_file s01 s02 14 | diff_a_file s02 s03 15 | diff_a_file s03 s04 16 | diff_a_file s04 s05 17 | diff_a_file s05 s06 18 | diff_a_file s06 s07 19 | diff_a_file s07 s08 20 | diff_a_file s08 s09 21 | diff_a_file s09 s10 22 | diff_a_file s10 s11 23 | diff_a_file s11 s12 24 | diff_a_file s12 s13 25 | -------------------------------------------------------------------------------- /reactor/reactor.mk: -------------------------------------------------------------------------------- 1 | CXXFLAGS = -O0 -g -Wall -I ../.. -pthread 2 | LDFLAGS = -lpthread 3 | BASE_SRC = ../../logging/Logging.cc ../../logging/LogStream.cc ../../thread/Thread.cc ../../datetime/Timestamp.cc 4 | 5 | $(BINARIES): 6 | g++ $(CXXFLAGS) -o $@ $(LIB_SRC) $(BASE_SRC) $(filter %.cc,$^) $(LDFLAGS) 7 | 8 | clean: 9 | rm -f $(BINARIES) core 10 | 11 | -------------------------------------------------------------------------------- /reactor/reactor_lib.mk: -------------------------------------------------------------------------------- 1 | CXXFLAGS = -O0 -g -Wall -I ../.. -pthread 2 | LDFLAGS = -lpthread -lmuduo -L. 3 | BASE_SRC = ../../logging/Logging.cc ../../logging/LogStream.cc ../../thread/Thread.cc ../../datetime/Timestamp.cc 4 | MUDUO_SRC = $(notdir $(LIB_SRC) $(BASE_SRC)) 5 | OBJS = $(patsubst %.cc,%.o,$(MUDUO_SRC)) 6 | 7 | libmuduo.a: $(BASE_SRC) $(LIB_SRC) 8 | g++ $(CXXFLAGS) -c $^ 9 | ar rcs $@ $(OBJS) 10 | 11 | $(BINARIES): libmuduo.a 12 | g++ $(CXXFLAGS) -o $@ $(filter %.cc,$^) $(LDFLAGS) 13 | 14 | clean: 15 | rm -f $(BINARIES) *.o *.a core 16 | 17 | -------------------------------------------------------------------------------- /reactor/s00/EventLoop.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_EVENTLOOP_H 9 | #define MUDUO_NET_EVENTLOOP_H 10 | 11 | #include "thread/Thread.h" 12 | 13 | namespace muduo 14 | { 15 | 16 | class EventLoop : boost::noncopyable 17 | { 18 | public: 19 | 20 | EventLoop(); 21 | ~EventLoop(); 22 | 23 | void loop(); 24 | 25 | void assertInLoopThread() 26 | { 27 | if (!isInLoopThread()) 28 | { 29 | abortNotInLoopThread(); 30 | } 31 | } 32 | 33 | bool isInLoopThread() const { return threadId_ == CurrentThread::tid(); } 34 | 35 | private: 36 | 37 | void abortNotInLoopThread(); 38 | 39 | bool looping_; /* atomic */ 40 | const pid_t threadId_; 41 | }; 42 | 43 | } 44 | 45 | #endif // MUDUO_NET_EVENTLOOP_H 46 | -------------------------------------------------------------------------------- /reactor/s00/Makefile: -------------------------------------------------------------------------------- 1 | LIB_SRC = EventLoop.cc 2 | BINARIES = test1 test2 3 | 4 | all: $(BINARIES) 5 | 6 | include ../reactor.mk 7 | 8 | test1: test1.cc 9 | test2: test2.cc 10 | -------------------------------------------------------------------------------- /reactor/s00/test1.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | #include 4 | 5 | void threadFunc() 6 | { 7 | printf("threadFunc(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | 10 | muduo::EventLoop loop; 11 | loop.loop(); 12 | } 13 | 14 | int main() 15 | { 16 | printf("main(): pid = %d, tid = %d\n", 17 | getpid(), muduo::CurrentThread::tid()); 18 | 19 | muduo::EventLoop loop; 20 | 21 | muduo::Thread thread(threadFunc); 22 | thread.start(); 23 | 24 | loop.loop(); 25 | pthread_exit(NULL); 26 | } 27 | -------------------------------------------------------------------------------- /reactor/s00/test2.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | 4 | muduo::EventLoop* g_loop; 5 | 6 | void threadFunc() 7 | { 8 | g_loop->loop(); 9 | } 10 | 11 | int main() 12 | { 13 | muduo::EventLoop loop; 14 | g_loop = &loop; 15 | muduo::Thread t(threadFunc); 16 | t.start(); 17 | t.join(); 18 | } 19 | -------------------------------------------------------------------------------- /reactor/s01/Makefile: -------------------------------------------------------------------------------- 1 | LIB_SRC = Channel.cc EventLoop.cc Poller.cc 2 | BINARIES = test1 test2 test3 3 | 4 | all: $(BINARIES) 5 | 6 | include ../reactor.mk 7 | 8 | test1: test1.cc 9 | test2: test2.cc 10 | test3: test3.cc 11 | -------------------------------------------------------------------------------- /reactor/s01/test1.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | #include 4 | 5 | void threadFunc() 6 | { 7 | printf("threadFunc(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | 10 | muduo::EventLoop loop; 11 | loop.loop(); 12 | } 13 | 14 | int main() 15 | { 16 | printf("main(): pid = %d, tid = %d\n", 17 | getpid(), muduo::CurrentThread::tid()); 18 | 19 | muduo::EventLoop loop; 20 | 21 | muduo::Thread thread(threadFunc); 22 | thread.start(); 23 | 24 | loop.loop(); 25 | pthread_exit(NULL); 26 | } 27 | -------------------------------------------------------------------------------- /reactor/s01/test2.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | 4 | muduo::EventLoop* g_loop; 5 | 6 | void threadFunc() 7 | { 8 | g_loop->loop(); 9 | } 10 | 11 | int main() 12 | { 13 | muduo::EventLoop loop; 14 | g_loop = &loop; 15 | muduo::Thread t(threadFunc); 16 | t.start(); 17 | t.join(); 18 | } 19 | -------------------------------------------------------------------------------- /reactor/s01/test3.cc: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | 4 | #include 5 | #include 6 | 7 | muduo::EventLoop* g_loop; 8 | 9 | void timeout() 10 | { 11 | printf("Timeout!\n"); 12 | g_loop->quit(); 13 | } 14 | 15 | int main() 16 | { 17 | muduo::EventLoop loop; 18 | g_loop = &loop; 19 | 20 | int timerfd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 21 | muduo::Channel channel(&loop, timerfd); 22 | channel.setReadCallback(timeout); 23 | channel.enableReading(); 24 | 25 | struct itimerspec howlong; 26 | bzero(&howlong, sizeof howlong); 27 | howlong.it_value.tv_sec = 5; 28 | ::timerfd_settime(timerfd, 0, &howlong, NULL); 29 | 30 | loop.loop(); 31 | 32 | ::close(timerfd); 33 | } 34 | -------------------------------------------------------------------------------- /reactor/s02/Callbacks.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_CALLBACKS_H 9 | #define MUDUO_NET_CALLBACKS_H 10 | 11 | #include 12 | #include 13 | 14 | #include "datetime/Timestamp.h" 15 | 16 | namespace muduo 17 | { 18 | 19 | // All client visible callbacks go here. 20 | 21 | typedef boost::function TimerCallback; 22 | 23 | } 24 | 25 | #endif // MUDUO_NET_CALLBACKS_H 26 | -------------------------------------------------------------------------------- /reactor/s02/Makefile: -------------------------------------------------------------------------------- 1 | LIB_SRC = Channel.cc EventLoop.cc Poller.cc Timer.cc TimerQueue.cc 2 | BINARIES = test1 test2 test3 test4 3 | 4 | all: $(BINARIES) 5 | 6 | include ../reactor.mk 7 | 8 | test1: test1.cc 9 | test2: test2.cc 10 | test3: test3.cc 11 | test4: test4.cc 12 | -------------------------------------------------------------------------------- /reactor/s02/Timer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Timer.h" 9 | 10 | using namespace muduo; 11 | 12 | void Timer::restart(Timestamp now) 13 | { 14 | if (repeat_) 15 | { 16 | expiration_ = addTime(now, interval_); 17 | } 18 | else 19 | { 20 | expiration_ = Timestamp::invalid(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /reactor/s02/TimerId.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_TIMERID_H 9 | #define MUDUO_NET_TIMERID_H 10 | 11 | #include "datetime/copyable.h" 12 | 13 | namespace muduo 14 | { 15 | 16 | class Timer; 17 | 18 | /// 19 | /// An opaque identifier, for canceling Timer. 20 | /// 21 | class TimerId : public muduo::copyable 22 | { 23 | public: 24 | explicit TimerId(Timer* timer) 25 | : value_(timer) 26 | { 27 | } 28 | 29 | // default copy-ctor, dtor and assignment are okay 30 | 31 | private: 32 | Timer* value_; 33 | }; 34 | 35 | } 36 | 37 | #endif // MUDUO_NET_TIMERID_H 38 | -------------------------------------------------------------------------------- /reactor/s02/test1.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | #include 4 | 5 | void threadFunc() 6 | { 7 | printf("threadFunc(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | 10 | muduo::EventLoop loop; 11 | loop.loop(); 12 | } 13 | 14 | int main() 15 | { 16 | printf("main(): pid = %d, tid = %d\n", 17 | getpid(), muduo::CurrentThread::tid()); 18 | 19 | muduo::EventLoop loop; 20 | 21 | muduo::Thread thread(threadFunc); 22 | thread.start(); 23 | 24 | loop.loop(); 25 | pthread_exit(NULL); 26 | } 27 | -------------------------------------------------------------------------------- /reactor/s02/test2.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | 4 | muduo::EventLoop* g_loop; 5 | 6 | void threadFunc() 7 | { 8 | g_loop->loop(); 9 | } 10 | 11 | int main() 12 | { 13 | muduo::EventLoop loop; 14 | g_loop = &loop; 15 | muduo::Thread t(threadFunc); 16 | t.start(); 17 | t.join(); 18 | } 19 | -------------------------------------------------------------------------------- /reactor/s02/test3.cc: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | 4 | #include 5 | #include 6 | 7 | muduo::EventLoop* g_loop; 8 | 9 | void timeout() 10 | { 11 | printf("Timeout!\n"); 12 | g_loop->quit(); 13 | } 14 | 15 | int main() 16 | { 17 | muduo::EventLoop loop; 18 | g_loop = &loop; 19 | 20 | int timerfd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 21 | muduo::Channel channel(&loop, timerfd); 22 | channel.setReadCallback(timeout); 23 | channel.enableReading(); 24 | 25 | struct itimerspec howlong; 26 | bzero(&howlong, sizeof howlong); 27 | howlong.it_value.tv_sec = 5; 28 | ::timerfd_settime(timerfd, 0, &howlong, NULL); 29 | 30 | loop.loop(); 31 | 32 | ::close(timerfd); 33 | } 34 | -------------------------------------------------------------------------------- /reactor/s03/Callbacks.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_CALLBACKS_H 9 | #define MUDUO_NET_CALLBACKS_H 10 | 11 | #include 12 | #include 13 | 14 | #include "datetime/Timestamp.h" 15 | 16 | namespace muduo 17 | { 18 | 19 | // All client visible callbacks go here. 20 | 21 | typedef boost::function TimerCallback; 22 | 23 | } 24 | 25 | #endif // MUDUO_NET_CALLBACKS_H 26 | -------------------------------------------------------------------------------- /reactor/s03/EventLoopThread.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_EVENTLOOPTHREAD_H 9 | #define MUDUO_NET_EVENTLOOPTHREAD_H 10 | 11 | #include "thread/Condition.h" 12 | #include "thread/Mutex.h" 13 | #include "thread/Thread.h" 14 | 15 | #include 16 | 17 | namespace muduo 18 | { 19 | 20 | class EventLoop; 21 | 22 | class EventLoopThread : boost::noncopyable 23 | { 24 | public: 25 | EventLoopThread(); 26 | ~EventLoopThread(); 27 | EventLoop* startLoop(); 28 | 29 | private: 30 | void threadFunc(); 31 | 32 | EventLoop* loop_; 33 | bool exiting_; 34 | Thread thread_; 35 | MutexLock mutex_; 36 | Condition cond_; 37 | }; 38 | 39 | } 40 | 41 | #endif // MUDUO_NET_EVENTLOOPTHREAD_H 42 | 43 | -------------------------------------------------------------------------------- /reactor/s03/Makefile: -------------------------------------------------------------------------------- 1 | LIB_SRC = Channel.cc EventLoop.cc EventLoopThread.cc Poller.cc Timer.cc TimerQueue.cc 2 | BINARIES = test1 test2 test3 test4 test5 test6 3 | 4 | all: $(BINARIES) 5 | 6 | include ../reactor.mk 7 | 8 | test1: test1.cc 9 | test2: test2.cc 10 | test3: test3.cc 11 | test4: test4.cc 12 | test5: test5.cc 13 | test6: test6.cc 14 | -------------------------------------------------------------------------------- /reactor/s03/Timer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Timer.h" 9 | 10 | using namespace muduo; 11 | 12 | void Timer::restart(Timestamp now) 13 | { 14 | if (repeat_) 15 | { 16 | expiration_ = addTime(now, interval_); 17 | } 18 | else 19 | { 20 | expiration_ = Timestamp::invalid(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /reactor/s03/TimerId.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_TIMERID_H 9 | #define MUDUO_NET_TIMERID_H 10 | 11 | #include "datetime/copyable.h" 12 | 13 | namespace muduo 14 | { 15 | 16 | class Timer; 17 | 18 | /// 19 | /// An opaque identifier, for canceling Timer. 20 | /// 21 | class TimerId : public muduo::copyable 22 | { 23 | public: 24 | explicit TimerId(Timer* timer) 25 | : value_(timer) 26 | { 27 | } 28 | 29 | // default copy-ctor, dtor and assignment are okay 30 | 31 | private: 32 | Timer* value_; 33 | }; 34 | 35 | } 36 | 37 | #endif // MUDUO_NET_TIMERID_H 38 | -------------------------------------------------------------------------------- /reactor/s03/test1.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | #include 4 | 5 | void threadFunc() 6 | { 7 | printf("threadFunc(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | 10 | muduo::EventLoop loop; 11 | loop.loop(); 12 | } 13 | 14 | int main() 15 | { 16 | printf("main(): pid = %d, tid = %d\n", 17 | getpid(), muduo::CurrentThread::tid()); 18 | 19 | muduo::EventLoop loop; 20 | 21 | muduo::Thread thread(threadFunc); 22 | thread.start(); 23 | 24 | loop.loop(); 25 | pthread_exit(NULL); 26 | } 27 | -------------------------------------------------------------------------------- /reactor/s03/test2.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | 4 | muduo::EventLoop* g_loop; 5 | 6 | void threadFunc() 7 | { 8 | g_loop->loop(); 9 | } 10 | 11 | int main() 12 | { 13 | muduo::EventLoop loop; 14 | g_loop = &loop; 15 | muduo::Thread t(threadFunc); 16 | t.start(); 17 | t.join(); 18 | } 19 | -------------------------------------------------------------------------------- /reactor/s03/test3.cc: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | 4 | #include 5 | #include 6 | 7 | muduo::EventLoop* g_loop; 8 | 9 | void timeout() 10 | { 11 | printf("Timeout!\n"); 12 | g_loop->quit(); 13 | } 14 | 15 | int main() 16 | { 17 | muduo::EventLoop loop; 18 | g_loop = &loop; 19 | 20 | int timerfd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 21 | muduo::Channel channel(&loop, timerfd); 22 | channel.setReadCallback(timeout); 23 | channel.enableReading(); 24 | 25 | struct itimerspec howlong; 26 | bzero(&howlong, sizeof howlong); 27 | howlong.it_value.tv_sec = 5; 28 | ::timerfd_settime(timerfd, 0, &howlong, NULL); 29 | 30 | loop.loop(); 31 | 32 | ::close(timerfd); 33 | } 34 | -------------------------------------------------------------------------------- /reactor/s03/test5.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include 3 | 4 | muduo::EventLoop* g_loop; 5 | int g_flag = 0; 6 | 7 | void run4() 8 | { 9 | printf("run4(): pid = %d, flag = %d\n", getpid(), g_flag); 10 | g_loop->quit(); 11 | } 12 | 13 | void run3() 14 | { 15 | printf("run3(): pid = %d, flag = %d\n", getpid(), g_flag); 16 | g_loop->runAfter(3, run4); 17 | g_flag = 3; 18 | } 19 | 20 | void run2() 21 | { 22 | printf("run2(): pid = %d, flag = %d\n", getpid(), g_flag); 23 | g_loop->queueInLoop(run3); 24 | } 25 | 26 | void run1() 27 | { 28 | g_flag = 1; 29 | printf("run1(): pid = %d, flag = %d\n", getpid(), g_flag); 30 | g_loop->runInLoop(run2); 31 | g_flag = 2; 32 | } 33 | 34 | int main() 35 | { 36 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 37 | 38 | muduo::EventLoop loop; 39 | g_loop = &loop; 40 | 41 | loop.runAfter(2, run1); 42 | loop.loop(); 43 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 44 | } 45 | -------------------------------------------------------------------------------- /reactor/s03/test6.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "EventLoopThread.h" 3 | #include 4 | 5 | void runInThread() 6 | { 7 | printf("runInThread(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | } 10 | 11 | int main() 12 | { 13 | printf("main(): pid = %d, tid = %d\n", 14 | getpid(), muduo::CurrentThread::tid()); 15 | 16 | muduo::EventLoopThread loopThread; 17 | muduo::EventLoop* loop = loopThread.startLoop(); 18 | loop->runInLoop(runInThread); 19 | sleep(1); 20 | loop->runAfter(2, runInThread); 21 | sleep(3); 22 | loop->quit(); 23 | 24 | printf("exit main().\n"); 25 | } 26 | -------------------------------------------------------------------------------- /reactor/s04/Callbacks.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_CALLBACKS_H 9 | #define MUDUO_NET_CALLBACKS_H 10 | 11 | #include 12 | #include 13 | 14 | #include "datetime/Timestamp.h" 15 | 16 | namespace muduo 17 | { 18 | 19 | // All client visible callbacks go here. 20 | 21 | typedef boost::function TimerCallback; 22 | 23 | } 24 | 25 | #endif // MUDUO_NET_CALLBACKS_H 26 | -------------------------------------------------------------------------------- /reactor/s04/EventLoopThread.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_EVENTLOOPTHREAD_H 9 | #define MUDUO_NET_EVENTLOOPTHREAD_H 10 | 11 | #include "thread/Condition.h" 12 | #include "thread/Mutex.h" 13 | #include "thread/Thread.h" 14 | 15 | #include 16 | 17 | namespace muduo 18 | { 19 | 20 | class EventLoop; 21 | 22 | class EventLoopThread : boost::noncopyable 23 | { 24 | public: 25 | EventLoopThread(); 26 | ~EventLoopThread(); 27 | EventLoop* startLoop(); 28 | 29 | private: 30 | void threadFunc(); 31 | 32 | EventLoop* loop_; 33 | bool exiting_; 34 | Thread thread_; 35 | MutexLock mutex_; 36 | Condition cond_; 37 | }; 38 | 39 | } 40 | 41 | #endif // MUDUO_NET_EVENTLOOPTHREAD_H 42 | 43 | -------------------------------------------------------------------------------- /reactor/s04/Makefile: -------------------------------------------------------------------------------- 1 | LIB_SRC = \ 2 | Acceptor.cc \ 3 | Channel.cc \ 4 | EventLoop.cc \ 5 | EventLoopThread.cc \ 6 | InetAddress.cc \ 7 | Poller.cc \ 8 | Socket.cc \ 9 | SocketsOps.cc \ 10 | Timer.cc \ 11 | TimerQueue.cc 12 | 13 | BINARIES = test1 test2 test3 test4 test5 test6 test7 14 | 15 | all: $(BINARIES) 16 | 17 | include ../reactor_lib.mk 18 | 19 | test1: test1.cc 20 | test2: test2.cc 21 | test3: test3.cc 22 | test4: test4.cc 23 | test5: test5.cc 24 | test6: test6.cc 25 | test7: test7.cc 26 | -------------------------------------------------------------------------------- /reactor/s04/Timer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Timer.h" 9 | 10 | using namespace muduo; 11 | 12 | void Timer::restart(Timestamp now) 13 | { 14 | if (repeat_) 15 | { 16 | expiration_ = addTime(now, interval_); 17 | } 18 | else 19 | { 20 | expiration_ = Timestamp::invalid(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /reactor/s04/TimerId.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_TIMERID_H 9 | #define MUDUO_NET_TIMERID_H 10 | 11 | #include "datetime/copyable.h" 12 | 13 | namespace muduo 14 | { 15 | 16 | class Timer; 17 | 18 | /// 19 | /// An opaque identifier, for canceling Timer. 20 | /// 21 | class TimerId : public muduo::copyable 22 | { 23 | public: 24 | explicit TimerId(Timer* timer) 25 | : value_(timer) 26 | { 27 | } 28 | 29 | // default copy-ctor, dtor and assignment are okay 30 | 31 | private: 32 | Timer* value_; 33 | }; 34 | 35 | } 36 | 37 | #endif // MUDUO_NET_TIMERID_H 38 | -------------------------------------------------------------------------------- /reactor/s04/test1.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | #include 4 | 5 | void threadFunc() 6 | { 7 | printf("threadFunc(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | 10 | muduo::EventLoop loop; 11 | loop.loop(); 12 | } 13 | 14 | int main() 15 | { 16 | printf("main(): pid = %d, tid = %d\n", 17 | getpid(), muduo::CurrentThread::tid()); 18 | 19 | muduo::EventLoop loop; 20 | 21 | muduo::Thread thread(threadFunc); 22 | thread.start(); 23 | 24 | loop.loop(); 25 | pthread_exit(NULL); 26 | } 27 | -------------------------------------------------------------------------------- /reactor/s04/test2.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | 4 | muduo::EventLoop* g_loop; 5 | 6 | void threadFunc() 7 | { 8 | g_loop->loop(); 9 | } 10 | 11 | int main() 12 | { 13 | muduo::EventLoop loop; 14 | g_loop = &loop; 15 | muduo::Thread t(threadFunc); 16 | t.start(); 17 | t.join(); 18 | } 19 | -------------------------------------------------------------------------------- /reactor/s04/test3.cc: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | 4 | #include 5 | #include 6 | 7 | muduo::EventLoop* g_loop; 8 | 9 | void timeout() 10 | { 11 | printf("Timeout!\n"); 12 | g_loop->quit(); 13 | } 14 | 15 | int main() 16 | { 17 | muduo::EventLoop loop; 18 | g_loop = &loop; 19 | 20 | int timerfd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 21 | muduo::Channel channel(&loop, timerfd); 22 | channel.setReadCallback(timeout); 23 | channel.enableReading(); 24 | 25 | struct itimerspec howlong; 26 | bzero(&howlong, sizeof howlong); 27 | howlong.it_value.tv_sec = 5; 28 | ::timerfd_settime(timerfd, 0, &howlong, NULL); 29 | 30 | loop.loop(); 31 | 32 | ::close(timerfd); 33 | } 34 | -------------------------------------------------------------------------------- /reactor/s04/test5.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include 3 | 4 | muduo::EventLoop* g_loop; 5 | int g_flag = 0; 6 | 7 | void run4() 8 | { 9 | printf("run4(): pid = %d, flag = %d\n", getpid(), g_flag); 10 | g_loop->quit(); 11 | } 12 | 13 | void run3() 14 | { 15 | printf("run3(): pid = %d, flag = %d\n", getpid(), g_flag); 16 | g_loop->runAfter(3, run4); 17 | g_flag = 3; 18 | } 19 | 20 | void run2() 21 | { 22 | printf("run2(): pid = %d, flag = %d\n", getpid(), g_flag); 23 | g_loop->queueInLoop(run3); 24 | } 25 | 26 | void run1() 27 | { 28 | g_flag = 1; 29 | printf("run1(): pid = %d, flag = %d\n", getpid(), g_flag); 30 | g_loop->runInLoop(run2); 31 | g_flag = 2; 32 | } 33 | 34 | int main() 35 | { 36 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 37 | 38 | muduo::EventLoop loop; 39 | g_loop = &loop; 40 | 41 | loop.runAfter(2, run1); 42 | loop.loop(); 43 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 44 | } 45 | -------------------------------------------------------------------------------- /reactor/s04/test6.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "EventLoopThread.h" 3 | #include 4 | 5 | void runInThread() 6 | { 7 | printf("runInThread(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | } 10 | 11 | int main() 12 | { 13 | printf("main(): pid = %d, tid = %d\n", 14 | getpid(), muduo::CurrentThread::tid()); 15 | 16 | muduo::EventLoopThread loopThread; 17 | muduo::EventLoop* loop = loopThread.startLoop(); 18 | loop->runInLoop(runInThread); 19 | sleep(1); 20 | loop->runAfter(2, runInThread); 21 | sleep(3); 22 | loop->quit(); 23 | 24 | printf("exit main().\n"); 25 | } 26 | -------------------------------------------------------------------------------- /reactor/s04/test7.cc: -------------------------------------------------------------------------------- 1 | #include "Acceptor.h" 2 | #include "EventLoop.h" 3 | #include "InetAddress.h" 4 | #include "SocketsOps.h" 5 | #include 6 | 7 | void newConnection(int sockfd, const muduo::InetAddress& peerAddr) 8 | { 9 | printf("newConnection(): accepted a new connection from %s\n", 10 | peerAddr.toHostPort().c_str()); 11 | ::write(sockfd, "How are you?\n", 13); 12 | muduo::sockets::close(sockfd); 13 | } 14 | 15 | int main() 16 | { 17 | printf("main(): pid = %d\n", getpid()); 18 | 19 | muduo::InetAddress listenAddr(9981); 20 | muduo::EventLoop loop; 21 | 22 | muduo::Acceptor acceptor(&loop, listenAddr); 23 | acceptor.setNewConnectionCallback(newConnection); 24 | acceptor.listen(); 25 | 26 | loop.loop(); 27 | } 28 | -------------------------------------------------------------------------------- /reactor/s05-s04-Callbacks.h.diff: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_CALLBACKS_H 9 | #define MUDUO_NET_CALLBACKS_H 10 | 11 | #include 12 | #include 13 | 14 | #include "datetime/Timestamp.h" 15 | 16 | namespace muduo 17 | { 18 | 19 | // All client visible callbacks go here. 20 | 21 | +class TcpConnection; 22 | +typedef boost::shared_ptr TcpConnectionPtr; 23 | + 24 | typedef boost::function TimerCallback; 25 | +typedef boost::function ConnectionCallback; 26 | +typedef boost::function MessageCallback; 29 | 30 | } 31 | 32 | #endif // MUDUO_NET_CALLBACKS_H 33 | -------------------------------------------------------------------------------- /reactor/s05/Callbacks.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_CALLBACKS_H 9 | #define MUDUO_NET_CALLBACKS_H 10 | 11 | #include 12 | #include 13 | 14 | #include "datetime/Timestamp.h" 15 | 16 | namespace muduo 17 | { 18 | 19 | // All client visible callbacks go here. 20 | 21 | class TcpConnection; 22 | typedef boost::shared_ptr TcpConnectionPtr; 23 | 24 | typedef boost::function TimerCallback; 25 | typedef boost::function ConnectionCallback; 26 | typedef boost::function MessageCallback; 29 | 30 | } 31 | 32 | #endif // MUDUO_NET_CALLBACKS_H 33 | -------------------------------------------------------------------------------- /reactor/s05/EventLoopThread.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_EVENTLOOPTHREAD_H 9 | #define MUDUO_NET_EVENTLOOPTHREAD_H 10 | 11 | #include "thread/Condition.h" 12 | #include "thread/Mutex.h" 13 | #include "thread/Thread.h" 14 | 15 | #include 16 | 17 | namespace muduo 18 | { 19 | 20 | class EventLoop; 21 | 22 | class EventLoopThread : boost::noncopyable 23 | { 24 | public: 25 | EventLoopThread(); 26 | ~EventLoopThread(); 27 | EventLoop* startLoop(); 28 | 29 | private: 30 | void threadFunc(); 31 | 32 | EventLoop* loop_; 33 | bool exiting_; 34 | Thread thread_; 35 | MutexLock mutex_; 36 | Condition cond_; 37 | }; 38 | 39 | } 40 | 41 | #endif // MUDUO_NET_EVENTLOOPTHREAD_H 42 | 43 | -------------------------------------------------------------------------------- /reactor/s05/Makefile: -------------------------------------------------------------------------------- 1 | LIB_SRC = \ 2 | Acceptor.cc \ 3 | Channel.cc \ 4 | EventLoop.cc \ 5 | EventLoopThread.cc \ 6 | InetAddress.cc \ 7 | Poller.cc \ 8 | Socket.cc \ 9 | SocketsOps.cc \ 10 | TcpConnection.cc \ 11 | TcpServer.cc \ 12 | Timer.cc \ 13 | TimerQueue.cc 14 | 15 | BINARIES = test1 test2 test3 test4 test5 test6 test7 test8 16 | 17 | all: $(BINARIES) 18 | 19 | include ../reactor_lib.mk 20 | 21 | test1: test1.cc 22 | test2: test2.cc 23 | test3: test3.cc 24 | test4: test4.cc 25 | test5: test5.cc 26 | test6: test6.cc 27 | test7: test7.cc 28 | test8: test8.cc 29 | -------------------------------------------------------------------------------- /reactor/s05/Timer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Timer.h" 9 | 10 | using namespace muduo; 11 | 12 | void Timer::restart(Timestamp now) 13 | { 14 | if (repeat_) 15 | { 16 | expiration_ = addTime(now, interval_); 17 | } 18 | else 19 | { 20 | expiration_ = Timestamp::invalid(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /reactor/s05/TimerId.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_TIMERID_H 9 | #define MUDUO_NET_TIMERID_H 10 | 11 | #include "datetime/copyable.h" 12 | 13 | namespace muduo 14 | { 15 | 16 | class Timer; 17 | 18 | /// 19 | /// An opaque identifier, for canceling Timer. 20 | /// 21 | class TimerId : public muduo::copyable 22 | { 23 | public: 24 | explicit TimerId(Timer* timer) 25 | : value_(timer) 26 | { 27 | } 28 | 29 | // default copy-ctor, dtor and assignment are okay 30 | 31 | private: 32 | Timer* value_; 33 | }; 34 | 35 | } 36 | 37 | #endif // MUDUO_NET_TIMERID_H 38 | -------------------------------------------------------------------------------- /reactor/s05/test1.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | #include 4 | 5 | void threadFunc() 6 | { 7 | printf("threadFunc(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | 10 | muduo::EventLoop loop; 11 | loop.loop(); 12 | } 13 | 14 | int main() 15 | { 16 | printf("main(): pid = %d, tid = %d\n", 17 | getpid(), muduo::CurrentThread::tid()); 18 | 19 | muduo::EventLoop loop; 20 | 21 | muduo::Thread thread(threadFunc); 22 | thread.start(); 23 | 24 | loop.loop(); 25 | pthread_exit(NULL); 26 | } 27 | -------------------------------------------------------------------------------- /reactor/s05/test2.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | 4 | muduo::EventLoop* g_loop; 5 | 6 | void threadFunc() 7 | { 8 | g_loop->loop(); 9 | } 10 | 11 | int main() 12 | { 13 | muduo::EventLoop loop; 14 | g_loop = &loop; 15 | muduo::Thread t(threadFunc); 16 | t.start(); 17 | t.join(); 18 | } 19 | -------------------------------------------------------------------------------- /reactor/s05/test3.cc: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | 4 | #include 5 | #include 6 | 7 | muduo::EventLoop* g_loop; 8 | 9 | void timeout() 10 | { 11 | printf("Timeout!\n"); 12 | g_loop->quit(); 13 | } 14 | 15 | int main() 16 | { 17 | muduo::EventLoop loop; 18 | g_loop = &loop; 19 | 20 | int timerfd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 21 | muduo::Channel channel(&loop, timerfd); 22 | channel.setReadCallback(timeout); 23 | channel.enableReading(); 24 | 25 | struct itimerspec howlong; 26 | bzero(&howlong, sizeof howlong); 27 | howlong.it_value.tv_sec = 5; 28 | ::timerfd_settime(timerfd, 0, &howlong, NULL); 29 | 30 | loop.loop(); 31 | 32 | ::close(timerfd); 33 | } 34 | -------------------------------------------------------------------------------- /reactor/s05/test5.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include 3 | 4 | muduo::EventLoop* g_loop; 5 | int g_flag = 0; 6 | 7 | void run4() 8 | { 9 | printf("run4(): pid = %d, flag = %d\n", getpid(), g_flag); 10 | g_loop->quit(); 11 | } 12 | 13 | void run3() 14 | { 15 | printf("run3(): pid = %d, flag = %d\n", getpid(), g_flag); 16 | g_loop->runAfter(3, run4); 17 | g_flag = 3; 18 | } 19 | 20 | void run2() 21 | { 22 | printf("run2(): pid = %d, flag = %d\n", getpid(), g_flag); 23 | g_loop->queueInLoop(run3); 24 | } 25 | 26 | void run1() 27 | { 28 | g_flag = 1; 29 | printf("run1(): pid = %d, flag = %d\n", getpid(), g_flag); 30 | g_loop->runInLoop(run2); 31 | g_flag = 2; 32 | } 33 | 34 | int main() 35 | { 36 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 37 | 38 | muduo::EventLoop loop; 39 | g_loop = &loop; 40 | 41 | loop.runAfter(2, run1); 42 | loop.loop(); 43 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 44 | } 45 | -------------------------------------------------------------------------------- /reactor/s05/test6.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "EventLoopThread.h" 3 | #include 4 | 5 | void runInThread() 6 | { 7 | printf("runInThread(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | } 10 | 11 | int main() 12 | { 13 | printf("main(): pid = %d, tid = %d\n", 14 | getpid(), muduo::CurrentThread::tid()); 15 | 16 | muduo::EventLoopThread loopThread; 17 | muduo::EventLoop* loop = loopThread.startLoop(); 18 | loop->runInLoop(runInThread); 19 | sleep(1); 20 | loop->runAfter(2, runInThread); 21 | sleep(3); 22 | loop->quit(); 23 | 24 | printf("exit main().\n"); 25 | } 26 | -------------------------------------------------------------------------------- /reactor/s05/test7.cc: -------------------------------------------------------------------------------- 1 | #include "Acceptor.h" 2 | #include "EventLoop.h" 3 | #include "InetAddress.h" 4 | #include "SocketsOps.h" 5 | #include 6 | 7 | void newConnection(int sockfd, const muduo::InetAddress& peerAddr) 8 | { 9 | printf("newConnection(): accepted a new connection from %s\n", 10 | peerAddr.toHostPort().c_str()); 11 | ::write(sockfd, "How are you?\n", 13); 12 | muduo::sockets::close(sockfd); 13 | } 14 | 15 | int main() 16 | { 17 | printf("main(): pid = %d\n", getpid()); 18 | 19 | muduo::InetAddress listenAddr(9981); 20 | muduo::EventLoop loop; 21 | 22 | muduo::Acceptor acceptor(&loop, listenAddr); 23 | acceptor.setNewConnectionCallback(newConnection); 24 | acceptor.listen(); 25 | 26 | loop.loop(); 27 | } 28 | -------------------------------------------------------------------------------- /reactor/s06-s05-Callbacks.h.diff: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_CALLBACKS_H 9 | #define MUDUO_NET_CALLBACKS_H 10 | 11 | #include 12 | #include 13 | 14 | #include "datetime/Timestamp.h" 15 | 16 | namespace muduo 17 | { 18 | 19 | // All client visible callbacks go here. 20 | 21 | class TcpConnection; 22 | typedef boost::shared_ptr TcpConnectionPtr; 23 | 24 | typedef boost::function TimerCallback; 25 | typedef boost::function ConnectionCallback; 26 | typedef boost::function MessageCallback; 29 | +typedef boost::function CloseCallback; 30 | 31 | } 32 | 33 | #endif // MUDUO_NET_CALLBACKS_H 34 | -------------------------------------------------------------------------------- /reactor/s06/Callbacks.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_CALLBACKS_H 9 | #define MUDUO_NET_CALLBACKS_H 10 | 11 | #include 12 | #include 13 | 14 | #include "datetime/Timestamp.h" 15 | 16 | namespace muduo 17 | { 18 | 19 | // All client visible callbacks go here. 20 | 21 | class TcpConnection; 22 | typedef boost::shared_ptr TcpConnectionPtr; 23 | 24 | typedef boost::function TimerCallback; 25 | typedef boost::function ConnectionCallback; 26 | typedef boost::function MessageCallback; 29 | typedef boost::function CloseCallback; 30 | 31 | } 32 | 33 | #endif // MUDUO_NET_CALLBACKS_H 34 | -------------------------------------------------------------------------------- /reactor/s06/EventLoopThread.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_EVENTLOOPTHREAD_H 9 | #define MUDUO_NET_EVENTLOOPTHREAD_H 10 | 11 | #include "thread/Condition.h" 12 | #include "thread/Mutex.h" 13 | #include "thread/Thread.h" 14 | 15 | #include 16 | 17 | namespace muduo 18 | { 19 | 20 | class EventLoop; 21 | 22 | class EventLoopThread : boost::noncopyable 23 | { 24 | public: 25 | EventLoopThread(); 26 | ~EventLoopThread(); 27 | EventLoop* startLoop(); 28 | 29 | private: 30 | void threadFunc(); 31 | 32 | EventLoop* loop_; 33 | bool exiting_; 34 | Thread thread_; 35 | MutexLock mutex_; 36 | Condition cond_; 37 | }; 38 | 39 | } 40 | 41 | #endif // MUDUO_NET_EVENTLOOPTHREAD_H 42 | 43 | -------------------------------------------------------------------------------- /reactor/s06/Makefile: -------------------------------------------------------------------------------- 1 | LIB_SRC = \ 2 | Acceptor.cc \ 3 | Channel.cc \ 4 | EventLoop.cc \ 5 | EventLoopThread.cc \ 6 | InetAddress.cc \ 7 | Poller.cc \ 8 | Socket.cc \ 9 | SocketsOps.cc \ 10 | TcpConnection.cc \ 11 | TcpServer.cc \ 12 | Timer.cc \ 13 | TimerQueue.cc 14 | 15 | BINARIES = test1 test2 test3 test4 test5 test6 test7 test8 16 | 17 | all: $(BINARIES) 18 | 19 | include ../reactor_lib.mk 20 | 21 | test1: test1.cc 22 | test2: test2.cc 23 | test3: test3.cc 24 | test4: test4.cc 25 | test5: test5.cc 26 | test6: test6.cc 27 | test7: test7.cc 28 | test8: test8.cc 29 | -------------------------------------------------------------------------------- /reactor/s06/Timer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Timer.h" 9 | 10 | using namespace muduo; 11 | 12 | void Timer::restart(Timestamp now) 13 | { 14 | if (repeat_) 15 | { 16 | expiration_ = addTime(now, interval_); 17 | } 18 | else 19 | { 20 | expiration_ = Timestamp::invalid(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /reactor/s06/TimerId.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_TIMERID_H 9 | #define MUDUO_NET_TIMERID_H 10 | 11 | #include "datetime/copyable.h" 12 | 13 | namespace muduo 14 | { 15 | 16 | class Timer; 17 | 18 | /// 19 | /// An opaque identifier, for canceling Timer. 20 | /// 21 | class TimerId : public muduo::copyable 22 | { 23 | public: 24 | explicit TimerId(Timer* timer) 25 | : value_(timer) 26 | { 27 | } 28 | 29 | // default copy-ctor, dtor and assignment are okay 30 | 31 | private: 32 | Timer* value_; 33 | }; 34 | 35 | } 36 | 37 | #endif // MUDUO_NET_TIMERID_H 38 | -------------------------------------------------------------------------------- /reactor/s06/test1.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | #include 4 | 5 | void threadFunc() 6 | { 7 | printf("threadFunc(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | 10 | muduo::EventLoop loop; 11 | loop.loop(); 12 | } 13 | 14 | int main() 15 | { 16 | printf("main(): pid = %d, tid = %d\n", 17 | getpid(), muduo::CurrentThread::tid()); 18 | 19 | muduo::EventLoop loop; 20 | 21 | muduo::Thread thread(threadFunc); 22 | thread.start(); 23 | 24 | loop.loop(); 25 | pthread_exit(NULL); 26 | } 27 | -------------------------------------------------------------------------------- /reactor/s06/test2.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | 4 | muduo::EventLoop* g_loop; 5 | 6 | void threadFunc() 7 | { 8 | g_loop->loop(); 9 | } 10 | 11 | int main() 12 | { 13 | muduo::EventLoop loop; 14 | g_loop = &loop; 15 | muduo::Thread t(threadFunc); 16 | t.start(); 17 | t.join(); 18 | } 19 | -------------------------------------------------------------------------------- /reactor/s06/test3.cc: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | 4 | #include 5 | #include 6 | 7 | muduo::EventLoop* g_loop; 8 | 9 | void timeout() 10 | { 11 | printf("Timeout!\n"); 12 | g_loop->quit(); 13 | } 14 | 15 | int main() 16 | { 17 | muduo::EventLoop loop; 18 | g_loop = &loop; 19 | 20 | int timerfd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 21 | muduo::Channel channel(&loop, timerfd); 22 | channel.setReadCallback(timeout); 23 | channel.enableReading(); 24 | 25 | struct itimerspec howlong; 26 | bzero(&howlong, sizeof howlong); 27 | howlong.it_value.tv_sec = 5; 28 | ::timerfd_settime(timerfd, 0, &howlong, NULL); 29 | 30 | loop.loop(); 31 | 32 | ::close(timerfd); 33 | } 34 | -------------------------------------------------------------------------------- /reactor/s06/test5.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include 3 | 4 | muduo::EventLoop* g_loop; 5 | int g_flag = 0; 6 | 7 | void run4() 8 | { 9 | printf("run4(): pid = %d, flag = %d\n", getpid(), g_flag); 10 | g_loop->quit(); 11 | } 12 | 13 | void run3() 14 | { 15 | printf("run3(): pid = %d, flag = %d\n", getpid(), g_flag); 16 | g_loop->runAfter(3, run4); 17 | g_flag = 3; 18 | } 19 | 20 | void run2() 21 | { 22 | printf("run2(): pid = %d, flag = %d\n", getpid(), g_flag); 23 | g_loop->queueInLoop(run3); 24 | } 25 | 26 | void run1() 27 | { 28 | g_flag = 1; 29 | printf("run1(): pid = %d, flag = %d\n", getpid(), g_flag); 30 | g_loop->runInLoop(run2); 31 | g_flag = 2; 32 | } 33 | 34 | int main() 35 | { 36 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 37 | 38 | muduo::EventLoop loop; 39 | g_loop = &loop; 40 | 41 | loop.runAfter(2, run1); 42 | loop.loop(); 43 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 44 | } 45 | -------------------------------------------------------------------------------- /reactor/s06/test6.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "EventLoopThread.h" 3 | #include 4 | 5 | void runInThread() 6 | { 7 | printf("runInThread(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | } 10 | 11 | int main() 12 | { 13 | printf("main(): pid = %d, tid = %d\n", 14 | getpid(), muduo::CurrentThread::tid()); 15 | 16 | muduo::EventLoopThread loopThread; 17 | muduo::EventLoop* loop = loopThread.startLoop(); 18 | loop->runInLoop(runInThread); 19 | sleep(1); 20 | loop->runAfter(2, runInThread); 21 | sleep(3); 22 | loop->quit(); 23 | 24 | printf("exit main().\n"); 25 | } 26 | -------------------------------------------------------------------------------- /reactor/s06/test7.cc: -------------------------------------------------------------------------------- 1 | #include "Acceptor.h" 2 | #include "EventLoop.h" 3 | #include "InetAddress.h" 4 | #include "SocketsOps.h" 5 | #include 6 | 7 | void newConnection(int sockfd, const muduo::InetAddress& peerAddr) 8 | { 9 | printf("newConnection(): accepted a new connection from %s\n", 10 | peerAddr.toHostPort().c_str()); 11 | ::write(sockfd, "How are you?\n", 13); 12 | muduo::sockets::close(sockfd); 13 | } 14 | 15 | int main() 16 | { 17 | printf("main(): pid = %d\n", getpid()); 18 | 19 | muduo::InetAddress listenAddr(9981); 20 | muduo::EventLoop loop; 21 | 22 | muduo::Acceptor acceptor(&loop, listenAddr); 23 | acceptor.setNewConnectionCallback(newConnection); 24 | acceptor.listen(); 25 | 26 | loop.loop(); 27 | } 28 | -------------------------------------------------------------------------------- /reactor/s07-s06-test3.cc.diff: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | 4 | #include 5 | #include 6 | 7 | muduo::EventLoop* g_loop; 8 | 9 | !void timeout(muduo::Timestamp receiveTime) 10 | { 11 | ! printf("%s Timeout!\n", receiveTime.toFormattedString().c_str()); 12 | g_loop->quit(); 13 | } 14 | 15 | int main() 16 | { 17 | + printf("%s started\n", muduo::Timestamp::now().toFormattedString().c_str()); 18 | muduo::EventLoop loop; 19 | g_loop = &loop; 20 | 21 | int timerfd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 22 | muduo::Channel channel(&loop, timerfd); 23 | channel.setReadCallback(timeout); 24 | channel.enableReading(); 25 | 26 | struct itimerspec howlong; 27 | bzero(&howlong, sizeof howlong); 28 | howlong.it_value.tv_sec = 5; 29 | ::timerfd_settime(timerfd, 0, &howlong, NULL); 30 | 31 | loop.loop(); 32 | 33 | ::close(timerfd); 34 | } 35 | -------------------------------------------------------------------------------- /reactor/s07/Buffer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Buffer.h" 9 | #include "SocketsOps.h" 10 | #include "logging/Logging.h" 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace muduo; 17 | 18 | ssize_t Buffer::readFd(int fd, int* savedErrno) 19 | { 20 | char extrabuf[65536]; 21 | struct iovec vec[2]; 22 | const size_t writable = writableBytes(); 23 | vec[0].iov_base = begin()+writerIndex_; 24 | vec[0].iov_len = writable; 25 | vec[1].iov_base = extrabuf; 26 | vec[1].iov_len = sizeof extrabuf; 27 | const ssize_t n = readv(fd, vec, 2); 28 | if (n < 0) { 29 | *savedErrno = errno; 30 | } else if (implicit_cast(n) <= writable) { 31 | writerIndex_ += n; 32 | } else { 33 | writerIndex_ = buffer_.size(); 34 | append(extrabuf, n - writable); 35 | } 36 | return n; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /reactor/s07/Callbacks.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_CALLBACKS_H 9 | #define MUDUO_NET_CALLBACKS_H 10 | 11 | #include 12 | #include 13 | 14 | #include "datetime/Timestamp.h" 15 | 16 | namespace muduo 17 | { 18 | 19 | // All client visible callbacks go here. 20 | 21 | class Buffer; 22 | class TcpConnection; 23 | typedef boost::shared_ptr TcpConnectionPtr; 24 | 25 | typedef boost::function TimerCallback; 26 | typedef boost::function ConnectionCallback; 27 | typedef boost::function MessageCallback; 30 | typedef boost::function CloseCallback; 31 | 32 | } 33 | 34 | #endif // MUDUO_NET_CALLBACKS_H 35 | -------------------------------------------------------------------------------- /reactor/s07/EventLoopThread.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_EVENTLOOPTHREAD_H 9 | #define MUDUO_NET_EVENTLOOPTHREAD_H 10 | 11 | #include "thread/Condition.h" 12 | #include "thread/Mutex.h" 13 | #include "thread/Thread.h" 14 | 15 | #include 16 | 17 | namespace muduo 18 | { 19 | 20 | class EventLoop; 21 | 22 | class EventLoopThread : boost::noncopyable 23 | { 24 | public: 25 | EventLoopThread(); 26 | ~EventLoopThread(); 27 | EventLoop* startLoop(); 28 | 29 | private: 30 | void threadFunc(); 31 | 32 | EventLoop* loop_; 33 | bool exiting_; 34 | Thread thread_; 35 | MutexLock mutex_; 36 | Condition cond_; 37 | }; 38 | 39 | } 40 | 41 | #endif // MUDUO_NET_EVENTLOOPTHREAD_H 42 | 43 | -------------------------------------------------------------------------------- /reactor/s07/Makefile: -------------------------------------------------------------------------------- 1 | LIB_SRC = \ 2 | Acceptor.cc \ 3 | Buffer.cc \ 4 | Channel.cc \ 5 | EventLoop.cc \ 6 | EventLoopThread.cc \ 7 | InetAddress.cc \ 8 | Poller.cc \ 9 | Socket.cc \ 10 | SocketsOps.cc \ 11 | TcpConnection.cc \ 12 | TcpServer.cc \ 13 | Timer.cc \ 14 | TimerQueue.cc 15 | 16 | BINARIES = test1 test2 test3 test4 test5 test6 test7 test8 17 | 18 | all: $(BINARIES) 19 | 20 | include ../reactor_lib.mk 21 | 22 | test1: test1.cc 23 | test2: test2.cc 24 | test3: test3.cc 25 | test4: test4.cc 26 | test5: test5.cc 27 | test6: test6.cc 28 | test7: test7.cc 29 | test8: test8.cc 30 | -------------------------------------------------------------------------------- /reactor/s07/Timer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Timer.h" 9 | 10 | using namespace muduo; 11 | 12 | void Timer::restart(Timestamp now) 13 | { 14 | if (repeat_) 15 | { 16 | expiration_ = addTime(now, interval_); 17 | } 18 | else 19 | { 20 | expiration_ = Timestamp::invalid(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /reactor/s07/TimerId.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_TIMERID_H 9 | #define MUDUO_NET_TIMERID_H 10 | 11 | #include "datetime/copyable.h" 12 | 13 | namespace muduo 14 | { 15 | 16 | class Timer; 17 | 18 | /// 19 | /// An opaque identifier, for canceling Timer. 20 | /// 21 | class TimerId : public muduo::copyable 22 | { 23 | public: 24 | explicit TimerId(Timer* timer) 25 | : value_(timer) 26 | { 27 | } 28 | 29 | // default copy-ctor, dtor and assignment are okay 30 | 31 | private: 32 | Timer* value_; 33 | }; 34 | 35 | } 36 | 37 | #endif // MUDUO_NET_TIMERID_H 38 | -------------------------------------------------------------------------------- /reactor/s07/test1.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | #include 4 | 5 | void threadFunc() 6 | { 7 | printf("threadFunc(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | 10 | muduo::EventLoop loop; 11 | loop.loop(); 12 | } 13 | 14 | int main() 15 | { 16 | printf("main(): pid = %d, tid = %d\n", 17 | getpid(), muduo::CurrentThread::tid()); 18 | 19 | muduo::EventLoop loop; 20 | 21 | muduo::Thread thread(threadFunc); 22 | thread.start(); 23 | 24 | loop.loop(); 25 | pthread_exit(NULL); 26 | } 27 | -------------------------------------------------------------------------------- /reactor/s07/test2.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | 4 | muduo::EventLoop* g_loop; 5 | 6 | void threadFunc() 7 | { 8 | g_loop->loop(); 9 | } 10 | 11 | int main() 12 | { 13 | muduo::EventLoop loop; 14 | g_loop = &loop; 15 | muduo::Thread t(threadFunc); 16 | t.start(); 17 | t.join(); 18 | } 19 | -------------------------------------------------------------------------------- /reactor/s07/test3.cc: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | 4 | #include 5 | #include 6 | 7 | muduo::EventLoop* g_loop; 8 | 9 | void timeout(muduo::Timestamp receiveTime) 10 | { 11 | printf("%s Timeout!\n", receiveTime.toFormattedString().c_str()); 12 | g_loop->quit(); 13 | } 14 | 15 | int main() 16 | { 17 | printf("%s started\n", muduo::Timestamp::now().toFormattedString().c_str()); 18 | muduo::EventLoop loop; 19 | g_loop = &loop; 20 | 21 | int timerfd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 22 | muduo::Channel channel(&loop, timerfd); 23 | channel.setReadCallback(timeout); 24 | channel.enableReading(); 25 | 26 | struct itimerspec howlong; 27 | bzero(&howlong, sizeof howlong); 28 | howlong.it_value.tv_sec = 5; 29 | ::timerfd_settime(timerfd, 0, &howlong, NULL); 30 | 31 | loop.loop(); 32 | 33 | ::close(timerfd); 34 | } 35 | -------------------------------------------------------------------------------- /reactor/s07/test5.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include 3 | 4 | muduo::EventLoop* g_loop; 5 | int g_flag = 0; 6 | 7 | void run4() 8 | { 9 | printf("run4(): pid = %d, flag = %d\n", getpid(), g_flag); 10 | g_loop->quit(); 11 | } 12 | 13 | void run3() 14 | { 15 | printf("run3(): pid = %d, flag = %d\n", getpid(), g_flag); 16 | g_loop->runAfter(3, run4); 17 | g_flag = 3; 18 | } 19 | 20 | void run2() 21 | { 22 | printf("run2(): pid = %d, flag = %d\n", getpid(), g_flag); 23 | g_loop->queueInLoop(run3); 24 | } 25 | 26 | void run1() 27 | { 28 | g_flag = 1; 29 | printf("run1(): pid = %d, flag = %d\n", getpid(), g_flag); 30 | g_loop->runInLoop(run2); 31 | g_flag = 2; 32 | } 33 | 34 | int main() 35 | { 36 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 37 | 38 | muduo::EventLoop loop; 39 | g_loop = &loop; 40 | 41 | loop.runAfter(2, run1); 42 | loop.loop(); 43 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 44 | } 45 | -------------------------------------------------------------------------------- /reactor/s07/test6.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "EventLoopThread.h" 3 | #include 4 | 5 | void runInThread() 6 | { 7 | printf("runInThread(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | } 10 | 11 | int main() 12 | { 13 | printf("main(): pid = %d, tid = %d\n", 14 | getpid(), muduo::CurrentThread::tid()); 15 | 16 | muduo::EventLoopThread loopThread; 17 | muduo::EventLoop* loop = loopThread.startLoop(); 18 | loop->runInLoop(runInThread); 19 | sleep(1); 20 | loop->runAfter(2, runInThread); 21 | sleep(3); 22 | loop->quit(); 23 | 24 | printf("exit main().\n"); 25 | } 26 | -------------------------------------------------------------------------------- /reactor/s07/test7.cc: -------------------------------------------------------------------------------- 1 | #include "Acceptor.h" 2 | #include "EventLoop.h" 3 | #include "InetAddress.h" 4 | #include "SocketsOps.h" 5 | #include 6 | 7 | void newConnection(int sockfd, const muduo::InetAddress& peerAddr) 8 | { 9 | printf("newConnection(): accepted a new connection from %s\n", 10 | peerAddr.toHostPort().c_str()); 11 | ::write(sockfd, "How are you?\n", 13); 12 | muduo::sockets::close(sockfd); 13 | } 14 | 15 | int main() 16 | { 17 | printf("main(): pid = %d\n", getpid()); 18 | 19 | muduo::InetAddress listenAddr(9981); 20 | muduo::EventLoop loop; 21 | 22 | muduo::Acceptor acceptor(&loop, listenAddr); 23 | acceptor.setNewConnectionCallback(newConnection); 24 | acceptor.listen(); 25 | 26 | loop.loop(); 27 | } 28 | -------------------------------------------------------------------------------- /reactor/s08/Buffer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Buffer.h" 9 | #include "SocketsOps.h" 10 | #include "logging/Logging.h" 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace muduo; 17 | 18 | ssize_t Buffer::readFd(int fd, int* savedErrno) 19 | { 20 | char extrabuf[65536]; 21 | struct iovec vec[2]; 22 | const size_t writable = writableBytes(); 23 | vec[0].iov_base = begin()+writerIndex_; 24 | vec[0].iov_len = writable; 25 | vec[1].iov_base = extrabuf; 26 | vec[1].iov_len = sizeof extrabuf; 27 | const ssize_t n = readv(fd, vec, 2); 28 | if (n < 0) { 29 | *savedErrno = errno; 30 | } else if (implicit_cast(n) <= writable) { 31 | writerIndex_ += n; 32 | } else { 33 | writerIndex_ = buffer_.size(); 34 | append(extrabuf, n - writable); 35 | } 36 | return n; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /reactor/s08/Callbacks.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_CALLBACKS_H 9 | #define MUDUO_NET_CALLBACKS_H 10 | 11 | #include 12 | #include 13 | 14 | #include "datetime/Timestamp.h" 15 | 16 | namespace muduo 17 | { 18 | 19 | // All client visible callbacks go here. 20 | 21 | class Buffer; 22 | class TcpConnection; 23 | typedef boost::shared_ptr TcpConnectionPtr; 24 | 25 | typedef boost::function TimerCallback; 26 | typedef boost::function ConnectionCallback; 27 | typedef boost::function MessageCallback; 30 | typedef boost::function CloseCallback; 31 | 32 | } 33 | 34 | #endif // MUDUO_NET_CALLBACKS_H 35 | -------------------------------------------------------------------------------- /reactor/s08/EventLoopThread.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_EVENTLOOPTHREAD_H 9 | #define MUDUO_NET_EVENTLOOPTHREAD_H 10 | 11 | #include "thread/Condition.h" 12 | #include "thread/Mutex.h" 13 | #include "thread/Thread.h" 14 | 15 | #include 16 | 17 | namespace muduo 18 | { 19 | 20 | class EventLoop; 21 | 22 | class EventLoopThread : boost::noncopyable 23 | { 24 | public: 25 | EventLoopThread(); 26 | ~EventLoopThread(); 27 | EventLoop* startLoop(); 28 | 29 | private: 30 | void threadFunc(); 31 | 32 | EventLoop* loop_; 33 | bool exiting_; 34 | Thread thread_; 35 | MutexLock mutex_; 36 | Condition cond_; 37 | }; 38 | 39 | } 40 | 41 | #endif // MUDUO_NET_EVENTLOOPTHREAD_H 42 | 43 | -------------------------------------------------------------------------------- /reactor/s08/Makefile: -------------------------------------------------------------------------------- 1 | LIB_SRC = \ 2 | Acceptor.cc \ 3 | Buffer.cc \ 4 | Channel.cc \ 5 | EventLoop.cc \ 6 | EventLoopThread.cc \ 7 | InetAddress.cc \ 8 | Poller.cc \ 9 | Socket.cc \ 10 | SocketsOps.cc \ 11 | TcpConnection.cc \ 12 | TcpServer.cc \ 13 | Timer.cc \ 14 | TimerQueue.cc 15 | 16 | BINARIES = test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 17 | 18 | all: $(BINARIES) 19 | 20 | include ../reactor_lib.mk 21 | 22 | test1: test1.cc 23 | test2: test2.cc 24 | test3: test3.cc 25 | test4: test4.cc 26 | test5: test5.cc 27 | test6: test6.cc 28 | test7: test7.cc 29 | test8: test8.cc 30 | test9: test9.cc 31 | test10: test10.cc 32 | -------------------------------------------------------------------------------- /reactor/s08/Timer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Timer.h" 9 | 10 | using namespace muduo; 11 | 12 | void Timer::restart(Timestamp now) 13 | { 14 | if (repeat_) 15 | { 16 | expiration_ = addTime(now, interval_); 17 | } 18 | else 19 | { 20 | expiration_ = Timestamp::invalid(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /reactor/s08/TimerId.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_TIMERID_H 9 | #define MUDUO_NET_TIMERID_H 10 | 11 | #include "datetime/copyable.h" 12 | 13 | namespace muduo 14 | { 15 | 16 | class Timer; 17 | 18 | /// 19 | /// An opaque identifier, for canceling Timer. 20 | /// 21 | class TimerId : public muduo::copyable 22 | { 23 | public: 24 | explicit TimerId(Timer* timer) 25 | : value_(timer) 26 | { 27 | } 28 | 29 | // default copy-ctor, dtor and assignment are okay 30 | 31 | private: 32 | Timer* value_; 33 | }; 34 | 35 | } 36 | 37 | #endif // MUDUO_NET_TIMERID_H 38 | -------------------------------------------------------------------------------- /reactor/s08/test1.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | #include 4 | 5 | void threadFunc() 6 | { 7 | printf("threadFunc(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | 10 | muduo::EventLoop loop; 11 | loop.loop(); 12 | } 13 | 14 | int main() 15 | { 16 | printf("main(): pid = %d, tid = %d\n", 17 | getpid(), muduo::CurrentThread::tid()); 18 | 19 | muduo::EventLoop loop; 20 | 21 | muduo::Thread thread(threadFunc); 22 | thread.start(); 23 | 24 | loop.loop(); 25 | pthread_exit(NULL); 26 | } 27 | -------------------------------------------------------------------------------- /reactor/s08/test2.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | 4 | muduo::EventLoop* g_loop; 5 | 6 | void threadFunc() 7 | { 8 | g_loop->loop(); 9 | } 10 | 11 | int main() 12 | { 13 | muduo::EventLoop loop; 14 | g_loop = &loop; 15 | muduo::Thread t(threadFunc); 16 | t.start(); 17 | t.join(); 18 | } 19 | -------------------------------------------------------------------------------- /reactor/s08/test3.cc: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | 4 | #include 5 | #include 6 | 7 | muduo::EventLoop* g_loop; 8 | 9 | void timeout(muduo::Timestamp receiveTime) 10 | { 11 | printf("%s Timeout!\n", receiveTime.toFormattedString().c_str()); 12 | g_loop->quit(); 13 | } 14 | 15 | int main() 16 | { 17 | printf("%s started\n", muduo::Timestamp::now().toFormattedString().c_str()); 18 | muduo::EventLoop loop; 19 | g_loop = &loop; 20 | 21 | int timerfd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 22 | muduo::Channel channel(&loop, timerfd); 23 | channel.setReadCallback(timeout); 24 | channel.enableReading(); 25 | 26 | struct itimerspec howlong; 27 | bzero(&howlong, sizeof howlong); 28 | howlong.it_value.tv_sec = 5; 29 | ::timerfd_settime(timerfd, 0, &howlong, NULL); 30 | 31 | loop.loop(); 32 | 33 | ::close(timerfd); 34 | } 35 | -------------------------------------------------------------------------------- /reactor/s08/test5.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include 3 | 4 | muduo::EventLoop* g_loop; 5 | int g_flag = 0; 6 | 7 | void run4() 8 | { 9 | printf("run4(): pid = %d, flag = %d\n", getpid(), g_flag); 10 | g_loop->quit(); 11 | } 12 | 13 | void run3() 14 | { 15 | printf("run3(): pid = %d, flag = %d\n", getpid(), g_flag); 16 | g_loop->runAfter(3, run4); 17 | g_flag = 3; 18 | } 19 | 20 | void run2() 21 | { 22 | printf("run2(): pid = %d, flag = %d\n", getpid(), g_flag); 23 | g_loop->queueInLoop(run3); 24 | } 25 | 26 | void run1() 27 | { 28 | g_flag = 1; 29 | printf("run1(): pid = %d, flag = %d\n", getpid(), g_flag); 30 | g_loop->runInLoop(run2); 31 | g_flag = 2; 32 | } 33 | 34 | int main() 35 | { 36 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 37 | 38 | muduo::EventLoop loop; 39 | g_loop = &loop; 40 | 41 | loop.runAfter(2, run1); 42 | loop.loop(); 43 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 44 | } 45 | -------------------------------------------------------------------------------- /reactor/s08/test6.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "EventLoopThread.h" 3 | #include 4 | 5 | void runInThread() 6 | { 7 | printf("runInThread(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | } 10 | 11 | int main() 12 | { 13 | printf("main(): pid = %d, tid = %d\n", 14 | getpid(), muduo::CurrentThread::tid()); 15 | 16 | muduo::EventLoopThread loopThread; 17 | muduo::EventLoop* loop = loopThread.startLoop(); 18 | loop->runInLoop(runInThread); 19 | sleep(1); 20 | loop->runAfter(2, runInThread); 21 | sleep(3); 22 | loop->quit(); 23 | 24 | printf("exit main().\n"); 25 | } 26 | -------------------------------------------------------------------------------- /reactor/s08/test7.cc: -------------------------------------------------------------------------------- 1 | #include "Acceptor.h" 2 | #include "EventLoop.h" 3 | #include "InetAddress.h" 4 | #include "SocketsOps.h" 5 | #include 6 | 7 | void newConnection(int sockfd, const muduo::InetAddress& peerAddr) 8 | { 9 | printf("newConnection(): accepted a new connection from %s\n", 10 | peerAddr.toHostPort().c_str()); 11 | ::write(sockfd, "How are you?\n", 13); 12 | muduo::sockets::close(sockfd); 13 | } 14 | 15 | int main() 16 | { 17 | printf("main(): pid = %d\n", getpid()); 18 | 19 | muduo::InetAddress listenAddr(9981); 20 | muduo::EventLoop loop; 21 | 22 | muduo::Acceptor acceptor(&loop, listenAddr); 23 | acceptor.setNewConnectionCallback(newConnection); 24 | acceptor.listen(); 25 | 26 | loop.loop(); 27 | } 28 | -------------------------------------------------------------------------------- /reactor/s09/Buffer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Buffer.h" 9 | #include "SocketsOps.h" 10 | #include "logging/Logging.h" 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace muduo; 17 | 18 | ssize_t Buffer::readFd(int fd, int* savedErrno) 19 | { 20 | char extrabuf[65536]; 21 | struct iovec vec[2]; 22 | const size_t writable = writableBytes(); 23 | vec[0].iov_base = begin()+writerIndex_; 24 | vec[0].iov_len = writable; 25 | vec[1].iov_base = extrabuf; 26 | vec[1].iov_len = sizeof extrabuf; 27 | const ssize_t n = readv(fd, vec, 2); 28 | if (n < 0) { 29 | *savedErrno = errno; 30 | } else if (implicit_cast(n) <= writable) { 31 | writerIndex_ += n; 32 | } else { 33 | writerIndex_ = buffer_.size(); 34 | append(extrabuf, n - writable); 35 | } 36 | return n; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /reactor/s09/EventLoopThread.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_EVENTLOOPTHREAD_H 9 | #define MUDUO_NET_EVENTLOOPTHREAD_H 10 | 11 | #include "thread/Condition.h" 12 | #include "thread/Mutex.h" 13 | #include "thread/Thread.h" 14 | 15 | #include 16 | 17 | namespace muduo 18 | { 19 | 20 | class EventLoop; 21 | 22 | class EventLoopThread : boost::noncopyable 23 | { 24 | public: 25 | EventLoopThread(); 26 | ~EventLoopThread(); 27 | EventLoop* startLoop(); 28 | 29 | private: 30 | void threadFunc(); 31 | 32 | EventLoop* loop_; 33 | bool exiting_; 34 | Thread thread_; 35 | MutexLock mutex_; 36 | Condition cond_; 37 | }; 38 | 39 | } 40 | 41 | #endif // MUDUO_NET_EVENTLOOPTHREAD_H 42 | 43 | -------------------------------------------------------------------------------- /reactor/s09/Makefile: -------------------------------------------------------------------------------- 1 | LIB_SRC = \ 2 | Acceptor.cc \ 3 | Buffer.cc \ 4 | Channel.cc \ 5 | EventLoop.cc \ 6 | EventLoopThread.cc \ 7 | InetAddress.cc \ 8 | Poller.cc \ 9 | Socket.cc \ 10 | SocketsOps.cc \ 11 | TcpConnection.cc \ 12 | TcpServer.cc \ 13 | Timer.cc \ 14 | TimerQueue.cc 15 | 16 | BINARIES = test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 \ 17 | test11 18 | 19 | all: $(BINARIES) 20 | 21 | include ../reactor_lib.mk 22 | 23 | test1: test1.cc 24 | test2: test2.cc 25 | test3: test3.cc 26 | test4: test4.cc 27 | test5: test5.cc 28 | test6: test6.cc 29 | test7: test7.cc 30 | test8: test8.cc 31 | test9: test9.cc 32 | test10: test10.cc 33 | test11: test11.cc 34 | -------------------------------------------------------------------------------- /reactor/s09/Timer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Timer.h" 9 | 10 | using namespace muduo; 11 | 12 | void Timer::restart(Timestamp now) 13 | { 14 | if (repeat_) 15 | { 16 | expiration_ = addTime(now, interval_); 17 | } 18 | else 19 | { 20 | expiration_ = Timestamp::invalid(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /reactor/s09/TimerId.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_TIMERID_H 9 | #define MUDUO_NET_TIMERID_H 10 | 11 | #include "datetime/copyable.h" 12 | 13 | namespace muduo 14 | { 15 | 16 | class Timer; 17 | 18 | /// 19 | /// An opaque identifier, for canceling Timer. 20 | /// 21 | class TimerId : public muduo::copyable 22 | { 23 | public: 24 | explicit TimerId(Timer* timer) 25 | : value_(timer) 26 | { 27 | } 28 | 29 | // default copy-ctor, dtor and assignment are okay 30 | 31 | private: 32 | Timer* value_; 33 | }; 34 | 35 | } 36 | 37 | #endif // MUDUO_NET_TIMERID_H 38 | -------------------------------------------------------------------------------- /reactor/s09/test1.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | #include 4 | 5 | void threadFunc() 6 | { 7 | printf("threadFunc(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | 10 | muduo::EventLoop loop; 11 | loop.loop(); 12 | } 13 | 14 | int main() 15 | { 16 | printf("main(): pid = %d, tid = %d\n", 17 | getpid(), muduo::CurrentThread::tid()); 18 | 19 | muduo::EventLoop loop; 20 | 21 | muduo::Thread thread(threadFunc); 22 | thread.start(); 23 | 24 | loop.loop(); 25 | pthread_exit(NULL); 26 | } 27 | -------------------------------------------------------------------------------- /reactor/s09/test2.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | 4 | muduo::EventLoop* g_loop; 5 | 6 | void threadFunc() 7 | { 8 | g_loop->loop(); 9 | } 10 | 11 | int main() 12 | { 13 | muduo::EventLoop loop; 14 | g_loop = &loop; 15 | muduo::Thread t(threadFunc); 16 | t.start(); 17 | t.join(); 18 | } 19 | -------------------------------------------------------------------------------- /reactor/s09/test3.cc: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | 4 | #include 5 | #include 6 | 7 | muduo::EventLoop* g_loop; 8 | 9 | void timeout(muduo::Timestamp receiveTime) 10 | { 11 | printf("%s Timeout!\n", receiveTime.toFormattedString().c_str()); 12 | g_loop->quit(); 13 | } 14 | 15 | int main() 16 | { 17 | printf("%s started\n", muduo::Timestamp::now().toFormattedString().c_str()); 18 | muduo::EventLoop loop; 19 | g_loop = &loop; 20 | 21 | int timerfd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 22 | muduo::Channel channel(&loop, timerfd); 23 | channel.setReadCallback(timeout); 24 | channel.enableReading(); 25 | 26 | struct itimerspec howlong; 27 | bzero(&howlong, sizeof howlong); 28 | howlong.it_value.tv_sec = 5; 29 | ::timerfd_settime(timerfd, 0, &howlong, NULL); 30 | 31 | loop.loop(); 32 | 33 | ::close(timerfd); 34 | } 35 | -------------------------------------------------------------------------------- /reactor/s09/test5.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include 3 | 4 | muduo::EventLoop* g_loop; 5 | int g_flag = 0; 6 | 7 | void run4() 8 | { 9 | printf("run4(): pid = %d, flag = %d\n", getpid(), g_flag); 10 | g_loop->quit(); 11 | } 12 | 13 | void run3() 14 | { 15 | printf("run3(): pid = %d, flag = %d\n", getpid(), g_flag); 16 | g_loop->runAfter(3, run4); 17 | g_flag = 3; 18 | } 19 | 20 | void run2() 21 | { 22 | printf("run2(): pid = %d, flag = %d\n", getpid(), g_flag); 23 | g_loop->queueInLoop(run3); 24 | } 25 | 26 | void run1() 27 | { 28 | g_flag = 1; 29 | printf("run1(): pid = %d, flag = %d\n", getpid(), g_flag); 30 | g_loop->runInLoop(run2); 31 | g_flag = 2; 32 | } 33 | 34 | int main() 35 | { 36 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 37 | 38 | muduo::EventLoop loop; 39 | g_loop = &loop; 40 | 41 | loop.runAfter(2, run1); 42 | loop.loop(); 43 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 44 | } 45 | -------------------------------------------------------------------------------- /reactor/s09/test6.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "EventLoopThread.h" 3 | #include 4 | 5 | void runInThread() 6 | { 7 | printf("runInThread(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | } 10 | 11 | int main() 12 | { 13 | printf("main(): pid = %d, tid = %d\n", 14 | getpid(), muduo::CurrentThread::tid()); 15 | 16 | muduo::EventLoopThread loopThread; 17 | muduo::EventLoop* loop = loopThread.startLoop(); 18 | loop->runInLoop(runInThread); 19 | sleep(1); 20 | loop->runAfter(2, runInThread); 21 | sleep(3); 22 | loop->quit(); 23 | 24 | printf("exit main().\n"); 25 | } 26 | -------------------------------------------------------------------------------- /reactor/s09/test7.cc: -------------------------------------------------------------------------------- 1 | #include "Acceptor.h" 2 | #include "EventLoop.h" 3 | #include "InetAddress.h" 4 | #include "SocketsOps.h" 5 | #include 6 | 7 | void newConnection(int sockfd, const muduo::InetAddress& peerAddr) 8 | { 9 | printf("newConnection(): accepted a new connection from %s\n", 10 | peerAddr.toHostPort().c_str()); 11 | ::write(sockfd, "How are you?\n", 13); 12 | muduo::sockets::close(sockfd); 13 | } 14 | 15 | int main() 16 | { 17 | printf("main(): pid = %d\n", getpid()); 18 | 19 | muduo::InetAddress listenAddr(9981); 20 | muduo::EventLoop loop; 21 | 22 | muduo::Acceptor acceptor(&loop, listenAddr); 23 | acceptor.setNewConnectionCallback(newConnection); 24 | acceptor.listen(); 25 | 26 | loop.loop(); 27 | } 28 | -------------------------------------------------------------------------------- /reactor/s10/Buffer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Buffer.h" 9 | #include "SocketsOps.h" 10 | #include "logging/Logging.h" 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace muduo; 17 | 18 | ssize_t Buffer::readFd(int fd, int* savedErrno) 19 | { 20 | char extrabuf[65536]; 21 | struct iovec vec[2]; 22 | const size_t writable = writableBytes(); 23 | vec[0].iov_base = begin()+writerIndex_; 24 | vec[0].iov_len = writable; 25 | vec[1].iov_base = extrabuf; 26 | vec[1].iov_len = sizeof extrabuf; 27 | const ssize_t n = readv(fd, vec, 2); 28 | if (n < 0) { 29 | *savedErrno = errno; 30 | } else if (implicit_cast(n) <= writable) { 31 | writerIndex_ += n; 32 | } else { 33 | writerIndex_ = buffer_.size(); 34 | append(extrabuf, n - writable); 35 | } 36 | return n; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /reactor/s10/EventLoopThread.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_EVENTLOOPTHREAD_H 9 | #define MUDUO_NET_EVENTLOOPTHREAD_H 10 | 11 | #include "thread/Condition.h" 12 | #include "thread/Mutex.h" 13 | #include "thread/Thread.h" 14 | 15 | #include 16 | 17 | namespace muduo 18 | { 19 | 20 | class EventLoop; 21 | 22 | class EventLoopThread : boost::noncopyable 23 | { 24 | public: 25 | EventLoopThread(); 26 | ~EventLoopThread(); 27 | EventLoop* startLoop(); 28 | 29 | private: 30 | void threadFunc(); 31 | 32 | EventLoop* loop_; 33 | bool exiting_; 34 | Thread thread_; 35 | MutexLock mutex_; 36 | Condition cond_; 37 | }; 38 | 39 | } 40 | 41 | #endif // MUDUO_NET_EVENTLOOPTHREAD_H 42 | 43 | -------------------------------------------------------------------------------- /reactor/s10/Makefile: -------------------------------------------------------------------------------- 1 | LIB_SRC = \ 2 | Acceptor.cc \ 3 | Buffer.cc \ 4 | Channel.cc \ 5 | EventLoop.cc \ 6 | EventLoopThread.cc \ 7 | EventLoopThreadPool.cc \ 8 | InetAddress.cc \ 9 | Poller.cc \ 10 | Socket.cc \ 11 | SocketsOps.cc \ 12 | TcpConnection.cc \ 13 | TcpServer.cc \ 14 | Timer.cc \ 15 | TimerQueue.cc 16 | 17 | BINARIES = test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 \ 18 | test11 19 | 20 | all: $(BINARIES) 21 | 22 | include ../reactor_lib.mk 23 | 24 | test1: test1.cc 25 | test2: test2.cc 26 | test3: test3.cc 27 | test4: test4.cc 28 | test5: test5.cc 29 | test6: test6.cc 30 | test7: test7.cc 31 | test8: test8.cc 32 | test9: test9.cc 33 | test10: test10.cc 34 | test11: test11.cc 35 | -------------------------------------------------------------------------------- /reactor/s10/Timer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Timer.h" 9 | 10 | using namespace muduo; 11 | 12 | void Timer::restart(Timestamp now) 13 | { 14 | if (repeat_) 15 | { 16 | expiration_ = addTime(now, interval_); 17 | } 18 | else 19 | { 20 | expiration_ = Timestamp::invalid(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /reactor/s10/TimerId.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_TIMERID_H 9 | #define MUDUO_NET_TIMERID_H 10 | 11 | #include "datetime/copyable.h" 12 | 13 | namespace muduo 14 | { 15 | 16 | class Timer; 17 | 18 | /// 19 | /// An opaque identifier, for canceling Timer. 20 | /// 21 | class TimerId : public muduo::copyable 22 | { 23 | public: 24 | explicit TimerId(Timer* timer) 25 | : value_(timer) 26 | { 27 | } 28 | 29 | // default copy-ctor, dtor and assignment are okay 30 | 31 | private: 32 | Timer* value_; 33 | }; 34 | 35 | } 36 | 37 | #endif // MUDUO_NET_TIMERID_H 38 | -------------------------------------------------------------------------------- /reactor/s10/test1.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | #include 4 | 5 | void threadFunc() 6 | { 7 | printf("threadFunc(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | 10 | muduo::EventLoop loop; 11 | loop.loop(); 12 | } 13 | 14 | int main() 15 | { 16 | printf("main(): pid = %d, tid = %d\n", 17 | getpid(), muduo::CurrentThread::tid()); 18 | 19 | muduo::EventLoop loop; 20 | 21 | muduo::Thread thread(threadFunc); 22 | thread.start(); 23 | 24 | loop.loop(); 25 | pthread_exit(NULL); 26 | } 27 | -------------------------------------------------------------------------------- /reactor/s10/test2.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | 4 | muduo::EventLoop* g_loop; 5 | 6 | void threadFunc() 7 | { 8 | g_loop->loop(); 9 | } 10 | 11 | int main() 12 | { 13 | muduo::EventLoop loop; 14 | g_loop = &loop; 15 | muduo::Thread t(threadFunc); 16 | t.start(); 17 | t.join(); 18 | } 19 | -------------------------------------------------------------------------------- /reactor/s10/test3.cc: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | 4 | #include 5 | #include 6 | 7 | muduo::EventLoop* g_loop; 8 | 9 | void timeout(muduo::Timestamp receiveTime) 10 | { 11 | printf("%s Timeout!\n", receiveTime.toFormattedString().c_str()); 12 | g_loop->quit(); 13 | } 14 | 15 | int main() 16 | { 17 | printf("%s started\n", muduo::Timestamp::now().toFormattedString().c_str()); 18 | muduo::EventLoop loop; 19 | g_loop = &loop; 20 | 21 | int timerfd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 22 | muduo::Channel channel(&loop, timerfd); 23 | channel.setReadCallback(timeout); 24 | channel.enableReading(); 25 | 26 | struct itimerspec howlong; 27 | bzero(&howlong, sizeof howlong); 28 | howlong.it_value.tv_sec = 5; 29 | ::timerfd_settime(timerfd, 0, &howlong, NULL); 30 | 31 | loop.loop(); 32 | 33 | ::close(timerfd); 34 | } 35 | -------------------------------------------------------------------------------- /reactor/s10/test5.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include 3 | 4 | muduo::EventLoop* g_loop; 5 | int g_flag = 0; 6 | 7 | void run4() 8 | { 9 | printf("run4(): pid = %d, flag = %d\n", getpid(), g_flag); 10 | g_loop->quit(); 11 | } 12 | 13 | void run3() 14 | { 15 | printf("run3(): pid = %d, flag = %d\n", getpid(), g_flag); 16 | g_loop->runAfter(3, run4); 17 | g_flag = 3; 18 | } 19 | 20 | void run2() 21 | { 22 | printf("run2(): pid = %d, flag = %d\n", getpid(), g_flag); 23 | g_loop->queueInLoop(run3); 24 | } 25 | 26 | void run1() 27 | { 28 | g_flag = 1; 29 | printf("run1(): pid = %d, flag = %d\n", getpid(), g_flag); 30 | g_loop->runInLoop(run2); 31 | g_flag = 2; 32 | } 33 | 34 | int main() 35 | { 36 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 37 | 38 | muduo::EventLoop loop; 39 | g_loop = &loop; 40 | 41 | loop.runAfter(2, run1); 42 | loop.loop(); 43 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 44 | } 45 | -------------------------------------------------------------------------------- /reactor/s10/test6.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "EventLoopThread.h" 3 | #include 4 | 5 | void runInThread() 6 | { 7 | printf("runInThread(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | } 10 | 11 | int main() 12 | { 13 | printf("main(): pid = %d, tid = %d\n", 14 | getpid(), muduo::CurrentThread::tid()); 15 | 16 | muduo::EventLoopThread loopThread; 17 | muduo::EventLoop* loop = loopThread.startLoop(); 18 | loop->runInLoop(runInThread); 19 | sleep(1); 20 | loop->runAfter(2, runInThread); 21 | sleep(3); 22 | loop->quit(); 23 | 24 | printf("exit main().\n"); 25 | } 26 | -------------------------------------------------------------------------------- /reactor/s10/test7.cc: -------------------------------------------------------------------------------- 1 | #include "Acceptor.h" 2 | #include "EventLoop.h" 3 | #include "InetAddress.h" 4 | #include "SocketsOps.h" 5 | #include 6 | 7 | void newConnection(int sockfd, const muduo::InetAddress& peerAddr) 8 | { 9 | printf("newConnection(): accepted a new connection from %s\n", 10 | peerAddr.toHostPort().c_str()); 11 | ::write(sockfd, "How are you?\n", 13); 12 | muduo::sockets::close(sockfd); 13 | } 14 | 15 | int main() 16 | { 17 | printf("main(): pid = %d\n", getpid()); 18 | 19 | muduo::InetAddress listenAddr(9981); 20 | muduo::EventLoop loop; 21 | 22 | muduo::Acceptor acceptor(&loop, listenAddr); 23 | acceptor.setNewConnectionCallback(newConnection); 24 | acceptor.listen(); 25 | 26 | loop.loop(); 27 | } 28 | -------------------------------------------------------------------------------- /reactor/s11-s10-Timer.cc.diff: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Timer.h" 9 | 10 | using namespace muduo; 11 | 12 | +AtomicInt64 Timer::s_numCreated_; 13 | + 14 | void Timer::restart(Timestamp now) 15 | { 16 | if (repeat_) 17 | { 18 | expiration_ = addTime(now, interval_); 19 | } 20 | else 21 | { 22 | expiration_ = Timestamp::invalid(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /reactor/s11-s10-TimerId.h.diff: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_TIMERID_H 9 | #define MUDUO_NET_TIMERID_H 10 | 11 | #include "datetime/copyable.h" 12 | 13 | namespace muduo 14 | { 15 | 16 | class Timer; 17 | 18 | /// 19 | /// An opaque identifier, for canceling Timer. 20 | /// 21 | class TimerId : public muduo::copyable 22 | { 23 | public: 24 | ! TimerId(Timer* timer = NULL, int64_t seq = 0) 25 | : timer_(timer), 26 | + seq_(seq) 27 | { 28 | } 29 | 30 | // default copy-ctor, dtor and assignment are okay 31 | 32 | + friend class TimerQueue; 33 | + 34 | private: 35 | Timer* timer_; 36 | + int64_t seq_; 37 | }; 38 | 39 | } 40 | 41 | #endif // MUDUO_NET_TIMERID_H 42 | -------------------------------------------------------------------------------- /reactor/s11/Buffer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Buffer.h" 9 | #include "SocketsOps.h" 10 | #include "logging/Logging.h" 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace muduo; 17 | 18 | ssize_t Buffer::readFd(int fd, int* savedErrno) 19 | { 20 | char extrabuf[65536]; 21 | struct iovec vec[2]; 22 | const size_t writable = writableBytes(); 23 | vec[0].iov_base = begin()+writerIndex_; 24 | vec[0].iov_len = writable; 25 | vec[1].iov_base = extrabuf; 26 | vec[1].iov_len = sizeof extrabuf; 27 | const ssize_t n = readv(fd, vec, 2); 28 | if (n < 0) { 29 | *savedErrno = errno; 30 | } else if (implicit_cast(n) <= writable) { 31 | writerIndex_ += n; 32 | } else { 33 | writerIndex_ = buffer_.size(); 34 | append(extrabuf, n - writable); 35 | } 36 | return n; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /reactor/s11/EventLoopThread.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_EVENTLOOPTHREAD_H 9 | #define MUDUO_NET_EVENTLOOPTHREAD_H 10 | 11 | #include "thread/Condition.h" 12 | #include "thread/Mutex.h" 13 | #include "thread/Thread.h" 14 | 15 | #include 16 | 17 | namespace muduo 18 | { 19 | 20 | class EventLoop; 21 | 22 | class EventLoopThread : boost::noncopyable 23 | { 24 | public: 25 | EventLoopThread(); 26 | ~EventLoopThread(); 27 | EventLoop* startLoop(); 28 | 29 | private: 30 | void threadFunc(); 31 | 32 | EventLoop* loop_; 33 | bool exiting_; 34 | Thread thread_; 35 | MutexLock mutex_; 36 | Condition cond_; 37 | }; 38 | 39 | } 40 | 41 | #endif // MUDUO_NET_EVENTLOOPTHREAD_H 42 | 43 | -------------------------------------------------------------------------------- /reactor/s11/Makefile: -------------------------------------------------------------------------------- 1 | LIB_SRC = \ 2 | Acceptor.cc \ 3 | Buffer.cc \ 4 | Channel.cc \ 5 | Connector.cc \ 6 | EventLoop.cc \ 7 | EventLoopThread.cc \ 8 | EventLoopThreadPool.cc \ 9 | InetAddress.cc \ 10 | Poller.cc \ 11 | Socket.cc \ 12 | SocketsOps.cc \ 13 | TcpConnection.cc \ 14 | TcpServer.cc \ 15 | Timer.cc \ 16 | TimerQueue.cc 17 | 18 | BINARIES = test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 \ 19 | test11 test12 20 | 21 | all: $(BINARIES) 22 | 23 | include ../reactor_lib.mk 24 | 25 | test1: test1.cc 26 | test2: test2.cc 27 | test3: test3.cc 28 | test4: test4.cc 29 | test5: test5.cc 30 | test6: test6.cc 31 | test7: test7.cc 32 | test8: test8.cc 33 | test9: test9.cc 34 | test10: test10.cc 35 | test11: test11.cc 36 | test12: test12.cc 37 | -------------------------------------------------------------------------------- /reactor/s11/Timer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Timer.h" 9 | 10 | using namespace muduo; 11 | 12 | AtomicInt64 Timer::s_numCreated_; 13 | 14 | void Timer::restart(Timestamp now) 15 | { 16 | if (repeat_) 17 | { 18 | expiration_ = addTime(now, interval_); 19 | } 20 | else 21 | { 22 | expiration_ = Timestamp::invalid(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /reactor/s11/TimerId.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_TIMERID_H 9 | #define MUDUO_NET_TIMERID_H 10 | 11 | #include "datetime/copyable.h" 12 | 13 | namespace muduo 14 | { 15 | 16 | class Timer; 17 | 18 | /// 19 | /// An opaque identifier, for canceling Timer. 20 | /// 21 | class TimerId : public muduo::copyable 22 | { 23 | public: 24 | TimerId(Timer* timer = NULL, int64_t seq = 0) 25 | : timer_(timer), 26 | sequence_(seq) 27 | { 28 | } 29 | 30 | // default copy-ctor, dtor and assignment are okay 31 | 32 | friend class TimerQueue; 33 | 34 | private: 35 | Timer* timer_; 36 | int64_t sequence_; 37 | }; 38 | 39 | } 40 | 41 | #endif // MUDUO_NET_TIMERID_H 42 | -------------------------------------------------------------------------------- /reactor/s11/test1.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | #include 4 | 5 | void threadFunc() 6 | { 7 | printf("threadFunc(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | 10 | muduo::EventLoop loop; 11 | loop.loop(); 12 | } 13 | 14 | int main() 15 | { 16 | printf("main(): pid = %d, tid = %d\n", 17 | getpid(), muduo::CurrentThread::tid()); 18 | 19 | muduo::EventLoop loop; 20 | 21 | muduo::Thread thread(threadFunc); 22 | thread.start(); 23 | 24 | loop.loop(); 25 | pthread_exit(NULL); 26 | } 27 | -------------------------------------------------------------------------------- /reactor/s11/test12.cc: -------------------------------------------------------------------------------- 1 | #include "Connector.h" 2 | #include "EventLoop.h" 3 | 4 | #include 5 | 6 | muduo::EventLoop* g_loop; 7 | 8 | void connectCallback(int sockfd) 9 | { 10 | printf("connected.\n"); 11 | g_loop->quit(); 12 | } 13 | 14 | int main(int argc, char* argv[]) 15 | { 16 | muduo::EventLoop loop; 17 | g_loop = &loop; 18 | muduo::InetAddress addr("127.0.0.1", 9981); 19 | muduo::ConnectorPtr connector(new muduo::Connector(&loop, addr)); 20 | connector->setNewConnectionCallback(connectCallback); 21 | connector->start(); 22 | 23 | loop.loop(); 24 | } 25 | -------------------------------------------------------------------------------- /reactor/s11/test2.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | 4 | muduo::EventLoop* g_loop; 5 | 6 | void threadFunc() 7 | { 8 | g_loop->loop(); 9 | } 10 | 11 | int main() 12 | { 13 | muduo::EventLoop loop; 14 | g_loop = &loop; 15 | muduo::Thread t(threadFunc); 16 | t.start(); 17 | t.join(); 18 | } 19 | -------------------------------------------------------------------------------- /reactor/s11/test3.cc: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | 4 | #include 5 | #include 6 | 7 | muduo::EventLoop* g_loop; 8 | 9 | void timeout(muduo::Timestamp receiveTime) 10 | { 11 | printf("%s Timeout!\n", receiveTime.toFormattedString().c_str()); 12 | g_loop->quit(); 13 | } 14 | 15 | int main() 16 | { 17 | printf("%s started\n", muduo::Timestamp::now().toFormattedString().c_str()); 18 | muduo::EventLoop loop; 19 | g_loop = &loop; 20 | 21 | int timerfd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 22 | muduo::Channel channel(&loop, timerfd); 23 | channel.setReadCallback(timeout); 24 | channel.enableReading(); 25 | 26 | struct itimerspec howlong; 27 | bzero(&howlong, sizeof howlong); 28 | howlong.it_value.tv_sec = 5; 29 | ::timerfd_settime(timerfd, 0, &howlong, NULL); 30 | 31 | loop.loop(); 32 | 33 | ::close(timerfd); 34 | } 35 | -------------------------------------------------------------------------------- /reactor/s11/test5.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include 3 | 4 | muduo::EventLoop* g_loop; 5 | int g_flag = 0; 6 | 7 | void run4() 8 | { 9 | printf("run4(): pid = %d, flag = %d\n", getpid(), g_flag); 10 | g_loop->quit(); 11 | } 12 | 13 | void run3() 14 | { 15 | printf("run3(): pid = %d, flag = %d\n", getpid(), g_flag); 16 | g_loop->runAfter(3, run4); 17 | g_flag = 3; 18 | } 19 | 20 | void run2() 21 | { 22 | printf("run2(): pid = %d, flag = %d\n", getpid(), g_flag); 23 | g_loop->queueInLoop(run3); 24 | } 25 | 26 | void run1() 27 | { 28 | g_flag = 1; 29 | printf("run1(): pid = %d, flag = %d\n", getpid(), g_flag); 30 | g_loop->runInLoop(run2); 31 | g_flag = 2; 32 | } 33 | 34 | int main() 35 | { 36 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 37 | 38 | muduo::EventLoop loop; 39 | g_loop = &loop; 40 | 41 | loop.runAfter(2, run1); 42 | loop.loop(); 43 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 44 | } 45 | -------------------------------------------------------------------------------- /reactor/s11/test6.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "EventLoopThread.h" 3 | #include 4 | 5 | void runInThread() 6 | { 7 | printf("runInThread(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | } 10 | 11 | int main() 12 | { 13 | printf("main(): pid = %d, tid = %d\n", 14 | getpid(), muduo::CurrentThread::tid()); 15 | 16 | muduo::EventLoopThread loopThread; 17 | muduo::EventLoop* loop = loopThread.startLoop(); 18 | loop->runInLoop(runInThread); 19 | sleep(1); 20 | loop->runAfter(2, runInThread); 21 | sleep(3); 22 | loop->quit(); 23 | 24 | printf("exit main().\n"); 25 | } 26 | -------------------------------------------------------------------------------- /reactor/s11/test7.cc: -------------------------------------------------------------------------------- 1 | #include "Acceptor.h" 2 | #include "EventLoop.h" 3 | #include "InetAddress.h" 4 | #include "SocketsOps.h" 5 | #include 6 | 7 | void newConnection(int sockfd, const muduo::InetAddress& peerAddr) 8 | { 9 | printf("newConnection(): accepted a new connection from %s\n", 10 | peerAddr.toHostPort().c_str()); 11 | ::write(sockfd, "How are you?\n", 13); 12 | muduo::sockets::close(sockfd); 13 | } 14 | 15 | int main() 16 | { 17 | printf("main(): pid = %d\n", getpid()); 18 | 19 | muduo::InetAddress listenAddr(9981); 20 | muduo::EventLoop loop; 21 | 22 | muduo::Acceptor acceptor(&loop, listenAddr); 23 | acceptor.setNewConnectionCallback(newConnection); 24 | acceptor.listen(); 25 | 26 | loop.loop(); 27 | } 28 | -------------------------------------------------------------------------------- /reactor/s12/Buffer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Buffer.h" 9 | #include "SocketsOps.h" 10 | #include "logging/Logging.h" 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace muduo; 17 | 18 | ssize_t Buffer::readFd(int fd, int* savedErrno) 19 | { 20 | char extrabuf[65536]; 21 | struct iovec vec[2]; 22 | const size_t writable = writableBytes(); 23 | vec[0].iov_base = begin()+writerIndex_; 24 | vec[0].iov_len = writable; 25 | vec[1].iov_base = extrabuf; 26 | vec[1].iov_len = sizeof extrabuf; 27 | const ssize_t n = readv(fd, vec, 2); 28 | if (n < 0) { 29 | *savedErrno = errno; 30 | } else if (implicit_cast(n) <= writable) { 31 | writerIndex_ += n; 32 | } else { 33 | writerIndex_ = buffer_.size(); 34 | append(extrabuf, n - writable); 35 | } 36 | return n; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /reactor/s12/EventLoopThread.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_EVENTLOOPTHREAD_H 9 | #define MUDUO_NET_EVENTLOOPTHREAD_H 10 | 11 | #include "thread/Condition.h" 12 | #include "thread/Mutex.h" 13 | #include "thread/Thread.h" 14 | 15 | #include 16 | 17 | namespace muduo 18 | { 19 | 20 | class EventLoop; 21 | 22 | class EventLoopThread : boost::noncopyable 23 | { 24 | public: 25 | EventLoopThread(); 26 | ~EventLoopThread(); 27 | EventLoop* startLoop(); 28 | 29 | private: 30 | void threadFunc(); 31 | 32 | EventLoop* loop_; 33 | bool exiting_; 34 | Thread thread_; 35 | MutexLock mutex_; 36 | Condition cond_; 37 | }; 38 | 39 | } 40 | 41 | #endif // MUDUO_NET_EVENTLOOPTHREAD_H 42 | 43 | -------------------------------------------------------------------------------- /reactor/s12/Makefile: -------------------------------------------------------------------------------- 1 | LIB_SRC = \ 2 | Acceptor.cc \ 3 | Buffer.cc \ 4 | Channel.cc \ 5 | Connector.cc \ 6 | EventLoop.cc \ 7 | EventLoopThread.cc \ 8 | EventLoopThreadPool.cc \ 9 | InetAddress.cc \ 10 | Poller.cc \ 11 | Socket.cc \ 12 | SocketsOps.cc \ 13 | TcpClient.cc \ 14 | TcpConnection.cc \ 15 | TcpServer.cc \ 16 | Timer.cc \ 17 | TimerQueue.cc 18 | 19 | BINARIES = test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 \ 20 | test11 test12 test13 21 | 22 | all: $(BINARIES) 23 | 24 | include ../reactor_lib.mk 25 | 26 | test1: test1.cc 27 | test2: test2.cc 28 | test3: test3.cc 29 | test4: test4.cc 30 | test5: test5.cc 31 | test6: test6.cc 32 | test7: test7.cc 33 | test8: test8.cc 34 | test9: test9.cc 35 | test10: test10.cc 36 | test11: test11.cc 37 | test12: test12.cc 38 | test13: test13.cc 39 | -------------------------------------------------------------------------------- /reactor/s12/Timer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Timer.h" 9 | 10 | using namespace muduo; 11 | 12 | AtomicInt64 Timer::s_numCreated_; 13 | 14 | void Timer::restart(Timestamp now) 15 | { 16 | if (repeat_) 17 | { 18 | expiration_ = addTime(now, interval_); 19 | } 20 | else 21 | { 22 | expiration_ = Timestamp::invalid(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /reactor/s12/TimerId.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_TIMERID_H 9 | #define MUDUO_NET_TIMERID_H 10 | 11 | #include "datetime/copyable.h" 12 | 13 | namespace muduo 14 | { 15 | 16 | class Timer; 17 | 18 | /// 19 | /// An opaque identifier, for canceling Timer. 20 | /// 21 | class TimerId : public muduo::copyable 22 | { 23 | public: 24 | TimerId(Timer* timer = NULL, int64_t seq = 0) 25 | : timer_(timer), 26 | sequence_(seq) 27 | { 28 | } 29 | 30 | // default copy-ctor, dtor and assignment are okay 31 | 32 | friend class TimerQueue; 33 | 34 | private: 35 | Timer* timer_; 36 | int64_t sequence_; 37 | }; 38 | 39 | } 40 | 41 | #endif // MUDUO_NET_TIMERID_H 42 | -------------------------------------------------------------------------------- /reactor/s12/test1.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | #include 4 | 5 | void threadFunc() 6 | { 7 | printf("threadFunc(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | 10 | muduo::EventLoop loop; 11 | loop.loop(); 12 | } 13 | 14 | int main() 15 | { 16 | printf("main(): pid = %d, tid = %d\n", 17 | getpid(), muduo::CurrentThread::tid()); 18 | 19 | muduo::EventLoop loop; 20 | 21 | muduo::Thread thread(threadFunc); 22 | thread.start(); 23 | 24 | loop.loop(); 25 | pthread_exit(NULL); 26 | } 27 | -------------------------------------------------------------------------------- /reactor/s12/test12.cc: -------------------------------------------------------------------------------- 1 | #include "Connector.h" 2 | #include "EventLoop.h" 3 | 4 | #include 5 | 6 | muduo::EventLoop* g_loop; 7 | 8 | void connectCallback(int sockfd) 9 | { 10 | printf("connected.\n"); 11 | g_loop->quit(); 12 | } 13 | 14 | int main(int argc, char* argv[]) 15 | { 16 | muduo::EventLoop loop; 17 | g_loop = &loop; 18 | muduo::InetAddress addr("127.0.0.1", 9981); 19 | muduo::ConnectorPtr connector(new muduo::Connector(&loop, addr)); 20 | connector->setNewConnectionCallback(connectCallback); 21 | connector->start(); 22 | 23 | loop.loop(); 24 | } 25 | -------------------------------------------------------------------------------- /reactor/s12/test2.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | 4 | muduo::EventLoop* g_loop; 5 | 6 | void threadFunc() 7 | { 8 | g_loop->loop(); 9 | } 10 | 11 | int main() 12 | { 13 | muduo::EventLoop loop; 14 | g_loop = &loop; 15 | muduo::Thread t(threadFunc); 16 | t.start(); 17 | t.join(); 18 | } 19 | -------------------------------------------------------------------------------- /reactor/s12/test3.cc: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | 4 | #include 5 | #include 6 | 7 | muduo::EventLoop* g_loop; 8 | 9 | void timeout(muduo::Timestamp receiveTime) 10 | { 11 | printf("%s Timeout!\n", receiveTime.toFormattedString().c_str()); 12 | g_loop->quit(); 13 | } 14 | 15 | int main() 16 | { 17 | printf("%s started\n", muduo::Timestamp::now().toFormattedString().c_str()); 18 | muduo::EventLoop loop; 19 | g_loop = &loop; 20 | 21 | int timerfd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 22 | muduo::Channel channel(&loop, timerfd); 23 | channel.setReadCallback(timeout); 24 | channel.enableReading(); 25 | 26 | struct itimerspec howlong; 27 | bzero(&howlong, sizeof howlong); 28 | howlong.it_value.tv_sec = 5; 29 | ::timerfd_settime(timerfd, 0, &howlong, NULL); 30 | 31 | loop.loop(); 32 | 33 | ::close(timerfd); 34 | } 35 | -------------------------------------------------------------------------------- /reactor/s12/test5.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include 3 | 4 | muduo::EventLoop* g_loop; 5 | int g_flag = 0; 6 | 7 | void run4() 8 | { 9 | printf("run4(): pid = %d, flag = %d\n", getpid(), g_flag); 10 | g_loop->quit(); 11 | } 12 | 13 | void run3() 14 | { 15 | printf("run3(): pid = %d, flag = %d\n", getpid(), g_flag); 16 | g_loop->runAfter(3, run4); 17 | g_flag = 3; 18 | } 19 | 20 | void run2() 21 | { 22 | printf("run2(): pid = %d, flag = %d\n", getpid(), g_flag); 23 | g_loop->queueInLoop(run3); 24 | } 25 | 26 | void run1() 27 | { 28 | g_flag = 1; 29 | printf("run1(): pid = %d, flag = %d\n", getpid(), g_flag); 30 | g_loop->runInLoop(run2); 31 | g_flag = 2; 32 | } 33 | 34 | int main() 35 | { 36 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 37 | 38 | muduo::EventLoop loop; 39 | g_loop = &loop; 40 | 41 | loop.runAfter(2, run1); 42 | loop.loop(); 43 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 44 | } 45 | -------------------------------------------------------------------------------- /reactor/s12/test6.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "EventLoopThread.h" 3 | #include 4 | 5 | void runInThread() 6 | { 7 | printf("runInThread(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | } 10 | 11 | int main() 12 | { 13 | printf("main(): pid = %d, tid = %d\n", 14 | getpid(), muduo::CurrentThread::tid()); 15 | 16 | muduo::EventLoopThread loopThread; 17 | muduo::EventLoop* loop = loopThread.startLoop(); 18 | loop->runInLoop(runInThread); 19 | sleep(1); 20 | loop->runAfter(2, runInThread); 21 | sleep(3); 22 | loop->quit(); 23 | 24 | printf("exit main().\n"); 25 | } 26 | -------------------------------------------------------------------------------- /reactor/s12/test7.cc: -------------------------------------------------------------------------------- 1 | #include "Acceptor.h" 2 | #include "EventLoop.h" 3 | #include "InetAddress.h" 4 | #include "SocketsOps.h" 5 | #include 6 | 7 | void newConnection(int sockfd, const muduo::InetAddress& peerAddr) 8 | { 9 | printf("newConnection(): accepted a new connection from %s\n", 10 | peerAddr.toHostPort().c_str()); 11 | ::write(sockfd, "How are you?\n", 13); 12 | muduo::sockets::close(sockfd); 13 | } 14 | 15 | int main() 16 | { 17 | printf("main(): pid = %d\n", getpid()); 18 | 19 | muduo::InetAddress listenAddr(9981); 20 | muduo::EventLoop loop; 21 | 22 | muduo::Acceptor acceptor(&loop, listenAddr); 23 | acceptor.setNewConnectionCallback(newConnection); 24 | acceptor.listen(); 25 | 26 | loop.loop(); 27 | } 28 | -------------------------------------------------------------------------------- /reactor/s13/Buffer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Buffer.h" 9 | #include "SocketsOps.h" 10 | #include "logging/Logging.h" 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace muduo; 17 | 18 | ssize_t Buffer::readFd(int fd, int* savedErrno) 19 | { 20 | char extrabuf[65536]; 21 | struct iovec vec[2]; 22 | const size_t writable = writableBytes(); 23 | vec[0].iov_base = begin()+writerIndex_; 24 | vec[0].iov_len = writable; 25 | vec[1].iov_base = extrabuf; 26 | vec[1].iov_len = sizeof extrabuf; 27 | const ssize_t n = readv(fd, vec, 2); 28 | if (n < 0) { 29 | *savedErrno = errno; 30 | } else if (implicit_cast(n) <= writable) { 31 | writerIndex_ += n; 32 | } else { 33 | writerIndex_ = buffer_.size(); 34 | append(extrabuf, n - writable); 35 | } 36 | return n; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /reactor/s13/EventLoopThread.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_EVENTLOOPTHREAD_H 9 | #define MUDUO_NET_EVENTLOOPTHREAD_H 10 | 11 | #include "thread/Condition.h" 12 | #include "thread/Mutex.h" 13 | #include "thread/Thread.h" 14 | 15 | #include 16 | 17 | namespace muduo 18 | { 19 | 20 | class EventLoop; 21 | 22 | class EventLoopThread : boost::noncopyable 23 | { 24 | public: 25 | EventLoopThread(); 26 | ~EventLoopThread(); 27 | EventLoop* startLoop(); 28 | 29 | private: 30 | void threadFunc(); 31 | 32 | EventLoop* loop_; 33 | bool exiting_; 34 | Thread thread_; 35 | MutexLock mutex_; 36 | Condition cond_; 37 | }; 38 | 39 | } 40 | 41 | #endif // MUDUO_NET_EVENTLOOPTHREAD_H 42 | 43 | -------------------------------------------------------------------------------- /reactor/s13/Makefile: -------------------------------------------------------------------------------- 1 | LIB_SRC = \ 2 | Acceptor.cc \ 3 | Buffer.cc \ 4 | Channel.cc \ 5 | Connector.cc \ 6 | EPoller.cc \ 7 | EventLoop.cc \ 8 | EventLoopThread.cc \ 9 | EventLoopThreadPool.cc \ 10 | InetAddress.cc \ 11 | Poller.cc \ 12 | Socket.cc \ 13 | SocketsOps.cc \ 14 | TcpClient.cc \ 15 | TcpConnection.cc \ 16 | TcpServer.cc \ 17 | Timer.cc \ 18 | TimerQueue.cc 19 | 20 | BINARIES = test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 \ 21 | test11 test12 test13 22 | 23 | all: $(BINARIES) 24 | 25 | include ../reactor_lib.mk 26 | 27 | test1: test1.cc 28 | test2: test2.cc 29 | test3: test3.cc 30 | test4: test4.cc 31 | test5: test5.cc 32 | test6: test6.cc 33 | test7: test7.cc 34 | test8: test8.cc 35 | test9: test9.cc 36 | test10: test10.cc 37 | test11: test11.cc 38 | test12: test12.cc 39 | test13: test13.cc 40 | -------------------------------------------------------------------------------- /reactor/s13/Timer.cc: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #include "Timer.h" 9 | 10 | using namespace muduo; 11 | 12 | AtomicInt64 Timer::s_numCreated_; 13 | 14 | void Timer::restart(Timestamp now) 15 | { 16 | if (repeat_) 17 | { 18 | expiration_ = addTime(now, interval_); 19 | } 20 | else 21 | { 22 | expiration_ = Timestamp::invalid(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /reactor/s13/TimerId.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 | 8 | #ifndef MUDUO_NET_TIMERID_H 9 | #define MUDUO_NET_TIMERID_H 10 | 11 | #include "datetime/copyable.h" 12 | 13 | namespace muduo 14 | { 15 | 16 | class Timer; 17 | 18 | /// 19 | /// An opaque identifier, for canceling Timer. 20 | /// 21 | class TimerId : public muduo::copyable 22 | { 23 | public: 24 | TimerId(Timer* timer = NULL, int64_t seq = 0) 25 | : timer_(timer), 26 | sequence_(seq) 27 | { 28 | } 29 | 30 | // default copy-ctor, dtor and assignment are okay 31 | 32 | friend class TimerQueue; 33 | 34 | private: 35 | Timer* timer_; 36 | int64_t sequence_; 37 | }; 38 | 39 | } 40 | 41 | #endif // MUDUO_NET_TIMERID_H 42 | -------------------------------------------------------------------------------- /reactor/s13/test1.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | #include 4 | 5 | void threadFunc() 6 | { 7 | printf("threadFunc(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | 10 | muduo::EventLoop loop; 11 | loop.loop(); 12 | } 13 | 14 | int main() 15 | { 16 | printf("main(): pid = %d, tid = %d\n", 17 | getpid(), muduo::CurrentThread::tid()); 18 | 19 | muduo::EventLoop loop; 20 | 21 | muduo::Thread thread(threadFunc); 22 | thread.start(); 23 | 24 | loop.loop(); 25 | pthread_exit(NULL); 26 | } 27 | -------------------------------------------------------------------------------- /reactor/s13/test12.cc: -------------------------------------------------------------------------------- 1 | #include "Connector.h" 2 | #include "EventLoop.h" 3 | 4 | #include 5 | 6 | muduo::EventLoop* g_loop; 7 | 8 | void connectCallback(int sockfd) 9 | { 10 | printf("connected.\n"); 11 | g_loop->quit(); 12 | } 13 | 14 | int main(int argc, char* argv[]) 15 | { 16 | muduo::EventLoop loop; 17 | g_loop = &loop; 18 | muduo::InetAddress addr("127.0.0.1", 9981); 19 | muduo::ConnectorPtr connector(new muduo::Connector(&loop, addr)); 20 | connector->setNewConnectionCallback(connectCallback); 21 | connector->start(); 22 | 23 | loop.loop(); 24 | } 25 | -------------------------------------------------------------------------------- /reactor/s13/test2.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "thread/Thread.h" 3 | 4 | muduo::EventLoop* g_loop; 5 | 6 | void threadFunc() 7 | { 8 | g_loop->loop(); 9 | } 10 | 11 | int main() 12 | { 13 | muduo::EventLoop loop; 14 | g_loop = &loop; 15 | muduo::Thread t(threadFunc); 16 | t.start(); 17 | t.join(); 18 | } 19 | -------------------------------------------------------------------------------- /reactor/s13/test3.cc: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | 4 | #include 5 | #include 6 | 7 | muduo::EventLoop* g_loop; 8 | 9 | void timeout(muduo::Timestamp receiveTime) 10 | { 11 | printf("%s Timeout!\n", receiveTime.toFormattedString().c_str()); 12 | g_loop->quit(); 13 | } 14 | 15 | int main() 16 | { 17 | printf("%s started\n", muduo::Timestamp::now().toFormattedString().c_str()); 18 | muduo::EventLoop loop; 19 | g_loop = &loop; 20 | 21 | int timerfd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 22 | muduo::Channel channel(&loop, timerfd); 23 | channel.setReadCallback(timeout); 24 | channel.enableReading(); 25 | 26 | struct itimerspec howlong; 27 | bzero(&howlong, sizeof howlong); 28 | howlong.it_value.tv_sec = 5; 29 | ::timerfd_settime(timerfd, 0, &howlong, NULL); 30 | 31 | loop.loop(); 32 | 33 | ::close(timerfd); 34 | } 35 | -------------------------------------------------------------------------------- /reactor/s13/test5.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include 3 | 4 | muduo::EventLoop* g_loop; 5 | int g_flag = 0; 6 | 7 | void run4() 8 | { 9 | printf("run4(): pid = %d, flag = %d\n", getpid(), g_flag); 10 | g_loop->quit(); 11 | } 12 | 13 | void run3() 14 | { 15 | printf("run3(): pid = %d, flag = %d\n", getpid(), g_flag); 16 | g_loop->runAfter(3, run4); 17 | g_flag = 3; 18 | } 19 | 20 | void run2() 21 | { 22 | printf("run2(): pid = %d, flag = %d\n", getpid(), g_flag); 23 | g_loop->queueInLoop(run3); 24 | } 25 | 26 | void run1() 27 | { 28 | g_flag = 1; 29 | printf("run1(): pid = %d, flag = %d\n", getpid(), g_flag); 30 | g_loop->runInLoop(run2); 31 | g_flag = 2; 32 | } 33 | 34 | int main() 35 | { 36 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 37 | 38 | muduo::EventLoop loop; 39 | g_loop = &loop; 40 | 41 | loop.runAfter(2, run1); 42 | loop.loop(); 43 | printf("main(): pid = %d, flag = %d\n", getpid(), g_flag); 44 | } 45 | -------------------------------------------------------------------------------- /reactor/s13/test6.cc: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "EventLoopThread.h" 3 | #include 4 | 5 | void runInThread() 6 | { 7 | printf("runInThread(): pid = %d, tid = %d\n", 8 | getpid(), muduo::CurrentThread::tid()); 9 | } 10 | 11 | int main() 12 | { 13 | printf("main(): pid = %d, tid = %d\n", 14 | getpid(), muduo::CurrentThread::tid()); 15 | 16 | muduo::EventLoopThread loopThread; 17 | muduo::EventLoop* loop = loopThread.startLoop(); 18 | loop->runInLoop(runInThread); 19 | sleep(1); 20 | loop->runAfter(2, runInThread); 21 | sleep(3); 22 | loop->quit(); 23 | 24 | printf("exit main().\n"); 25 | } 26 | -------------------------------------------------------------------------------- /reactor/s13/test7.cc: -------------------------------------------------------------------------------- 1 | #include "Acceptor.h" 2 | #include "EventLoop.h" 3 | #include "InetAddress.h" 4 | #include "SocketsOps.h" 5 | #include 6 | 7 | void newConnection(int sockfd, const muduo::InetAddress& peerAddr) 8 | { 9 | printf("newConnection(): accepted a new connection from %s\n", 10 | peerAddr.toHostPort().c_str()); 11 | ::write(sockfd, "How are you?\n", 13); 12 | muduo::sockets::close(sockfd); 13 | } 14 | 15 | int main() 16 | { 17 | printf("main(): pid = %d\n", getpid()); 18 | 19 | muduo::InetAddress listenAddr(9981); 20 | muduo::EventLoop loop; 21 | 22 | muduo::Acceptor acceptor(&loop, listenAddr); 23 | acceptor.setNewConnectionCallback(newConnection); 24 | acceptor.listen(); 25 | 26 | loop.loop(); 27 | } 28 | -------------------------------------------------------------------------------- /ssl/.gitignore: -------------------------------------------------------------------------------- 1 | benchmark-libressl 2 | loop-libressl 3 | -------------------------------------------------------------------------------- /ssl/TlsAcceptor.cc: -------------------------------------------------------------------------------- 1 | #include "TlsAcceptor.h" 2 | 3 | #include "TlsStream.h" 4 | 5 | #include 6 | #include 7 | 8 | TlsAcceptor::TlsAcceptor(TlsConfig* config, const InetAddress& listenAddr) 9 | : context_(TlsContext::kServer, config), 10 | listenSock_(Socket::createTCP(AF_INET)) 11 | { 12 | listenSock_.setReuseAddr(true); 13 | listenSock_.bindOrDie(listenAddr); 14 | listenSock_.listenOrDie(); 15 | } 16 | 17 | TlsStreamPtr TlsAcceptor::accept() 18 | { 19 | // FIXME: use accept4 20 | int sockfd = ::accept(listenSock_.fd(), NULL, NULL); 21 | if (sockfd >= 0) 22 | { 23 | TlsContext context = context_.accept(sockfd); 24 | if (context.handshake()) 25 | { 26 | LOG_ERROR << context.error(); 27 | return TlsStreamPtr(); 28 | } 29 | return TlsStreamPtr(new TlsStream(std::move(context))); 30 | } 31 | else 32 | { 33 | perror("TlsAcceptor::accept"); 34 | return TlsStreamPtr(); 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /ssl/TlsAcceptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Common.h" 3 | #include "Socket.h" 4 | 5 | #include "TlsContext.h" 6 | 7 | #include 8 | 9 | class InetAddress; 10 | 11 | class TlsStream; 12 | typedef std::unique_ptr TlsStreamPtr; 13 | 14 | class TlsAcceptor : noncopyable 15 | { 16 | public: 17 | TlsAcceptor(TlsConfig* config, const InetAddress& listenAddr); 18 | 19 | ~TlsAcceptor() = default; 20 | TlsAcceptor(TlsAcceptor&&) = default; 21 | TlsAcceptor& operator=(TlsAcceptor&&) = default; 22 | 23 | // thread safe 24 | TlsStreamPtr accept(); 25 | 26 | private: 27 | TlsContext context_; 28 | Socket listenSock_; 29 | }; 30 | 31 | 32 | -------------------------------------------------------------------------------- /ssl/TlsConfig.cc: -------------------------------------------------------------------------------- 1 | 2 | #include "TlsConfig.h" 3 | #include "TlsStream.h" 4 | 5 | int TlsConfig::initialized = tls_init() + 1; 6 | -------------------------------------------------------------------------------- /ssl/TlsConfig.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Common.h" 4 | #include "logging/Logging.h" 5 | 6 | #include 7 | 8 | class TlsConfig : noncopyable 9 | { 10 | public: 11 | TlsConfig() 12 | : config_(CHECK_NOTNULL(tls_config_new())) 13 | { 14 | if (initialized <= 0) 15 | { 16 | LOG_FATAL; 17 | } 18 | } 19 | 20 | ~TlsConfig() 21 | { 22 | tls_config_free(config_); 23 | } 24 | 25 | void setCaFile(StringArg caFile) 26 | { 27 | check(tls_config_set_ca_file(config_, caFile.c_str())); 28 | } 29 | 30 | void setCertFile(StringArg certFile) 31 | { 32 | check(tls_config_set_cert_file(config_, certFile.c_str())); 33 | } 34 | 35 | void setKeyFile(StringArg keyFile) 36 | { 37 | check(tls_config_set_key_file(config_, keyFile.c_str())); 38 | } 39 | 40 | struct tls_config* get() { return config_; } 41 | 42 | private: 43 | void check(int ret) 44 | { 45 | if (ret != 0) 46 | { 47 | LOG_FATAL << tls_config_error(config_); 48 | } 49 | } 50 | 51 | struct tls_config* config_; 52 | 53 | static int initialized; 54 | }; 55 | -------------------------------------------------------------------------------- /ssl/TlsStream.cc: -------------------------------------------------------------------------------- 1 | #include "TlsStream.h" 2 | 3 | TlsStreamPtr TlsStream::connect(TlsConfig* config, const char* hostport, const char* servername) 4 | { 5 | TlsStreamPtr stream; 6 | TlsContext context(TlsContext::kClient, config); 7 | if (context.connect(hostport, servername)) 8 | { 9 | LOG_ERROR << context.error(); 10 | return stream; 11 | } 12 | if (context.handshake()) 13 | { 14 | LOG_ERROR << context.error(); 15 | return stream; 16 | } 17 | stream.reset(new TlsStream(std::move(context))); 18 | return stream; 19 | } 20 | 21 | int TlsStream::receiveSome(void* buf, int len) 22 | { 23 | return context_.read(buf, len); 24 | } 25 | 26 | int TlsStream::sendSome(const void* buf, int len) 27 | { 28 | return context_.write(buf, len); 29 | } 30 | -------------------------------------------------------------------------------- /ssl/TlsStream.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TlsContext.h" 4 | 5 | class InetAddress; 6 | 7 | class TlsStream; 8 | typedef std::unique_ptr TlsStreamPtr; 9 | 10 | // A blocking TLS stream 11 | class TlsStream : noncopyable 12 | { 13 | public: 14 | explicit TlsStream(TlsContext&& context) 15 | : context_(std::move(context)) // must be established 16 | { 17 | LOG_INFO << context_.cipher(); 18 | } 19 | 20 | ~TlsStream() = default; 21 | TlsStream(TlsStream&&) = default; 22 | // TlsStream& operator=(TlsStream&&) = default; 23 | 24 | static TlsStreamPtr connect(TlsConfig* config, const char* hostport, const char* servername = nullptr); 25 | 26 | // NOT thread safe 27 | int receiveAll(void* buf, int len); // read len bytes, unless error happens 28 | int receiveSome(void* buf, int len); // read len or less bytes 29 | 30 | int sendAll(const void* buf, int len); // send len bytes, unless error happens 31 | int sendSome(const void* buf, int len); // send len or less bytes 32 | 33 | private: 34 | TlsContext context_; 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /ssl/client.cc: -------------------------------------------------------------------------------- 1 | #include "timer.h" 2 | 3 | #include "TlsConfig.h" 4 | #include "TlsStream.h" 5 | 6 | int main(int argc, char* argv[]) 7 | { 8 | TlsConfig config; 9 | config.setCaFile("ca.pem"); 10 | const char* hostport = "localhost:4433"; 11 | if (argc > 1) 12 | hostport = argv[1]; 13 | TlsStreamPtr stream = TlsStream::connect(&config, hostport, "Test Server Cert"); 14 | if (stream) 15 | { 16 | LOG_INFO << "OK"; 17 | char buf[16384] = { 0 }; 18 | int64_t total = 0; 19 | Timer t; 20 | t.start(); 21 | while (total < 1e10) 22 | { 23 | int nw = stream->sendSome(buf, sizeof buf); 24 | total += nw; 25 | } 26 | t.stop(); 27 | LOG_INFO << t.seconds(); 28 | // FIXME: getrusage() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ssl/server.cc: -------------------------------------------------------------------------------- 1 | #include "timer.h" 2 | 3 | #include "InetAddress.h" 4 | #include "TlsAcceptor.h" 5 | #include "TlsConfig.h" 6 | #include "TlsStream.h" 7 | 8 | int main(int argc, char* argv[]) 9 | { 10 | TlsConfig config; 11 | // config.setCaFile("ca.pem"); 12 | config.setCertFile("server.pem"); 13 | config.setKeyFile("server.pem"); 14 | 15 | InetAddress listenAddr(4433); 16 | TlsAcceptor acceptor(&config, listenAddr); 17 | 18 | TlsStreamPtr stream = acceptor.accept(); 19 | if (stream) 20 | { 21 | LOG_INFO << "OK"; 22 | int64_t total = 0; 23 | char buf[20 * 1024]; 24 | int nr = 0; 25 | Timer t; 26 | t.start(); 27 | while ( (nr = stream->receiveSome(buf, sizeof buf)) > 0) { 28 | // LOG_INFO << "nr = " << nr; 29 | total += nr; 30 | } 31 | // LOG_INFO << "nr = " << nr; 32 | t.stop(); 33 | LOG_INFO << "DONE " << total 34 | << " " << (total / t.seconds() / 1e6) << " MB/s"; 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /ssl/timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | inline double now() 7 | { 8 | struct timeval tv; 9 | gettimeofday(&tv, NULL); 10 | return tv.tv_sec + tv.tv_usec / 1e6; 11 | } 12 | 13 | 14 | struct Timer 15 | { 16 | Timer() 17 | : start_(0), total_(0) 18 | { 19 | } 20 | 21 | void start() 22 | { 23 | start_ = gettime(); 24 | } 25 | 26 | void stop() 27 | { 28 | total_ += gettime() - start_; 29 | } 30 | 31 | void reset() 32 | { 33 | start_ = 0; 34 | total_ = 0; 35 | } 36 | 37 | double seconds() const 38 | { 39 | return total_ / 1e9; 40 | } 41 | 42 | static int64_t gettime() 43 | { 44 | struct timespec ts; 45 | clock_gettime(CLOCK_MONOTONIC_RAW, &ts); 46 | return ts.tv_sec * 1e9 + ts.tv_nsec; 47 | } 48 | 49 | private: 50 | int64_t start_, total_; 51 | }; 52 | -------------------------------------------------------------------------------- /string/StringTrivialTest.cc: -------------------------------------------------------------------------------- 1 | #include "StringTrivial.h" 2 | #include 3 | 4 | using namespace trivial2; 5 | 6 | const char String::kEmpty[] = ""; 7 | 8 | void foo(String x) 9 | { 10 | } 11 | 12 | void bar(const String& x) 13 | { 14 | } 15 | 16 | String baz() 17 | { 18 | String ret("world"); 19 | return ret; 20 | } 21 | 22 | int main() 23 | { 24 | String s0; 25 | String s1("hello"); 26 | String s2(s0); 27 | String s3(s1); 28 | s2 = s1; 29 | s3 = s3; 30 | s1 = "aewsome"; 31 | 32 | foo(s1); 33 | bar(s1); 34 | foo("temporary"); 35 | bar("temporary"); 36 | String s4 = baz(); 37 | s4 = baz(); 38 | 39 | std::vector svec; 40 | svec.push_back(s0); 41 | svec.push_back(s1); 42 | svec.push_back("good job"); 43 | } 44 | 45 | -------------------------------------------------------------------------------- /string/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -x 4 | g++ StringEager.cc main.cc -Wall -m64 -o e64 && ./e64 5 | g++ StringEager.cc main.cc -Wall -m32 -o e32 && ./e32 6 | g++ StringEager.cc main.cc -Wall -m64 -std=c++0x -o f64 && ./f64 7 | g++ StringEager.cc main.cc -Wall -m32 -std=c++0x -o f32 && ./f32 8 | 9 | g++ StringEager.cc test.cc -Wall -DBOOST_TEST_DYN_LINK -lboost_unit_test_framework -m64 -o w64 && ./w64 10 | g++ StringEager.cc test.cc -Wall -m32 -o w32 && ./w32 11 | g++ StringEager.cc test.cc -Wall -DBOOST_TEST_DYN_LINK -lboost_unit_test_framework -m64 -std=c++0x -o u64 && ./u64 12 | g++ StringEager.cc test.cc -Wall -m32 -std=c++0x -o u32 && ./u32 13 | 14 | -------------------------------------------------------------------------------- /string/main.cc: -------------------------------------------------------------------------------- 1 | #include "StringEager.h" 2 | #include "StringSso.h" 3 | #include 4 | 5 | int main() 6 | { 7 | printf("%zd\n", sizeof(muduo::StringEager)); 8 | printf("%zd\n", sizeof(muduo::StringSso)); 9 | muduo::StringEager x; 10 | } 11 | -------------------------------------------------------------------------------- /string/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | g++ StringEager.cc test.cc -Wall -g -DBOOST_TEST_DYN_LINK -lboost_unit_test_framework -m64 -std=c++0x -o u64 3 | ./u64 4 | 5 | -------------------------------------------------------------------------------- /sudoku/Makefile: -------------------------------------------------------------------------------- 1 | CXXFLAGS+=-O2 -ggdb -DDEBUG 2 | CXXFLAGS+=-Wall -Wextra 3 | 4 | all: sudoku 5 | 6 | sudoku: main.cc neighbor.cc sudoku_basic.cc sudoku_min_arity.cc sudoku_min_arity_cache.cc sudoku_dancing_links.cc 7 | g++ -O2 -o $@ $^ 8 | -------------------------------------------------------------------------------- /sudoku/README: -------------------------------------------------------------------------------- 1 | A backtracking sudoku solver, four algorithms are shown. 2 | 3 | test cases are from http://people.csse.uwa.edu.au/gordon/sudokumin.php 4 | -------------------------------------------------------------------------------- /sudoku/sudoku.h: -------------------------------------------------------------------------------- 1 | #ifndef SUDOKU_H 2 | #define SUDOKU_H 3 | 4 | const bool DEBUG_MODE = false; 5 | enum { ROW=9, COL=9, N = 81, NEIGHBOR = 20 }; 6 | const int NUM = 9; 7 | 8 | extern int neighbors[N][NEIGHBOR]; 9 | extern int board[N]; 10 | extern int spaces[N]; 11 | extern int nspaces; 12 | extern int (*chess)[COL]; 13 | 14 | void init_neighbors(); 15 | void input(const char in[N]); 16 | void init_cache(); 17 | 18 | bool available(int guess, int cell); 19 | 20 | bool solve_sudoku_basic(int which_space); 21 | bool solve_sudoku_min_arity(int which_space); 22 | bool solve_sudoku_min_arity_cache(int which_space); 23 | bool solve_sudoku_dancing_links(int unused); 24 | bool solved(); 25 | #endif 26 | -------------------------------------------------------------------------------- /sudoku/test1: -------------------------------------------------------------------------------- 1 | 000000010400000000020000000000050407008000300001090000300400200050100000000806000 2 | -------------------------------------------------------------------------------- /thread/Exception.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (giantchen at gmail dot com) 7 | 8 | #ifndef MUDUO_BASE_EXCEPTION_H 9 | #define MUDUO_BASE_EXCEPTION_H 10 | 11 | #include 12 | #include 13 | 14 | namespace muduo 15 | { 16 | 17 | class Exception : public std::exception 18 | { 19 | public: 20 | explicit Exception(const char* what); 21 | virtual ~Exception() throw(); 22 | virtual const char* what() const throw(); 23 | const char* stackTrace() const throw(); 24 | 25 | private: 26 | std::string message_; 27 | std::string stack_; 28 | }; 29 | 30 | } 31 | 32 | #endif // MUDUO_BASE_EXCEPTION_H 33 | -------------------------------------------------------------------------------- /thread/README: -------------------------------------------------------------------------------- 1 | This is an old version of thread library, 2 | please use the version in muduo/base. 3 | 4 | http://github.com/chenshuo/muduo 5 | 6 | -------------------------------------------------------------------------------- /thread/SignalSlotTrivial.h: -------------------------------------------------------------------------------- 1 | #ifndef MUDUO_BASE_SIGNALSLOTTRIVIAL_H 2 | #define MUDUO_BASE_SIGNALSLOTTRIVIAL_H 3 | 4 | #include 5 | #include 6 | 7 | template 8 | class SignalTrivial; 9 | 10 | template 11 | class SignalTrivial 12 | { 13 | public: 14 | typedef std::function Functor; 15 | 16 | void connect(Functor&& func) 17 | { 18 | functors_.push_back(std::forward(func)); 19 | } 20 | 21 | void call(ARGS&&... args) 22 | { 23 | // gcc 4.6 supports 24 | //for (const Functor& f: functors_) 25 | typename std::vector::iterator it = functors_.begin(); 26 | for (; it != functors_.end(); ++it) 27 | { 28 | (*it)(args...); 29 | } 30 | } 31 | 32 | private: 33 | std::vector functors_; 34 | }; 35 | 36 | #endif // MUDUO_BASE_SIGNALSLOTTRIVIAL_H 37 | -------------------------------------------------------------------------------- /thread/ThreadLocalSingleton.h: -------------------------------------------------------------------------------- 1 | // excerpts from http://code.google.com/p/muduo/ 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the License file. 5 | // 6 | // Author: Shuo Chen (giantchen at gmail dot com) 7 | 8 | #ifndef MUDUO_BASE_THREADLOCALSINGLETON_H 9 | #define MUDUO_BASE_THREADLOCALSINGLETON_H 10 | 11 | #include 12 | 13 | namespace muduo 14 | { 15 | 16 | template 17 | class ThreadLocalSingleton : boost::noncopyable 18 | { 19 | public: 20 | 21 | static T& instance() 22 | { 23 | if (!t_value_) 24 | { 25 | t_value_ = new T(); 26 | } 27 | return *t_value_; 28 | } 29 | 30 | // See muduo/base/ThreadLocalSingleton.h for how to delete it automatically. 31 | static void destroy() 32 | { 33 | delete t_value_; 34 | t_value_ = 0; 35 | } 36 | 37 | private: 38 | ThreadLocalSingleton(); 39 | ~ThreadLocalSingleton(); 40 | 41 | static __thread T* t_value_; 42 | }; 43 | 44 | template 45 | __thread T* ThreadLocalSingleton::t_value_ = 0; 46 | 47 | } 48 | #endif 49 | -------------------------------------------------------------------------------- /thread/test/Atomic_unittest.cc: -------------------------------------------------------------------------------- 1 | #include "../Atomic.h" 2 | #include 3 | 4 | int main() 5 | { 6 | { 7 | muduo::AtomicInt64 a0; 8 | assert(a0.get() == 0); 9 | assert(a0.getAndAdd(1) == 0); 10 | assert(a0.get() == 1); 11 | assert(a0.addAndGet(2) == 3); 12 | assert(a0.get() == 3); 13 | assert(a0.incrementAndGet() == 4); 14 | assert(a0.get() == 4); 15 | a0.increment(); 16 | assert(a0.get() == 5); 17 | assert(a0.addAndGet(-3) == 2); 18 | assert(a0.getAndSet(100) == 2); 19 | assert(a0.get() == 100); 20 | } 21 | 22 | { 23 | muduo::AtomicInt32 a1; 24 | assert(a1.get() == 0); 25 | assert(a1.getAndAdd(1) == 0); 26 | assert(a1.get() == 1); 27 | assert(a1.addAndGet(2) == 3); 28 | assert(a1.get() == 3); 29 | assert(a1.incrementAndGet() == 4); 30 | assert(a1.get() == 4); 31 | a1.increment(); 32 | assert(a1.get() == 5); 33 | assert(a1.addAndGet(-3) == 2); 34 | assert(a1.getAndSet(100) == 2); 35 | assert(a1.get() == 100); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /thread/test/Exception_test.cc: -------------------------------------------------------------------------------- 1 | #include "../Exception.h" 2 | #include 3 | 4 | class Bar 5 | { 6 | public: 7 | void test() 8 | { 9 | throw muduo::Exception("oops"); 10 | } 11 | }; 12 | 13 | void foo() 14 | { 15 | Bar b; 16 | b.test(); 17 | } 18 | 19 | int main() 20 | { 21 | try 22 | { 23 | foo(); 24 | } 25 | catch (const muduo::Exception& ex) 26 | { 27 | printf("reason: %s\n", ex.what()); 28 | printf("stack trace: %s\n", ex.stackTrace()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /thread/test/ExitDeadLock.cc: -------------------------------------------------------------------------------- 1 | #include "../Mutex.h" 2 | 3 | #include 4 | #include 5 | 6 | using namespace muduo; 7 | 8 | void someFunctionMayCallExit() 9 | { 10 | exit(1); 11 | } 12 | 13 | class GlobalObject 14 | { 15 | public: 16 | void doit() 17 | { 18 | MutexLockGuard lock(mutex_); 19 | someFunctionMayCallExit(); 20 | } 21 | 22 | ~GlobalObject() 23 | { 24 | printf("GlobalObject:~GlobalObject\n"); 25 | MutexLockGuard g(mutex_); 26 | // clean up 27 | printf("GlobalObject:~GlobalObject cleanning\n"); 28 | } 29 | 30 | private: 31 | MutexLock mutex_; 32 | }; 33 | 34 | GlobalObject g_obj; 35 | 36 | int main() 37 | { 38 | g_obj.doit(); 39 | } 40 | -------------------------------------------------------------------------------- /thread/test/Fork_test.cc: -------------------------------------------------------------------------------- 1 | #include "../Thread.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | __thread int x = 0; 8 | 9 | void print() 10 | { 11 | printf("pid=%d tid=%d x=%d\n", getpid(), muduo::CurrentThread::tid(), x); 12 | } 13 | 14 | int main() 15 | { 16 | printf("parent %d\n", getpid()); 17 | print(); 18 | x = 1; 19 | print(); 20 | pid_t p = fork(); 21 | 22 | if (p == 0) 23 | { 24 | printf("chlid %d\n", getpid()); 25 | // child 26 | print(); 27 | x = 2; 28 | print(); 29 | 30 | if (fork() == 0) 31 | { 32 | printf("grandchlid %d\n", getpid()); 33 | print(); 34 | x = 3; 35 | print(); 36 | } 37 | } 38 | else 39 | { 40 | // parent 41 | print(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /thread/test/NonRecursiveMutex_test.cc: -------------------------------------------------------------------------------- 1 | #include "../Mutex.h" 2 | #include "../Thread.h" 3 | #include 4 | #include 5 | 6 | using namespace muduo; 7 | 8 | class Foo 9 | { 10 | public: 11 | void doit() const; 12 | }; 13 | 14 | MutexLock mutex; 15 | std::vector foos; 16 | 17 | void post(const Foo& f) 18 | { 19 | MutexLockGuard lock(mutex); 20 | foos.push_back(f); 21 | } 22 | 23 | void traverse() 24 | { 25 | MutexLockGuard lock(mutex); 26 | for (std::vector::const_iterator it = foos.begin(); 27 | it != foos.end(); ++it) 28 | { 29 | it->doit(); 30 | } 31 | } 32 | 33 | void Foo::doit() const 34 | { 35 | Foo f; 36 | post(f); 37 | } 38 | 39 | int main() 40 | { 41 | Foo f; 42 | post(f); 43 | traverse(); 44 | } 45 | 46 | -------------------------------------------------------------------------------- /thread/test/SelfDeadLock.cc: -------------------------------------------------------------------------------- 1 | #include "../Mutex.h" 2 | 3 | class Request 4 | { 5 | public: 6 | void process() // __attribute__ ((noinline)) 7 | { 8 | muduo::MutexLockGuard lock(mutex_); 9 | print(); 10 | } 11 | 12 | void print() const // __attribute__ ((noinline)) 13 | { 14 | muduo::MutexLockGuard lock(mutex_); 15 | } 16 | 17 | private: 18 | mutable muduo::MutexLock mutex_; 19 | }; 20 | 21 | int main() 22 | { 23 | Request req; 24 | req.process(); 25 | } 26 | -------------------------------------------------------------------------------- /thread/test/ThreadPool_test.cc: -------------------------------------------------------------------------------- 1 | #include "../ThreadPool.h" 2 | #include "../CountDownLatch.h" 3 | 4 | #include 5 | #include 6 | 7 | void print() 8 | { 9 | printf("tid=%d\n", muduo::CurrentThread::tid()); 10 | } 11 | 12 | void printString(const std::string& str) 13 | { 14 | printf("tid=%d, str=%s\n", muduo::CurrentThread::tid(), str.c_str()); 15 | } 16 | 17 | int main() 18 | { 19 | muduo::ThreadPool pool("MainThreadPool"); 20 | pool.start(5); 21 | 22 | pool.run(print); 23 | pool.run(print); 24 | for (int i = 0; i < 100; ++i) 25 | { 26 | char buf[32]; 27 | snprintf(buf, sizeof buf, "task %d", i); 28 | pool.run(boost::bind(printString, std::string(buf))); 29 | } 30 | 31 | muduo::CountDownLatch latch(1); 32 | pool.run(boost::bind(&muduo::CountDownLatch::countDown, &latch)); 33 | latch.wait(); 34 | pool.stop(); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /thread/test/destruct.cc: -------------------------------------------------------------------------------- 1 | #include "../Mutex.h" 2 | #include 3 | 4 | using std::string; 5 | 6 | muduo::MutexLock g_mutex; 7 | string g_str = "Hello"; 8 | int32_t g_int32 = 123; 9 | int64_t g_int64 = 4321; 10 | 11 | string getString() 12 | { 13 | muduo::MutexLockGuard lock(g_mutex); 14 | return g_str; 15 | } 16 | 17 | int32_t getInt32() 18 | { 19 | muduo::MutexLockGuard lock(g_mutex); 20 | return g_int32; 21 | } 22 | 23 | int64_t getInt64() 24 | { 25 | muduo::MutexLockGuard lock(g_mutex); 26 | return g_int64; 27 | } 28 | 29 | int main() 30 | { 31 | getString(); 32 | getInt32(); 33 | getInt64(); 34 | } 35 | -------------------------------------------------------------------------------- /topk/.gitignore: -------------------------------------------------------------------------------- 1 | sender 2 | merger 3 | word_freq 4 | word_freq_shards 5 | word_freq_sort 6 | bazel-* 7 | -------------------------------------------------------------------------------- /topk/BUILD.bazel: -------------------------------------------------------------------------------- 1 | cc_binary( 2 | name = "word_freq_shards_basic", 3 | srcs = ["word_freq_shards_basic.cc"], 4 | # linkopts = ["-ltcmalloc_and_profiler"], 5 | deps = [ 6 | ":common", 7 | "@absl//absl/container:flat_hash_map", 8 | ], 9 | ) 10 | 11 | cc_binary( 12 | name = "word_freq_sort_basic", 13 | srcs = ["word_freq_sort_basic.cc"], 14 | # linkopts = ["-lprofiler"], 15 | deps = [ 16 | ":common", 17 | "@muduo//muduo/base", 18 | ], 19 | ) 20 | 21 | cc_library( 22 | name = "common", 23 | hdrs = [ 24 | "file.h", 25 | "input.h", 26 | "merge.h", 27 | "timer.h", 28 | ], 29 | deps = [ 30 | "@absl//absl/strings:str_format", 31 | "@muduo//muduo/base", 32 | ], 33 | ) 34 | 35 | cc_test( 36 | name = "benchmark", 37 | srcs = ["benchmark.cc"], 38 | # linkopts = ["-ltcmalloc_and_profiler"], 39 | deps = [ 40 | ":common", 41 | "@absl//absl/container:flat_hash_set", 42 | ], 43 | ) 44 | -------------------------------------------------------------------------------- /topk/Makefile: -------------------------------------------------------------------------------- 1 | MUDUO_BUILD ?= release 2 | MUDUO_DIRECTORY ?= $(HOME)/build/$(MUDUO_BUILD)-install 3 | MUDUO_INCLUDE = $(MUDUO_DIRECTORY)/include 4 | MUDUO_LIBRARY = $(MUDUO_DIRECTORY)/lib 5 | 6 | CXXFLAGS = -g -Og -Wall -Wextra -Werror \ 7 | -Wno-unused-parameter -Wconversion\ 8 | -Wold-style-cast -Woverloaded-virtual \ 9 | -Wpointer-arith -Wshadow -Wwrite-strings \ 10 | -march=native -rdynamic \ 11 | -I$(MUDUO_INCLUDE) 12 | 13 | LDFLAGS = -L$(MUDUO_LIBRARY) -lmuduo_net -lmuduo_base -lpthread 14 | 15 | BINARIES = sender merger word_freq word_freq_shards word_freq_sort 16 | 17 | all: $(BINARIES) 18 | 19 | clean: 20 | rm -f $(BINARIES) core 21 | 22 | sender: sender.cc 23 | g++ $(CXXFLAGS) -o $@ $^ $(LDFLAGS) 24 | 25 | merger: merger.cc 26 | g++ $(CXXFLAGS) -o $@ $^ -lboost_system -lpthread 27 | 28 | word_freq: word_freq.cc 29 | g++ $(CXXFLAGS) -std=c++1y -o $@ $^ 30 | 31 | word_freq_shards: word_freq_shards.cc 32 | g++ $(CXXFLAGS) -std=c++11 -o $@ $^ 33 | 34 | word_freq_sort: word_freq_sort.cc 35 | g++ $(CXXFLAGS) -std=c++11 -o $@ $^ 36 | 37 | .PHONY: all clean 38 | -------------------------------------------------------------------------------- /topk/WORKSPACE: -------------------------------------------------------------------------------- 1 | workspace(name = "com_chenshuo_recipes_topk") 2 | 3 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 4 | 5 | # abseil 6 | http_archive( 7 | name = "absl", 8 | strip_prefix = "abseil-cpp-master", 9 | urls = ["https://github.com/abseil/abseil-cpp/archive/master.zip"], 10 | ) 11 | 12 | # muduo 13 | http_archive( 14 | name = "muduo", 15 | strip_prefix = "muduo-master", 16 | urls = ["https://github.com/chenshuo/muduo/archive/master.zip"], 17 | ) 18 | -------------------------------------------------------------------------------- /topk/gen.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // generate a 10G input of 1B entries (472M unique), top entries are: 5 | /* 6 | 31 3209505773 7 | 29 2131583786 8 | 29 2912700161 9 | 29 494155588 10 | 29 244318914 11 | 29 3795640459 12 | 29 3736353633 13 | 29 3792368229 14 | 28 2134003008 15 | 28 3755101979 16 | 28 2615920895 17 | 28 4103497323 18 | 28 124613411 19 | 28 3877714427 20 | */ 21 | int main() 22 | { 23 | int iter = 0; 24 | for (int x = 500 * 1000 * 1000; x > 0; x /= 2) 25 | { 26 | std::mt19937 gen(43); 27 | for (int i = 0; i < x; ++i) 28 | printf("%lu\n", gen()); 29 | ++iter; 30 | } 31 | printf("%d\n", iter); 32 | } 33 | -------------------------------------------------------------------------------- /topk/gen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import numpy 4 | 5 | words = 100*1000*1000 6 | S = 1.0001 7 | 8 | output = open('random_words', 'w') 9 | 10 | for x in range(words): 11 | output.write("%x\n" % numpy.random.zipf(S)) 12 | -------------------------------------------------------------------------------- /topk/gen_count.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import random 4 | 5 | word_len = 5 6 | alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' 7 | 8 | output = open('word_count', 'w') 9 | words = set() 10 | N = 1000*1000 11 | for x in xrange(N): 12 | arr = [random.choice(alphabet) for i in range(word_len)] 13 | words.add(''.join(arr)) 14 | 15 | print len(words) 16 | for word in words: 17 | output.write(word) 18 | output.write('\t') 19 | output.write(str(random.randint(1, 2*N))) 20 | output.write('\n') 21 | 22 | -------------------------------------------------------------------------------- /topk/split.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | std::string getOutputName(int n) 5 | { 6 | char buf[256]; 7 | snprintf(buf, sizeof buf, "input-%03d", n); 8 | printf("%s\n", buf); 9 | return buf; 10 | } 11 | 12 | int main(int argc, char* argv[]) 13 | { 14 | std::ifstream in(argv[1]); 15 | std::string line; 16 | int count = 0; 17 | int size = 0; 18 | int64_t total = 0; 19 | std::unique_ptr out(new std::ofstream(getOutputName(count))); 20 | while (getline(in, line)) 21 | { 22 | line.append("\n"); 23 | size += line.size(); 24 | total += size; 25 | *out << line; 26 | if (size >= 1000'000'000) 27 | { 28 | ++count; 29 | out.reset(new std::ofstream(getOutputName(count))); 30 | size = 0; 31 | } 32 | } 33 | // out.reset(); 34 | } 35 | 36 | 37 | -------------------------------------------------------------------------------- /topk/timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "absl/strings/str_format.h" 6 | #include "muduo/base/ProcessInfo.h" 7 | #include "muduo/base/Timestamp.h" 8 | 9 | class Timer 10 | { 11 | public: 12 | Timer() 13 | : start_(now()), 14 | start_cpu_(muduo::ProcessInfo::cpuTime()) 15 | { 16 | } 17 | 18 | std::string report(int64_t bytes) const 19 | { 20 | muduo::ProcessInfo::CpuTime end_cpu(muduo::ProcessInfo::cpuTime()); 21 | double seconds = now() - start_; 22 | char buf[64]; 23 | snprintf(buf, sizeof buf, "%'zd", bytes); 24 | return absl::StrFormat("%.2fs real %.2fs cpu %6.2f MiB/s %s bytes", 25 | seconds, end_cpu.total() - start_cpu_.total(), 26 | bytes / seconds / 1024 / 1024, buf); 27 | } 28 | 29 | static double now() 30 | { 31 | struct timeval tv = { 0, 0 }; 32 | gettimeofday(&tv, nullptr); 33 | return tv.tv_sec + tv.tv_usec / 1000000.0; 34 | } 35 | 36 | private: 37 | const double start_; 38 | const muduo::ProcessInfo::CpuTime start_cpu_; 39 | }; 40 | -------------------------------------------------------------------------------- /topk/word_freq.cc: -------------------------------------------------------------------------------- 1 | // sort word by frequency, in-memory version. 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | typedef std::unordered_map WordCount; 8 | 9 | int main() 10 | { 11 | WordCount counts; 12 | std::string word; 13 | while (std::cin >> word) 14 | { 15 | counts[word]++; 16 | } 17 | 18 | std::vector> freq; 19 | freq.reserve(counts.size()); 20 | for (auto it = counts.cbegin(); it != counts.cend(); ++it) 21 | { 22 | freq.push_back(make_pair(it->second, it)); 23 | } 24 | 25 | std::sort(freq.begin(), freq.end(), [](const std::pair& lhs, // const auto& lhs in C++14 26 | const std::pair& rhs) { 27 | return lhs.first > rhs.first; 28 | }); 29 | // printf("%zd\n", sizeof(freq[0])); 30 | for (auto item : freq) 31 | { 32 | std::cout << item.first << '\t' << item.second->first << '\n'; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tpc/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CXXFLAGS = -Wall -std=c++11 -pthread -O2 -g -iquote include/ -I../ -I/usr/local/include 3 | LDFLAGS = -L lib/ -L/usr/local/lib -ltpc 4 | 5 | LIB_HEADERS := $(wildcard include/*.h) ../datetime/Timestamp.h ../thread/Atomic.h 6 | LIB_SRCS := $(wildcard lib/*.cc) ../datetime/Timestamp.cc 7 | LIB_OBJS := $(LIB_SRCS:.cc=.o) 8 | LIB := lib/libtpc.a 9 | 10 | BIN_SRCS := $(wildcard bin/*.cc) 11 | BINS := $(BIN_SRCS:.cc=) 12 | 13 | all: $(BINS) 14 | lib: $(LIB) 15 | 16 | $(LIB_OBJS) : Makefile $(LIB_HEADERS) 17 | 18 | $(LIB): $(LIB_OBJS) 19 | ar rcs $@ $^ 20 | 21 | $(BINS): $(LIB) 22 | 23 | bin/ttcp: LDLIBS += -lboost_program_options 24 | 25 | clean: 26 | rm -f $(LIB_OBJS) $(LIB) $(BINS) 27 | 28 | -------------------------------------------------------------------------------- /tpc/README: -------------------------------------------------------------------------------- 1 | A simple wrapper of Sockets API in C++11, supports blocking IO only. 2 | TPC stands for thread-per-connection, which is the current model for blocking IO. 3 | -------------------------------------------------------------------------------- /tpc/bin/.gitignore: -------------------------------------------------------------------------------- 1 | chargen 2 | discard 3 | echo 4 | echo_client 5 | footprint 6 | netcat 7 | nodelay 8 | nodelay_server 9 | perf.data 10 | roundtrip_tcp 11 | roundtrip_udp 12 | sender 13 | sendoob 14 | sudoku_stress 15 | tcpperf 16 | ttcp 17 | 18 | -------------------------------------------------------------------------------- /tpc/bin/sendoob.cc: -------------------------------------------------------------------------------- 1 | #include "InetAddress.h" 2 | #include "Socket.h" 3 | #include 4 | 5 | // RFC6093: On the Implementation of the TCP Urgent Mechanism, 2011/01. 6 | // Which recommends against the use of urgent mechanism. 7 | 8 | int main(int argc, char* argv[]) 9 | { 10 | if (argc < 3) 11 | { 12 | printf("Usage:\n %s hostname port\n", argv[0]); 13 | return 0; 14 | } 15 | 16 | int port = atoi(argv[2]); 17 | InetAddress addr; 18 | const char* hostname = argv[1]; 19 | if (InetAddress::resolve(hostname, port, &addr)) 20 | { 21 | Socket sock(Socket::createTCP(addr.family())); 22 | if (sock.connect(addr) == 0) 23 | { 24 | const char* buf = "hello"; 25 | ssize_t nw = ::send(sock.fd(), buf, strlen(buf), MSG_OOB); 26 | printf("sent %zd bytes\n", nw); 27 | getchar(); 28 | } 29 | else 30 | { 31 | perror("connect"); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tpc/include/Acceptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Common.h" 3 | #include "Socket.h" 4 | 5 | #include 6 | 7 | class InetAddress; 8 | 9 | class TcpStream; 10 | typedef std::unique_ptr TcpStreamPtr; 11 | 12 | class Acceptor : noncopyable 13 | { 14 | public: 15 | explicit Acceptor(const InetAddress& listenAddr); 16 | 17 | ~Acceptor() = default; 18 | Acceptor(Acceptor&&) = default; 19 | Acceptor& operator=(Acceptor&&) = default; 20 | 21 | // thread safe 22 | TcpStreamPtr accept(); 23 | Socket acceptSocketOrDie(); 24 | 25 | private: 26 | Socket listenSock_; 27 | }; 28 | 29 | 30 | -------------------------------------------------------------------------------- /tpc/include/Common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include // memset 5 | 6 | inline void memZero(void* p, size_t n) 7 | { 8 | memset(p, 0, n); 9 | } 10 | 11 | class noncopyable 12 | { 13 | protected: 14 | noncopyable() {} 15 | 16 | private: 17 | noncopyable(const noncopyable&) = delete; 18 | void operator=(const noncopyable&) = delete; 19 | }; 20 | 21 | struct copyable 22 | { 23 | }; 24 | 25 | // For passing C-style string argument to a function. 26 | class StringArg : copyable 27 | { 28 | public: 29 | StringArg(const char* str) 30 | : str_(str) 31 | { } 32 | 33 | StringArg(const std::string& str) 34 | : str_(str.c_str()) 35 | { } 36 | 37 | const char* c_str() const { return str_; } 38 | 39 | private: 40 | const char* str_; 41 | }; 42 | 43 | template 44 | inline To implicit_cast(From f) 45 | { 46 | return f; 47 | } 48 | -------------------------------------------------------------------------------- /tpc/lib/Acceptor.cc: -------------------------------------------------------------------------------- 1 | #include "Acceptor.h" 2 | 3 | #include "InetAddress.h" 4 | #include "TcpStream.h" 5 | 6 | #include 7 | #include 8 | 9 | Acceptor::Acceptor(const InetAddress& listenAddr) 10 | : listenSock_(Socket::createTCP(listenAddr.family())) 11 | { 12 | listenSock_.setReuseAddr(true); 13 | listenSock_.bindOrDie(listenAddr); 14 | listenSock_.listenOrDie(); 15 | } 16 | 17 | TcpStreamPtr Acceptor::accept() 18 | { 19 | // FIXME: use accept4 20 | int sockfd = ::accept(listenSock_.fd(), NULL, NULL); 21 | if (sockfd >= 0) 22 | { 23 | return TcpStreamPtr(new TcpStream(Socket(sockfd))); 24 | } 25 | else 26 | { 27 | perror("Acceptor::accept"); 28 | return TcpStreamPtr(); 29 | } 30 | } 31 | 32 | Socket Acceptor::acceptSocketOrDie() 33 | { 34 | // FIXME: use accept4 35 | int sockfd = ::accept(listenSock_.fd(), NULL, NULL); 36 | if (sockfd >= 0) 37 | { 38 | return Socket(sockfd); 39 | } 40 | else 41 | { 42 | perror("Acceptor::acceptSocketOrDie"); 43 | abort(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /utility/Makefile: -------------------------------------------------------------------------------- 1 | LIBDIR=/usr/local/lib 2 | 3 | CXXFLAGS=-g -Wall -O2 -pthread 4 | #LDFLAGS=-lprotobuf -lz -lpthread -Wl,-rpath -Wl,$(LIBDIR) 5 | 6 | SRCS=x 7 | BINARIES=cwc 8 | 9 | all: $(BINARIES) 10 | 11 | cwc: cwc.cc 12 | 13 | $(BINARIES): 14 | g++ $(CXXFLAGS) $(LDFLAGS) $(filter %.cc,$^) -o $@ 15 | 16 | clean: 17 | rm -f $(BINARIES) 18 | 19 | --------------------------------------------------------------------------------