├── .gitignore ├── .gitmodules ├── .travis.yml ├── 3rdparty ├── astyle_2.06_linux.tar.gz ├── gtest │ ├── gtest-death-test.h │ ├── gtest-message.h │ ├── gtest-param-test.h │ ├── gtest-param-test.h.pump │ ├── gtest-printers.h │ ├── gtest-spi.h │ ├── gtest-test-part.h │ ├── gtest-typed-test.h │ ├── gtest.h │ ├── gtest_pred_impl.h │ ├── gtest_prod.h │ ├── internal │ │ ├── gtest-death-test-internal.h │ │ ├── gtest-filepath.h │ │ ├── gtest-internal.h │ │ ├── gtest-linked_ptr.h │ │ ├── gtest-param-util-generated.h │ │ ├── gtest-param-util-generated.h.pump │ │ ├── gtest-param-util.h │ │ ├── gtest-port.h │ │ ├── gtest-string.h │ │ ├── gtest-tuple.h │ │ ├── gtest-tuple.h.pump │ │ ├── gtest-type-util.h │ │ └── gtest-type-util.h.pump │ └── src │ │ ├── gtest-all.cc │ │ ├── gtest-death-test.cc │ │ ├── gtest-filepath.cc │ │ ├── gtest-internal-inl.h │ │ ├── gtest-port.cc │ │ ├── gtest-printers.cc │ │ ├── gtest-test-part.cc │ │ ├── gtest-typed-test.cc │ │ ├── gtest.cc │ │ └── gtest_main.cc ├── libhashkit │ ├── Makefile │ ├── algorithm.c │ ├── algorithm.h │ ├── behavior.c │ ├── behavior.h │ ├── common.h │ ├── configure.h │ ├── crc32.c │ ├── digest.c │ ├── digest.h │ ├── fnv.c │ ├── function.c │ ├── function.h │ ├── hashkit.c │ ├── hashkit.h │ ├── hsieh.c │ ├── include.am │ ├── jenkins.c │ ├── ketama.c │ ├── md5.c │ ├── murmur.c │ ├── one_at_a_time.c │ ├── strerror.c │ ├── strerror.h │ ├── types.h │ └── visibility.h ├── memcached │ ├── protocol_binary.h │ └── vbucket.h ├── rapidjson │ ├── allocators.h │ ├── document.h │ ├── encodedstream.h │ ├── encodings.h │ ├── error │ │ ├── en.h │ │ └── error.h │ ├── filereadstream.h │ ├── filewritestream.h │ ├── internal │ │ ├── biginteger.h │ │ ├── diyfp.h │ │ ├── dtoa.h │ │ ├── ieee754.h │ │ ├── itoa.h │ │ ├── meta.h │ │ ├── pow10.h │ │ ├── stack.h │ │ ├── strfunc.h │ │ └── strtod.h │ ├── memorybuffer.h │ ├── memorystream.h │ ├── msinttypes │ │ ├── inttypes.h │ │ └── stdint.h │ ├── prettywriter.h │ ├── rapidjson.h │ ├── reader.h │ ├── stringbuffer.h │ ├── version.txt │ └── writer.h ├── win32code │ └── getopt │ │ ├── getopt.c │ │ ├── getopt.h │ │ └── getopt_long.c └── wininclude │ └── getopt.h ├── CMakeLists.txt ├── LICENSE ├── apps ├── CMakeLists.txt ├── evmc │ ├── .gitignore │ ├── CMakeLists.txt │ ├── binary_codec.cc │ ├── binary_codec.h │ ├── command.cc │ ├── command.h │ ├── config.h │ ├── extract_vbucket_conf.cc │ ├── extract_vbucket_conf.h │ ├── likely.h │ ├── mctypes.h │ ├── memcache_client.cc │ ├── memcache_client.h │ ├── memcache_client_base.cc │ ├── memcache_client_base.h │ ├── memcache_client_pool.cc │ ├── memcache_client_pool.h │ ├── memcache_client_serial.cc │ ├── memcache_client_serial.h │ ├── memcached.h │ ├── random.h │ ├── readme.md │ ├── test │ │ ├── CMakeLists.txt │ │ ├── kill_storage_cluster.json │ │ └── mcpool_test.cc │ ├── vbucket_config.cc │ └── vbucket_config.h ├── evnsq │ ├── CMakeLists.txt │ ├── client.cc │ ├── client.h │ ├── command.cc │ ├── command.h │ ├── config.h │ ├── consumer.cc │ ├── consumer.h │ ├── evnsqtail │ │ ├── CMakeLists.txt │ │ └── main.cc │ ├── message.h │ ├── nsq_conn.cc │ ├── nsq_conn.h │ ├── option.cc │ ├── option.h │ ├── producer.cc │ ├── producer.h │ ├── readme.md │ ├── test │ │ ├── CMakeLists.txt │ │ └── producer_with_auth │ │ │ ├── CMakeLists.txt │ │ │ └── main.cc │ └── windows_port.h └── readme.md ├── benchmark ├── CMakeLists.txt ├── gettimeofday │ ├── CMakeLists.txt │ └── gettimeofday.cc ├── http │ ├── CMakeLists.txt │ ├── evpp │ │ ├── CMakeLists.txt │ │ └── evpp_http_bench.cc │ └── libevent │ │ ├── CMakeLists.txt │ │ └── libevent_http_bench.c ├── ioevent │ ├── CMakeLists.txt │ ├── asio │ │ └── run_ioevent_bench.sh │ ├── evpp │ │ ├── CMakeLists.txt │ │ ├── evpp_ioevent_bench.cc │ │ └── evpp_ioevent_pipe_watcher.cc │ ├── fd_channel_vs_pipe_event_watcher │ │ ├── CMakeLists.txt │ │ └── fd_channel_vs_pipe_event_watcher.cc │ ├── libevent │ │ ├── CMakeLists.txt │ │ ├── README │ │ ├── libevent_ioevent_bench.c │ │ └── run_bench.sh │ └── run_ioevent_bench.sh ├── post_task │ ├── CMakeLists.txt │ ├── bench.sh │ ├── post_task1.cc │ ├── post_task2.cc │ ├── post_task3.cc │ ├── post_task4.cc │ ├── post_task5.cc │ ├── post_task6.cc │ └── readme.md ├── throughput │ ├── CMakeLists.txt │ ├── asio │ │ ├── multiple_thread.sh │ │ └── single_thread.sh │ ├── asio_from_chenshuo │ │ ├── CMakeLists.txt │ │ ├── LICENSE_1_0.txt │ │ ├── README │ │ ├── asio.hpp │ │ ├── build.sh │ │ ├── client.cpp │ │ ├── handler_allocator.hpp │ │ ├── multiple_thread.sh │ │ ├── server.cpp │ │ └── single_thread.sh │ ├── evpp │ │ ├── CMakeLists.txt │ │ ├── README │ │ ├── client.cc │ │ ├── client_fixed_size.cc │ │ ├── multiple_thread.sh │ │ ├── server.cc │ │ └── single_thread.sh │ └── libevent │ │ ├── CMakeLists.txt │ │ ├── Makefile │ │ ├── README │ │ ├── bench.c │ │ ├── client.c │ │ ├── run_bench.sh │ │ ├── server-half-close.c │ │ ├── server-line-echo.c │ │ ├── server.c │ │ └── single_thread.sh └── throughput_header_body │ ├── CMakeLists.txt │ ├── asio │ └── m3.sh │ ├── evpp │ ├── CMakeLists.txt │ ├── client.cc │ ├── header.h │ ├── m3.sh │ └── server.cc │ └── readme.md ├── cmake ├── git_checkin_count.sh ├── packages.cmake ├── rpm_kernel_release.sh └── utils.cmake ├── docs ├── benchmark │ ├── http-rps │ │ └── rps-http-1thread-evpp-vs-libevent.chart │ ├── ioevent │ │ ├── ioevent-evpp-boost.chart │ │ └── ioevent-evpp-muduo-boost-libevent-opt.chart │ ├── post_task │ │ ├── boost-lockfree-vs-mutex-benchmark-1v1.chart │ │ ├── boost-lockfree-vs-mutex-benchmark.chart │ │ ├── evpp-post-task.chart │ │ └── post.log │ ├── throughput │ │ ├── throughput-1thread-evpp-vs-asio-1.chart │ │ ├── throughput-1thread-evpp-vs-asio-2.chart │ │ ├── throughput-1thread-evpp-vs-asio-3.chart │ │ ├── throughput-1thread-evpp-vs-asio-4.chart │ │ ├── throughput-1thread-evpp-vs-asio-5.chart │ │ ├── throughput-1thread-evpp-vs-asio-6.chart │ │ ├── throughput-1thread-evpp-vs-asio-all.chart │ │ ├── throughput-1thread-evpp-vs-asio-from-chenshuo-recipes.chart │ │ ├── throughput-1thread-evpp-vs-libevent-1.chart │ │ ├── throughput-1thread-evpp-vs-libevent-2.chart │ │ ├── throughput-1thread-evpp-vs-libevent-3.chart │ │ ├── throughput-1thread-evpp-vs-libevent-4.chart │ │ ├── throughput-1thread-evpp-vs-libevent-5.chart │ │ ├── throughput-1thread-evpp-vs-libevent-all.chart │ │ ├── throughput-1thread-evpp-vs-muduo.chart │ │ ├── throughput-1thread-evpp.chart │ │ ├── throughput-multi-thread-4096bytes-evpp-vs-asio.chart │ │ ├── throughput-multi-thread-evpp-vs-asio-1.chart │ │ ├── throughput-multi-thread-evpp-vs-asio-2.chart │ │ └── throughput-multi-thread-evpp-vs-muduo.chart │ └── throughput_header_body │ │ ├── multi-thread-evpp-vs-asio-100.chart │ │ ├── multi-thread-evpp-vs-asio-1000.chart │ │ └── multi-thread-evpp-vs-asio-10000.chart ├── benchmark_ioevent_performance_vs_asio.md ├── benchmark_lockfree_vs_mutex.md ├── benchmark_lockfree_vs_mutex_cn.md ├── benchmark_ping_pong_spend_time_vs_asio.md ├── benchmark_throughput_vs_asio.md ├── benchmark_throughput_vs_asio_cn.md ├── benchmark_throughput_vs_libevent.md ├── benchmark_throughput_vs_muduo_cn.md ├── quick_start.md └── quick_start_windows_with_visualstudio.md ├── evpp ├── CMakeLists.txt ├── any.h ├── buffer.cc ├── buffer.h ├── connector.cc ├── connector.h ├── dns_resolver.cc ├── dns_resolver.h ├── duration.cc ├── duration.h ├── duration.inl.h ├── event_loop.cc ├── event_loop.h ├── event_loop_thread.cc ├── event_loop_thread.h ├── event_loop_thread_pool.cc ├── event_loop_thread_pool.h ├── event_watcher.cc ├── event_watcher.h ├── evpphttp │ ├── http_parser.h │ ├── http_parser_cpp.cc │ ├── http_request.cc │ ├── http_request.h │ ├── http_response.cc │ ├── http_response.h │ ├── service.cc │ └── service.h ├── fd_channel.cc ├── fd_channel.h ├── gettimeofday.h ├── http │ ├── context.cc │ ├── context.h │ ├── http_server.cc │ ├── http_server.h │ ├── service.cc │ ├── service.h │ └── stats.h ├── httpc │ ├── conn.cc │ ├── conn.h │ ├── conn_pool.cc │ ├── conn_pool.h │ ├── request.cc │ ├── request.h │ ├── response.cc │ ├── response.h │ ├── ssl.cc │ ├── ssl.h │ ├── url_parser.cc │ └── url_parser.h ├── inner_pre.cc ├── inner_pre.h ├── invoke_timer.cc ├── invoke_timer.h ├── libevent.cc ├── libevent.h ├── listener.cc ├── listener.h ├── logging.h ├── memmem.h ├── platform_config.h ├── server_status.h ├── slice.h ├── sockets.cc ├── sockets.h ├── sys_addrinfo.h ├── sys_sockets.h ├── tcp_callbacks.h ├── tcp_client.cc ├── tcp_client.h ├── tcp_conn.cc ├── tcp_conn.h ├── tcp_server.cc ├── tcp_server.h ├── thread_dispatch_policy.h ├── timestamp.h ├── timestamp.inl.h ├── udp │ ├── sync_udp_client.cc │ ├── sync_udp_client.h │ ├── udp_message.h │ ├── udp_server.cc │ └── udp_server.h ├── utility.h └── windows_port.h ├── examples ├── CMakeLists.txt ├── apps │ ├── CMakeLists.txt │ └── evnsq │ │ ├── CMakeLists.txt │ │ ├── evnsq_producer │ │ └── main.cc │ │ └── evnsq_tail │ │ └── main.cc ├── c10m │ ├── CMakeLists.txt │ ├── c10m01 │ │ ├── CMakeLists.txt │ │ └── main.cc │ └── client │ │ ├── CMakeLists.txt │ │ └── main.cc ├── chatroom │ ├── CMakeLists.txt │ └── simple │ │ ├── CMakeLists.txt │ │ ├── client.cc │ │ ├── codec.h │ │ ├── readme.md │ │ └── server.cc ├── dns_resolve │ └── main.cc ├── echo │ ├── httpecho │ │ └── main.cc │ ├── tcpecho │ │ ├── main.cc │ │ └── winmain-inl.h │ └── udpecho │ │ └── main.cc ├── http │ ├── CMakeLists.txt │ ├── evpphttp_server │ │ ├── CMakeLists.txt │ │ └── main.cc │ ├── http_client_request │ │ ├── CMakeLists.txt │ │ ├── client01.cc │ │ ├── client02.cc │ │ ├── client03.cc │ │ ├── client04.cc │ │ └── client05.cc │ └── simple_proxy │ │ ├── CMakeLists.txt │ │ └── main.cc ├── multi_accept │ └── main.cc ├── pingpong │ ├── client.cc │ └── server.cc ├── recipes │ ├── CMakeLists.txt │ └── self_control_timer │ │ ├── CMakeLists.txt │ │ ├── basic_01 │ │ ├── CMakeLists.txt │ │ ├── event_watcher.cc │ │ ├── event_watcher.h │ │ ├── invoke_timer.cc │ │ ├── invoke_timer.h │ │ ├── main.cc │ │ └── winmain-inl.h │ │ ├── basic_02 │ │ ├── CMakeLists.txt │ │ ├── event_watcher.cc │ │ ├── event_watcher.h │ │ ├── invoke_timer.cc │ │ ├── invoke_timer.h │ │ ├── main.cc │ │ └── winmain-inl.h │ │ ├── cancel_03 │ │ ├── CMakeLists.txt │ │ ├── event_watcher.cc │ │ ├── event_watcher.h │ │ ├── invoke_timer.cc │ │ ├── invoke_timer.h │ │ ├── main.cc │ │ └── winmain-inl.h │ │ ├── periodic_04 │ │ ├── CMakeLists.txt │ │ ├── event_watcher.cc │ │ ├── event_watcher.h │ │ ├── invoke_timer.cc │ │ ├── invoke_timer.h │ │ ├── main.cc │ │ └── winmain-inl.h │ │ └── readme.md ├── signal │ ├── signal01.cc │ └── signal02.cc ├── tcp │ ├── tcp_client.cc │ └── tcp_server.cc ├── timer │ ├── timer01.cc │ ├── timer02.cc │ ├── timer03.cc │ ├── timer04.cc │ └── timer05.cc ├── twisted │ ├── pubsubserver │ │ ├── main.cc │ │ └── readme.md │ └── webserver │ │ ├── main.cc │ │ └── readme.md └── winmain-inl.h ├── labs ├── CMakeLists.txt └── evthrift │ ├── CMakeLists.txt │ ├── tests │ ├── .gitignore │ ├── CMakeLists.txt │ ├── echo │ │ ├── CMakeLists.txt │ │ ├── echo.thrift │ │ ├── echo_server.cc │ │ └── echoclient.py │ └── ping │ │ ├── CMakeLists.txt │ │ ├── ping.thrift │ │ ├── ping_server.cc │ │ └── pingclient.py │ ├── thrift_conn.cc │ ├── thrift_conn.h │ ├── thrift_server.cc │ └── thrift_server.h ├── readme.md ├── readme_cn.md ├── test ├── CMakeLists.txt ├── any_test.cc ├── buffer_test.cc ├── dns_resolver_test.cc ├── event_condition_test.cc ├── event_loop_test.cc ├── event_loop_thread_pool_test.cc ├── event_loop_thread_test.cc ├── event_watcher_test.cc ├── evhttp_client_test.cc ├── evpphttp_server_test.cc ├── glog_test.cc ├── http_client_test.cc ├── http_server_test.cc ├── http_trivial_test.cc ├── https_client_test.cc ├── invoke_timer_test.cc ├── kill_storage_cluster.json ├── more_tests │ ├── CMakeLists.txt │ └── fork │ │ ├── CMakeLists.txt │ │ └── main.cc ├── sockets_test.cc ├── stability │ ├── CMakeLists.txt │ ├── run_stability.sh │ ├── stability.cc │ ├── stability.h │ ├── stability_dns.h │ ├── stability_tcp1_client.h │ ├── stability_tcp2_client.h │ └── stability_tcp3.h ├── tcp_client_reconnect_test.cc ├── tcp_client_test.cc ├── tcp_server_test.cc ├── test_common.h ├── test_go │ └── tcpclient.go ├── time_test.cc ├── trivial_test.cc ├── udp_server_test.cc ├── utility_test.cc └── winmain.cc ├── tools ├── astyle_format_code.sh ├── benchmark-build.sh ├── debug-build.sh ├── release-build.sh ├── test_scripts │ └── evnsq_test.sh └── win32-build.sh └── vsprojects ├── bin ├── Debug │ └── .placeholder └── Release │ └── .placeholder ├── echo.vcxproj ├── echo.vcxproj.filters ├── evmc-test.vcxproj ├── evnsq-test.vcxproj ├── evnsqtail.vcxproj ├── httpecho.vcxproj ├── libevmc.vcxproj ├── libevmc.vcxproj.filters ├── libevnsq.vcxproj ├── libevnsq.vcxproj.filters ├── libevpp-test.vcxproj ├── libevpp-test.vcxproj.filters ├── libevpp.sln ├── libevpp.vcxproj ├── libevpp.vcxproj.filters ├── pingpong_client.vcxproj ├── pingpong_client.vcxproj.user ├── pingpong_server.vcxproj └── udpecho.vcxproj /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "3rdparty/concurrentqueue"] 2 | path = 3rdparty/concurrentqueue 3 | url = https://github.com/cameron314/concurrentqueue 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | language: cpp 3 | compiler: 4 | - g++ 5 | 6 | branches: 7 | only: 8 | - master 9 | - dev 10 | 11 | env: 12 | global: 13 | - CI_HOME=`pwd` 14 | 15 | 16 | install: 17 | - sudo apt-get install libboost-all-dev -y 18 | - sudo apt-get install libevent-dev -y 19 | - sudo apt-get install libgflags-dev -y 20 | - sudo apt-get install libgtest-dev -y 21 | - sudo apt-get install libgoogle-glog-dev -y 22 | 23 | script: 24 | - g++ --version 25 | - cmake --version 26 | - cd $CI_HOME 27 | - pwd 28 | - git submodule update --init --recursive 29 | - mkdir build && cd build 30 | - cmake -DCMAKE_BUILD_TYPE=debug .. 31 | - make -j2 32 | - cd .. 33 | - mkdir build-release && cd build-release 34 | - cmake -DCMAKE_BUILD_TYPE=release .. 35 | - make -j2 36 | - pwd 37 | 38 | after_success: 39 | - cd $CI_HOME 40 | - pwd 41 | - curl -L https://github.com/nsqio/nsq/releases/download/v0.3.8/nsq-0.3.8.linux-amd64.go1.6.2.tar.gz -o nsq-0.3.8.linux-amd64.go1.6.2.tar.gz 42 | - tar zxvf nsq-0.3.8.linux-amd64.go1.6.2.tar.gz 43 | - pwd 44 | - make test -C build 45 | - make test -C build-release 46 | - cd $CI_HOME 47 | - pwd 48 | - cd tools/test_scripts 49 | - pwd 50 | - /bin/bash ./evnsq_test.sh 51 | - pwd 52 | # - coveralls --exclude dependencies --exclude test --gcov /usr/bin/gcov-5 53 | 54 | -------------------------------------------------------------------------------- /3rdparty/astyle_2.06_linux.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qihoo360/evpp/477033f938fd47dfecde43c82257cd286d9fa38e/3rdparty/astyle_2.06_linux.tar.gz -------------------------------------------------------------------------------- /3rdparty/libhashkit/Makefile: -------------------------------------------------------------------------------- 1 | SRCS := $(wildcard *.c) 2 | OBJS := $(patsubst %.c, %.o, $(SRCS)) 3 | 4 | libhashkit.a : $(OBJS) 5 | ar cru $@ $(OBJS) 6 | ranlib $@ 7 | 8 | %.o : %.c 9 | gcc -std=gnu99 -c $< -I.. 10 | 11 | clean : 12 | rm -fv *.o libhashkit.a 13 | 14 | -------------------------------------------------------------------------------- /3rdparty/libhashkit/algorithm.c: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2006-2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #include "common.h" 10 | 11 | uint32_t libhashkit_one_at_a_time(const char *key, size_t key_length) 12 | { 13 | return hashkit_one_at_a_time(key, key_length, NULL); 14 | } 15 | 16 | uint32_t libhashkit_fnv1_64(const char *key, size_t key_length) 17 | { 18 | return hashkit_fnv1_64(key, key_length, NULL); 19 | } 20 | 21 | uint32_t libhashkit_fnv1a_64(const char *key, size_t key_length) 22 | { 23 | return hashkit_fnv1a_64(key, key_length, NULL); 24 | } 25 | 26 | uint32_t libhashkit_fnv1_32(const char *key, size_t key_length) 27 | { 28 | return hashkit_fnv1_32(key, key_length, NULL); 29 | } 30 | 31 | uint32_t libhashkit_fnv1a_32(const char *key, size_t key_length) 32 | { 33 | return hashkit_fnv1a_32(key, key_length, NULL); 34 | } 35 | 36 | uint32_t libhashkit_crc32(const char *key, size_t key_length) 37 | { 38 | return hashkit_crc32(key, key_length, NULL); 39 | } 40 | 41 | #ifdef HAVE_HSIEH_HASH 42 | uint32_t libhashkit_hsieh(const char *key, size_t key_length) 43 | { 44 | return hashkit_hsieh(key, key_length, NULL); 45 | } 46 | #endif 47 | 48 | uint32_t libhashkit_murmur(const char *key, size_t key_length) 49 | { 50 | return hashkit_murmur(key, key_length, NULL); 51 | } 52 | 53 | uint32_t libhashkit_jenkins(const char *key, size_t key_length) 54 | { 55 | return hashkit_jenkins(key, key_length, NULL); 56 | } 57 | 58 | uint32_t libhashkit_md5(const char *key, size_t key_length) 59 | { 60 | return hashkit_md5(key, key_length, NULL); 61 | } 62 | 63 | void libhashkit_md5_signature(const unsigned char *key, size_t length, unsigned char *result) 64 | { 65 | md5_signature(key, (uint32_t)length, result); 66 | } 67 | 68 | -------------------------------------------------------------------------------- /3rdparty/libhashkit/behavior.c: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #include "common.h" 10 | -------------------------------------------------------------------------------- /3rdparty/libhashkit/behavior.h: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | /** 10 | * @file 11 | * @brief HashKit Header 12 | */ 13 | 14 | #ifndef HASHKIT_BEHAVIOR_H 15 | #define HASHKIT_BEHAVIOR_H 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | #endif /* HASHKIT_BEHAVIOR_H */ 27 | -------------------------------------------------------------------------------- /3rdparty/libhashkit/common.h: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #ifndef HASHKIT_COMMON_H 10 | #define HASHKIT_COMMON_H 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | #ifdef WIN32 17 | #define __attribute__(x) 18 | #endif 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "hashkit.h" 27 | 28 | HASHKIT_LOCAL 29 | void md5_signature(const unsigned char *key, unsigned int length, unsigned char *result); 30 | 31 | HASHKIT_LOCAL 32 | int update_continuum(hashkit_st *hashkit); 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif /* HASHKIT_COMMON_H */ 39 | -------------------------------------------------------------------------------- /3rdparty/libhashkit/configure.h: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2009-2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | #ifndef LIBHASHKIT_CONFIGURE_H 9 | #define LIBHASHKIT_CONFIGURE_H 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif /* LIBHASHKIT_CONFIGURE_H */ 20 | -------------------------------------------------------------------------------- /3rdparty/libhashkit/digest.c: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #include "common.h" 10 | 11 | uint32_t hashkit_digest(const hashkit_st *self, const char *key, size_t key_length) 12 | { 13 | return self->base_hash.function(key, key_length, self->base_hash.context); 14 | } 15 | 16 | uint32_t libhashkit_digest(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm) 17 | { 18 | switch (hash_algorithm) 19 | { 20 | case HASHKIT_HASH_DEFAULT: 21 | return libhashkit_one_at_a_time(key, key_length); 22 | case HASHKIT_HASH_MD5: 23 | return libhashkit_md5(key, key_length); 24 | case HASHKIT_HASH_CRC: 25 | return libhashkit_crc32(key, key_length); 26 | case HASHKIT_HASH_FNV1_64: 27 | return libhashkit_fnv1_64(key, key_length); 28 | case HASHKIT_HASH_FNV1A_64: 29 | return libhashkit_fnv1a_64(key, key_length); 30 | case HASHKIT_HASH_FNV1_32: 31 | return libhashkit_fnv1_32(key, key_length); 32 | case HASHKIT_HASH_FNV1A_32: 33 | return libhashkit_fnv1a_32(key, key_length); 34 | case HASHKIT_HASH_HSIEH: 35 | #ifdef HAVE_HSIEH_HASH 36 | return libhashkit_hsieh(key, key_length); 37 | #else 38 | return 1; 39 | #endif 40 | case HASHKIT_HASH_MURMUR: 41 | return libhashkit_murmur(key, key_length); 42 | case HASHKIT_HASH_JENKINS: 43 | return libhashkit_jenkins(key, key_length); 44 | case HASHKIT_HASH_CUSTOM: 45 | case HASHKIT_HASH_MAX: 46 | default: 47 | #ifdef HAVE_DEBUG 48 | fprintf(stderr, "hashkit_hash_t was extended but libhashkit_generate_value was not updated\n"); 49 | fflush(stderr); 50 | assert(0); 51 | #endif 52 | break; 53 | } 54 | 55 | return 1; 56 | } 57 | -------------------------------------------------------------------------------- /3rdparty/libhashkit/digest.h: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #ifndef HASHKIT_DIGEST_H 10 | #define HASHKIT_DIGEST_H 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | HASHKIT_API 17 | uint32_t hashkit_digest(const hashkit_st *self, const char *key, size_t key_length); 18 | 19 | /** 20 | This is a utilitly function provided so that you can directly access hashes with a hashkit_st. 21 | */ 22 | 23 | HASHKIT_API 24 | uint32_t libhashkit_digest(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm); 25 | 26 | #ifdef __cplusplus 27 | } 28 | #endif 29 | 30 | #endif /* HASHKIT_DIGEST_H */ 31 | -------------------------------------------------------------------------------- /3rdparty/libhashkit/function.h: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #ifndef HASHKIT_FUNCTION_H 10 | #define HASHKIT_FUNCTION_H 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | /** 17 | This sets/gets the default function we will be using. 18 | */ 19 | HASHKIT_API 20 | hashkit_return_t hashkit_set_function(hashkit_st *hash, hashkit_hash_algorithm_t hash_algorithm); 21 | 22 | HASHKIT_API 23 | hashkit_return_t hashkit_set_custom_function(hashkit_st *hash, hashkit_hash_fn function, void *context); 24 | 25 | HASHKIT_API 26 | hashkit_hash_algorithm_t hashkit_get_function(const hashkit_st *hash); 27 | 28 | /** 29 | This sets/gets the function we use for distribution. 30 | */ 31 | HASHKIT_API 32 | hashkit_return_t hashkit_set_distribution_function(hashkit_st *hash, hashkit_hash_algorithm_t hash_algorithm); 33 | 34 | HASHKIT_API 35 | hashkit_return_t hashkit_set_custom_distribution_function(hashkit_st *self, hashkit_hash_fn function, void *context); 36 | 37 | HASHKIT_API 38 | hashkit_hash_algorithm_t hashkit_get_distribution_function(const hashkit_st *self); 39 | 40 | #ifdef __cplusplus 41 | } 42 | #endif 43 | 44 | #endif /* HASHKIT_FUNCTION_H */ 45 | -------------------------------------------------------------------------------- /3rdparty/libhashkit/include.am: -------------------------------------------------------------------------------- 1 | # vim:ft=automake 2 | # included from Top Level Makefile.am 3 | # All paths should be given relative to the root 4 | # 5 | # HashKit 6 | # Copyright (C) 2009 Brian Aker 7 | # All rights reserved. 8 | # 9 | # Use and distribution licensed under the BSD license. See 10 | # the COPYING file in the parent directory for full text. 11 | 12 | lib_LTLIBRARIES+= libhashkit/libhashkit.la 13 | 14 | EXTRA_DIST+= \ 15 | libhashkit/configure.h.in 16 | 17 | 18 | nobase_include_HEADERS+= \ 19 | libhashkit/algorithm.h \ 20 | libhashkit/behavior.h \ 21 | libhashkit/configure.h \ 22 | libhashkit/digest.h \ 23 | libhashkit/function.h \ 24 | libhashkit/hashkit.h \ 25 | libhashkit/strerror.h \ 26 | libhashkit/types.h \ 27 | libhashkit/visibility.h 28 | 29 | noinst_HEADERS+= \ 30 | libhashkit/common.h 31 | 32 | libhashkit_libhashkit_la_SOURCES= \ 33 | libhashkit/algorithm.c \ 34 | libhashkit/behavior.c \ 35 | libhashkit/crc32.c \ 36 | libhashkit/fnv.c \ 37 | libhashkit/digest.c \ 38 | libhashkit/function.c \ 39 | libhashkit/hashkit.c \ 40 | libhashkit/jenkins.c \ 41 | libhashkit/ketama.c \ 42 | libhashkit/md5.c \ 43 | libhashkit/murmur.c \ 44 | libhashkit/one_at_a_time.c \ 45 | libhashkit/strerror.c 46 | 47 | if INCLUDE_HSIEH_SRC 48 | libhashkit_libhashkit_la_SOURCES+= libhashkit/hsieh.c 49 | endif 50 | 51 | libhashkit_libhashkit_la_CFLAGS= \ 52 | ${AM_CFLAGS} \ 53 | -DBUILDING_HASHKIT 54 | 55 | libhashkit_libhashkit_la_LDFLAGS= \ 56 | $(LIBM) \ 57 | -version-info $(HASHKIT_LIBRARY_VERSION) 58 | 59 | noinst_LTLIBRARIES+= libhashkit/libhashkitinc.la 60 | 61 | libhashkit_libhashkitinc_la_SOURCES= ${libhashkit_libhashkit_la_SOURCES} 62 | libhashkit_libhashkitinc_la_CFLAGS= ${libhashkit_libhashkit_la_CFLAGS} 63 | libhashkit_libhashkitinc_la_LDFLAGS= $(LIBM) 64 | -------------------------------------------------------------------------------- /3rdparty/libhashkit/murmur.c: -------------------------------------------------------------------------------- 1 | /* 2 | "Murmur" hash provided by Austin, tanjent@gmail.com 3 | http://murmurhash.googlepages.com/ 4 | 5 | Note - This code makes a few assumptions about how your machine behaves - 6 | 7 | 1. We can read a 4-byte value from any address without crashing 8 | 2. sizeof(int) == 4 9 | 10 | And it has a few limitations - 11 | 1. It will not work incrementally. 12 | 2. It will not produce the same results on little-endian and big-endian 13 | machines. 14 | 15 | Updated to murmur2 hash - BP 16 | */ 17 | 18 | #include "common.h" 19 | 20 | uint32_t hashkit_murmur(const char *key, size_t length, void *context __attribute__((unused))) 21 | { 22 | /* 23 | 'm' and 'r' are mixing constants generated offline. They're not 24 | really 'magic', they just happen to work well. 25 | */ 26 | 27 | const unsigned int m= 0x5bd1e995; 28 | const uint32_t seed= (0xdeadbeef * (uint32_t)length); 29 | const int r= 24; 30 | 31 | 32 | // Initialize the hash to a 'random' value 33 | 34 | uint32_t h= seed ^ (uint32_t)length; 35 | 36 | // Mix 4 bytes at a time into the hash 37 | 38 | const unsigned char * data= (const unsigned char *)key; 39 | 40 | while(length >= 4) 41 | { 42 | unsigned int k = *(unsigned int *)data; 43 | 44 | k *= m; 45 | k ^= k >> r; 46 | k *= m; 47 | 48 | h *= m; 49 | h ^= k; 50 | 51 | data += 4; 52 | length -= 4; 53 | } 54 | 55 | // Handle the last few bytes of the input array 56 | 57 | switch(length) 58 | { 59 | case 3: h ^= ((uint32_t)data[2]) << 16; 60 | case 2: h ^= ((uint32_t)data[1]) << 8; 61 | case 1: h ^= data[0]; 62 | h *= m; 63 | default: break; 64 | }; 65 | 66 | /* 67 | Do a few final mixes of the hash to ensure the last few bytes are 68 | well-incorporated. 69 | */ 70 | 71 | h ^= h >> 13; 72 | h *= m; 73 | h ^= h >> 15; 74 | 75 | return h; 76 | } 77 | -------------------------------------------------------------------------------- /3rdparty/libhashkit/one_at_a_time.c: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | /* 10 | This has is Jenkin's "One at A time Hash". 11 | http://en.wikipedia.org/wiki/Jenkins_hash_function 12 | */ 13 | 14 | #include "common.h" 15 | 16 | uint32_t hashkit_one_at_a_time(const char *key, size_t key_length, void *context __attribute__((unused))) 17 | { 18 | const char *ptr= key; 19 | uint32_t value= 0; 20 | 21 | while (key_length--) 22 | { 23 | uint32_t val= (uint32_t) *ptr++; 24 | value += val; 25 | value += (value << 10); 26 | value ^= (value >> 6); 27 | } 28 | value += (value << 3); 29 | value ^= (value >> 11); 30 | value += (value << 15); 31 | 32 | return value; 33 | } 34 | -------------------------------------------------------------------------------- /3rdparty/libhashkit/strerror.c: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #include "common.h" 10 | 11 | const char *hashkit_strerror(hashkit_st *ptr __attribute__((unused)), hashkit_return_t rc) 12 | { 13 | switch (rc) 14 | { 15 | case HASHKIT_SUCCESS: 16 | return "SUCCESS"; 17 | case HASHKIT_FAILURE: 18 | return "FAILURE"; 19 | case HASHKIT_MEMORY_ALLOCATION_FAILURE: 20 | return "MEMORY ALLOCATION FAILURE"; 21 | case HASHKIT_MAXIMUM_RETURN: 22 | return "Gibberish returned!"; 23 | default: 24 | return "Gibberish returned!"; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /3rdparty/libhashkit/strerror.h: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #ifndef HASHKIT_STRERROR_H 10 | #define HASHKIT_STRERROR_H 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | HASHKIT_API 17 | const char *hashkit_strerror(hashkit_st *ptr, hashkit_return_t rc); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif /* HASHKIT_STRERROR_H */ 24 | -------------------------------------------------------------------------------- /3rdparty/libhashkit/types.h: -------------------------------------------------------------------------------- 1 | 2 | /* HashKit 3 | * Copyright (C) 2009 Brian Aker 4 | * All rights reserved. 5 | * 6 | * Use and distribution licensed under the BSD license. See 7 | * the COPYING file in the parent directory for full text. 8 | */ 9 | 10 | #ifndef HASHKIT_TYPES_H 11 | #define HASHKIT_TYPES_H 12 | 13 | #ifdef __cplusplus 14 | 15 | extern "C" { 16 | #endif 17 | 18 | typedef enum { 19 | HASHKIT_SUCCESS, 20 | HASHKIT_FAILURE, 21 | HASHKIT_MEMORY_ALLOCATION_FAILURE, 22 | HASHKIT_MAXIMUM_RETURN /* Always add new error code before */ 23 | } hashkit_return_t; 24 | 25 | typedef enum { 26 | HASHKIT_HASH_DEFAULT= 0, // hashkit_one_at_a_time() 27 | HASHKIT_HASH_MD5, 28 | HASHKIT_HASH_CRC, 29 | HASHKIT_HASH_FNV1_64, 30 | HASHKIT_HASH_FNV1A_64, 31 | HASHKIT_HASH_FNV1_32, 32 | HASHKIT_HASH_FNV1A_32, 33 | HASHKIT_HASH_HSIEH, 34 | HASHKIT_HASH_MURMUR, 35 | HASHKIT_HASH_JENKINS, 36 | HASHKIT_HASH_CUSTOM, 37 | HASHKIT_HASH_MAX 38 | } hashkit_hash_algorithm_t; 39 | 40 | /** 41 | * Hash distributions that are available to use. 42 | */ 43 | typedef enum 44 | { 45 | HASHKIT_DISTRIBUTION_MODULA, 46 | HASHKIT_DISTRIBUTION_RANDOM, 47 | HASHKIT_DISTRIBUTION_KETAMA, 48 | HASHKIT_DISTRIBUTION_MAX /* Always add new values before this. */ 49 | } hashkit_distribution_t; 50 | 51 | 52 | typedef struct hashkit_st hashkit_st; 53 | 54 | typedef uint32_t (*hashkit_hash_fn)(const char *key, size_t key_length, void *context); 55 | 56 | #ifdef __cplusplus 57 | } 58 | #endif 59 | 60 | #endif /* HASHKIT_TYPES_H */ 61 | -------------------------------------------------------------------------------- /3rdparty/libhashkit/visibility.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Summary: interface for HashKit functions 3 | * Description: visibitliy macros for HashKit library 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in this directory for full text. 7 | * 8 | * Author: Monty Taylor 9 | */ 10 | 11 | /** 12 | * @file 13 | * @brief Visibility control macros 14 | */ 15 | 16 | #ifndef HASHKIT_VISIBILITY_H 17 | #define HASHKIT_VISIBILITY_H 18 | 19 | /** 20 | * 21 | * HASHKIT_API is used for the public API symbols. It either DLL imports or 22 | * DLL exports (or does nothing for static build). 23 | * 24 | * HASHKIT_LOCAL is used for non-api symbols. 25 | */ 26 | 27 | #if defined(BUILDING_HASHKIT) 28 | # if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY 29 | # define HASHKIT_API __attribute__ ((visibility("default"))) 30 | # define HASHKIT_LOCAL __attribute__ ((visibility("hidden"))) 31 | # elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550) 32 | # define HASHKIT_API __global 33 | # define HASHKIT_LOCAL __hidden 34 | # elif defined(_MSC_VER) 35 | //# define HASHKIT_API extern __declspec(dllexport) 36 | # define HASHKIT_API // static link 37 | # define HASHKIT_LOCAL 38 | # else 39 | # define HASHKIT_API 40 | # define HASHKIT_LOCAL 41 | # endif /* defined(HAVE_VISIBILITY) */ 42 | #else /* defined(BUILDING_HASHKIT) */ 43 | # if defined(_MSC_VER) 44 | //# define HASHKIT_API extern __declspec(dllimport) 45 | # define HASHKIT_API // static link 46 | # define HASHKIT_LOCAL 47 | # else 48 | # define HASHKIT_API 49 | # define HASHKIT_LOCAL 50 | # endif /* defined(_MSC_VER) */ 51 | #endif /* defined(BUILDING_HASHKIT) */ 52 | 53 | #endif /* HASHKIT_VISIBILITY_H */ 54 | -------------------------------------------------------------------------------- /3rdparty/memcached/vbucket.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 | #ifndef MEMCACHED_VBUCKET_H 3 | #define MEMCACHED_VBUCKET_H 1 4 | 5 | #ifdef __cplusplus 6 | extern "C" 7 | { 8 | #endif 9 | 10 | typedef enum { 11 | vbucket_state_active = 1, /**< Actively servicing a vbucket. */ 12 | vbucket_state_replica, /**< Servicing a vbucket as a replica only. */ 13 | vbucket_state_pending, /**< Pending active. */ 14 | vbucket_state_dead /**< Not in use, pending deletion. */ 15 | } vbucket_state_t; 16 | 17 | #define is_valid_vbucket_state_t(state) \ 18 | (state == vbucket_state_active || \ 19 | state == vbucket_state_replica || \ 20 | state == vbucket_state_pending || \ 21 | state == vbucket_state_dead) 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | #endif 27 | -------------------------------------------------------------------------------- /3rdparty/rapidjson/internal/strfunc.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ 16 | #define RAPIDJSON_INTERNAL_STRFUNC_H_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | //! Custom strlen() which works on different character types. 24 | /*! \tparam Ch Character type (e.g. char, wchar_t, short) 25 | \param s Null-terminated input string. 26 | \return Number of characters in the string. 27 | \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. 28 | */ 29 | template 30 | inline SizeType StrLen(const Ch* s) { 31 | const Ch* p = s; 32 | while (*p) ++p; 33 | return SizeType(p - s); 34 | } 35 | 36 | } // namespace internal 37 | RAPIDJSON_NAMESPACE_END 38 | 39 | #endif // RAPIDJSON_INTERNAL_STRFUNC_H_ 40 | -------------------------------------------------------------------------------- /3rdparty/rapidjson/version.txt: -------------------------------------------------------------------------------- 1 | 1.0.2 -------------------------------------------------------------------------------- /3rdparty/win32code/getopt/getopt.h: -------------------------------------------------------------------------------- 1 | #ifndef __GETOPT_H__ 2 | #define __GETOPT_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | extern int opterr; /* if error message should be printed */ 9 | extern int optind; /* index into parent argv vector */ 10 | extern int optopt; /* character checked for validity */ 11 | extern int optreset; /* reset getopt */ 12 | extern char *optarg; /* argument associated with option */ 13 | 14 | struct option 15 | { 16 | const char *name; 17 | int has_arg; 18 | int *flag; 19 | int val; 20 | }; 21 | 22 | #define no_argument 0 23 | #define required_argument 1 24 | #define optional_argument 2 25 | 26 | int getopt(int, char**, const char*); 27 | int getopt_long(int, char**, const char*, const struct option*, int*); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | #endif /* __GETOPT_H__ */ 34 | -------------------------------------------------------------------------------- /3rdparty/wininclude/getopt.h: -------------------------------------------------------------------------------- 1 | #ifndef __GETOPT_H__ 2 | #define __GETOPT_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | extern int opterr; /* if error message should be printed */ 9 | extern int optind; /* index into parent argv vector */ 10 | extern int optopt; /* character checked for validity */ 11 | extern int optreset; /* reset getopt */ 12 | extern char *optarg; /* argument associated with option */ 13 | 14 | struct option 15 | { 16 | const char *name; 17 | int has_arg; 18 | int *flag; 19 | int val; 20 | }; 21 | 22 | #define no_argument 0 23 | #define required_argument 1 24 | #define optional_argument 2 25 | 26 | int getopt(int, char**, const char*); 27 | int getopt_long(int, char**, const char*, const struct option*, int*); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | #endif /* __GETOPT_H__ */ 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, Qihoo 360 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /apps/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | include_directories(${PROJECT_SOURCE_DIR}/apps ${PROJECT_SOURCE_DIR}/3rdparty) 3 | 4 | if (UNIX) 5 | set(LIBRARIES evpp_concurrentqueue event glog pthread) 6 | link_directories("/home/s/safe/lib" ${PROJECT_BUILD_DIR}/lib) 7 | else(UNIX) 8 | set(LIBRARIES evpp_static event glog) 9 | link_directories(${PROJECT_SOURCE_DIR}/vsprojects/bin/${CMAKE_BUILD_TYPE}/ 10 | ${LIBRARY_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}/) 11 | endif(UNIX) 12 | 13 | add_subdirectory(evnsq) 14 | add_subdirectory(evmc) 15 | 16 | 17 | -------------------------------------------------------------------------------- /apps/evmc/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | test/test_evmc 3 | -------------------------------------------------------------------------------- /apps/evmc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(CMAKE_C_FLAGS -std=gnu99) 3 | file(GLOB evmc_SRCS *.cc 4 | *.h 5 | ${PROJECT_SOURCE_DIR}/3rdparty/libhashkit/*.c) 6 | file(GLOB evmc_PUBLIC_HEADERS *.h) 7 | 8 | add_library(evmc_static STATIC ${evmc_SRCS}) 9 | target_link_libraries(evmc_static ${LIBRARIES}) 10 | 11 | if (UNIX) 12 | add_library(evmc SHARED ${evmc_SRCS}) 13 | target_link_libraries(evmc ${LIBRARIES}) 14 | 15 | set (CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") 16 | include (utils) 17 | include (packages) 18 | set_target_properties ( 19 | evmc evnsq PROPERTIES 20 | VERSION "${PACKAGE_VERSION}" 21 | SOVERSION "${PACKAGE_SOVERSION}" 22 | ) 23 | 24 | install ( 25 | TARGETS evmc 26 | LIBRARY DESTINATION lib 27 | ARCHIVE DESTINATION lib) 28 | endif (UNIX) 29 | 30 | install ( 31 | TARGETS evmc_static 32 | LIBRARY DESTINATION lib 33 | ARCHIVE DESTINATION lib) 34 | install (FILES ${evmc_PUBLIC_HEADERS} DESTINATION "include/evmc") 35 | 36 | 37 | if (NOT EVPP_VCPKG_BUILD) 38 | add_subdirectory(test) 39 | endif () -------------------------------------------------------------------------------- /apps/evmc/binary_codec.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qihoo360/evpp/477033f938fd47dfecde43c82257cd286d9fa38e/apps/evmc/binary_codec.h -------------------------------------------------------------------------------- /apps/evmc/command.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qihoo360/evpp/477033f938fd47dfecde43c82257cd286d9fa38e/apps/evmc/command.h -------------------------------------------------------------------------------- /apps/evmc/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _WIN32 4 | #ifndef EVMC_EXPORTS 5 | #pragma comment(lib, "evmc_static.lib") 6 | #endif 7 | #endif 8 | 9 | #include 10 | #include -------------------------------------------------------------------------------- /apps/evmc/extract_vbucket_conf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "evpp/httpc/request.h" 4 | 5 | namespace evmc { 6 | enum { 7 | READ_VBUCKET_CONF_FAILED = -1, 8 | }; 9 | struct HttpReqDoneArg { 10 | event_base* event; 11 | std::string* retstr; 12 | int retcode; 13 | }; 14 | class GetVbucketConf { 15 | public: 16 | static int GetVbucketConfContext(const std::string& conf_addr, std::string& context); 17 | private: 18 | static void OnHttpReqDone(struct evhttp_request* req, void* arg); 19 | static int GetRemoteVbucketConf(const std::string& conf_addr, std::string& context); 20 | }; 21 | } -------------------------------------------------------------------------------- /apps/evmc/likely.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #undef LIKELY 4 | #undef UNLIKELY 5 | #if defined(__GNUC__) && __GNUC__ >= 4 6 | #define LIKELY(x) (__builtin_expect(((bool)(x)), 1)) 7 | #define UNLIKELY(x) (__builtin_expect(((bool)(x)), 0)) 8 | #else 9 | #define LIKELY(x) (x) 10 | #define UNLIKELY(x) (x) 11 | #endif 12 | -------------------------------------------------------------------------------- /apps/evmc/memcache_client_base.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | #include "evmc/config.h" 8 | 9 | #include "evpp/event_loop_thread_pool.h" 10 | 11 | #include "vbucket_config.h" 12 | #include "memcache_client.h" 13 | 14 | namespace evmc { 15 | class MemcacheClientBase { 16 | public: 17 | virtual ~MemcacheClientBase(); 18 | MemcacheClientBase(const char* vbucket_conf); 19 | MultiModeVbucketConfig* vbucket_config(); 20 | virtual void LaunchCommand(CommandPtr& command) = 0; 21 | protected: 22 | bool Start(bool is_reload = false); 23 | 24 | void Stop(); 25 | void BuilderMemClient(evpp::EventLoop* loop, std::string& server, std::map& client_map, const int timeout_ms); 26 | void OnClientConnection(const evpp::TCPConnPtr& conn, MemcacheClientPtr memc_client); 27 | private: 28 | void DoReloadConf(); 29 | void LoadThread(); 30 | private: 31 | std::string vbucket_conf_; 32 | evpp::EventLoop* load_loop_; 33 | std::thread* load_thread_; 34 | MultiModeVbucketConfig* vbconf_cur_, *vbconf_1_, *vbconf_2_; 35 | std::mutex vbucket_config_mutex_; 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /apps/evmc/memcache_client_serial.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "mctypes.h" 6 | #include "vbucket_config.h" 7 | #include "memcache_client_base.h" 8 | #include "evpp/event_loop_thread_pool.h" 9 | 10 | namespace evmc { 11 | 12 | class MemcacheClientSerial : public MemcacheClientBase { 13 | public: 14 | MemcacheClientSerial(const char* vbucket_conf, int timeout_ms) 15 | : MemcacheClientBase(vbucket_conf), server_(vbucket_conf), timeout_ms_(timeout_ms), loop_(nullptr), memclient_(MemcacheClientPtr()), id_seq_(0) { 16 | } 17 | 18 | virtual ~MemcacheClientSerial(); 19 | void Stop(); 20 | bool Start(evpp::EventLoop* loop); 21 | void Set(const std::string& key, const std::string& value, uint32_t flags, 22 | uint32_t expire, SetCallback callback); 23 | inline void Set(const std::string& key, const std::string& value, SetCallback callback) { 24 | Set(key, value, 0, 0, callback); 25 | } 26 | void Remove(const std::string& key, RemoveCallback callback); 27 | void Get(const std::string& key, GetCallback callback); 28 | void MultiGet(const std::vector& keys, MultiGetCallback callback); 29 | 30 | virtual void LaunchCommand(CommandPtr& command); 31 | private: 32 | inline uint32_t next_id() { 33 | return ++id_seq_; 34 | } 35 | private: 36 | std::string server_; 37 | int32_t timeout_ms_; 38 | evpp::EventLoop* loop_; 39 | MemcacheClientPtr memclient_; 40 | uint32_t id_seq_; 41 | }; 42 | } 43 | -------------------------------------------------------------------------------- /apps/evmc/memcached.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "evmc/config.h" 4 | #include "evmc/memcache_client_pool.h" 5 | #include "evmc/memcache_client_serial.h" 6 | -------------------------------------------------------------------------------- /apps/evmc/readme.md: -------------------------------------------------------------------------------- 1 | evmc 2 | --- 3 | 4 | `evmc` is a nonblocking async C++ client library for memcached and membase. It is based on [evpp](https://github.com/Qihoo360/evpp) which is a modern C++ network library. 5 | 6 | ### Status 7 | 8 | This library is currently used in production which sends more than 300 billions requests every day. 9 | 10 | ### Features 11 | 12 | 1. Support single `memcached` instance 13 | 2. Support a cluster of `memcached` which are configurated by vbucket, like `membase` or `couchbase` 14 | 3. Support failover and load balance 15 | 16 | ### Dependencies 17 | 18 | - libhashkit 19 | - [evpp](https://github.com/Qihoo360/evpp) 20 | - [rapidjson](https://github.com/miloyip/rapidjson) 21 | - [libevent](https://github.com/libevent/libevent) 22 | - [glog](https://github.com/google/glog) 23 | -------------------------------------------------------------------------------- /apps/evmc/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(evmc_test mcpool_test.cc) 3 | target_link_libraries(evmc_test evmc_static ${LIBRARIES}) 4 | -------------------------------------------------------------------------------- /apps/evmc/vbucket_config.cc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qihoo360/evpp/477033f938fd47dfecde43c82257cd286d9fa38e/apps/evmc/vbucket_config.cc -------------------------------------------------------------------------------- /apps/evnsq/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB evnsq_SRCS *.cc *.h) 2 | file(GLOB evnsq_PUBLIC_HEADERS *.h) 3 | 4 | add_library(evnsq_static STATIC ${evnsq_SRCS}) 5 | target_link_libraries(evnsq_static ${LIBRARIES}) 6 | 7 | if (UNIX) 8 | add_library(evnsq SHARED ${evnsq_SRCS}) 9 | target_link_libraries(evnsq ${LIBRARIES}) 10 | 11 | set (CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") 12 | include (utils) 13 | include (packages) 14 | set_target_properties ( 15 | evnsq PROPERTIES 16 | VERSION "${PACKAGE_VERSION}" 17 | SOVERSION "${PACKAGE_SOVERSION}" 18 | ) 19 | 20 | install ( 21 | TARGETS evnsq 22 | LIBRARY DESTINATION lib 23 | ARCHIVE DESTINATION lib) 24 | endif (UNIX) 25 | 26 | install ( 27 | TARGETS evnsq_static 28 | LIBRARY DESTINATION lib 29 | ARCHIVE DESTINATION lib) 30 | install (FILES ${evnsq_PUBLIC_HEADERS} DESTINATION "include/evnsq") 31 | 32 | if (NOT EVPP_VCPKG_BUILD) 33 | add_subdirectory(evnsqtail) 34 | add_subdirectory(test) 35 | endif () 36 | -------------------------------------------------------------------------------- /apps/evnsq/command.cc: -------------------------------------------------------------------------------- 1 | #include "command.h" 2 | 3 | namespace evnsq { 4 | void Command::WriteTo(evpp::Buffer* buf) const { 5 | buf->Append(name_); 6 | 7 | if (!params_.empty()) { 8 | auto it = params_.begin(); 9 | auto ite = params_.end(); 10 | 11 | for (; it != ite; ++it) { 12 | buf->AppendInt8(' '); 13 | buf->Append(*it); 14 | } 15 | } 16 | 17 | buf->AppendInt8('\n'); 18 | 19 | if (body_.empty()) { 20 | return; 21 | } 22 | 23 | if (body_.size() == 1) { 24 | const std::string& d = body_[0]; 25 | buf->AppendInt32(int32_t(d.size())); 26 | buf->Append(d); 27 | } else { 28 | assert(body_.size() > 1); 29 | assert(name_ == "MPUB"); 30 | int32_t mpub_body_size = 4; 31 | 32 | for (size_t i = 0; i < body_.size(); ++i) { 33 | mpub_body_size += 4; 34 | mpub_body_size += body_[i].size(); 35 | } 36 | 37 | buf->AppendInt32(mpub_body_size); 38 | buf->AppendInt32(int32_t(body_.size())); 39 | 40 | for (size_t i = 0; i < body_.size(); ++i) { 41 | const std::string& msg = body_[i]; 42 | buf->AppendInt32(int32_t(msg.size())); 43 | buf->Append(msg); 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /apps/evnsq/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #ifdef _WIN32 5 | #include "evnsq/windows_port.h" 6 | #else 7 | #define EVNSQ_EXPORT 8 | #endif -------------------------------------------------------------------------------- /apps/evnsq/consumer.cc: -------------------------------------------------------------------------------- 1 | #include "consumer.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include "command.h" 13 | #include "option.h" 14 | 15 | namespace evnsq { 16 | Consumer::Consumer(evpp::EventLoop* l, const std::string& topic, const std::string& channel, const Option& ops) 17 | : Client(l, kConsumer, ops) { 18 | set_topic(topic); 19 | set_channel(channel); 20 | } 21 | 22 | Consumer::~Consumer() { 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /apps/evnsq/consumer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "evnsq/config.h" 11 | 12 | #include "client.h" 13 | 14 | namespace evnsq { 15 | class Command; 16 | 17 | class EVNSQ_EXPORT Consumer : public Client { 18 | public: 19 | Consumer(evpp::EventLoop* loop, const std::string& topic, const std::string& channel, const Option& ops); 20 | ~Consumer(); 21 | }; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /apps/evnsq/evnsqtail/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(evnsq_tail main.cc) 2 | target_link_libraries(evnsq_tail evnsq_static ${LIBRARIES}) 3 | -------------------------------------------------------------------------------- /apps/evnsq/evnsqtail/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | int OnMessage(const evnsq::Message* msg) { 6 | LOG_INFO << "Received a message, id=" << msg->id << " message=[" << msg->body.ToString() << "]"; 7 | return 0; 8 | } 9 | 10 | int main(int argc, char* argv[]) { 11 | std::string nsqd_tcp_addr; 12 | std::string lookupd_http_url; 13 | nsqd_tcp_addr = "127.0.0.1:4150"; 14 | //nsqd_tcp_addr = "weizili-L1:4150"; 15 | //lookupd_http_url = "http://127.0.0.1:4161/lookup?topic=test"; 16 | 17 | if (argc == 2) { 18 | if (strncmp(argv[1], "http", 4) == 0) { 19 | lookupd_http_url = argv[1]; 20 | } else { 21 | nsqd_tcp_addr = argv[1]; 22 | } 23 | } 24 | 25 | evpp::EventLoop loop; 26 | evnsq::Consumer client(&loop, "test", "ch1", evnsq::Option()); 27 | client.SetMessageCallback(&OnMessage); 28 | 29 | if (!lookupd_http_url.empty()) { 30 | client.ConnectToLookupds(lookupd_http_url); 31 | } else { 32 | client.ConnectToNSQDs(nsqd_tcp_addr); 33 | } 34 | 35 | loop.Run(); 36 | return 0; 37 | } 38 | 39 | #ifdef WIN32 40 | #include "../../../examples/echo/tcpecho/winmain-inl.h" 41 | #endif 42 | -------------------------------------------------------------------------------- /apps/evnsq/option.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "evnsq/config.h" 6 | 7 | #include 8 | 9 | namespace evnsq { 10 | 11 | // Option is a struct of NSQ options 12 | struct EVNSQ_EXPORT Option { 13 | public: 14 | Option(); 15 | std::string ToJSON() const; 16 | 17 | public: 18 | evpp::Duration dial_timeout = evpp::Duration(1.0); 19 | 20 | // Deadlines for network reads and writes 21 | evpp::Duration read_timeout = evpp::Duration(60.0); // min:"100ms" max:"5m" 22 | evpp::Duration write_timeout = evpp::Duration(1.0); // min:"100ms" max:"5m" 23 | 24 | // The server-side message timeout for messages delivered to this client 25 | // min:"0" 26 | evpp::Duration msg_timeout = evpp::Duration(0); 27 | 28 | // Identifiers sent to nsqd representing this client 29 | // UserAgent is in the spirit of HTTP (default: "/") 30 | std::string client_id = "evnsq"; // (defaults: short hostname) 31 | std::string hostname = "evnsq.localhost.com"; 32 | std::string user_agent = "evnsq/1.0"; 33 | 34 | // Duration of time between heartbeats. This must be less than read_timeout 35 | evpp::Duration heartbeat_interval = evpp::Duration(30.0); 36 | 37 | // Duration of interval time to query nsqlookupd 38 | evpp::Duration query_nsqlookupd_interval = evpp::Duration(30.0); 39 | 40 | //authorization 41 | std::string auth_secret; 42 | 43 | bool feature_negotiation = true; 44 | 45 | // Integer percentage to sample the channel (requires nsqd 0.2.25+) 46 | // min:"0" max : "99" 47 | int sample_rate = 0; 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /apps/evnsq/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(producer_with_auth) -------------------------------------------------------------------------------- /apps/evnsq/test/producer_with_auth/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set (unittest_evnsq_producer_with_auth_SRCS main.cc) 3 | if (WIN32) 4 | list (APPEND unittest_evnsq_producer_with_auth_SRCS ${PROJECT_SOURCE_DIR}/3rdparty/win32code/getopt/getopt.c) 5 | list (APPEND unittest_evnsq_producer_with_auth_SRCS ${PROJECT_SOURCE_DIR}/3rdparty/win32code/getopt/getopt_long.c) 6 | endif (WIN32) 7 | 8 | add_executable(unittest_evnsq_producer_with_auth ${unittest_evnsq_producer_with_auth_SRCS}) 9 | target_link_libraries(unittest_evnsq_producer_with_auth evnsq_static ${LIBRARIES}) 10 | 11 | -------------------------------------------------------------------------------- /apps/evnsq/windows_port.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // We must link against these libraries on windows platform for Visual Studio IDE 6 | #ifdef _WIN32 7 | #ifndef EVNSQ_EXPORTS 8 | #pragma comment(lib, "evnsq_static.lib") 9 | #endif 10 | #endif 11 | 12 | 13 | //! Module symbol export 14 | // #ifdef H_WINDOWS_API 15 | // # ifndef H_STATIC_LIB_LIBEVNSQ 16 | // # ifdef EVNSQ_EXPORTS 17 | // # define EVNSQ_EXPORT __declspec(dllexport) 18 | // # else 19 | // # define EVNSQ_EXPORT __declspec(dllimport) 20 | // # endif 21 | // # else 22 | // # define EVNSQ_EXPORT 23 | // # endif 24 | // #else 25 | // # define EVNSQ_EXPORT 26 | // #endif // H_STATIC_LIB_ 27 | 28 | #define EVNSQ_EXPORT -------------------------------------------------------------------------------- /apps/readme.md: -------------------------------------------------------------------------------- 1 | 2 | This directory holds some libraries based on [evpp]: 3 | 4 | 1. [evmc] a nonblocking async C++ memcached (or membase cluster) client library. This library is currently used in production which sends more than 100 billion requests every day. See [evmc readme](/apps/evmc/readme.md) for more details. 5 | 2. [evnsq] a nonblocking async C++ NSQ client library. This library is currently used in production which processes more than 20 billion messages every day. See [evnsq readme](/apps/evnsq/readme.md) for more details. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | [evpp]:https://github.com/Qihoo360/evpp 14 | [evmc]:https://github.com/Qihoo360/evpp/tree/master/apps/evmc 15 | [evnsq]:https://github.com/Qihoo360/evpp/tree/master/apps/evnsq -------------------------------------------------------------------------------- /benchmark/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(throughput) 2 | add_subdirectory(gettimeofday) 3 | add_subdirectory(http) 4 | add_subdirectory(ioevent) 5 | add_subdirectory(post_task) 6 | add_subdirectory(throughput_header_body) 7 | -------------------------------------------------------------------------------- /benchmark/gettimeofday/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories("../../../") 2 | 3 | add_executable(benchmark_gettimeofday gettimeofday.cc) 4 | -------------------------------------------------------------------------------- /benchmark/http/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if (UNIX) 2 | add_subdirectory(libevent) 3 | endif (UNIX) 4 | 5 | add_subdirectory(evpp) -------------------------------------------------------------------------------- /benchmark/http/evpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | if (UNIX) 3 | else(UNIX) 4 | link_directories(${PROJECT_SOURCE_DIR}/vsprojects/bin/${CMAKE_BUILD_TYPE}/ 5 | ${LIBRARY_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}/ 6 | ${PROJECT_SOURCE_DIR}/3rdparty/glog-0.3.4/${CMAKE_BUILD_TYPE}) 7 | endif(UNIX) 8 | 9 | add_executable(benchmark_http_evpp evpp_http_bench.cc ) 10 | target_link_libraries(benchmark_http_evpp evpp_static ${DEPENDENT_LIBRARIES}) 11 | 12 | -------------------------------------------------------------------------------- /benchmark/http/libevent/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(benchmark_http_libevent libevent_http_bench.c) 3 | target_link_libraries(benchmark_http_libevent event) 4 | -------------------------------------------------------------------------------- /benchmark/ioevent/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if (UNIX) 2 | add_subdirectory(libevent) 3 | endif (UNIX) 4 | 5 | add_subdirectory(evpp) 6 | add_subdirectory(fd_channel_vs_pipe_event_watcher) 7 | -------------------------------------------------------------------------------- /benchmark/ioevent/asio/run_ioevent_bench.sh: -------------------------------------------------------------------------------- 1 | 2 | 3 | for num in 500 1000 10000 30000; do 4 | for loop in 1 2 3 4 5 6 7 8 9 10; do 5 | echo "Bench index=$loop num=$num" 6 | taskset -c 3 ./asio_test.exe socketpair $num 100 $num 7 | done 8 | done 9 | -------------------------------------------------------------------------------- /benchmark/ioevent/evpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | if (UNIX) 3 | else (UNIX) 4 | link_directories(${PROJECT_SOURCE_DIR}/vsprojects/bin/${CMAKE_BUILD_TYPE}/ 5 | ${LIBRARY_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}/ 6 | ${PROJECT_SOURCE_DIR}/3rdparty/glog-0.3.4/${CMAKE_BUILD_TYPE}) 7 | endif(UNIX) 8 | 9 | set (evpp_SRCS evpp_ioevent_bench.cc) 10 | if (WIN32) 11 | list (APPEND evpp_SRCS ${PROJECT_SOURCE_DIR}/3rdparty/win32code/getopt/getopt.c) 12 | list (APPEND evpp_SRCS ${PROJECT_SOURCE_DIR}/3rdparty/win32code/getopt/getopt_long.c) 13 | endif (WIN32) 14 | add_executable(benchmark_ioevent_evpp ${evpp_SRCS}) 15 | target_link_libraries(benchmark_ioevent_evpp evpp_static ${DEPENDENT_LIBRARIES}) 16 | 17 | 18 | 19 | set (evpp_SRCS evpp_ioevent_pipe_watcher.cc) 20 | if (WIN32) 21 | list (APPEND evpp_SRCS ${PROJECT_SOURCE_DIR}/3rdparty/win32code/getopt/getopt.c) 22 | list (APPEND evpp_SRCS ${PROJECT_SOURCE_DIR}/3rdparty/win32code/getopt/getopt_long.c) 23 | endif (WIN32) 24 | 25 | add_executable(benchmark_ioevent_evpp_pipe_watcher ${evpp_SRCS}) 26 | target_link_libraries(benchmark_ioevent_evpp_pipe_watcher evpp_static ${DEPENDENT_LIBRARIES}) 27 | 28 | 29 | -------------------------------------------------------------------------------- /benchmark/ioevent/fd_channel_vs_pipe_event_watcher/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | if (UNIX) 3 | else(UNIX) 4 | link_directories(${PROJECT_SOURCE_DIR}/vsprojects/bin/${CMAKE_BUILD_TYPE}/ 5 | ${LIBRARY_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}/ 6 | ${PROJECT_SOURCE_DIR}/3rdparty/glog-0.3.4/${CMAKE_BUILD_TYPE}) 7 | endif(UNIX) 8 | 9 | add_executable(benchmark_fd_channel_vs_pipe_event_watcher fd_channel_vs_pipe_event_watcher.cc) 10 | target_link_libraries(benchmark_fd_channel_vs_pipe_event_watcher evpp_static ${DEPENDENT_LIBRARIES}) 11 | 12 | 13 | -------------------------------------------------------------------------------- /benchmark/ioevent/libevent/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(benchmark_ioevent_libevent libevent_ioevent_bench.c) 3 | target_link_libraries(benchmark_ioevent_libevent event) 4 | -------------------------------------------------------------------------------- /benchmark/ioevent/libevent/README: -------------------------------------------------------------------------------- 1 | 2 | 1. copy benchmark_ioevent_libevent and benchmark_ioevent_evpp to this directory 3 | 2. copy muduo's pingpong_bench to this directory 4 | -------------------------------------------------------------------------------- /benchmark/ioevent/run_ioevent_bench.sh: -------------------------------------------------------------------------------- 1 | 2 | for num in 500 1000 10000 30000; do 3 | for loop in 1 2 3 4 5 6 7 8 9 10; do 4 | taskset -c 3 ../../build-release/bin/benchmark_ioevent_evpp_pipe_watcher -n $num -a 100 -w $num 5 | taskset -c 3 ../../build-release/bin/benchmark_ioevent_evpp -n $num -a 100 -w $num 6 | taskset -c 3 ../../build-release/bin/benchmark_ioevent_libevent -n $num -a 100 -w $num 7 | taskset -c 3 ../../../build/release/bin/pingpong_bench -n $num -a 100 -w $num 8 | done 9 | done 10 | -------------------------------------------------------------------------------- /benchmark/post_task/bench.sh: -------------------------------------------------------------------------------- 1 | 2 | for count in 1000000; do 3 | for thread in 1 2 4 6 8 12 16 20; do 4 | ../../build-release/bin/benchmark_post_task1 $thread $count 5 | ../../build-release/bin/benchmark_post_task_boost_lockfree_queue_queue1 $thread $count 6 | ../../build-release/bin/benchmark_post_task2 $thread $count 7 | ../../build-release/bin/benchmark_post_task_boost_lockfree_queue_queue2 $thread $count 8 | ../../build-release/bin/benchmark_post_task6 $thread $count 9 | ../../build-release/bin/benchmark_post_task_boost_lockfree_queue_queue6 $thread $count 10 | ../../build-release/bin/benchmark_post_task_concurrentqueue6 $thread $count 11 | done 12 | ../../build-release/bin/benchmark_post_task3 $count 13 | ../../build-release/bin/benchmark_post_task_boost_lockfree_queue_queue3 $count 14 | ../../build-release/bin/benchmark_post_task4 $count 15 | ../../build-release/bin/benchmark_post_task_boost_lockfree_queue_queue4 $count 16 | ../../build-release/bin/benchmark_post_task5 $count 17 | ../../build-release/bin/benchmark_post_task_boost_lockfree_queue_queue5 $count 18 | done 19 | -------------------------------------------------------------------------------- /benchmark/post_task/readme.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1. posttask1是多个线程排成一圈,依次给下一个线程post task,task为递增一个成员变量,直到递增到设定次数为止。 4 | 1. posttask2是偶数个线程两两分成多组,组内两个线程来回post task,task为递增一个成员变量(需要用atomic),直到递增到设定次数为止。 5 | 1. postask3是线程1向线程2发送指定数量的task。 6 | 1. postask4是线程1向线程2发送指定数量的task,但是并不真正发送这么多次,而是检查一个带锁的队列,如果队列不为空则直接插入不发送。 7 | 1. postask5是posttask4的改进版。队列直接保存task本身。这更接近真实情况。posttask4过于简化任务了。 8 | 1. postask6是多个线程同时向同一个线程post task,task为递增一个成员变量,直到递增到设定次数为止。在多个生产者,单消费者的情况下,使用boost::lockfree之后的性能大约是std::mutex的两倍。推荐使用boost::lockfree 9 | 10 | [huyuguang@dtrans1 ~/code/asio]$ ./asio_test.exe posttask3 10000000 use time(us): 9077386 11 | 12 | [huyuguang@dtrans1 ~/code/asio]$ ./asio_test.exe posttask4 10000000 use time(us): 638762 13 | 14 | [huyuguang@dtrans1 ~/code/asio]$ ./asio_test.exe posttask5 10000000 use time(us): 4202412 15 | 16 | posttask4是理想情况。posttask5比较接近真实情况。但实际上由于posttask5的实现是高度优化的,包括用了2个实现reserved的vector来回swap,因此我怀疑并不值得采用posttask5这样的上层优化。 17 | -------------------------------------------------------------------------------- /benchmark/throughput/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if (UNIX) 2 | add_subdirectory(asio_from_chenshuo) 3 | add_subdirectory(libevent) 4 | endif(UNIX) 5 | 6 | add_subdirectory(evpp) 7 | -------------------------------------------------------------------------------- /benchmark/throughput/asio/multiple_thread.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #set -x 4 | 5 | killall asio_test.exe 6 | timeout=${timeout:-10} 7 | bufsize=${bufsize:-16384} 8 | nothreads=1 9 | 10 | for nosessions in 100 1000; do 11 | for nothreads in 2 3 4 6 8; do 12 | echo "======================> (test1) Bufsize: $bufsize Threads: $nothreads Sessions: $nosessions" 13 | sleep 1 14 | ./asio_test.exe server1 127.0.0.1 33333 $nothreads $bufsize & srvpid=$! 15 | sleep 1 16 | ./asio_test.exe client1 127.0.0.1 33333 $nothreads $bufsize $nosessions $timeout 17 | sleep 1 18 | kill -9 $srvpid 19 | sleep 5 20 | done 21 | done 22 | 23 | for nosessions in 100 1000; do 24 | for nothreads in 2 3 4 6 8; do 25 | echo "======================> (test2) Bufsize: $bufsize Threads: $nothreads Sessions: $nosessions" 26 | sleep 1 27 | ./asio_test.exe server2 127.0.0.1 33333 $nothreads $bufsize & srvpid=$! 28 | sleep 1 29 | ./asio_test.exe client2 127.0.0.1 33333 $nothreads $bufsize $nosessions $timeout 30 | sleep 1 31 | kill -9 $srvpid 32 | sleep 5 33 | done 34 | done 35 | -------------------------------------------------------------------------------- /benchmark/throughput/asio/single_thread.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #set -x 4 | 5 | killall asio_test.exe 6 | timeout=${timeout:-10} 7 | #bufsize=${bufsize:-16384} 8 | nothreads=1 9 | 10 | for bufsize in 1024 2048 4096 8192 16384 81920; do 11 | for nosessions in 1 10 100 1000 10000; do 12 | echo "======================> (test1) Bufsize: $bufsize Threads: $nothreads Sessions: $nosessions" 13 | sleep 1 14 | taskset -c 1 ./asio_test.exe server1 127.0.0.1 33333 $nothreads $bufsize & srvpid=$! 15 | sleep 1 16 | taskset -c 2 ./asio_test.exe client1 127.0.0.1 33333 $nothreads $bufsize $nosessions $timeout 17 | sleep 1 18 | kill -9 $srvpid 19 | sleep 5 20 | done 21 | done 22 | 23 | for bufsize in 1024 2048 4096 8192 16384 81920; do 24 | for nosessions in 1 10 100 1000 10000; do 25 | echo "======================> (test2) Bufsize: $bufsize Threads: $nothreads Sessions: $nosessions" 26 | sleep 1 27 | taskset -c 1 ./asio_test.exe server2 127.0.0.1 33333 $nothreads $bufsize & srvpid=$! 28 | sleep 1 29 | taskset -c 2 ./asio_test.exe client2 127.0.0.1 33333 $nothreads $bufsize $nosessions $timeout 30 | sleep 1 31 | kill -9 $srvpid 32 | sleep 5 33 | done 34 | done 35 | -------------------------------------------------------------------------------- /benchmark/throughput/asio_from_chenshuo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(Boost REQUIRED COMPONENTS system thread) 2 | 3 | add_executable(benchmark_tcp_asio_client client.cpp) 4 | target_link_libraries(benchmark_tcp_asio_client ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} pthread) 5 | 6 | add_executable(benchmark_tcp_asio_server server.cpp) 7 | target_link_libraries(benchmark_tcp_asio_server ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} pthread) 8 | 9 | -------------------------------------------------------------------------------- /benchmark/throughput/asio_from_chenshuo/LICENSE_1_0.txt: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /benchmark/throughput/asio_from_chenshuo/README: -------------------------------------------------------------------------------- 1 | 2 | The following files are retrieved from http://asio.cvs.sourceforge.net/viewvc/asio/asio/src/tests/performance/ 3 | 4 | client.cpp 5 | server.cpp 6 | handler_allocator.hpp 7 | 8 | The author of them is Christopher M. Kohlhoff (chris at kohlhoff dot com). 9 | 10 | 11 | The rest of other files in this directory are retrieved from https://github.com/chenshuo/recipes/tree/master/pingpong/asio 12 | The author of them is Chen Shuo (chenshuo at chenshuox dot com). 13 | 14 | 15 | -------------------------------------------------------------------------------- /benchmark/throughput/asio_from_chenshuo/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 | -------------------------------------------------------------------------------- /benchmark/throughput/asio_from_chenshuo/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | g++ -O2 -finline-limit=1000 server.cpp -o benchmark_tcp_asio_server -lpthread -lboost_thread -lboost_system 3 | g++ -O2 -finline-limit=1000 client.cpp -o benchmark_tcp_asio_client -lpthread -lboost_thread -lboost_system 4 | -------------------------------------------------------------------------------- /benchmark/throughput/asio_from_chenshuo/multiple_thread.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | killall benchmark_tcp_asio_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 | ./benchmark_tcp_asio_server 0.0.0.0 55555 $nothreads $bufsize & srvpid=$! 12 | sleep 1 13 | ./benchmark_tcp_asio_client 127.0.0.1 55555 $nothreads $bufsize $nosessions $timeout 14 | kill -9 $srvpid 15 | done 16 | done 17 | -------------------------------------------------------------------------------- /benchmark/throughput/asio_from_chenshuo/single_thread.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | killall benchmark_tcp_asio_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 ./benchmark_tcp_asio_server 0.0.0.0 55555 $nothreads $bufsize & srvpid=$! 12 | sleep 1 13 | taskset -c 2 ./benchmark_tcp_asio_client 127.0.0.1 55555 $nothreads $bufsize $nosessions $timeout 14 | kill -9 $srvpid 15 | done 16 | 17 | -------------------------------------------------------------------------------- /benchmark/throughput/evpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/3rdparty) 2 | 3 | set(LIBRARIES evpp_static ${DEPENDENT_LIBRARIES}) 4 | if (WIN32) 5 | link_directories(${PROJECT_SOURCE_DIR}/vsprojects/bin/${CMAKE_BUILD_TYPE}/ 6 | ${PROJECT_SOURCE_DIR}/3rdparty/glog-0.3.4/${CMAKE_BUILD_TYPE}) 7 | endif(WIN32) 8 | 9 | add_executable(benchmark_pingpong_client client.cc) 10 | target_link_libraries(benchmark_pingpong_client ${LIBRARIES}) 11 | 12 | add_executable(benchmark_pingpong_client_fixed_size client_fixed_size.cc) 13 | target_link_libraries(benchmark_pingpong_client_fixed_size ${LIBRARIES}) 14 | 15 | add_executable(benchmark_pingpong_server server.cc) 16 | target_link_libraries(benchmark_pingpong_server ${LIBRARIES}) 17 | -------------------------------------------------------------------------------- /benchmark/throughput/evpp/README: -------------------------------------------------------------------------------- 1 | 2 | Start scripts of ping pong test. 3 | 4 | Copy *.sh to evpp/build-release/bin, and run. 5 | -------------------------------------------------------------------------------- /benchmark/throughput/evpp/multiple_thread.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | killall benchmark_pingpong_server 4 | timeout=${timeout:-100} 5 | bufsize=${bufsize:-16384} 6 | 7 | for nosessions in 100 1000; do 8 | for nothreads in 2 3 4 6 8; do 9 | sleep 5 10 | echo "Bufsize: $bufsize Threads: $nothreads Sessions: $nosessions" 11 | ./benchmark_pingpong_server 33333 $nothreads & srvpid=$! 12 | sleep 1 13 | ./benchmark_pingpong_client 127.0.0.1 33333 $nothreads $bufsize $nosessions $timeout 14 | kill -9 $srvpid 15 | done 16 | done 17 | -------------------------------------------------------------------------------- /benchmark/throughput/evpp/server.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void OnConnection(const evpp::TCPConnPtr& conn) { 6 | if (conn->IsConnected()) { 7 | conn->SetTCPNoDelay(true); 8 | } 9 | } 10 | 11 | void OnMessage(const evpp::TCPConnPtr& conn, 12 | evpp::Buffer* msg) { 13 | conn->Send(msg); 14 | } 15 | 16 | int main(int argc, char* argv[]) { 17 | std::string addr = "0.0.0.0:9099"; 18 | int thread_num = 4; 19 | 20 | if (argc != 1 && argc != 3) { 21 | printf("Usage: %s \n", argv[0]); 22 | printf(" e.g: %s 9099 12\n", argv[0]); 23 | return 0; 24 | } 25 | 26 | if (argc == 3) { 27 | addr = std::string("0.0.0.0:") + argv[1]; 28 | thread_num = atoi(argv[2]); 29 | } 30 | 31 | evpp::EventLoop loop; 32 | evpp::TCPServer server(&loop, addr, "TCPPingPongServer", thread_num); 33 | server.SetMessageCallback(&OnMessage); 34 | server.SetConnectionCallback(&OnConnection); 35 | server.Init(); 36 | server.Start(); 37 | loop.Run(); 38 | return 0; 39 | } 40 | 41 | 42 | #include "../../../examples/echo/tcpecho/winmain-inl.h" 43 | 44 | 45 | -------------------------------------------------------------------------------- /benchmark/throughput/evpp/single_thread.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -x 4 | 5 | killall benchmark_pingpong_server 6 | timeout=${timeout:-100} 7 | #bufsize=${bufsize:-16384} 8 | nothreads=1 9 | 10 | for bufsize in 1024 2048 4096 8192 16384 81920 409600; do 11 | for nosessions in 1 10 100 1000 10000; do 12 | echo "======================> Bufsize: $bufsize Threads: $nothreads Sessions: $nosessions" 13 | taskset -c 1 ./benchmark_pingpong_server 33333 $nothreads & srvpid=$! 14 | sleep 1 15 | taskset -c 2 ./benchmark_pingpong_client 127.0.0.1 33333 $nothreads $bufsize $nosessions $timeout 16 | sleep 1 17 | taskset -c 2 ./benchmark_pingpong_client_fixed_size 127.0.0.1 33333 $nothreads $bufsize $nosessions $timeout 18 | kill -9 $srvpid 19 | sleep 5 20 | done 21 | done 22 | -------------------------------------------------------------------------------- /benchmark/throughput/libevent/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(benchmark_tcp_libevent_client client.c) 2 | target_link_libraries(benchmark_tcp_libevent_client event) 3 | 4 | add_executable(benchmark_tcp_libevent_server server.c) 5 | target_link_libraries(benchmark_tcp_libevent_server event) 6 | -------------------------------------------------------------------------------- /benchmark/throughput/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 | -------------------------------------------------------------------------------- /benchmark/throughput/libevent/README: -------------------------------------------------------------------------------- 1 | The files in this directory are retrieved from https://github.com/chenshuo/recipes/tree/master/pingpong/libevent 2 | The author of them is Chen Shuo (chenshuo at chenshuox dot com). 3 | 4 | 5 | -------------------------------------------------------------------------------- /benchmark/throughput/libevent/single_thread.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | killall benchmark_tcp_libevent_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 ./benchmark_tcp_libevent_server 2> /dev/null & srvpid=$! 12 | sleep 1 13 | taskset -c 2 ./benchmark_tcp_libevent_client 9876 $bufsize $nosessions $timeout 14 | kill -9 $srvpid 15 | done 16 | 17 | -------------------------------------------------------------------------------- /benchmark/throughput_header_body/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | add_subdirectory(evpp) 4 | -------------------------------------------------------------------------------- /benchmark/throughput_header_body/asio/m3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -x 4 | 5 | killall asio_test.exe 6 | totalcount=${totalcount:-8192} 7 | 8 | #Usage: asio_test server3
9 | #Usage: asio_test client3 10 | 11 | for nosessions in 100 1000 10000; do 12 | for nothreads in 1 2 3 4 6 8; do 13 | echo "======================> (test1) TotalCount: $totalcount Threads: $nothreads Sessions: $nosessions" 14 | sleep 1 15 | ./asio_test.exe server3 127.0.0.1 33333 $nothreads $totalcount & srvpid=$! 16 | sleep 1 17 | ./asio_test.exe client3 127.0.0.1 33333 $nothreads $totalcount $nosessions 18 | sleep 1 19 | kill -9 $srvpid 20 | sleep 5 21 | done 22 | done 23 | 24 | -------------------------------------------------------------------------------- /benchmark/throughput_header_body/evpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/3rdparty) 2 | 3 | set(LIBRARIES evpp_static ${DEPENDENT_LIBRARIES}) 4 | if (WIN32) 5 | link_directories(${PROJECT_SOURCE_DIR}/vsprojects/bin/${CMAKE_BUILD_TYPE}/ 6 | ${PROJECT_SOURCE_DIR}/3rdparty/glog-0.3.4/${CMAKE_BUILD_TYPE}) 7 | endif(WIN32) 8 | 9 | add_executable(benchmark_pingpong_header_body_client client.cc) 10 | target_link_libraries(benchmark_pingpong_header_body_client ${LIBRARIES}) 11 | 12 | add_executable(benchmark_pingpong_header_body_server server.cc) 13 | target_link_libraries(benchmark_pingpong_header_body_server ${LIBRARIES}) 14 | -------------------------------------------------------------------------------- /benchmark/throughput_header_body/evpp/header.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #pragma pack(push,1) 5 | struct Header { 6 | uint32_t body_size_; // net order 7 | uint32_t packet_count_; // net order 8 | 9 | uint32_t get_body_size() const { 10 | return ntohl(body_size_); 11 | } 12 | uint32_t get_full_size() const { 13 | return sizeof(Header) + ntohl(body_size_); 14 | } 15 | void inc_packet_count() { 16 | uint32_t count = ntohl(packet_count_) + 1; 17 | packet_count_ = htonl(count); 18 | } 19 | }; 20 | #pragma pack(pop) 21 | 22 | const size_t kMaxSize = 10000; -------------------------------------------------------------------------------- /benchmark/throughput_header_body/evpp/m3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -x 4 | 5 | killall asio_test.exe 6 | totalcount=${totalcount:-8192} 7 | 8 | for nosessions in 100 1000 10000; do 9 | for nothreads in 1 2 3 4 6 8; do 10 | echo "======================> (test1) TotalCount: $totalcount Threads: $nothreads Sessions: $nosessions" 11 | sleep 1 12 | ../../../build-release/bin/benchmark_pingpong_header_body_server 6666 $nothreads $totalcount & srvpid=$! 13 | sleep 1 14 | ../../../build-release/bin/benchmark_pingpong_header_body_client 127.0.0.1 6666 $nothreads $totalcount $nosessions 15 | sleep 1 16 | kill -9 $srvpid 17 | sleep 5 18 | done 19 | done 20 | 21 | -------------------------------------------------------------------------------- /benchmark/throughput_header_body/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Another ping pong benchmark test 3 | 4 |
 5 |     // Decode deserializes data (as Buffer*) to this message
 6 |     // message format:
 7 |     // [x][x][x][x][x][x][x][x][x][x][x][x]...
 8 |     // |(int32)   ||(int32)   || (binary)
 9 |     // |4-byte    ||4-byte    || N-byte
10 |     // |body size ||packet num|| msg body
11 | 
12 | 13 | The first 4 bytes is header, and following data body. 14 | -------------------------------------------------------------------------------- /cmake/git_checkin_count.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | COUNT=`git rev-list --all | wc -l` 3 | echo -n ${COUNT} 4 | -------------------------------------------------------------------------------- /cmake/rpm_kernel_release.sh: -------------------------------------------------------------------------------- 1 | echo -n $(/usr/lib/rpm/redhat/dist.sh --dist | awk -F '.' '{print $2}').$(uname -m) 2 | -------------------------------------------------------------------------------- /docs/benchmark/ioevent/ioevent-evpp-boost.chart: -------------------------------------------------------------------------------- 1 | 2 | # The chart type , option : spline/line/bar/column/area 3 | ChartType = column 4 | Title = IO Event Benchmark 5 | SubTitle = 1 thread, X Axis is the count of connection pipes 6 | ValueSuffix = us 7 | 8 | Height = 600 9 | 10 | # The x Axis numbers. The count this numbers MUST be the same with the data series 11 | XAxisNumbers = 500, 1000, 10000, 30000 12 | 13 | # The y Axis text 14 | YAxisText = time in microsecons (lower is better) 15 | 16 | # Every data is the average of 10 times of running 17 | Data|asio = 1002,1766,15637,45996 18 | Data|evpp-PipeEventWatcher = 608,1160,10845,32803 19 | Data|evpp-FdChannel = 616,1140,10663,32753 20 | Data|libevent = 566,1077,10616,32158 21 | 22 | 23 | # evpp-0.2.4 24 | # libevent 2.0.21 25 | # muduo v1.0.9 26 | # 27 | # evpp Changed: 28 | # optimized : Delete `space` relative code. 29 | # - send(pipes[i * space + 1], "e", 1, 0); 30 | # + send(pipes[i * 2 + 1], "e", 1, 0); 31 | # 32 | # Explaination: 33 | # 1. The `evpp_pipe` is used PipeEventWatcher to implement the benchmark test 34 | # 2. The `evpp_channel` is used FdChannel to implement the benchmark test 35 | # 36 | # Conclusion : 37 | # 1. `evpp_pipe`, `evpp_channel` and `libevent` has the similar performance 38 | # 2. The `muduo` has 4.1% higher performance than `evpp_channel` 39 | -------------------------------------------------------------------------------- /docs/benchmark/ioevent/ioevent-evpp-muduo-boost-libevent-opt.chart: -------------------------------------------------------------------------------- 1 | 2 | # The chart type , option : spline/line/bar/column/area 3 | ChartType = column 4 | Title = IO Event Benchmark 5 | SubTitle = 1 thread, X Axis is the count of connection pipes 6 | ValueSuffix = us 7 | 8 | Height = 600 9 | 10 | # The x Axis numbers. The count this numbers MUST be the same with the data series 11 | XAxisNumbers = 500, 1000, 10000, 30000 12 | 13 | # The y Axis text 14 | YAxisText = time in microsecons (lower is better) 15 | 16 | # Every data is the average of 10 times of running 17 | Data|asio = 1002,1766,15637,45996 18 | Data|evpp-PipeEventWatcher = 608,1160,10845,32803 19 | Data|evpp-FdChannel = 616,1140,10663,32753 20 | Data|muduo = 581,1092,10443,32075 21 | Data|libevent = 566,1077,10616,32158 22 | 23 | 24 | # evpp-0.2.4 25 | # libevent 2.0.21 26 | # muduo v1.0.9 27 | # 28 | # evpp Changed: 29 | # optimized : Delete `space` relative code. 30 | # - send(pipes[i * space + 1], "e", 1, 0); 31 | # + send(pipes[i * 2 + 1], "e", 1, 0); 32 | # 33 | # Explaination: 34 | # 1. The `evpp_pipe` is used PipeEventWatcher to implement the benchmark test 35 | # 2. The `evpp_channel` is used FdChannel to implement the benchmark test 36 | # 37 | # Conclusion : 38 | # 1. `evpp_pipe`, `evpp_channel` and `libevent` has the similar performance 39 | # 2. The `muduo` has 4.1% higher performance than `evpp_channel` 40 | -------------------------------------------------------------------------------- /docs/benchmark/post_task/boost-lockfree-vs-mutex-benchmark-1v1.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Post Task Test 4 | SubTitle = 1 thread reads and 1 thread writes. X Axis is sequence number of the testing. Total write count 1000000 5 | ValueSuffix = s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1,2,3,4,5,6,7,8,9,10 9 | 10 | # The y Axis text 11 | YAxisText = Cost Time (s) Lower is better 12 | 13 | # The data and the name of the lines 14 | 15 | #Data|std::mutex = 0.888882,1.5874,0.887219,0.889635,0.885486,1.663,0.857667,1.71721,0.865579,0.840093 16 | #Data|boost::lockfree = 0.896792,0.848745,0.75508,0.739209,0.76087,0.78627,0.852692,0.785489,0.828407,0.830652 17 | 18 | Data|std::mutex = 0.850816,0.859067,0.882146,0.876389,0.900036,1.03817,0.99159,0.87904,1.1289,0.861899 19 | Data|boost::lockfree::queue = 0.825175,0.816926,0.75426,1.00524,0.810757,0.890165,1.42837,0.864659,1.06019,0.821592 20 | Data|moodycamel::ConcurrentQueue = 0.582711,1.0248,0.566609,0.802074,1.01207,0.626012,0.607837,0.831595,0.736251,0.622935 21 | 22 | # evpp : v0.3.1 23 | 24 | -------------------------------------------------------------------------------- /docs/benchmark/post_task/boost-lockfree-vs-mutex-benchmark.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Post Task Test 4 | SubTitle = 1 thread reads, multi threads write. X Axis is the writing thread count. Total write count 1000000 5 | ValueSuffix = s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 2, 4, 6, 8, 12, 16, 20 9 | 10 | # The y Axis text 11 | YAxisText = Cost Time (s) Lower is better 12 | 13 | # The data and the name of the lines 14 | 15 | Data|std::mutex = 2.04538,5.45523,9.03564,13.6443,19.3664,27.0369,33.8794 16 | Data|boost::lockfree::queue = 1.27025,2.17819,4.058,4.99668,11.778,14.6983,19.3277 17 | Data|moodycamel::ConcurrentQueue = 1.00532,1.08969,2.37993,2.78818,4.65252,6.97016,9.68365 18 | 19 | # evpp : v0.3.1 20 | 21 | -------------------------------------------------------------------------------- /docs/benchmark/post_task/evpp-post-task.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Post Task Test 4 | SubTitle = X Axis is the count of post task 5 | ValueSuffix = s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 10000, 100000, 1000000 9 | 10 | # The y Axis text 11 | YAxisText = Cost Time (s) Lower is better 12 | 13 | # The data and the name of the lines 14 | 15 | 16 | Data|mutex-thread2 = 0.051724,0.51696,5.04023 17 | Data|lockfree-thread2 = 0.019066,0.108174,0.914753 18 | 19 | Data|mutex-thread4 = 0.052972,0.557792,5.17756 20 | Data|lockfree-thread4 = 0.053121,0.60298,5.32116 21 | 22 | Data|mutex-thread8 = 0.061376,0.573648,5.37257 23 | Data|lockfree-thread8 = 0.06144,0.608494,5.88405 24 | 25 | # evpp : v0.3.1 26 | 27 | -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-1thread-evpp-vs-asio-1.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Throughput 4 | SubTitle = 1 thread, 100 seconds, message size is 1024, X Axis is the connection count 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1, 10, 100, 1000, 10000 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) 12 | 13 | # The data and the name of the lines 14 | 15 | Data|asio-1024 = 60.1116,168.622,172.527,154.808,107.583 16 | Data|evpp-1024 = 64.2529,188.201,198.164,167.661,105.592 17 | 18 | # evpp : v0.2.4 19 | # asio : v1.10.8 code is here https://github.com/huyuguang/asio_benchmark 20 | 21 | -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-1thread-evpp-vs-asio-2.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Throughput 4 | SubTitle = 1 thread, 100 seconds, message size is 2048, X Axis is the connection count 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1, 10, 100, 1000, 10000 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) 12 | 13 | # The data and the name of the lines 14 | 15 | Data|asio-2048 = 114.856,308.395,310.189,255.19,219.42 16 | Data|evpp-2048 = 119.362,342.96,369.187,265.609,198.586 17 | 18 | 19 | # evpp : v0.2.4 20 | # asio : v1.10.8 code is here https://github.com/huyuguang/asio_benchmark 21 | 22 | -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-1thread-evpp-vs-asio-3.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Throughput 4 | SubTitle = 1 thread, 100 seconds, message size is 4096, X Axis is the connection count 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1, 10, 100, 1000, 10000 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) 12 | 13 | # The data and the name of the lines 14 | 15 | Data|asio-4096 = 213.333,578.202,594.896,479.957,413.962 16 | Data|evpp-4096 = 229.274,631.611,671.219,495.566,366.071 17 | 18 | # evpp : v0.2.4 19 | # asio : v1.10.8 code is here https://github.com/huyuguang/asio_benchmark 20 | 21 | -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-1thread-evpp-vs-asio-4.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Throughput 4 | SubTitle = 1 thread, 100 seconds, message size is 8192, X Axis is the connection count 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1, 10, 100, 1000, 10000 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) 12 | 13 | # The data and the name of the lines 14 | 15 | 16 | Data|asio-8192 = 385.035,966.732,1006.34,752.303,685.108 17 | Data|evpp-8192 = 394.162,1079.67,1127.09,786.706,645.866 18 | 19 | # evpp : v0.2.4 20 | # asio : v1.10.8 code is here https://github.com/huyuguang/asio_benchmark 21 | 22 | -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-1thread-evpp-vs-asio-5.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Throughput 4 | SubTitle = 1 thread, 100 seconds, message size is 16384, X Axis is the connection count 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1, 10, 100, 1000, 10000 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) 12 | 13 | # The data and the name of the lines 14 | 15 | Data|asio-16384 = 609.898,1470.03,1489.4,1053.52,976.443 16 | Data|evpp-16384 = 631.047,1593.7,1662.23,1104.53,949.325 17 | 18 | # evpp : v0.2.4 19 | # asio : v1.10.8 code is here https://github.com/huyuguang/asio_benchmark 20 | 21 | -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-1thread-evpp-vs-asio-6.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Throughput 4 | SubTitle = 1 thread, 100 seconds, message size is 81920, X Axis is the connection count 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1, 10, 100, 1000, 10000 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) 12 | 13 | # The data and the name of the lines 14 | 15 | Data|asio-81920 = 944.895,2136.54,1476.44,1326.11,1286.93 16 | Data|evpp-81920 = 1565.22,2079.77,1464.16,1323.09,1297.18 17 | 18 | # evpp : v0.2.4 19 | # asio : v1.10.8 code is here https://github.com/huyuguang/asio_benchmark 20 | 21 | -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-1thread-evpp-vs-asio-all.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Throughput 4 | SubTitle = 1 thread, 100 seconds, X Axis is the connection count 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1, 10, 100, 1000, 10000 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) 12 | 13 | # The data and the name of the lines 14 | 15 | Data|asio-1024 = 60.1116,168.622,172.527,154.808,107.583 16 | Data|evpp-1024 = 64.2529,188.201,198.164,167.661,105.592 17 | Data|asio-2048 = 114.856,308.395,310.189,255.19,219.42 18 | Data|evpp-2048 = 119.362,342.96,369.187,265.609,198.586 19 | Data|asio-4096 = 213.333,578.202,594.896,479.957,413.962 20 | Data|evpp-4096 = 229.274,631.611,671.219,495.566,366.071 21 | Data|asio-8192 = 385.035,966.732,1006.34,752.303,685.108 22 | Data|evpp-8192 = 394.162,1079.67,1127.09,786.706,645.866 23 | Data|asio-16384 = 609.898,1470.03,1489.4,1053.52,976.443 24 | Data|evpp-16384 = 631.047,1593.7,1662.23,1104.53,949.325 25 | Data|asio-81920 = 944.895,2136.54,1476.44,1326.11,1286.93 26 | Data|evpp-81920 = 1565.22,2079.77,1464.16,1323.09,1297.18 27 | 28 | # evpp : v0.2.4 29 | # asio : v1.10.8 code is here https://github.com/huyuguang/asio_benchmark 30 | 31 | -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-1thread-evpp-vs-asio-from-chenshuo-recipes.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = spline 3 | Title = Throughput 4 | SubTitle = 1 thread, 100 seconds, X Axis is the connection count 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1, 10, 100, 1000, 10000 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) 12 | 13 | # The data and the name of the lines 14 | Data|evpp-4096 = 176.687, 511.97 , 527.447, 382.304, 293.661 15 | Data|asio-4096 = 149.091, 374.831, 371.053, 324.166, 270.279 16 | Data|evpp-2048 = 91.2897, 272.091, 286.151, 202.784, 157.1 17 | Data|asio-2048 = 80.9793, 206.252, 210.062, 182.487, 150.382 18 | Data|evpp-1024 = 49.0243, 148.691, 154.736, 113.056, 87.2173 19 | Data|asio-1024 = 42.4815, 114.369, 116.932, 98.9972, 80.4348 20 | Data|evpp-8192 = 318.147, 880.07 , 902.783, 612.031, 505.419 21 | Data|asio-8192 = 253.269, 607.09 , 599.779, 502.172, 443.609 22 | 23 | # evpp : v0.2.1 base on libevent 2.0.21 24 | # asio : from boost-1.53 , code is at here : https://github.com/chenshuo/recipes/tree/master/pingpong/asio 25 | -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-1thread-evpp-vs-libevent-1.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Throughput 4 | SubTitle = 1 thread, 100 seconds, X Axis is the connection count, message size 1024 bytes 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1, 10, 100, 1000, 10000 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) (larger is better) 12 | 13 | # The data and the name of the lines 14 | 15 | Data|evpp-1024 = 49.0243, 148.691, 154.736, 113.056, 87.2173 16 | Data|libevent-1024 = 44.453, 126.838, 135.216, 99.796, 67.020 -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-1thread-evpp-vs-libevent-2.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Throughput 4 | SubTitle = 1 thread, 100 seconds, X Axis is the connection count, message size 2048 bytes 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1, 10, 100, 1000, 10000 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) (larger is better) 12 | 13 | # The data and the name of the lines 14 | 15 | Data|evpp-2048 = 91.2897, 272.091, 286.151, 202.784, 157.1 16 | Data|libevent-2048 = 86.826, 239.404, 245.364, 174.577, 123.516 -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-1thread-evpp-vs-libevent-3.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Throughput 4 | SubTitle = 1 thread, 100 seconds, X Axis is the connection count, message size 4096 bytes 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1, 10, 100, 1000, 10000 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) (larger is better) 12 | 13 | # The data and the name of the lines 14 | 15 | 16 | Data|evpp-4096 = 176.687, 511.97 , 527.447, 382.304, 293.661 17 | Data|libevent-4096 = 164.296, 437.895, 448.102, 299.499, 213.457 18 | -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-1thread-evpp-vs-libevent-4.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Throughput 4 | SubTitle = 1 thread, 100 seconds, X Axis is the connection count, message size 8192 bytes 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1, 10, 100, 1000, 10000 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) (larger is better) 12 | 13 | # The data and the name of the lines 14 | 15 | Data|evpp-8192 = 318.147, 880.07 , 902.783, 612.031, 505.419 16 | Data|libevent-8192 = 259.809, 658.876, 661.269, 430.584, 388.728 17 | -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-1thread-evpp-vs-libevent-5.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Throughput 4 | SubTitle = 1 thread, 100 seconds, X Axis is the connection count, message size 16384 bytes 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1, 10, 100, 1000, 10000 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) (larger is better) 12 | 13 | # The data and the name of the lines 14 | 15 | 16 | Data|evpp-16384 = 513.816, 1353.46, 1297.01, 877.761, 725.397 17 | Data|libevent-16384 = 527.474, 669.445, 632.214, 370.356, 314.427 18 | -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-1thread-evpp-vs-libevent-all.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Throughput 4 | SubTitle = 1 thread, 100 seconds, X Axis is the connection count 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1, 10, 100, 1000, 10000 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) (larger is better) 12 | 13 | # The data and the name of the lines 14 | 15 | Data|evpp-1024 = 49.0243, 148.691, 154.736, 113.056, 87.2173 16 | Data|libevent-1024 = 44.453, 126.838, 135.216, 99.796, 67.020 17 | Data|evpp-2048 = 91.2897, 272.091, 286.151, 202.784, 157.1 18 | Data|libevent-2048 = 86.826, 239.404, 245.364, 174.577, 123.516 19 | Data|evpp-4096 = 176.687, 511.97 , 527.447, 382.304, 293.661 20 | Data|libevent-4096 = 164.296, 437.895, 448.102, 299.499, 213.457 21 | Data|evpp-8192 = 318.147, 880.07 , 902.783, 612.031, 505.419 22 | Data|libevent-8192 = 259.809, 658.876, 661.269, 430.584, 388.728 23 | Data|evpp-16384 = 513.816, 1353.46, 1297.01, 877.761, 725.397 24 | Data|libevent-16384 = 527.474, 669.445, 632.214, 370.356, 314.427 25 | -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-1thread-evpp-vs-muduo.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = spline 3 | Title = Throughput 4 | SubTitle = 1 thread, 100 seconds, X Axis is the connection count 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1, 10, 100, 1000, 10000 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) 12 | 13 | Height = 700 14 | 15 | # The data and the name of the lines 16 | 17 | Data|evpp-4096 = 229.274,631.611,671.219,495.566,366.071 18 | Data|muduo-4096 = 222.117, 609.152, 631.119, 514.235, 365.959 19 | 20 | Data|evpp-8192 = 394.162,1079.67,1127.09,786.706,645.866 21 | Data|muduo-8192 = 393.683, 1064.43, 1103.02, 815.269, 670.503 22 | 23 | 24 | Data|evpp-81920 = 1565.22,2079.77,1464.16,1323.09,1297.18 25 | Data|muduo-81920 = 1567.959, 2180.467, 1432.009, 1267.181, 1159.278 26 | 27 | Data|evpp-409600 = 1950.79,2363.68,1528.97,1290.17,1039.96 28 | Data|muduo-409600 = 1887.057, 2213.813, 1305.899, 1131.383, 1043.612 29 | 30 | # evpp : v0.2.4 31 | # muduo : v1.0.9 32 | -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-1thread-evpp.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = spline 3 | Title = Throughput 4 | SubTitle = 1 thread, 100 seconds, X Axis is the connection count 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1, 10, 100, 1000, 10000 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) 12 | 13 | # The data and the name of the lines 14 | Data|evpp-1024 = 64.2529,188.201,198.164,167.661,105.592 15 | Data|evpp-2048 = 119.362,342.96,369.187,265.609,198.586 16 | Data|evpp-4096 = 229.274,631.611,671.219,495.566,366.071 17 | Data|evpp-8192 = 394.162,1079.67,1127.09,786.706,645.866 18 | Data|evpp-16384 = 631.047,1593.7,1662.23,1104.53,949.325 19 | Data|evpp-81920 = 1565.22,2079.77,1464.16,1323.09,1297.18 20 | Data|evpp-409600 = 1950.79,2363.68,1528.97,1290.17,1039.96 21 | 22 | Data|evpp-fixed-size-1024 = 63.6883,187.08,197.526,165.117,106.053 23 | Data|evpp-fixed-size-2048 = 121.263,344.689,365.014,264.316,197.626 24 | Data|evpp-fixed-size-4096 = 226.614,635.582,665.151,491.015,374.453 25 | Data|evpp-fixed-size-8192 = 393.795,1061.85,1128.93,785.937,640.106 26 | Data|evpp-fixed-size-16384 = 640.559,1571.12,1648.69,1107.34,939.425 27 | Data|evpp-fixed-size-81920 = 1170.6,2043.03,1486.63,1313.34,1323.37 28 | Data|evpp-fixed-size-409600 = 1852.45,2198.88,1421.41,1311.22,1232.36 29 | 30 | # evpp : v0.2.4 -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-multi-thread-4096bytes-evpp-vs-asio.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = spline 3 | Title = Multi-thread Throughput 4 | SubTitle = 60 seconds, message size 4096 bytes, X Axis is the thread numbers, 100c means 100 sessions, 1000c means 1000 sessions. 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1, 2, 4, 6, 8 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) 12 | 13 | #Height = 600 14 | 15 | # The data and the name of the lines 16 | Data|evpp-100c = 527.447, 886.546, 1500.39, 2206.41, 2099.97 17 | Data|evpp-1000c = 382.304, 692.345, 1286.34, 1930.41, 1950.87 18 | Data|asio-100c = 324.166, 678.729, 1177.19, 1372.17, 1426.02 19 | Data|asio-1000c = 371.053, 638.697, 1093.74, 1247.36, 1225.62 20 | 21 | # evpp : v0.2.1 base on libevent 2.0.21 22 | # asio : from boost-1.53 , code is at here : https://github.com/chenshuo/recipes/tree/master/pingpong/asio 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-multi-thread-evpp-vs-asio-1.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Throughput 4 | SubTitle = 100 seconds, message size 16384, 100 connections, X Axis is thread count 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 2,3,4,6,8 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) 12 | 13 | # The data and the name of the lines 14 | Data|asio-100 = 2495.75,2972.09,4054.8,5594.72,6608.77 15 | Data|evpp-100 = 2285.48,2818.18,3826.82,4893.94,5648.08 16 | 17 | 18 | # evpp : v0.2.4 19 | # asio : v1.10.8 code is here https://github.com/huyuguang/asio_benchmark 20 | -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-multi-thread-evpp-vs-asio-2.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = Throughput 4 | SubTitle = 100 seconds, message size 16384, 1000 connections, X Axis is thread count 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 2,3,4,6,8 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) 12 | 13 | # The data and the name of the lines 14 | Data|asio-1000 = 1758.38,2198.68,2577.01,2423.85,2561.14 15 | Data|evpp-1000 = 1498.22,2092.2,2451.76,2735.9,3040.49 16 | 17 | 18 | # evpp : v0.2.4 19 | # asio : v1.10.8 code is here https://github.com/huyuguang/asio_benchmark 20 | -------------------------------------------------------------------------------- /docs/benchmark/throughput/throughput-multi-thread-evpp-vs-muduo.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = spline 3 | Title = Throughput 4 | SubTitle = 100 seconds, message size 16384, X Axis is thread count 5 | ValueSuffix = MB/s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 2,3,4,6,8 9 | 10 | # The y Axis text 11 | YAxisText = Throughput (MB/s) 12 | 13 | Height = 500 14 | 15 | # The data and the name of the lines 16 | Data|evpp-100 = 2285.48,2818.18,3826.82,4893.94,5648.08 17 | Data|muduo-100 = 1807.69,3086.99,4064.61,4727.83,5440.14 18 | Data|evpp-1000 = 1498.22,2092.2,2451.76,2735.9,3040.49 19 | Data|muduo-1000 = 1484.46,2025.54,2529.75,2862.99,2920.274 20 | 21 | 22 | # evpp : v0.2.4 23 | # muduo : v1.0.9 24 | 25 | -------------------------------------------------------------------------------- /docs/benchmark/throughput_header_body/multi-thread-evpp-vs-asio-100.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = The time spent to do the ping-pong benchmark test 4 | SubTitle = X Axis is thread number, total back and forth count is 8192, connection count is 100 5 | ValueSuffix = s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1,2,3,4,6,8 9 | 10 | # The y Axis text 11 | YAxisText = The time spent (lower is better) (s) 12 | 13 | Height = 500 14 | 15 | # The data and the name of the lines 16 | Data|asio-100 = 4.21429,1.90817,1.23637,0.918871,0.874255,0.683286 17 | Data|evpp-100 = 3.20859,1.61021,1.1048,0.852965,0.630243,0.574 18 | 19 | # evpp : v0.2.4 20 | # asio : v1.10.8 code is here https://github.com/huyuguang/asio_benchmark/{server3.cpp,client3.cpp} 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /docs/benchmark/throughput_header_body/multi-thread-evpp-vs-asio-1000.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = The time spent to do the ping-pong benchmark test 4 | SubTitle = X Axis is thread number, total back and forth count is 8192, connection count is 1000 5 | ValueSuffix = s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1,2,3,4,6,8 9 | 10 | # The y Axis text 11 | YAxisText = The time spent (lower is better) (s) 12 | 13 | Height = 500 14 | 15 | # The data and the name of the lines 16 | Data|asio-1000 = 41.8432,17.6584,12.3694,9.89324,7.52727,6.66348 17 | Data|evpp-1000 = 33.7593,17.6684,12.2256,8.89794,6.37029,5.81729 18 | 19 | 20 | # evpp : v0.2.4 21 | # asio : v1.10.8 code is here https://github.com/huyuguang/asio_benchmark/{server3.cpp,client3.cpp} 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /docs/benchmark/throughput_header_body/multi-thread-evpp-vs-asio-10000.chart: -------------------------------------------------------------------------------- 1 | # The chart type , option : spline/line/bar/column/area 2 | ChartType = column 3 | Title = The time spent to do the ping-pong benchmark test 4 | SubTitle = X Axis is thread number, total back and forth count is 8192, connection count is 10000 5 | ValueSuffix = s 6 | 7 | # The x Axis numbers. The count this numbers MUST be the same with the data series 8 | XAxisNumbers = 1,2,3,4,6,8 9 | 10 | # The y Axis text 11 | YAxisText = The time spent (lower is better) (s) 12 | 13 | Height = 500 14 | 15 | # The data and the name of the lines 16 | Data|asio-10000 = 549.673,253.366,184.834,150.111,112.563,100.358 17 | Data|evpp-10000 = 548.84,252.528,155.788,119.702,94.5803,90.9652 18 | 19 | 20 | # evpp : v0.2.4 21 | # asio : v1.10.8 code is here https://github.com/huyuguang/asio_benchmark/{server3.cpp,client3.cpp} 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /evpp/buffer.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010, Shuo Chen. All rights reserved. 2 | // http://code.google.com/p/muduo/ 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the License file. 6 | // 7 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 8 | // 9 | 10 | // Modified : zieckey (zieckey at gmail dot com) 11 | 12 | #include "evpp/inner_pre.h" 13 | #include "evpp/buffer.h" 14 | #include "evpp/sockets.h" 15 | 16 | namespace evpp { 17 | const char Buffer::kCRLF[] = "\r\n"; 18 | 19 | const size_t Buffer::kCheapPrependSize = 8; 20 | const size_t Buffer::kInitialSize = 1024; 21 | 22 | ssize_t Buffer::ReadFromFD(evpp_socket_t fd, int* savedErrno) { 23 | // saved an ioctl()/FIONREAD call to tell how much to read 24 | char extrabuf[65536]; 25 | struct iovec vec[2]; 26 | const size_t writable = WritableBytes(); 27 | vec[0].iov_base = begin() + write_index_; 28 | vec[0].iov_len = writable; 29 | vec[1].iov_base = extrabuf; 30 | vec[1].iov_len = sizeof extrabuf; 31 | // when there is enough space in this buffer, don't read into extrabuf. 32 | // when extrabuf is used, we read 64k bytes at most. 33 | const int iovcnt = (writable < sizeof extrabuf) ? 2 : 1; 34 | const ssize_t n = ::readv(fd, vec, iovcnt); 35 | 36 | if (n < 0) { 37 | *savedErrno = errno; 38 | } else if (static_cast(n) <= writable) { 39 | write_index_ += n; 40 | } else { 41 | write_index_ = capacity_; 42 | Append(extrabuf, n - writable); 43 | } 44 | 45 | return n; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /evpp/dns_resolver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "evpp/inner_pre.h" 4 | #include "evpp/duration.h" 5 | #include "evpp/sys_addrinfo.h" 6 | 7 | struct evdns_base; 8 | struct evdns_getaddrinfo_request; 9 | namespace evpp { 10 | class EventLoop; 11 | class TimerEventWatcher; 12 | class EVPP_EXPORT DNSResolver : public std::enable_shared_from_this { 13 | public: 14 | //TODO IPv6 DNS resolver 15 | typedef std::function& addrs)> Functor; 16 | 17 | DNSResolver(EventLoop* evloop, const std::string& host, Duration timeout, const Functor& f); 18 | ~DNSResolver(); 19 | void Start(); 20 | void Cancel(); 21 | const std::string& host() const { 22 | return host_; 23 | } 24 | private: 25 | void SyncDNSResolve(); 26 | void AsyncDNSResolve(); 27 | void AsyncWait(); 28 | void OnTimeout(); 29 | void OnCanceled(); 30 | void ClearTimer(); 31 | void OnResolved(int errcode, struct addrinfo* addr); 32 | void OnResolved(); 33 | static void OnResolved(int errcode, struct addrinfo* addr, void* arg); 34 | private: 35 | EventLoop* loop_; 36 | struct evdns_base* dnsbase_; 37 | struct evdns_getaddrinfo_request* dns_req_; 38 | std::string host_; 39 | Duration timeout_; 40 | Functor functor_; 41 | std::unique_ptr timer_; 42 | std::vector addrs_; 43 | }; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /evpp/duration.cc: -------------------------------------------------------------------------------- 1 | #include "evpp/inner_pre.h" 2 | 3 | #include "evpp/duration.h" 4 | 5 | namespace evpp { 6 | const int64_t Duration::kNanosecond = 1LL; 7 | const int64_t Duration::kMicrosecond = 1000 * kNanosecond; 8 | const int64_t Duration::kMillisecond = 1000 * kMicrosecond; 9 | const int64_t Duration::kSecond = 1000 * kMillisecond; 10 | const int64_t Duration::kMinute = 60 * kSecond; 11 | const int64_t Duration::kHour = 60 * kMinute; 12 | } -------------------------------------------------------------------------------- /evpp/event_loop_thread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "evpp/inner_pre.h" 7 | #include "evpp/server_status.h" 8 | 9 | struct event_base; 10 | struct event; 11 | 12 | namespace evpp { 13 | 14 | class EventLoop; 15 | 16 | class EVPP_EXPORT EventLoopThread : public ServerStatus { 17 | public: 18 | enum { kOK = 0 }; 19 | 20 | // Return 0 means OK, anything else means failed. 21 | typedef std::function Functor; 22 | 23 | EventLoopThread(); 24 | ~EventLoopThread(); 25 | 26 | // @param wait_thread_started - If it is true this method will block 27 | // until the thread totally started 28 | // @param pre - This functor will be executed immediately when the thread is started. 29 | // @param post - This functor will be executed at the moment when the thread is going to stop. 30 | bool Start(bool wait_thread_started = true, 31 | Functor pre = Functor(), 32 | Functor post = Functor()); 33 | 34 | void Stop(bool wait_thread_exit = false); 35 | 36 | // @brief Join the thread. If you forget to call this method, 37 | // it will be invoked automatically in the destruct method ~EventLoopThread(). 38 | // @note DO NOT call this method from any of the working thread. 39 | void Join(); 40 | 41 | void AfterFork(); 42 | 43 | public: 44 | void set_name(const std::string& n); 45 | const std::string& name() const; 46 | EventLoop* loop() const; 47 | struct event_base* event_base(); 48 | std::thread::id tid() const; 49 | bool IsRunning() const; 50 | 51 | private: 52 | void Run(const Functor& pre, const Functor& post); 53 | 54 | private: 55 | std::shared_ptr event_loop_; 56 | 57 | std::mutex mutex_; 58 | std::shared_ptr thread_; // Guard by mutex_ 59 | 60 | std::string name_; 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /evpp/event_loop_thread_pool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #include 5 | 6 | #include "evpp/event_loop_thread.h" 7 | 8 | namespace evpp { 9 | class EVPP_EXPORT EventLoopThreadPool : public ServerStatus { 10 | public: 11 | typedef std::function DoneCallback; 12 | 13 | EventLoopThreadPool(EventLoop* base_loop, uint32_t thread_num); 14 | ~EventLoopThreadPool(); 15 | 16 | bool Start(bool wait_thread_started = false); 17 | 18 | void Stop(bool wait_thread_exited = false); 19 | void Stop(DoneCallback fn); 20 | 21 | // @brief Join all the working thread. If you forget to call this method, 22 | // it will be invoked automatically in the destruct method ~EventLoopThreadPool(). 23 | // @note DO NOT call this method from any of the working thread. 24 | void Join(); 25 | 26 | // @brief Reinitialize some data fields after a fork 27 | void AfterFork(); 28 | public: 29 | EventLoop* GetNextLoop(); 30 | EventLoop* GetNextLoopWithHash(uint64_t hash); 31 | 32 | uint32_t thread_num() const; 33 | 34 | private: 35 | void Stop(bool wait_thread_exit, DoneCallback fn); 36 | void OnThreadStarted(uint32_t count); 37 | void OnThreadExited(uint32_t count); 38 | 39 | private: 40 | EventLoop* base_loop_; 41 | 42 | uint32_t thread_num_ = 0; 43 | std::atomic next_ = { 0 }; 44 | 45 | DoneCallback stopped_cb_; 46 | 47 | typedef std::shared_ptr EventLoopThreadPtr; 48 | std::vector threads_; 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /evpp/evpphttp/http_request.cc: -------------------------------------------------------------------------------- 1 | #include "evpp/evpphttp/http_request.h" 2 | namespace evpp { 3 | namespace evpphttp { 4 | HttpRequest::HttpRequest() { 5 | settings.on_message_begin = &HttpRequest::OnMessageBegin; 6 | settings.on_message_complete = &HttpRequest::OnMessageEnd; 7 | settings.on_header_field = &HttpRequest::OnField; 8 | settings.on_header_value = &HttpRequest::OnValue; 9 | settings.on_body = &HttpRequest::OnBody; 10 | settings.on_url = &HttpRequest::OnUrl; 11 | settings.on_headers_complete = &HttpRequest::OnHeaderComplete; 12 | settings.on_reason = &HttpRequest::EmptyDataCB; 13 | settings.on_chunk_header = &HttpRequest::EmptyCB; 14 | settings.on_chunk_complete = &HttpRequest::EmptyCB; 15 | http_parser_init(&parser, HTTP_REQUEST); 16 | } 17 | 18 | int HttpRequest::Parse(evpp::Buffer * buf) { 19 | parser.data = const_cast(this); 20 | size_t parsed = http_parser_execute(&parser, &settings, buf->data(), buf->size()); 21 | auto err = HTTP_PARSER_ERRNO(&parser); 22 | if (err != HPE_OK && err != HPE_PAUSED) { 23 | LOG_WARN << "http request header parsed failed, err=" << http_errno_name(err) << "," << http_errno_description(err); 24 | return err; 25 | } 26 | buf->Retrieve(parsed); 27 | return 0; 28 | } 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /evpp/evpphttp/service.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "evpp/inner_pre.h" 3 | #include "evpp/event_loop.h" 4 | #include "evpp/tcp_server.h" 5 | #include "evpp/evpphttp/http_request.h" 6 | #include "evpp/evpphttp/http_response.h" 7 | namespace evpp { 8 | namespace evpphttp { 9 | typedef std::function& response_field_value, const std::string& response_data)> HTTPSendResponseCallback; 10 | typedef std::function HTTPRequestCallback; 11 | class EVPP_EXPORT Service { 12 | private: 13 | typedef std::map HTTPRequestCallbackMap; 14 | public: 15 | Service(const std::string& listen_addr, const std::string& name, uint32_t thread_num); 16 | ~Service(); 17 | void Stop(); 18 | bool Init(const ConnectionCallback& cb = [](const TCPConnPtr& conn) { 19 | conn->SetTCPNoDelay(true); 20 | }); 21 | bool Start(); 22 | void RegisterHandler(const std::string& uri, const HTTPRequestCallback& callback); 23 | inline bool IsStopped() const { 24 | return is_stopped_; 25 | } 26 | 27 | inline void set_default_cb(const HTTPRequestCallback& cb) { 28 | default_callback_ = cb; 29 | } 30 | 31 | void AfterFork(); 32 | 33 | private: 34 | int RequestHandler(const evpp::TCPConnPtr& conn, evpp::Buffer* buf, HttpRequest& hr); 35 | void OnMessage(const evpp::TCPConnPtr& conn, evpp::Buffer* buf); 36 | private: 37 | std::string listen_addr_; 38 | std::string name_; 39 | const int thread_num_; 40 | EventLoop* listen_loop_{nullptr}; 41 | TCPServer* tcp_srv_{nullptr}; 42 | std::thread * listen_thr_{nullptr}; 43 | HTTPRequestCallback default_callback_; 44 | HTTPRequestCallbackMap callbacks_; 45 | bool is_stopped_{false}; 46 | }; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /evpp/gettimeofday.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #ifdef WIN32 7 | #define _WINSOCKAPI_ 8 | #include 9 | #include 10 | #else 11 | #include 12 | #endif 13 | 14 | #ifdef WIN32 15 | 16 | #ifndef H_GETTIMEOFDAY 17 | #define H_GETTIMEOFDAY 18 | inline int gettimeofday(struct timeval* tp, void* tzp) { 19 | uint64_t intervals; 20 | FILETIME ft; 21 | 22 | GetSystemTimeAsFileTime(&ft); 23 | 24 | /* 25 | * A file time is a 64-bit value that represents the number 26 | * of 100-nanosecond intervals that have elapsed since 27 | * January 1, 1601 12:00 A.M. UTC. 28 | * 29 | * Between January 1, 1970 (Epoch) and January 1, 1601 there were 30 | * 134744 days, 31 | * 11644473600 seconds or 32 | * 11644473600,000,000,0 100-nanosecond intervals. 33 | * 34 | * See also MSKB Q167296. 35 | */ 36 | 37 | intervals = ((uint64_t)ft.dwHighDateTime << 32) | ft.dwLowDateTime; 38 | intervals -= 116444736000000000; 39 | 40 | tp->tv_sec = (long)(intervals / 10000000); 41 | tp->tv_usec = (long)((intervals % 10000000) / 10); 42 | 43 | 44 | return (0); 45 | } 46 | #endif // end of H_GETTIMEOFDAY 47 | 48 | #endif //end of WIN32 49 | 50 | namespace evpp { 51 | inline double utcsecond() { 52 | struct timeval tv; 53 | gettimeofday(&tv, nullptr); 54 | return (double)(tv.tv_sec) + ((double)(tv.tv_usec)) / 1000000.0f; 55 | } 56 | 57 | inline uint64_t utcmicrosecond() { 58 | struct timeval tv; 59 | gettimeofday(&tv, nullptr); 60 | return (uint64_t)(((uint64_t)(tv.tv_sec)) * 1000000 + tv.tv_usec); 61 | } 62 | 63 | inline struct timeval timevalconv(uint64_t time_us) { 64 | struct timeval tv; 65 | tv.tv_sec = (long)time_us / 1000000; 66 | tv.tv_usec = (long)time_us % 1000000; 67 | return tv; 68 | } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /evpp/http/stats.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qihoo360/evpp/477033f938fd47dfecde43c82257cd286d9fa38e/evpp/http/stats.h -------------------------------------------------------------------------------- /evpp/httpc/conn.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "evpp/inner_pre.h" 4 | #include "evpp/event_loop.h" 5 | 6 | #if defined(EVPP_HTTP_CLIENT_SUPPORTS_SSL) 7 | #include 8 | #include 9 | #endif 10 | 11 | struct evhttp_connection; 12 | namespace evpp { 13 | namespace httpc { 14 | class ConnPool; 15 | class EVPP_EXPORT Conn { 16 | public: 17 | Conn(EventLoop* loop, const std::string& host, int port, 18 | #if defined(EVPP_HTTP_CLIENT_SUPPORTS_SSL) 19 | bool enable_ssl, 20 | #endif 21 | Duration timeout); 22 | ~Conn(); 23 | 24 | bool Init(); 25 | void Close(); 26 | 27 | EventLoop* loop() { 28 | return loop_; 29 | } 30 | struct evhttp_connection* evhttp_conn() { 31 | return evhttp_conn_; 32 | } 33 | const std::string& host() const { 34 | return host_; 35 | } 36 | int port() const { 37 | return port_; 38 | } 39 | #if defined(EVPP_HTTP_CLIENT_SUPPORTS_SSL) 40 | bool enable_ssl() const { 41 | return enable_ssl_; 42 | } 43 | struct bufferevent* bufferevent() const { 44 | return bufferevent_; 45 | } 46 | #endif 47 | Duration timeout() const { 48 | return timeout_; 49 | } 50 | private: 51 | friend class ConnPool; 52 | Conn(ConnPool* pool, EventLoop* loop); 53 | ConnPool* pool() { 54 | return pool_; 55 | } 56 | private: 57 | EventLoop* loop_; 58 | ConnPool* pool_; 59 | std::string host_; 60 | int port_; 61 | #if defined(EVPP_HTTP_CLIENT_SUPPORTS_SSL) 62 | bool enable_ssl_; 63 | SSL* ssl_; 64 | struct bufferevent* bufferevent_; 65 | #endif 66 | Duration timeout_; 67 | struct evhttp_connection* evhttp_conn_; 68 | }; 69 | } // httpc 70 | } // evpp 71 | -------------------------------------------------------------------------------- /evpp/httpc/conn_pool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "evpp/inner_pre.h" 8 | #include "evpp/duration.h" 9 | #include "evpp/event_loop.h" 10 | 11 | namespace evpp { 12 | namespace httpc { 13 | class Conn; 14 | typedef std::shared_ptr ConnPtr; 15 | class EVPP_EXPORT ConnPool { 16 | public: 17 | ConnPool(const std::string& host, int port, 18 | #if defined(EVPP_HTTP_CLIENT_SUPPORTS_SSL) 19 | bool enable_ssl, 20 | #endif 21 | Duration timeout, size_t max_pool_size = 1024); 22 | ~ConnPool(); 23 | 24 | ConnPtr Get(EventLoop* loop); 25 | void Put(const ConnPtr& c); 26 | 27 | // To make sure all Conn are released in it's own EventLoop 28 | void Clear(); 29 | 30 | const std::string& host() const { 31 | return host_; 32 | } 33 | int port() const { 34 | return port_; 35 | } 36 | #if defined(EVPP_HTTP_CLIENT_SUPPORTS_SSL) 37 | bool enable_ssl() const { 38 | return enable_ssl_; 39 | } 40 | #endif 41 | Duration timeout() const { 42 | return timeout_; 43 | } 44 | private: 45 | std::string host_; 46 | int port_; 47 | #if defined(EVPP_HTTP_CLIENT_SUPPORTS_SSL) 48 | bool enable_ssl_; 49 | #endif 50 | Duration timeout_; 51 | size_t max_pool_size_; // The max size of the pool for every EventLoop 52 | 53 | std::mutex mutex_; // The guard of pools_ 54 | std::map> pool_; // Every thread has its own pool which has a max size specified by max_pool_size_ 55 | }; 56 | } // httpc 57 | } // evpp 58 | -------------------------------------------------------------------------------- /evpp/httpc/response.cc: -------------------------------------------------------------------------------- 1 | 2 | #include "evpp/libevent.h" 3 | #include "evpp/httpc/conn.h" 4 | #include "evpp/httpc/conn_pool.h" 5 | #include "evpp/httpc/response.h" 6 | #include "evpp/httpc/request.h" 7 | 8 | namespace evpp { 9 | namespace httpc { 10 | #if defined(EVPP_HTTP_CLIENT_SUPPORTS_SSL) 11 | Response::Response(Request* r, struct evhttp_request* evreq, bool had_ssl_error) 12 | : request_(r), evreq_(evreq), http_code_(0), had_ssl_error_(had_ssl_error) { 13 | #else 14 | Response::Response(Request* r, struct evhttp_request* evreq) 15 | : request_(r), evreq_(evreq), http_code_(0) { 16 | #endif 17 | if (evreq) { 18 | http_code_ = evreq->response_code; 19 | 20 | #if LIBEVENT_VERSION_NUMBER >= 0x02001500 21 | struct evbuffer* evbuf = evhttp_request_get_input_buffer(evreq); 22 | size_t buffer_size = evbuffer_get_length(evbuf); 23 | if (buffer_size > 0) { 24 | this->body_ = evpp::Slice((char*)evbuffer_pullup(evbuf, -1), buffer_size); 25 | } 26 | #else 27 | if (evreq->input_buffer->off > 0) { 28 | this->body_ = evpp::Slice((char*)evreq->input_buffer->buffer, evreq->input_buffer->off); 29 | } 30 | #endif 31 | } 32 | } 33 | 34 | Response::~Response() { 35 | } 36 | 37 | const char* Response::FindHeader(const char* key) { 38 | if (http_code_ > 0) { 39 | assert(this->evreq_); 40 | return evhttp_find_header(this->evreq_->input_headers, key); 41 | } 42 | return nullptr; 43 | } 44 | 45 | } 46 | } 47 | 48 | 49 | -------------------------------------------------------------------------------- /evpp/httpc/response.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "evpp/inner_pre.h" 6 | #include "evpp/event_loop.h" 7 | #include "evpp/slice.h" 8 | 9 | struct evhttp_request; 10 | namespace evpp { 11 | namespace httpc { 12 | class Request; 13 | class EVPP_EXPORT Response { 14 | public: 15 | typedef std::map Headers; 16 | #if defined(EVPP_HTTP_CLIENT_SUPPORTS_SSL) 17 | Response(Request* r, struct evhttp_request* evreq, bool had_ssl_error = false); 18 | #else 19 | Response(Request* r, struct evhttp_request* evreq); 20 | #endif 21 | ~Response(); 22 | 23 | int http_code() const { 24 | return http_code_; 25 | } 26 | #if defined(EVPP_HTTP_CLIENT_SUPPORTS_SSL) 27 | bool had_ssl_error() const { 28 | return had_ssl_error_; 29 | } 30 | #endif 31 | const evpp::Slice& body() const { 32 | return body_; 33 | } 34 | const Request* request() const { 35 | return request_; 36 | } 37 | const char* FindHeader(const char* key); 38 | private: 39 | Request* request_; 40 | struct evhttp_request* evreq_; 41 | int http_code_; 42 | #if defined(EVPP_HTTP_CLIENT_SUPPORTS_SSL) 43 | bool had_ssl_error_; 44 | #endif 45 | evpp::Slice body_; 46 | }; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /evpp/httpc/ssl.cc: -------------------------------------------------------------------------------- 1 | #include "evpp/httpc/ssl.h" 2 | 3 | #if defined(EVPP_HTTP_CLIENT_SUPPORTS_SSL) 4 | #include "evpp/logging.h" 5 | 6 | #include 7 | #include 8 | 9 | namespace evpp { 10 | namespace httpc { 11 | SSL_CTX* g_ssl_ctx = nullptr; 12 | 13 | bool InitSSL() { 14 | SSL_library_init(); 15 | ERR_load_crypto_strings(); 16 | SSL_load_error_strings(); 17 | OpenSSL_add_all_algorithms(); 18 | int r = RAND_poll(); 19 | if (r == 0) { 20 | LOG_ERROR << "RAND_poll failed"; 21 | return false; 22 | } 23 | g_ssl_ctx = SSL_CTX_new(SSLv23_method()); 24 | if (!g_ssl_ctx) { 25 | LOG_ERROR << "SSL_CTX_new failed"; 26 | return false; 27 | } 28 | X509_STORE* store = SSL_CTX_get_cert_store(g_ssl_ctx); 29 | if (X509_STORE_set_default_paths(store) != 1) { 30 | LOG_ERROR << "X509_STORE_set_default_paths failed"; 31 | return false; 32 | } 33 | return true; 34 | } 35 | 36 | void CleanSSL() { 37 | if (g_ssl_ctx != nullptr) { 38 | SSL_CTX_free(g_ssl_ctx); 39 | } 40 | ERR_free_strings(); 41 | EVP_cleanup(); 42 | ERR_remove_thread_state(nullptr); 43 | CRYPTO_cleanup_all_ex_data(); 44 | } 45 | 46 | SSL_CTX* GetSSLCtx() { 47 | return g_ssl_ctx; 48 | } 49 | } // httpc 50 | } // evpp 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /evpp/httpc/ssl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(EVPP_HTTP_CLIENT_SUPPORTS_SSL) 4 | 5 | #include 6 | 7 | namespace evpp { 8 | namespace httpc { 9 | bool InitSSL(); 10 | void CleanSSL(); 11 | SSL_CTX* GetSSLCtx(); 12 | } // httpc 13 | } // evpp 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /evpp/httpc/url_parser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "evpp/inner_pre.h" 11 | 12 | namespace evpp { 13 | namespace httpc { 14 | struct EVPP_EXPORT URLParser { 15 | public: 16 | std::string schema; 17 | std::string host; 18 | int port; 19 | std::string path; 20 | std::string query; 21 | 22 | URLParser(const std::string& url); 23 | 24 | private: 25 | int parse(const std::string& url); 26 | }; 27 | } // httpc 28 | } // evpp -------------------------------------------------------------------------------- /evpp/inner_pre.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #ifdef __cplusplus 7 | #include 8 | #include 9 | #include 10 | #endif // end of define __cplusplus 11 | 12 | #include "platform_config.h" 13 | #include "sys_addrinfo.h" 14 | #include "sys_sockets.h" 15 | #include "sockets.h" 16 | #include "logging.h" 17 | 18 | struct event; 19 | namespace evpp { 20 | int EventAdd(struct event* ev, const struct timeval* timeout); 21 | int EventDel(struct event*); 22 | EVPP_EXPORT int GetActiveEventCount(); 23 | } 24 | -------------------------------------------------------------------------------- /evpp/libevent.cc: -------------------------------------------------------------------------------- 1 | #include "evpp/inner_pre.h" 2 | #include "evpp/libevent.h" 3 | 4 | #ifdef H_LIBEVENT_VERSION_14 5 | struct event* event_new(struct event_base* base, evpp_socket_t fd, short events, 6 | void(*cb)(int, short, void*), void* arg) { 7 | struct event* ev; 8 | ev = (struct event*)malloc(sizeof(struct event)); 9 | 10 | if (ev == nullptr) { 11 | return nullptr; 12 | } 13 | 14 | ::event_set(ev, fd, events, cb, arg); 15 | ::event_base_set(base, ev); 16 | return ev; 17 | } 18 | 19 | void event_free(struct event* ev) { 20 | evpp::EventDel(ev); 21 | free(ev); 22 | } 23 | 24 | 25 | struct evhttp_connection* evhttp_connection_base_new(struct event_base* base, struct evdns_base* dnsbase, const char* address, unsigned short port) { 26 | struct evhttp_connection* evhttp_conn = evhttp_connection_new(address, port); 27 | evhttp_connection_set_base(evhttp_conn, base); 28 | return evhttp_conn; 29 | } 30 | 31 | #endif 32 | 33 | #ifdef H_OS_MACOSX 34 | void avoid_macosx_ranlib_complain() { 35 | } 36 | #endif 37 | -------------------------------------------------------------------------------- /evpp/listener.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "evpp/inner_pre.h" 4 | #include "evpp/timestamp.h" 5 | 6 | namespace evpp { 7 | class EventLoop; 8 | class FdChannel; 9 | 10 | class EVPP_EXPORT Listener { 11 | public: 12 | typedef std::function < 13 | void(evpp_socket_t sockfd, 14 | const std::string& /*remote address with format "ip:port"*/, 15 | const struct sockaddr_in* /*remote address*/) > 16 | NewConnectionCallback; 17 | Listener(EventLoop* loop, const std::string& addr/*local listening address : ip:port*/); 18 | ~Listener(); 19 | 20 | // socket listen 21 | void Listen(int backlog = SOMAXCONN); 22 | 23 | // nonblocking accept 24 | void Accept(); 25 | 26 | void Stop(); 27 | 28 | void SetNewConnectionCallback(NewConnectionCallback cb) { 29 | new_conn_fn_ = cb; 30 | } 31 | 32 | private: 33 | void HandleAccept(); 34 | 35 | private: 36 | evpp_socket_t fd_ = -1;// The listening socket fd 37 | EventLoop* loop_; 38 | std::string addr_; 39 | std::unique_ptr chan_; 40 | NewConnectionCallback new_conn_fn_; 41 | }; 42 | } 43 | 44 | 45 | -------------------------------------------------------------------------------- /evpp/logging.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qihoo360/evpp/477033f938fd47dfecde43c82257cd286d9fa38e/evpp/logging.h -------------------------------------------------------------------------------- /evpp/platform_config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(__APPLE__) 4 | #define H_OS_MACOSX 5 | #endif 6 | 7 | #ifdef _DEBUG 8 | #ifndef H_DEBUG_MODE 9 | #define H_DEBUG_MODE 10 | #endif 11 | #endif 12 | 13 | #include "windows_port.h" 14 | -------------------------------------------------------------------------------- /evpp/server_status.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "evpp/inner_pre.h" 6 | #include "evpp/utility.h" 7 | 8 | namespace evpp { 9 | class ServerStatus { 10 | public: 11 | enum Status { 12 | kNull = 0, 13 | kInitializing = 1, 14 | kInitialized = 2, 15 | kStarting = 3, 16 | kRunning = 4, 17 | kStopping = 5, 18 | kStopped = 6, 19 | }; 20 | 21 | enum SubStatus { 22 | kSubStatusNull = 0, 23 | kStoppingListener = 1, 24 | kStoppingThreadPool = 2, 25 | }; 26 | 27 | std::string StatusToString() const { 28 | H_CASE_STRING_BIGIN(status_.load()); 29 | H_CASE_STRING(kNull); 30 | H_CASE_STRING(kInitialized); 31 | H_CASE_STRING(kRunning); 32 | H_CASE_STRING(kStopping); 33 | H_CASE_STRING(kStopped); 34 | H_CASE_STRING_END(); 35 | } 36 | 37 | bool IsRunning() const { 38 | return status_.load() == kRunning; 39 | } 40 | 41 | bool IsStopped() const { 42 | return status_.load() == kStopped; 43 | } 44 | 45 | bool IsStopping() const { 46 | return status_.load() == kStopping; 47 | } 48 | 49 | protected: 50 | std::atomic status_ = { kNull }; 51 | std::atomic substatus_ = { kSubStatusNull }; 52 | }; 53 | } -------------------------------------------------------------------------------- /evpp/sys_addrinfo.h: -------------------------------------------------------------------------------- 1 | // Copy from Chromium project. 2 | 3 | // This is a convenience header to pull in the platform-specific headers 4 | // that define at least: 5 | // 6 | // struct addrinfo 7 | // struct sockaddr* 8 | // getaddrinfo() 9 | // freeaddrinfo() 10 | // AI_* 11 | // AF_* 12 | // 13 | // Prefer including this file instead of directly writing the #if / #else, 14 | // since it avoids duplicating the platform-specific selections. 15 | 16 | #pragma once 17 | 18 | #include "platform_config.h" 19 | 20 | #ifdef H_OS_WINDOWS 21 | #include 22 | #include 23 | #else 24 | #include 25 | #include 26 | #include // for TCP_NODELAY 27 | #include 28 | #include 29 | #endif 30 | -------------------------------------------------------------------------------- /evpp/tcp_callbacks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "evpp/inner_pre.h" 4 | 5 | namespace evpp { 6 | class Buffer; 7 | class TCPConn; 8 | 9 | typedef std::shared_ptr TCPConnPtr; 10 | typedef std::function TimerCallback; 11 | 12 | // When a connection established, broken down, connecting failed, this callback will be called 13 | // This is called from a work-thread this is not the listening thread probably 14 | typedef std::function ConnectionCallback; 15 | 16 | 17 | typedef std::function CloseCallback; 18 | typedef std::function WriteCompleteCallback; 19 | typedef std::function HighWaterMarkCallback; 20 | 21 | typedef std::function MessageCallback; 22 | 23 | namespace internal { 24 | inline void DefaultConnectionCallback(const TCPConnPtr&) {} 25 | inline void DefaultMessageCallback(const TCPConnPtr&, Buffer*) {} 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /evpp/thread_dispatch_policy.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace evpp { 4 | class ThreadDispatchPolicy { 5 | public: 6 | enum Policy { 7 | kRoundRobin, 8 | kIPAddressHashing, 9 | }; 10 | 11 | ThreadDispatchPolicy() : policy_(kRoundRobin) {} 12 | 13 | void SetThreadDispatchPolicy(Policy v) { 14 | policy_ = v; 15 | } 16 | 17 | bool IsRoundRobin() const { 18 | return policy_ == kRoundRobin; 19 | } 20 | protected: 21 | Policy policy_; 22 | }; 23 | } -------------------------------------------------------------------------------- /evpp/timestamp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "duration.h" 4 | #include 5 | 6 | 7 | namespace evpp { 8 | class Timestamp { 9 | public: 10 | Timestamp(); 11 | explicit Timestamp(int64_t nanoseconds); 12 | explicit Timestamp(const struct timeval& t); 13 | 14 | static Timestamp Now(); // returns the current local time. 15 | 16 | struct timeval TimeVal() const; 17 | void To(struct timeval* t) const; 18 | 19 | // Unix returns t as a Unix time, the number of seconds elapsed 20 | // since January 1, 1970 UTC. 21 | int64_t Unix() const; 22 | 23 | // UnixNano returns t as a Unix time, the number of nanoseconds elapsed 24 | // since January 1, 1970 UTC. The result is undefined if the Unix time 25 | // in nanoseconds cannot be represented by an int64. 26 | int64_t UnixNano() const; 27 | 28 | // UnixNano returns t as a Unix time, the number of microseconds elapsed 29 | // since January 1, 1970 UTC. The result is undefined if the Unix time 30 | // in microseconds cannot be represented by an int64. 31 | int64_t UnixMicro() const; 32 | 33 | void Add(Duration d); 34 | 35 | bool IsEpoch() const; 36 | bool operator< (const Timestamp& rhs) const; 37 | bool operator==(const Timestamp& rhs) const; 38 | 39 | Timestamp operator+=(const Duration& rhs); 40 | Timestamp operator+ (const Duration& rhs) const; 41 | Timestamp operator-=(const Duration& rhs); 42 | Timestamp operator- (const Duration& rhs) const; 43 | Duration operator- (const Timestamp& rhs) const; 44 | 45 | private: 46 | // ns_ gives the number of nanoseconds elapsed since the Epoch 47 | // 1970-01-01 00:00:00 +0000 (UTC). 48 | int64_t ns_; 49 | }; 50 | } // namespace evpp 51 | 52 | #include "timestamp.inl.h" 53 | 54 | -------------------------------------------------------------------------------- /evpp/udp/sync_udp_client.h: -------------------------------------------------------------------------------- 1 | #include "evpp/inner_pre.h" 2 | 3 | #include "udp_message.h" 4 | 5 | namespace evpp { 6 | namespace udp { 7 | namespace sync { 8 | 9 | // It is not asynchronous, please do not use it production. 10 | // The only purpose it exists is for purpose of testing UDP Server. 11 | class EVPP_EXPORT Client { 12 | public: 13 | Client(); 14 | ~Client(); 15 | 16 | bool Connect(const char* host, int port); 17 | bool Connect(const char* addr/*host:port*/); 18 | bool Connect(const struct sockaddr_storage& addr); 19 | bool Connect(const struct sockaddr& addr); 20 | bool Connect(const struct sockaddr_in& addr); 21 | 22 | void Close(); 23 | 24 | bool Send(const std::string& msg); 25 | bool Send(const char* msg, size_t len); 26 | 27 | //! brief : Do a udp request and wait for remote udp server send response data 28 | //! param[in] - const std::string & udp_package_data 29 | //! return - std::string the response data 30 | std::string DoRequest(const std::string& udp_package_data, uint32_t timeout_ms); 31 | 32 | static std::string DoRequest(const std::string& remote_ip, int port, const std::string& udp_package_data, uint32_t timeout_ms); 33 | 34 | static bool Send(const std::string& msg, const struct sockaddr_in& addr); 35 | static bool Send(const char* msg, size_t len, const struct sockaddr_in& addr); 36 | static bool Send(const MessagePtr& msg); 37 | static bool Send(const Message* msg); 38 | public: 39 | evpp_socket_t sockfd() const { 40 | return sockfd_; 41 | } 42 | private: 43 | bool Connect(); 44 | evpp_socket_t sockfd_ = -1; 45 | bool connected_ = false; 46 | struct sockaddr_storage remote_addr_; 47 | }; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /evpp/udp/udp_server.cc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qihoo360/evpp/477033f938fd47dfecde43c82257cd286d9fa38e/evpp/udp/udp_server.cc -------------------------------------------------------------------------------- /evpp/utility.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #ifndef H_CASE_STRING_BIGIN 7 | #define H_CASE_STRING_BIGIN(state) switch(state){ 8 | #define H_CASE_STRING(state) case state:return #state;break; 9 | #define H_CASE_STRING_END() default:return "Unknown";break;} 10 | #endif 11 | 12 | namespace evpp { 13 | 14 | template< class StringVector, 15 | class StringType, 16 | class DelimType> 17 | inline void StringSplit( 18 | const StringType& str, 19 | const DelimType& delims, 20 | unsigned int maxSplits, 21 | StringVector& ret) { 22 | 23 | if (str.empty()) { 24 | return; 25 | } 26 | 27 | unsigned int numSplits = 0; 28 | 29 | // Use STL methods 30 | size_t start, pos; 31 | start = 0; 32 | 33 | do { 34 | pos = str.find_first_of(delims, start); 35 | 36 | if (pos == start) { 37 | ret.push_back(StringType()); 38 | start = pos + 1; 39 | } else if (pos == StringType::npos || (maxSplits && numSplits + 1 == maxSplits)) { 40 | // Copy the rest of the string 41 | ret.emplace_back(StringType()); 42 | *(ret.rbegin()) = StringType(str.data() + start, str.size() - start); 43 | break; 44 | } else { 45 | // Copy up to delimiter 46 | //ret.push_back( str.substr( start, pos - start ) ); 47 | ret.push_back(StringType()); 48 | *(ret.rbegin()) = StringType(str.data() + start, pos - start); 49 | start = pos + 1; 50 | } 51 | 52 | ++numSplits; 53 | 54 | } while (pos != StringType::npos); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /examples/apps/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(evnsq) -------------------------------------------------------------------------------- /examples/apps/evnsq/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${PROJECT_SOURCE_DIR}/apps ${PROJECT_SOURCE_DIR}/3rdparty) 2 | 3 | if (UNIX) 4 | set(LIBRARIES evpp ${DEPENDENT_LIBRARIES}) 5 | else(UNIX) 6 | set(LIBRARIES evpp_static ${DEPENDENT_LIBRARIES}) 7 | endif(UNIX) 8 | 9 | add_executable(example_evnsq_tail evnsq_tail/main.cc) 10 | target_link_libraries(example_evnsq_tail evnsq_static ${LIBRARIES}) 11 | 12 | set (evnsq_producer_SRCS evnsq_producer/main.cc) 13 | if (WIN32) 14 | list (APPEND evnsq_producer_SRCS ${PROJECT_SOURCE_DIR}/3rdparty/win32code/getopt/getopt.c) 15 | list (APPEND evnsq_producer_SRCS ${PROJECT_SOURCE_DIR}/3rdparty/win32code/getopt/getopt_long.c) 16 | endif (WIN32) 17 | 18 | add_executable(example_evnsq_producer ${evnsq_producer_SRCS}) 19 | target_link_libraries(example_evnsq_producer evnsq_static ${LIBRARIES}) 20 | -------------------------------------------------------------------------------- /examples/apps/evnsq/evnsq_tail/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | int OnMessage(const evnsq::Message* msg) { 6 | LOG_INFO << "Received a message, id=" << msg->id << " message=[" << msg->body.ToString() << "]"; 7 | return 0; 8 | } 9 | 10 | int main(int argc, char* argv[]) { 11 | std::string nsqd_tcp_addr; 12 | std::string lookupd_http_url; 13 | nsqd_tcp_addr = "127.0.0.1:4150"; 14 | //nsqd_tcp_addr = "weizili-L1:4150"; 15 | //lookupd_http_url = "http://127.0.0.1:4161/lookup?topic=test"; 16 | 17 | if (argc == 2) { 18 | if (strncmp(argv[1], "http", 4) == 0) { 19 | lookupd_http_url = argv[1]; 20 | } else { 21 | nsqd_tcp_addr = argv[1]; 22 | } 23 | } 24 | 25 | evpp::EventLoop loop; 26 | evnsq::Consumer client(&loop, "test1", "ch1", evnsq::Option()); 27 | client.SetMessageCallback(&OnMessage); 28 | 29 | if (!lookupd_http_url.empty()) { 30 | client.ConnectToLookupds(lookupd_http_url); 31 | } else { 32 | client.ConnectToNSQDs(nsqd_tcp_addr); 33 | } 34 | 35 | loop.Run(); 36 | return 0; 37 | } 38 | 39 | #ifdef WIN32 40 | #include "../../../echo/tcpecho/winmain-inl.h" 41 | #endif 42 | -------------------------------------------------------------------------------- /examples/c10m/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(c10m01) 2 | add_subdirectory(client) 3 | 4 | -------------------------------------------------------------------------------- /examples/c10m/c10m01/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(example_c10m01 main.cc) 3 | target_link_libraries(example_c10m01 ${LIBRARIES}) 4 | 5 | -------------------------------------------------------------------------------- /examples/c10m/client/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(example_c10m_client main.cc) 3 | target_link_libraries(example_c10m_client ${LIBRARIES} gflags) 4 | 5 | -------------------------------------------------------------------------------- /examples/c10m/client/main.cc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qihoo360/evpp/477033f938fd47dfecde43c82257cd286d9fa38e/examples/c10m/client/main.cc -------------------------------------------------------------------------------- /examples/chatroom/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(simple) 2 | 3 | -------------------------------------------------------------------------------- /examples/chatroom/simple/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(example_chatroom_simple_server server.cc codec.h) 3 | target_link_libraries(example_chatroom_simple_server ${LIBRARIES}) 4 | 5 | add_executable(example_chatroom_simple_client client.cc codec.h) 6 | target_link_libraries(example_chatroom_simple_client ${LIBRARIES}) 7 | -------------------------------------------------------------------------------- /examples/chatroom/simple/codec.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class LengthHeaderCodec { 7 | public: 8 | typedef std::function StringMessageCallback; 10 | 11 | explicit LengthHeaderCodec(const StringMessageCallback& cb) 12 | : messageCallback_(cb) {} 13 | 14 | void OnMessage(const evpp::TCPConnPtr& conn, 15 | evpp::Buffer* buf) { 16 | while (buf->size() >= kHeaderLen) { 17 | const int32_t len = buf->PeekInt32(); 18 | if (len > 65536 || len < 0) { 19 | LOG_ERROR << "Invalid length " << len; 20 | conn->Close(); 21 | break; 22 | } 23 | 24 | if (buf->size() >= len + kHeaderLen) { 25 | buf->Skip(kHeaderLen); 26 | std::string message(buf->NextString(len)); 27 | messageCallback_(conn, message); 28 | break; 29 | } else { 30 | break; 31 | } 32 | } 33 | } 34 | 35 | void Send(evpp::TCPConnPtr conn, 36 | const evpp::Slice& message) { 37 | evpp::Buffer buf; 38 | buf.Append(message.data(), message.size()); 39 | buf.PrependInt32(message.size()); 40 | conn->Send(&buf); 41 | } 42 | 43 | private: 44 | StringMessageCallback messageCallback_; 45 | const static size_t kHeaderLen = sizeof(int32_t); 46 | }; 47 | 48 | #include "../../winmain-inl.h" 49 | -------------------------------------------------------------------------------- /examples/chatroom/simple/readme.md: -------------------------------------------------------------------------------- 1 | A simple chatroom 2 | 3 | The original example code is at here [http://www.boost.org/doc/libs/1_35_0/doc/html/boost_asio/example/chat/chat_server.cpp](http://www.boost.org/doc/libs/1_35_0/doc/html/boost_asio/example/chat/chat_server.cpp). 4 | 5 | And the implementation of [evpp]'s simple chatroom is modified from [muduo]'s examples [https://github.com/chenshuo/muduo/tree/master/examples/asio/chat](https://github.com/chenshuo/muduo/tree/master/examples/asio/chat). 6 | 7 | 8 | 9 | [gtest]:https://github.com/google/googletest 10 | [glog]:https://github.com/google/glog 11 | [Golang]:https://golang.org 12 | [muduo]:https://github.com/chenshuo/muduo 13 | [libevent]:https://github.com/libevent/libevent 14 | [libevent2]:https://github.com/libevent/libevent 15 | [LevelDB]:https://github.com/google/leveldb 16 | [rapidjson]:https://github.com/miloyip/ 17 | [Boost.Asio]:http://www.boost.org/ 18 | [boost.asio]:http://www.boost.org/ 19 | [asio]:http://www.boost.org/ 20 | [boost]:http://www.boost.org/ 21 | [evpp]:https://github.com/Qihoo360/evpp 22 | [evmc]:https://github.com/Qihoo360/evpp/tree/master/apps/evmc 23 | [evnsq]:https://github.com/Qihoo360/evpp/tree/master/apps/evnsq 24 | 25 | -------------------------------------------------------------------------------- /examples/dns_resolve/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef WIN32 6 | #include "examples/winmain-inl.h" 7 | #endif 8 | 9 | int main(int argc, char* argv[]) { 10 | std::string host = "www.so.com"; 11 | if (argc > 1) { 12 | host = argv[1]; 13 | } 14 | 15 | evpp::EventLoop loop; 16 | 17 | auto fn_resolved = [&loop, &host](const std::vector & addrs) { 18 | LOG_INFO << "Entering fn_resolved"; 19 | for (auto addr : addrs) { 20 | struct sockaddr_in saddr; 21 | memset(&saddr, 0, sizeof(saddr)); 22 | saddr.sin_addr = addr; 23 | LOG_INFO << "DNS resolved " << host << " ip " << evpp::sock::ToIP(evpp::sock::sockaddr_cast(&saddr)); 24 | } 25 | 26 | loop.RunAfter(evpp::Duration(0.5), [&loop]() { loop.Stop(); }); 27 | }; 28 | 29 | std::shared_ptr dns_resolver(new evpp::DNSResolver(&loop , host, evpp::Duration(1.0), fn_resolved)); 30 | dns_resolver->Start(); 31 | loop.Run(); 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /examples/echo/tcpecho/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef _WIN32 6 | #include "../../winmain-inl.h" 7 | #endif 8 | 9 | void OnMessage(const evpp::TCPConnPtr& conn, 10 | evpp::Buffer* msg) { 11 | std::string s = msg->NextAllString(); 12 | LOG_INFO << "Received a message [" << s << "]"; 13 | conn->Send(s); 14 | 15 | if (s == "quit" || s == "exit") { 16 | conn->Close(); 17 | } 18 | } 19 | 20 | 21 | void OnConnection(const evpp::TCPConnPtr& conn) { 22 | if (conn->IsConnected()) { 23 | LOG_INFO << "Accept a new connection from " << conn->remote_addr(); 24 | } else { 25 | LOG_INFO << "Disconnected from " << conn->remote_addr(); 26 | } 27 | } 28 | 29 | 30 | int main(int argc, char* argv[]) { 31 | std::string port = "9099"; 32 | if (argc == 2) { 33 | port = argv[1]; 34 | } 35 | std::string addr = std::string("0.0.0.0:") + port; 36 | evpp::EventLoop loop; 37 | evpp::TCPServer server(&loop, addr, "TCPEcho", 0); 38 | server.SetMessageCallback(&OnMessage); 39 | server.SetConnectionCallback(&OnConnection); 40 | server.Init(); 41 | server.Start(); 42 | loop.Run(); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /examples/echo/tcpecho/winmain-inl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace { 4 | struct OnApp { 5 | OnApp() { 6 | #ifdef WIN32 7 | // Initialize Winsock 2.2 8 | WSADATA wsaData; 9 | int err = WSAStartup(MAKEWORD(2, 2), &wsaData); 10 | 11 | if (err) { 12 | std::cout << "WSAStartup() failed with error: %d" << err; 13 | } 14 | #endif 15 | } 16 | ~OnApp() { 17 | #ifdef WIN32 18 | system("pause"); 19 | WSACleanup(); 20 | #endif 21 | } 22 | } __s_onexit_pause; 23 | } 24 | -------------------------------------------------------------------------------- /examples/echo/udpecho/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef _WIN32 7 | #include "../../winmain-inl.h" 8 | #endif 9 | 10 | int main(int argc, char* argv[]) { 11 | std::vector ports = { 1053, 5353 }; 12 | int port = 29099; 13 | int thread_num = 2; 14 | 15 | if (argc > 1) { 16 | if (std::string("-h") == argv[1] || 17 | std::string("--h") == argv[1] || 18 | std::string("-help") == argv[1] || 19 | std::string("--help") == argv[1]) { 20 | std::cout << "usage : " << argv[0] << " \n"; 21 | std::cout << " e.g. : " << argv[0] << " 8080 24\n"; 22 | return 0; 23 | } 24 | } 25 | 26 | if (argc == 2) { 27 | port = atoi(argv[1]); 28 | } 29 | ports.push_back(port); 30 | 31 | if (argc == 3) { 32 | port = atoi(argv[1]); 33 | thread_num = atoi(argv[2]); 34 | } 35 | 36 | evpp::udp::Server server; 37 | server.SetThreadDispatchPolicy(evpp::ThreadDispatchPolicy::kIPAddressHashing); 38 | server.SetMessageHandler([](evpp::EventLoop* loop, evpp::udp::MessagePtr& msg) { 39 | std::stringstream oss; 40 | oss << "func=" << __FUNCTION__ << " OK" 41 | << " body=" << std::string(msg->data(), msg->size()) << "\n"; 42 | evpp::udp::SendMessage(msg); 43 | }); 44 | server.Init(ports); 45 | server.Start(); 46 | 47 | evpp::EventLoop loop; 48 | std::shared_ptr tpool(new evpp::EventLoopThreadPool(&loop, thread_num)); 49 | tpool->Start(true); 50 | server.SetEventLoopThreadPool(tpool); 51 | loop.Run(); 52 | server.Stop(true); 53 | tpool->Stop(true); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /examples/http/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(http_client_request) 2 | add_subdirectory(simple_proxy) 3 | add_subdirectory(evpphttp_server) 4 | 5 | -------------------------------------------------------------------------------- /examples/http/evpphttp_server/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB example_SRCS *.cc) 2 | 3 | 4 | #include_directories(${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/3rdparty) 5 | #link_directories(${PROJECT_SOURCE_DIR}/3rdparty/libevent-release-2.1.7-rc/build/lib/Debug/ 6 | # ${PROJECT_SOURCE_DIR}/msvc/bin/Debug/ 7 | # ${PROJECT_SOURCE_DIR}/build/lib/Debug/) 8 | # 9 | 10 | add_executable(example_evpphttp_server ${example_SRCS}) 11 | target_link_libraries(example_evpphttp_server ${LIBRARIES}) 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/http/evpphttp_server/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static int g_port = 29099; 5 | void DefaultHandler(evpp::EventLoop* loop, 6 | evpp::evpphttp::HttpRequest& ctx, 7 | const evpp::evpphttp::HTTPSendResponseCallback& cb) { 8 | std::stringstream oss; 9 | oss << "func=" << __FUNCTION__ << " OK" 10 | << " ip=" << ctx.remote_ip << "\n" 11 | << " uri=" << ctx.url_path() << "\n" 12 | << " body=" << ctx.body.ToString() << "\n"; 13 | std::map feild_value = { 14 | {"Content-Type", "application/octet-stream"}, 15 | {"Server", "evpp"} 16 | }; 17 | cb(200, feild_value, oss.str()); 18 | } 19 | 20 | 21 | int main(int argc, char* argv[]) { 22 | int thread_num = 2; 23 | 24 | if (argc > 1) { 25 | if (std::string("-h") == argv[1] || 26 | std::string("--h") == argv[1] || 27 | std::string("-help") == argv[1] || 28 | std::string("--help") == argv[1]) { 29 | std::cout << "usage : " << argv[0] << " \n"; 30 | std::cout << " e.g. : " << argv[0] << " 8080 24\n"; 31 | return 0; 32 | } 33 | } 34 | 35 | if (argc == 2) { 36 | g_port = atoi(argv[1]); 37 | } else if (argc == 3) { 38 | g_port = atoi(argv[1]); 39 | thread_num = atoi(argv[2]); 40 | } 41 | evpp::evpphttp::Service server(std::string("0.0.0.0:") + std::to_string(g_port), "test", thread_num); 42 | server.RegisterHandler("/echo", &DefaultHandler); 43 | if (!server.Start()) { 44 | std::cout << "start serv failed\n"; 45 | return -1; 46 | } 47 | std::cout << "start serv on 0.0.0.0:" << g_port << " suc\n"; 48 | while (!server.IsStopped()) { 49 | usleep(1); 50 | } 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /examples/http/http_client_request/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(example_http_client_request01 client01.cc) 3 | target_link_libraries(example_http_client_request01 ${LIBRARIES}) 4 | 5 | add_executable(example_http_client_request02 client02.cc) 6 | target_link_libraries(example_http_client_request02 ${LIBRARIES}) 7 | 8 | add_executable(example_http_client_request03 client03.cc) 9 | target_link_libraries(example_http_client_request03 ${LIBRARIES}) 10 | 11 | add_executable(example_http_client_request04 client04.cc) 12 | target_link_libraries(example_http_client_request04 ${LIBRARIES}) 13 | 14 | add_executable(example_http_client_request05 client05.cc) 15 | target_link_libraries(example_http_client_request05 ${LIBRARIES}) 16 | 17 | -------------------------------------------------------------------------------- /examples/http/http_client_request/client01.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "../../../examples/winmain-inl.h" 11 | 12 | static bool responsed = false; 13 | static void HandleHTTPResponse(const std::shared_ptr& response, evpp::httpc::GetRequest* request) { 14 | LOG_INFO << "http_code=" << response->http_code() << " [" << response->body().ToString() << "]"; 15 | std::string header = response->FindHeader("Connection"); 16 | LOG_INFO << "HTTP HEADER Connection=" << header; 17 | responsed = true; 18 | assert(request == response->request()); 19 | delete request; // The request MUST BE deleted in EventLoop thread. 20 | } 21 | 22 | int main(int argc, char* argv[]) { 23 | google::InitGoogleLogging(argv[0]); 24 | FLAGS_stderrthreshold = 0; 25 | FLAGS_minloglevel=0; 26 | 27 | evpp::EventLoopThread t; 28 | t.Start(true); 29 | evpp::httpc::GetRequest* r = new evpp::httpc::GetRequest(t.loop(), "http://www.so.com/status.html", evpp::Duration(2.0)); 30 | LOG_INFO << "Do http request"; 31 | r->Execute(std::bind(&HandleHTTPResponse, std::placeholders::_1, r)); 32 | 33 | while (!responsed) { 34 | usleep(1); 35 | } 36 | 37 | t.Stop(true); 38 | LOG_INFO << "EventLoopThread stopped."; 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /examples/http/http_client_request/client02.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "../../../examples/winmain-inl.h" 11 | 12 | static int responsed = 0; 13 | static void HandleHTTPResponse(const std::shared_ptr& response, evpp::httpc::GetRequest* request) { 14 | LOG_INFO << "http_code=" << response->http_code() 15 | << " URL=http://" << request->host() << request->uri() 16 | << " [" << response->body().ToString() << "]"; 17 | const char* header = response->FindHeader("Connection"); 18 | if (header) { 19 | LOG_INFO << "HTTP HEADER Connection=" << header; 20 | } 21 | responsed++; 22 | assert(request == response->request()); 23 | delete request; // The request MUST BE deleted in EventLoop thread. 24 | } 25 | 26 | int main() { 27 | evpp::EventLoopThread t; 28 | t.Start(true); 29 | evpp::httpc::GetRequest* r = new evpp::httpc::GetRequest(t.loop(), "http://www.360.cn/robots.txt", evpp::Duration(5.0)); 30 | r->Execute(std::bind(&HandleHTTPResponse, std::placeholders::_1, r)); 31 | r = new evpp::httpc::GetRequest(t.loop(), "http://www.sohu.com/robots.txt", evpp::Duration(5.0)); 32 | r->Execute(std::bind(&HandleHTTPResponse, std::placeholders::_1, r)); 33 | r = new evpp::httpc::GetRequest(t.loop(), "http://www.so.com/status.html", evpp::Duration(5.0)); 34 | r->Execute(std::bind(&HandleHTTPResponse, std::placeholders::_1, r)); 35 | while (responsed != 3) { 36 | usleep(1); 37 | } 38 | 39 | t.Stop(true); 40 | LOG_INFO << "EventLoopThread stopped."; 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /examples/http/http_client_request/client03.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "../../../examples/winmain-inl.h" 12 | 13 | static bool responsed = false; 14 | static void HandleHTTPResponse(const std::shared_ptr& response, evpp::httpc::Request* request) { 15 | LOG_INFO << "http_code=" << response->http_code() << " [" << response->body().ToString() << "]"; 16 | std::string header = response->FindHeader("Connection"); 17 | LOG_INFO << "HTTP HEADER Connection=" << header; 18 | responsed = true; 19 | assert(request == response->request()); 20 | delete request; // The request MUST BE deleted in EventLoop thread. 21 | } 22 | 23 | int main() { 24 | evpp::EventLoopThread t; 25 | t.Start(true); 26 | #if defined(EVPP_HTTP_CLIENT_SUPPORTS_SSL) 27 | std::shared_ptr pool(new evpp::httpc::ConnPool("www.360.cn", 443,true, evpp::Duration(2.0))); 28 | #else 29 | std::shared_ptr pool(new evpp::httpc::ConnPool("www.360.cn", 80, evpp::Duration(2.0))); 30 | #endif 31 | evpp::httpc::Request* r = new evpp::httpc::Request(pool.get(), t.loop(), "/robots.txt", ""); 32 | LOG_INFO << "Do http request"; 33 | r->Execute(std::bind(&HandleHTTPResponse, std::placeholders::_1, r)); 34 | 35 | while (!responsed) { 36 | usleep(1); 37 | } 38 | 39 | pool->Clear(); 40 | pool.reset(); 41 | t.Stop(true); 42 | LOG_INFO << "EventLoopThread stopped."; 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /examples/http/http_client_request/client04.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "../../../examples/winmain-inl.h" 12 | 13 | static int responsed = 0; 14 | static int retried = 0; 15 | static void HandleHTTPResponse(const std::shared_ptr& r, evpp::httpc::Request* req) { 16 | LOG_INFO << "http_code=" << r->http_code() << " [" << r->body().ToString() << "]"; 17 | responsed++; 18 | if (retried < 3) { 19 | retried++; 20 | req->Execute(std::bind(&HandleHTTPResponse, std::placeholders::_1, req)); 21 | } else { 22 | delete req; 23 | } 24 | } 25 | 26 | int main() { 27 | evpp::EventLoopThread t; 28 | t.Start(true); 29 | evpp::httpc::Request* r = new evpp::httpc::Request(t.loop(), "http://www.360.cn/robots.txt", "", evpp::Duration(2.0)); 30 | LOG_INFO << "Do http request"; 31 | r->Execute(std::bind(&HandleHTTPResponse, std::placeholders::_1, r)); 32 | 33 | while (responsed != 4) { 34 | usleep(1); 35 | } 36 | 37 | t.Stop(true); 38 | LOG_INFO << "EventLoopThread stopped."; 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /examples/http/http_client_request/client05.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "../../../examples/winmain-inl.h" 11 | 12 | static int responsed = 0; 13 | static void HandleHTTPResponse(const std::shared_ptr& response, evpp::httpc::PostRequest* request) { 14 | LOG_INFO << "http_code=" << response->http_code() 15 | << " URL=http://" << request->host() << request->uri() 16 | << " [" << response->body().ToString() << "]"; 17 | const char* header = response->FindHeader("Connection"); 18 | if (header) { 19 | LOG_INFO << "HTTP HEADER Connection=" << header; 20 | } 21 | responsed++; 22 | assert(request == response->request()); 23 | delete request; // The request MUST BE deleted in EventLoop thread. 24 | } 25 | 26 | int main() { 27 | evpp::EventLoopThread t; 28 | t.Start(true); 29 | evpp::httpc::PostRequest* r = new evpp::httpc::PostRequest(t.loop(), "http://www.360.cn/robots.txt", "HTTP POST BODY", evpp::Duration(5.0)); 30 | r->Execute(std::bind(&HandleHTTPResponse, std::placeholders::_1, r)); 31 | r = new evpp::httpc::PostRequest(t.loop(), "http://www.sohu.com/robots.txt", "HTTP POST BODY", evpp::Duration(5.0)); 32 | r->Execute(std::bind(&HandleHTTPResponse, std::placeholders::_1, r)); 33 | r = new evpp::httpc::PostRequest(t.loop(), "http://www.so.com/status.html", "HTTP POST BODY", evpp::Duration(5.0)); 34 | r->Execute(std::bind(&HandleHTTPResponse, std::placeholders::_1, r)); 35 | while (responsed != 3) { 36 | usleep(1); 37 | } 38 | 39 | t.Stop(true); 40 | LOG_INFO << "EventLoopThread stopped."; 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /examples/http/simple_proxy/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB example_SRCS *.cc) 2 | 3 | 4 | #include_directories(${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/3rdparty) 5 | #link_directories(${PROJECT_SOURCE_DIR}/3rdparty/libevent-release-2.1.7-rc/build/lib/Debug/ 6 | # ${PROJECT_SOURCE_DIR}/msvc/bin/Debug/ 7 | # ${PROJECT_SOURCE_DIR}/build/lib/Debug/) 8 | # 9 | 10 | add_executable(example_http_simple_proxy ${example_SRCS}) 11 | target_link_libraries(example_http_simple_proxy ${LIBRARIES}) 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/multi_accept/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void OnMessage(const evpp::TCPConnPtr& conn, 7 | evpp::Buffer* msg) { 8 | LOG_INFO << "tid=" << std::this_thread::get_id() << " Received a message len=" << msg->size(); 9 | if (msg->ToString() == "quit") { 10 | conn->Close(); 11 | return; 12 | } 13 | conn->Send(msg->data(), msg->size()); 14 | msg->Reset(); 15 | } 16 | 17 | int main(int argc, char* argv[]) { 18 | std::string addr = "0.0.0.0:9099"; 19 | uint32_t thread_num = 2; 20 | 21 | if (argc != 1 && argc != 3) { 22 | printf("Usage: %s \n", argv[0]); 23 | printf(" e.g: %s 9099 12\n", argv[0]); 24 | return 0; 25 | } 26 | 27 | if (argc == 3) { 28 | addr = std::string("0.0.0.0:") + argv[1]; 29 | thread_num = atoi(argv[2]); 30 | } 31 | 32 | evpp::EventLoop loop; 33 | evpp::EventLoopThreadPool tpool(&loop, thread_num); 34 | tpool.Start(true); 35 | 36 | std::vector> tcp_servers; 37 | for (uint32_t i = 0; i < thread_num; i++) { 38 | evpp::EventLoop* next = tpool.GetNextLoop(); 39 | std::shared_ptr s(new evpp::TCPServer(next, addr, std::to_string(i) + "#server", 0)); 40 | s->SetMessageCallback(&OnMessage); 41 | s->Init(); 42 | s->Start(); 43 | tcp_servers.push_back(s); 44 | } 45 | 46 | loop.Run(); 47 | return 0; 48 | } 49 | 50 | #ifdef WIN32 51 | #include "../echo/tcpecho/winmain-inl.h" 52 | #endif 53 | -------------------------------------------------------------------------------- /examples/pingpong/server.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void OnConnection(const evpp::TCPConnPtr& conn) { 6 | if (conn->IsConnected()) { 7 | conn->SetTCPNoDelay(true); 8 | } 9 | } 10 | 11 | void OnMessage(const evpp::TCPConnPtr& conn, 12 | evpp::Buffer* msg) { 13 | conn->Send(msg); 14 | } 15 | 16 | int main(int argc, char* argv[]) { 17 | std::string addr = "0.0.0.0:9099"; 18 | int thread_num = 4; 19 | 20 | if (argc != 1 && argc != 3) { 21 | printf("Usage: %s \n", argv[0]); 22 | printf(" e.g: %s 9099 12\n", argv[0]); 23 | return 0; 24 | } 25 | 26 | if (argc == 3) { 27 | addr = std::string("0.0.0.0:") + argv[1]; 28 | thread_num = atoi(argv[2]); 29 | } 30 | 31 | evpp::EventLoop loop; 32 | evpp::TCPServer server(&loop, addr, "TCPPingPongServer", thread_num); 33 | server.SetMessageCallback(&OnMessage); 34 | server.SetConnectionCallback(&OnConnection); 35 | server.Init(); 36 | server.Start(); 37 | loop.Run(); 38 | return 0; 39 | } 40 | 41 | #ifdef WIN32 42 | #include "../winmain-inl.h" 43 | #endif 44 | -------------------------------------------------------------------------------- /examples/recipes/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(self_control_timer) -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(basic_01) 2 | add_subdirectory(basic_02) 3 | add_subdirectory(cancel_03) 4 | add_subdirectory(periodic_04) 5 | -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/basic_01/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB SRCS *.cc *.h) 2 | 3 | add_executable(example_recipes_self_control_timer_basic_01 ${SRCS}) 4 | target_link_libraries(example_recipes_self_control_timer_basic_01 event) 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/basic_01/event_watcher.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | struct event; 10 | struct event_base; 11 | 12 | namespace recipes { 13 | 14 | class EventWatcher { 15 | public: 16 | typedef std::function Handler; 17 | virtual ~EventWatcher(); 18 | bool Init(); 19 | void Cancel(); 20 | 21 | void SetCancelCallback(const Handler& cb); 22 | void ClearHandler() { handler_ = Handler(); } 23 | protected: 24 | EventWatcher(struct event_base* evbase, const Handler& handler); 25 | bool Watch(double timeout_ms); 26 | void Close(); 27 | void FreeEvent(); 28 | 29 | virtual bool DoInit() = 0; 30 | virtual void DoClose() {} 31 | 32 | protected: 33 | struct event* event_; 34 | struct event_base* evbase_; 35 | bool attached_; 36 | Handler handler_; 37 | Handler cancel_callback_; 38 | }; 39 | 40 | class TimerEventWatcher : public EventWatcher { 41 | public: 42 | TimerEventWatcher(struct event_base* evbase, const Handler& handler, double timeout_ms); 43 | 44 | bool AsyncWait(); 45 | 46 | private: 47 | virtual bool DoInit(); 48 | static void HandlerFn(evutil_socket_t fd, short which, void* v); 49 | private: 50 | double timeout_ms_; 51 | }; 52 | 53 | } 54 | 55 | -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/basic_01/invoke_timer.cc: -------------------------------------------------------------------------------- 1 | #include "invoke_timer.h" 2 | #include "event_watcher.h" 3 | 4 | #include 5 | #include 6 | 7 | namespace recipes { 8 | 9 | InvokeTimer::InvokeTimer(struct event_base* evloop, double timeout_ms, const Functor& f) 10 | : loop_(evloop), timeout_ms_(timeout_ms), functor_(f) { 11 | std::cout << "InvokeTimer::InvokeTimer tid=" << std::this_thread::get_id() << " this=" << this << std::endl; 12 | } 13 | 14 | InvokeTimer::~InvokeTimer() { 15 | std::cout << "InvokeTimer::~InvokeTimer tid=" << std::this_thread::get_id() << " this=" << this << std::endl; 16 | } 17 | 18 | void InvokeTimer::Start() { 19 | std::cout << "InvokeTimer::Start tid=" << std::this_thread::get_id() << " this=" << this << std::endl; 20 | timer_.reset(new TimerEventWatcher(loop_, std::bind(&InvokeTimer::OnTimerTriggered, this), timeout_ms_)); 21 | timer_->Init(); 22 | timer_->AsyncWait(); 23 | std::cout << "InvokeTimer::Start(AsyncWait) tid=" << std::this_thread::get_id() << " timer=" << timer_.get() << " this=" << this << " timeout(ms)=" << timeout_ms_ << std::endl; 24 | } 25 | 26 | void InvokeTimer::OnTimerTriggered() { 27 | std::cout << "InvokeTimer::OnTimerTriggered tid=" << std::this_thread::get_id() << " this=" << this << std::endl; 28 | functor_(); 29 | functor_ = Functor(); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/basic_01/invoke_timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct event_base; 7 | 8 | namespace recipes { 9 | 10 | class TimerEventWatcher; 11 | class InvokeTimer; 12 | 13 | class InvokeTimer { 14 | public: 15 | typedef std::function Functor; 16 | 17 | InvokeTimer(struct event_base* evloop, double timeout_ms, const Functor& f); 18 | ~InvokeTimer(); 19 | 20 | void Start(); 21 | 22 | private: 23 | void OnTimerTriggered(); 24 | 25 | private: 26 | struct event_base* loop_; 27 | double timeout_ms_; 28 | Functor functor_; 29 | std::shared_ptr timer_; 30 | }; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/basic_01/main.cc: -------------------------------------------------------------------------------- 1 | #include "invoke_timer.h" 2 | #include "event_watcher.h" 3 | #include "winmain-inl.h" 4 | 5 | #include 6 | 7 | void Print() { 8 | std::cout << __FUNCTION__ << " hello world." << std::endl; 9 | } 10 | 11 | int main() { 12 | struct event_base* base = event_base_new(); 13 | auto timer = new recipes::InvokeTimer(base, 1000.0, &Print); 14 | timer->Start(); 15 | event_base_dispatch(base); 16 | delete timer; 17 | event_base_free(base); 18 | return 0; 19 | } -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/basic_01/winmain-inl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _WIN32 4 | #include 5 | #endif 6 | 7 | #include 8 | 9 | namespace { 10 | struct OnApp { 11 | OnApp() { 12 | #ifdef WIN32 13 | // Initialize Winsock 2.2 14 | WSADATA wsaData; 15 | int err = WSAStartup(MAKEWORD(2, 2), &wsaData); 16 | 17 | if (err) { 18 | std::cout << "WSAStartup() failed with error: %d" << err; 19 | } 20 | #endif 21 | } 22 | ~OnApp() { 23 | #ifdef WIN32 24 | system("pause"); 25 | WSACleanup(); 26 | #endif 27 | } 28 | } __s_onexit_pause; 29 | } 30 | 31 | 32 | #ifdef _WIN32 33 | #pragma comment(lib, "Ws2_32.lib") 34 | #pragma comment(lib, "event.lib") 35 | #pragma comment(lib, "event_core.lib") // libevent2.0 36 | #pragma comment(lib, "event_extra.lib") // libevent2.0 37 | #endif 38 | -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/basic_02/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB SRCS *.cc *.h) 2 | 3 | add_executable(example_recipes_self_control_timer_basic_02 ${SRCS}) 4 | target_link_libraries(example_recipes_self_control_timer_basic_02 event) 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/basic_02/event_watcher.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | struct event; 10 | struct event_base; 11 | 12 | namespace recipes { 13 | 14 | class EventWatcher { 15 | public: 16 | typedef std::function Handler; 17 | virtual ~EventWatcher(); 18 | bool Init(); 19 | void Cancel(); 20 | 21 | void SetCancelCallback(const Handler& cb); 22 | void ClearHandler() { handler_ = Handler(); } 23 | protected: 24 | EventWatcher(struct event_base* evbase, const Handler& handler); 25 | bool Watch(double timeout_ms); 26 | void Close(); 27 | void FreeEvent(); 28 | 29 | virtual bool DoInit() = 0; 30 | virtual void DoClose() {} 31 | 32 | protected: 33 | struct event* event_; 34 | struct event_base* evbase_; 35 | bool attached_; 36 | Handler handler_; 37 | Handler cancel_callback_; 38 | }; 39 | 40 | class TimerEventWatcher : public EventWatcher { 41 | public: 42 | TimerEventWatcher(struct event_base* evbase, const Handler& handler, double timeout_ms); 43 | 44 | bool AsyncWait(); 45 | 46 | private: 47 | virtual bool DoInit(); 48 | static void HandlerFn(evutil_socket_t fd, short which, void* v); 49 | private: 50 | double timeout_ms_; 51 | }; 52 | 53 | } 54 | 55 | -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/basic_02/invoke_timer.cc: -------------------------------------------------------------------------------- 1 | #include "invoke_timer.h" 2 | #include "event_watcher.h" 3 | 4 | #include 5 | #include 6 | 7 | namespace recipes { 8 | 9 | InvokeTimer::InvokeTimer(struct event_base* evloop, double timeout_ms, const Functor& f) 10 | : loop_(evloop), timeout_ms_(timeout_ms), functor_(f) { 11 | std::cout << "InvokeTimer::InvokeTimer tid=" << std::this_thread::get_id() << " this=" << this << std::endl; 12 | } 13 | 14 | InvokeTimer* InvokeTimer::Create(struct event_base* evloop, double timeout_ms, const Functor& f) { 15 | return new InvokeTimer(evloop, timeout_ms, f); 16 | } 17 | 18 | InvokeTimer::~InvokeTimer() { 19 | std::cout << "InvokeTimer::~InvokeTimer tid=" << std::this_thread::get_id() << " this=" << this << std::endl; 20 | } 21 | 22 | void InvokeTimer::Start() { 23 | std::cout << "InvokeTimer::Start tid=" << std::this_thread::get_id() << " this=" << this << std::endl; 24 | timer_.reset(new TimerEventWatcher(loop_, std::bind(&InvokeTimer::OnTimerTriggered, this), timeout_ms_)); 25 | timer_->Init(); 26 | timer_->AsyncWait(); 27 | std::cout << "InvokeTimer::Start(AsyncWait) tid=" << std::this_thread::get_id() << " timer=" << timer_.get() << " this=" << this << " timeout(ms)=" << timeout_ms_ << std::endl; 28 | } 29 | 30 | void InvokeTimer::OnTimerTriggered() { 31 | std::cout << "InvokeTimer::OnTimerTriggered tid=" << std::this_thread::get_id() << " this=" << this << std::endl; 32 | functor_(); 33 | functor_ = Functor(); 34 | delete this; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/basic_02/invoke_timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct event_base; 7 | 8 | namespace recipes { 9 | 10 | class TimerEventWatcher; 11 | class InvokeTimer; 12 | 13 | class InvokeTimer { 14 | public: 15 | typedef std::function Functor; 16 | 17 | static InvokeTimer* Create(struct event_base* evloop, 18 | double timeout_ms, 19 | const Functor& f); 20 | 21 | ~InvokeTimer(); 22 | 23 | void Start(); 24 | 25 | private: 26 | InvokeTimer(struct event_base* evloop, double timeout_ms, const Functor& f); 27 | void OnTimerTriggered(); 28 | 29 | private: 30 | struct event_base* loop_; 31 | double timeout_ms_; 32 | Functor functor_; 33 | std::shared_ptr timer_; 34 | }; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/basic_02/main.cc: -------------------------------------------------------------------------------- 1 | #include "invoke_timer.h" 2 | #include "event_watcher.h" 3 | #include "winmain-inl.h" 4 | 5 | #include 6 | 7 | void Print() { 8 | std::cout << __FUNCTION__ << " hello world." << std::endl; 9 | } 10 | 11 | int main() { 12 | struct event_base* base = event_base_new(); 13 | auto timer = recipes::InvokeTimer::Create(base, 1000.0, &Print); 14 | timer->Start(); 15 | event_base_dispatch(base); 16 | event_base_free(base); 17 | return 0; 18 | } -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/basic_02/winmain-inl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _WIN32 4 | #include 5 | #endif 6 | 7 | #include 8 | 9 | namespace { 10 | struct OnApp { 11 | OnApp() { 12 | #ifdef WIN32 13 | // Initialize Winsock 2.2 14 | WSADATA wsaData; 15 | int err = WSAStartup(MAKEWORD(2, 2), &wsaData); 16 | 17 | if (err) { 18 | std::cout << "WSAStartup() failed with error: %d" << err; 19 | } 20 | #endif 21 | } 22 | ~OnApp() { 23 | #ifdef WIN32 24 | system("pause"); 25 | WSACleanup(); 26 | #endif 27 | } 28 | } __s_onexit_pause; 29 | } 30 | 31 | 32 | #ifdef _WIN32 33 | #pragma comment(lib, "Ws2_32.lib") 34 | #pragma comment(lib, "event.lib") 35 | #pragma comment(lib, "event_core.lib") // libevent2.0 36 | #pragma comment(lib, "event_extra.lib") // libevent2.0 37 | #endif 38 | -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/cancel_03/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB SRCS *.cc *.h) 2 | 3 | add_executable(example_recipes_self_control_timer_cancel_03 ${SRCS}) 4 | target_link_libraries(example_recipes_self_control_timer_cancel_03 event) 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/cancel_03/invoke_timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct event_base; 7 | 8 | namespace recipes { 9 | 10 | class TimerEventWatcher; 11 | class InvokeTimer; 12 | 13 | typedef std::shared_ptr InvokeTimerPtr; 14 | 15 | class InvokeTimer : public std::enable_shared_from_this { 16 | public: 17 | typedef std::function Functor; 18 | 19 | static InvokeTimerPtr Create(struct event_base* evloop, 20 | double timeout_ms, 21 | const Functor& f); 22 | 23 | ~InvokeTimer(); 24 | 25 | void Start(); 26 | 27 | void Cancel(); 28 | 29 | void set_cancel_callback(const Functor& fn) { 30 | cancel_callback_ = fn; 31 | } 32 | private: 33 | InvokeTimer(struct event_base* evloop, double timeout_ms, const Functor& f); 34 | void OnTimerTriggered(); 35 | void OnCanceled(); 36 | 37 | private: 38 | struct event_base* loop_; 39 | double timeout_ms_; 40 | Functor functor_; 41 | Functor cancel_callback_; 42 | std::shared_ptr timer_; 43 | std::shared_ptr self_; // Hold myself 44 | }; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/cancel_03/main.cc: -------------------------------------------------------------------------------- 1 | #include "invoke_timer.h" 2 | #include "event_watcher.h" 3 | #include "winmain-inl.h" 4 | 5 | #include 6 | 7 | void Print() { 8 | std::cout << __FUNCTION__ << " hello world." << std::endl; 9 | } 10 | 11 | void OnCanceled() { 12 | std::cout << __FUNCTION__ << " called." << std::endl; 13 | } 14 | 15 | int main() { 16 | struct event_base* base = event_base_new(); 17 | auto timer1 = recipes::InvokeTimer::Create(base, 2000.0, &Print); 18 | timer1->set_cancel_callback(&OnCanceled); 19 | timer1->Start(); 20 | 21 | auto fn = [timer1]() { 22 | std::cout << " cancel the timer." << std::endl; 23 | timer1->Cancel(); 24 | }; 25 | auto timer2 = recipes::InvokeTimer::Create(base, 1000.0, fn); 26 | timer2->Start(); 27 | event_base_dispatch(base); 28 | timer1.reset(); 29 | event_base_free(base); 30 | return 0; 31 | } -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/cancel_03/winmain-inl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _WIN32 4 | #include 5 | #endif 6 | 7 | #include 8 | 9 | namespace { 10 | struct OnApp { 11 | OnApp() { 12 | #ifdef WIN32 13 | // Initialize Winsock 2.2 14 | WSADATA wsaData; 15 | int err = WSAStartup(MAKEWORD(2, 2), &wsaData); 16 | 17 | if (err) { 18 | std::cout << "WSAStartup() failed with error: %d" << err; 19 | } 20 | #endif 21 | } 22 | ~OnApp() { 23 | #ifdef WIN32 24 | system("pause"); 25 | WSACleanup(); 26 | #endif 27 | } 28 | } __s_onexit_pause; 29 | } 30 | 31 | 32 | #ifdef _WIN32 33 | #pragma comment(lib, "Ws2_32.lib") 34 | #pragma comment(lib, "event.lib") 35 | #pragma comment(lib, "event_core.lib") // libevent2.0 36 | #pragma comment(lib, "event_extra.lib") // libevent2.0 37 | #endif 38 | -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/periodic_04/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB SRCS *.cc *.h) 2 | 3 | add_executable(example_recipes_self_control_timer_periodic_04 ${SRCS}) 4 | target_link_libraries(example_recipes_self_control_timer_periodic_04 event) 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/periodic_04/invoke_timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct event_base; 7 | 8 | namespace recipes { 9 | 10 | class TimerEventWatcher; 11 | class InvokeTimer; 12 | 13 | typedef std::shared_ptr InvokeTimerPtr; 14 | 15 | class InvokeTimer : public std::enable_shared_from_this { 16 | public: 17 | typedef std::function Functor; 18 | 19 | static InvokeTimerPtr Create(struct event_base* evloop, 20 | double timeout_ms, 21 | const Functor& f, 22 | bool periodic); 23 | 24 | ~InvokeTimer(); 25 | 26 | void Start(); 27 | 28 | void Cancel(); 29 | 30 | void set_cancel_callback(const Functor& fn) { 31 | cancel_callback_ = fn; 32 | } 33 | private: 34 | InvokeTimer(struct event_base* evloop, double timeout_ms, const Functor& f, bool periodic); 35 | void OnTimerTriggered(); 36 | void OnCanceled(); 37 | 38 | private: 39 | struct event_base* loop_; 40 | double timeout_ms_; 41 | Functor functor_; 42 | Functor cancel_callback_; 43 | std::shared_ptr timer_; 44 | bool periodic_; 45 | std::shared_ptr self_; // Hold myself 46 | }; 47 | 48 | } 49 | -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/periodic_04/main.cc: -------------------------------------------------------------------------------- 1 | #include "invoke_timer.h" 2 | #include "event_watcher.h" 3 | #include "winmain-inl.h" 4 | 5 | #include 6 | 7 | void Print() { 8 | std::cout << __FUNCTION__ << " hello world." << std::endl; 9 | } 10 | 11 | int main() { 12 | struct event_base* base = event_base_new(); 13 | auto timer = recipes::InvokeTimer::Create(base, 1000.0, &Print, true); 14 | timer->Start(); 15 | timer.reset(); 16 | event_base_dispatch(base); 17 | event_base_free(base); 18 | return 0; 19 | } -------------------------------------------------------------------------------- /examples/recipes/self_control_timer/periodic_04/winmain-inl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _WIN32 4 | #include 5 | #endif 6 | 7 | #include 8 | 9 | namespace { 10 | struct OnApp { 11 | OnApp() { 12 | #ifdef WIN32 13 | // Initialize Winsock 2.2 14 | WSADATA wsaData; 15 | int err = WSAStartup(MAKEWORD(2, 2), &wsaData); 16 | 17 | if (err) { 18 | std::cout << "WSAStartup() failed with error: %d" << err; 19 | } 20 | #endif 21 | } 22 | ~OnApp() { 23 | #ifdef WIN32 24 | system("pause"); 25 | WSACleanup(); 26 | #endif 27 | } 28 | } __s_onexit_pause; 29 | } 30 | 31 | 32 | #ifdef _WIN32 33 | #pragma comment(lib, "Ws2_32.lib") 34 | #pragma comment(lib, "event.lib") 35 | #pragma comment(lib, "event_core.lib") // libevent2.0 36 | #pragma comment(lib, "event_extra.lib") // libevent2.0 37 | #endif 38 | -------------------------------------------------------------------------------- /examples/signal/signal01.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "examples/winmain-inl.h" 6 | 7 | int main(int argc, char* argv[]) { 8 | evpp::EventLoop loop; 9 | std::unique_ptr ev( 10 | new evpp::SignalEventWatcher( 11 | SIGINT, &loop, []() { LOG_INFO << "SIGINT caught.";})); 12 | ev->Init(); 13 | ev->AsyncWait(); 14 | loop.Run(); 15 | return 0; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /examples/signal/signal02.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "examples/winmain-inl.h" 6 | 7 | 8 | int main(int argc, char* argv[]) { 9 | evpp::EventLoop loop; 10 | std::unique_ptr ev; 11 | auto f = [&ev, &loop]() { 12 | ev.reset(new evpp::SignalEventWatcher( 13 | SIGINT, &loop, []() { 14 | LOG_INFO << "SIGINT caught."; 15 | })); 16 | ev->Init(); 17 | ev->AsyncWait(); 18 | }; 19 | loop.RunAfter(evpp::Duration(0.001), f); 20 | loop.Run(); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /examples/tcp/tcp_client.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char* argv[]) { 6 | std::string addr = "127.0.0.1:9099"; 7 | 8 | if (argc == 2) { 9 | addr = argv[1]; 10 | } 11 | 12 | evpp::EventLoop loop; 13 | evpp::TCPClient client(&loop, addr, "TCPPingPongClient"); 14 | client.SetMessageCallback([&loop, &client](const evpp::TCPConnPtr& conn, 15 | evpp::Buffer* msg) { 16 | LOG_TRACE << "Receive a message [" << msg->ToString() << "]"; 17 | client.Disconnect(); 18 | }); 19 | 20 | client.SetConnectionCallback([](const evpp::TCPConnPtr& conn) { 21 | if (conn->IsConnected()) { 22 | LOG_INFO << "Connected to " << conn->remote_addr(); 23 | conn->Send("hello"); 24 | } else { 25 | conn->loop()->Stop(); 26 | } 27 | }); 28 | client.Connect(); 29 | loop.Run(); 30 | return 0; 31 | } 32 | 33 | #include "../echo/tcpecho/winmain-inl.h" -------------------------------------------------------------------------------- /examples/tcp/tcp_server.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char* argv[]) { 6 | std::string addr = "0.0.0.0:9099"; 7 | int thread_num = 4; 8 | evpp::EventLoop loop; 9 | evpp::TCPServer server(&loop, addr, "TCPEchoServer", thread_num); 10 | server.SetMessageCallback([](const evpp::TCPConnPtr& conn, 11 | evpp::Buffer* msg) { 12 | conn->Send(msg); 13 | }); 14 | server.SetConnectionCallback([](const evpp::TCPConnPtr& conn) { 15 | if (conn->IsConnected()) { 16 | LOG_INFO << "A new connection from " << conn->remote_addr(); 17 | } else { 18 | LOG_INFO << "Lost the connection from " << conn->remote_addr(); 19 | } 20 | }); 21 | server.Init(); 22 | server.Start(); 23 | loop.Run(); 24 | return 0; 25 | } 26 | 27 | #include "../winmain-inl.h" 28 | 29 | -------------------------------------------------------------------------------- /examples/timer/timer01.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef _WIN32 4 | #include "../echo/tcpecho/winmain-inl.h" 5 | #endif 6 | 7 | void Print() { 8 | std::cout << "Hello, world!\n"; 9 | } 10 | 11 | int main() { 12 | evpp::EventLoop loop; 13 | loop.RunAfter(evpp::Duration(5.0), &Print); 14 | loop.Run(); 15 | return 0; 16 | } -------------------------------------------------------------------------------- /examples/timer/timer02.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef _WIN32 4 | #include "../echo/tcpecho/winmain-inl.h" 5 | #endif 6 | 7 | int main() { 8 | evpp::EventLoop loop; 9 | loop.RunEvery(evpp::Duration(1.0), []() { std::cout << "Hello, world!\n"; }); 10 | loop.Run(); 11 | return 0; 12 | } -------------------------------------------------------------------------------- /examples/timer/timer03.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef _WIN32 4 | #include "../echo/tcpecho/winmain-inl.h" 5 | #endif 6 | 7 | void Print(evpp::EventLoop* loop, int* count) { 8 | if (*count < 3) { 9 | std::cout << "Hello, world! count=" << *count << std::endl; 10 | ++(*count); 11 | loop->RunAfter(evpp::Duration(2.0), std::bind(&Print, loop, count)); 12 | } else { 13 | loop->Stop(); 14 | } 15 | } 16 | 17 | int main() { 18 | evpp::EventLoop loop; 19 | int count = 0; 20 | loop.RunAfter(evpp::Duration(2.0), std::bind(&Print, &loop, &count)); 21 | loop.Run(); 22 | return 0; 23 | } -------------------------------------------------------------------------------- /examples/timer/timer04.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef _WIN32 4 | #include "../echo/tcpecho/winmain-inl.h" 5 | #endif 6 | 7 | class Printer { 8 | public: 9 | Printer(evpp::EventLoop* l) : loop_(l), count_(0) {} 10 | void Print() { 11 | if (count_ < 10) { 12 | std::cout << "Hello, world! count=" << count_ << std::endl; 13 | ++count_; 14 | } else { 15 | loop_->Stop(); 16 | } 17 | } 18 | 19 | private: 20 | evpp::EventLoop* loop_; 21 | int count_; 22 | }; 23 | 24 | int main() { 25 | evpp::EventLoop loop; 26 | Printer printer(&loop); 27 | loop.RunEvery(evpp::Duration(1.0), std::bind(&Printer::Print, &printer)); 28 | loop.Run(); 29 | return 0; 30 | } -------------------------------------------------------------------------------- /examples/timer/timer05.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef _WIN32 4 | #include "../echo/tcpecho/winmain-inl.h" 5 | #endif 6 | 7 | class Printer { 8 | public: 9 | Printer(evpp::EventLoop* l) : loop_(l), count_(0) {} 10 | void Print1() { 11 | std::cout << "Print1 : count=" << count_ << std::endl; 12 | ++count_; 13 | } 14 | 15 | void Print2() { 16 | std::cout << "Print2 : count=" << count_ << std::endl; 17 | ++count_; 18 | } 19 | private: 20 | evpp::EventLoop* loop_; 21 | int count_; 22 | }; 23 | 24 | int main() { 25 | evpp::EventLoop loop; 26 | Printer printer(&loop); 27 | loop.RunEvery(evpp::Duration(1.0), std::bind(&Printer::Print1, &printer)); 28 | loop.RunEvery(evpp::Duration(2.0), std::bind(&Printer::Print2, &printer)); 29 | auto f = [&loop]() { 30 | loop.Stop(); 31 | }; 32 | loop.RunAfter(evpp::Duration(10.0), f); 33 | loop.Run(); 34 | return 0; 35 | } -------------------------------------------------------------------------------- /examples/twisted/webserver/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include "../../winmain-inl.h" 5 | 6 | // Example from // Example from http://twistedmatrix.com/trac/#webserver 7 | 8 | std::atomic request_count; 9 | 10 | void DefaultHandler(evpp::EventLoop* loop, 11 | const evpp::http::ContextPtr& ctx, 12 | const evpp::http::HTTPSendResponseCallback& cb) { 13 | ctx->AddResponseHeader("Content-Type", "text/plain"); 14 | std::ostringstream os; 15 | os << "I am request #" << ++request_count << "\n"; 16 | cb(os.str()); 17 | } 18 | 19 | int main(int argc, char* argv[]) { 20 | int port = 8080; 21 | if (argc == 2) { 22 | port = atoi(argv[1]); 23 | } 24 | 25 | evpp::http::Server server; 26 | server.RegisterDefaultHandler(&DefaultHandler); 27 | server.Init(port); 28 | server.Start(); 29 | while (!server.IsStopped()) { 30 | usleep(1); 31 | } 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /examples/twisted/webserver/readme.md: -------------------------------------------------------------------------------- 1 | Here is a C++ HTTP web server which implements the example of [twisted](http://twistedmatrix.com/trac/#webserver) 2 | 3 | ```C++ 4 | #include 5 | 6 | #include 7 | 8 | std::atomic request_count; 9 | 10 | void DefaultHandler(evpp::EventLoop* loop, 11 | const evpp::http::ContextPtr& ctx, 12 | const evpp::http::HTTPSendResponseCallback& cb) { 13 | ctx->AddResponseHeader("Content-Type", "text/plain"); 14 | std::ostringstream os; 15 | os << "I am request #" << ++request_count << "\n"; 16 | cb(os.str()); 17 | } 18 | 19 | int main(int argc, char* argv[]) { 20 | int port = 8080; 21 | if (argc == 2) { 22 | port = atoi(argv[1]); 23 | } 24 | 25 | evpp::http::Server server; 26 | server.RegisterDefaultHandler(&DefaultHandler); 27 | server.Init(port); 28 | server.Start(); 29 | while (!server.IsStopped()) { 30 | usleep(1); 31 | } 32 | return 0; 33 | } 34 | 35 | ``` 36 | -------------------------------------------------------------------------------- /examples/winmain-inl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace { 4 | struct OnApp { 5 | OnApp() { 6 | #ifdef WIN32 7 | // Initialize Winsock 2.2 8 | WSADATA wsaData; 9 | int err = WSAStartup(MAKEWORD(2, 2), &wsaData); 10 | 11 | if (err) { 12 | std::cout << "WSAStartup() failed with error: %d" << err; 13 | } 14 | #endif 15 | } 16 | ~OnApp() { 17 | #ifdef WIN32 18 | system("pause"); 19 | WSACleanup(); 20 | #endif 21 | } 22 | } __s_onexit_pause; 23 | } 24 | 25 | 26 | -------------------------------------------------------------------------------- /labs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | include_directories(${PROJECT_SOURCE_DIR}/apps 3 | ${PROJECT_SOURCE_DIR}/labs 4 | ${PROJECT_SOURCE_DIR}/3rdparty) 5 | 6 | if (UNIX) 7 | set(LIBRARIES evpp_concurrentqueue event glog pthread) 8 | link_directories("/home/s/safe/lib" ${PROJECT_BUILD_DIR}/lib) 9 | else(UNIX) 10 | set(LIBRARIES evpp_static event glog) 11 | link_directories(${PROJECT_SOURCE_DIR}/vsprojects/bin/${CMAKE_BUILD_TYPE}/ 12 | ${LIBRARY_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}/) 13 | endif(UNIX) 14 | 15 | 16 | if(THRIFT_COMPILER AND THRIFT_INCLUDE_DIR AND THRIFT_LIBRARY) 17 | add_subdirectory(evthrift) 18 | endif() 19 | 20 | -------------------------------------------------------------------------------- /labs/evthrift/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if (WIN32) 2 | # debug 3 | set(THRIFT_LIBRARY thriftmdd ssleay32 libeay32) 4 | else () 5 | set(THRIFT_LIBRARY thrift) 6 | endif () 7 | 8 | set(EVPP_THRIFT_SRCS 9 | thrift_conn.cc thrift_conn.h 10 | thrift_server.cc thrift_server.h 11 | ) 12 | 13 | add_library(evthrift_static ${EVPP_THRIFT_SRCS}) 14 | target_link_libraries(evthrift_static ${LIBRARIES} ${THRIFT_LIBRARY}) 15 | 16 | add_subdirectory(tests) 17 | 18 | -------------------------------------------------------------------------------- /labs/evthrift/tests/.gitignore: -------------------------------------------------------------------------------- 1 | gen-cpp 2 | gen-py 3 | -------------------------------------------------------------------------------- /labs/evthrift/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(echo) 2 | add_subdirectory(ping) 3 | -------------------------------------------------------------------------------- /labs/evthrift/tests/echo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(ECHO_THRIFT echo.thrift) 3 | execute_process(COMMAND ${THRIFT_COMPILER} --gen cpp ${ECHO_THRIFT} 4 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 5 | execute_process(COMMAND ${THRIFT_COMPILER} --gen py ${ECHO_THRIFT} 6 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 7 | set(ECHO_THRIFT_SRCS 8 | gen-cpp/echo_constants.cpp 9 | gen-cpp/echo_constants.h 10 | gen-cpp/echo_types.cpp 11 | gen-cpp/echo_types.h 12 | gen-cpp/Echo.cpp 13 | gen-cpp/Echo.h 14 | ) 15 | 16 | set(ECHO_SRCS 17 | echo_server.cc 18 | ) 19 | 20 | add_executable(evthrift_echo ${ECHO_SRCS} ${ECHO_THRIFT_SRCS}) 21 | target_link_libraries(evthrift_echo evthrift_static) 22 | 23 | 24 | -------------------------------------------------------------------------------- /labs/evthrift/tests/echo/echo.thrift: -------------------------------------------------------------------------------- 1 | namespace cpp echo 2 | namespace py echo 3 | 4 | struct Request { 5 | 1: i32 num1 = 0, 6 | 2: i32 num2, 7 | 3: string c, 8 | 4: string d, 9 | 5: optional string comment, 10 | } 11 | 12 | struct Response { 13 | 1: i32 result, 14 | 2: string x, 15 | 3: string y, 16 | 4: optional string z, 17 | } 18 | 19 | service Echo 20 | { 21 | string echo(1: string arg); 22 | Response execute(1: string name, 2: Request r); 23 | void ping(); 24 | } 25 | 26 | -------------------------------------------------------------------------------- /labs/evthrift/tests/echo/echo_server.cc: -------------------------------------------------------------------------------- 1 | 2 | #include "evthrift/thrift_server.h" 3 | 4 | #include "gen-cpp/Echo.h" 5 | 6 | using namespace echo; 7 | 8 | class EchoHandler : virtual public EchoIf { 9 | public: 10 | EchoHandler() {} 11 | 12 | void echo(std::string& str, const std::string& s) { 13 | LOG_INFO << "EchoHandler::echo:" << s; 14 | str = s; 15 | } 16 | 17 | void execute(Response& _return, const std::string& name, const Request& r) { 18 | using std::to_string; 19 | LOG_INFO << "name=" << name 20 | << "Request(" 21 | << "num1=" << to_string(r.num1) 22 | << ", " << "num2=" << to_string(r.num2) 23 | << ", " << "c=" << r.c 24 | << ", " << "d=" << r.d 25 | << ", " << "comment=" << (r.__isset.comment ? (r.comment) : ( "")) 26 | << ")"; 27 | _return.result = 0; 28 | _return.x = r.c; 29 | _return.y = r.d; 30 | _return.z = r.comment; 31 | } 32 | 33 | 34 | void ping() { 35 | LOG_INFO << "EchoHandler::ping ..."; 36 | } 37 | 38 | }; 39 | 40 | int main(int argc, char **argv) { 41 | evpp::EventLoop loop; 42 | std::string name("EchoServer"); 43 | std::string addr = "0.0.0.0:9099"; 44 | 45 | boost::shared_ptr handler(new EchoHandler()); 46 | boost::shared_ptr processor(new EchoProcessor(handler)); 47 | 48 | evthrift::ThriftServer server(processor, &loop, addr, name, 4); 49 | server.start(); 50 | loop.Run(); 51 | return 0; 52 | } 53 | 54 | 55 | #include "../../../../examples/winmain-inl.h" 56 | -------------------------------------------------------------------------------- /labs/evthrift/tests/echo/echoclient.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append('gen-py') 3 | 4 | from thrift.transport import TSocket 5 | from thrift.transport import TTransport 6 | from thrift.protocol import TBinaryProtocol 7 | 8 | from echo.ttypes import Request, Response 9 | from echo import Echo 10 | 11 | 12 | def echo(s, client): 13 | s = client.echo(s) 14 | print(s) 15 | return s 16 | 17 | def execute(client): 18 | r = Request(101, 102, "ccc", "ddd", "comments") 19 | result = client.execute("python-exec", r) 20 | print("execute finished") 21 | return result 22 | 23 | def ping(client): 24 | client.ping() 25 | print("ping ...") 26 | 27 | 28 | def main(): 29 | transport = TSocket.TSocket('127.0.0.1', 9099) 30 | tranport = TTransport.TFramedTransport(transport) 31 | protocol = TBinaryProtocol.TBinaryProtocol(tranport) 32 | client = Echo.Client(protocol) 33 | tranport.open() 34 | echo("42", client) 35 | ping(client); 36 | execute(client); 37 | tranport.close() 38 | 39 | 40 | if __name__ == '__main__': 41 | main() 42 | -------------------------------------------------------------------------------- /labs/evthrift/tests/ping/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(gen-cpp) 2 | set(PING_THRIFT ping.thrift) 3 | execute_process(COMMAND ${THRIFT_COMPILER} --gen cpp ${PING_THRIFT} 4 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 5 | execute_process(COMMAND ${THRIFT_COMPILER} --gen py ${PING_THRIFT} 6 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 7 | set(PING_THRIFT_SRCS 8 | gen-cpp/ping_constants.cpp 9 | gen-cpp/ping_types.cpp 10 | gen-cpp/Ping.cpp 11 | ) 12 | set(PING_SRCS 13 | ping_server.cc 14 | ) 15 | add_executable(evthrift_ping ${PING_SRCS} ${PING_THRIFT_SRCS}) 16 | target_link_libraries(evthrift_ping evthrift_static) 17 | -------------------------------------------------------------------------------- /labs/evthrift/tests/ping/ping.thrift: -------------------------------------------------------------------------------- 1 | namespace cpp ping 2 | namespace py ping 3 | 4 | service Ping 5 | { 6 | void ping(); 7 | } 8 | 9 | -------------------------------------------------------------------------------- /labs/evthrift/tests/ping/ping_server.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "evthrift/thrift_server.h" 4 | 5 | #include "gen-cpp/Ping.h" 6 | 7 | using apache::thrift::protocol::TCompactProtocolFactory; 8 | 9 | using namespace ping; 10 | 11 | class PingHandler : virtual public PingIf { 12 | public: 13 | PingHandler() {} 14 | 15 | void ping() { 16 | LOG_INFO << "ping"; 17 | } 18 | 19 | }; 20 | 21 | int main(int argc, char **argv) { 22 | evpp::EventLoop loop; 23 | std::string name("EchoServer"); 24 | std::string addr = "0.0.0.0:9099"; 25 | 26 | boost::shared_ptr handler(new PingHandler()); 27 | boost::shared_ptr processor(new PingProcessor(handler)); 28 | 29 | evthrift::ThriftServer server(processor, &loop, addr, name, 4); 30 | server.start(); 31 | loop.Run(); 32 | return 0; 33 | 34 | return 0; 35 | } 36 | 37 | 38 | #include "../../../../examples/winmain-inl.h" 39 | -------------------------------------------------------------------------------- /labs/evthrift/tests/ping/pingclient.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append('gen-py') 3 | 4 | from thrift.transport import TSocket 5 | from thrift.transport import TTransport 6 | from thrift.protocol import TCompactProtocol 7 | 8 | from ping import Ping 9 | 10 | 11 | def ping(): 12 | transport = TSocket.TSocket('127.0.0.1', 9099) 13 | tranport = TTransport.TFramedTransport(transport) 14 | protocol = TCompactProtocol.TCompactProtocol(tranport) 15 | client = Ping.Client(protocol) 16 | tranport.open() 17 | client.ping() 18 | tranport.close() 19 | 20 | 21 | def main(): 22 | ping() 23 | 24 | 25 | if __name__ == '__main__': 26 | main() 27 | -------------------------------------------------------------------------------- /labs/evthrift/thrift_conn.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace evthrift { 12 | 13 | using apache::thrift::TProcessor; 14 | using apache::thrift::protocol::TProtocol; 15 | using apache::thrift::transport::TMemoryBuffer; 16 | using apache::thrift::transport::TNullTransport; 17 | using apache::thrift::transport::TTransport; 18 | using apache::thrift::transport::TTransportException; 19 | 20 | class ThriftServer; 21 | 22 | class ThriftConn : public std::enable_shared_from_this { 23 | public: 24 | enum State { 25 | kExpectFrameSize, 26 | kExpectFrame 27 | }; 28 | 29 | ThriftConn(ThriftServer* server, const evpp::TCPConnPtr& conn); 30 | 31 | private: 32 | friend class ThriftServer; 33 | void OnMessage(const evpp::TCPConnPtr& conn, 34 | evpp::Buffer* buffer); 35 | 36 | void Process(); 37 | 38 | void Close(); 39 | 40 | private: 41 | ThriftServer* server_; 42 | evpp::TCPConnPtr conn_; 43 | 44 | boost::shared_ptr nullTransport_; 45 | 46 | boost::shared_ptr inputTransport_; 47 | boost::shared_ptr outputTransport_; 48 | 49 | boost::shared_ptr factoryInputTransport_; 50 | boost::shared_ptr factoryOutputTransport_; 51 | 52 | boost::shared_ptr inputProtocol_; 53 | boost::shared_ptr outputProtocol_; 54 | 55 | boost::shared_ptr processor_; 56 | 57 | enum State state_; 58 | uint32_t frameSize_; 59 | }; 60 | 61 | typedef std::shared_ptr ThriftConnectionPtr; 62 | 63 | } 64 | -------------------------------------------------------------------------------- /labs/evthrift/thrift_server.cc: -------------------------------------------------------------------------------- 1 | #include "thrift_server.h" 2 | 3 | namespace evthrift { 4 | 5 | ThriftServer::~ThriftServer() {} 6 | 7 | void ThriftServer::serve() { 8 | server_.SetMessageCallback(std::bind(&ThriftServer::OnMessage, 9 | this, std::placeholders::_1, 10 | std::placeholders::_2)); 11 | server_.Init(); 12 | server_.Start(); 13 | } 14 | 15 | void ThriftServer::stop() { 16 | server_.Stop(); 17 | } 18 | 19 | void ThriftServer::OnConnection(const evpp::TCPConnPtr& conn) { 20 | if (conn->IsConnected()) { 21 | ThriftConnectionPtr ptr(new ThriftConn(this, conn)); 22 | conn->set_context(evpp::Any(ptr)); 23 | } else { 24 | conn->set_context(evpp::Any()); 25 | } 26 | } 27 | 28 | void ThriftServer::OnMessage(const evpp::TCPConnPtr& conn, evpp::Buffer* buffer) { 29 | const evpp::Any& a = conn->context(); 30 | if (a.IsEmpty()) { 31 | LOG_ERROR << "The evpp::TCPConn is not assoiated with a Thrift Connection"; 32 | return; 33 | } 34 | 35 | ThriftConnectionPtr ptr = a.Get(); 36 | ptr->OnMessage(conn, buffer); 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB evpp_unittest_SRCS *.cc 2 | ${PROJECT_SOURCE_DIR}/3rdparty/gtest/src/gtest-all.cc 3 | ${PROJECT_SOURCE_DIR}/3rdparty/gtest/src/gtest_main.cc) 4 | list(REMOVE_ITEM evpp_unittest_SRCS ${PROJECT_SOURCE_DIR}/test/https_client_test.cc) 5 | file(GLOB evpp_https_unittest_SRCS https_client_test.cc 6 | ${PROJECT_SOURCE_DIR}/3rdparty/gtest/src/gtest-all.cc 7 | ${PROJECT_SOURCE_DIR}/3rdparty/gtest/src/gtest_main.cc) 8 | include_directories(${PROJECT_SOURCE_DIR}/3rdparty ${PROJECT_SOURCE_DIR}/3rdparty/gtest) 9 | 10 | if (MSVC) 11 | link_directories(${LIBRARY_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}/) 12 | endif (MSVC) 13 | 14 | add_executable(evpp_unittest ${evpp_unittest_SRCS}) 15 | target_link_libraries(evpp_unittest evpp_static ${DEPENDENT_LIBRARIES}) 16 | 17 | if (HTTPS) 18 | add_executable(evpp_https_unittest ${evpp_https_unittest_SRCS}) 19 | target_link_libraries(evpp_https_unittest evpp_https_static ${DEPENDENT_LIBRARIES}) 20 | endif (HTTPS) 21 | 22 | if (UNIX) 23 | add_executable(evpp_unittest_boost_lockfree ${evpp_unittest_SRCS}) 24 | target_link_libraries(evpp_unittest_boost_lockfree evpp_boost ${DEPENDENT_LIBRARIES}) 25 | 26 | add_executable(evpp_unittest_concurrentqueue ${evpp_unittest_SRCS}) 27 | target_link_libraries(evpp_unittest_concurrentqueue evpp_concurrentqueue ${DEPENDENT_LIBRARIES}) 28 | endif (UNIX) 29 | 30 | include (CTest) 31 | add_test(NAME evpp_unittest COMMAND evpp_unittest) 32 | 33 | if (UNIX) 34 | add_test(NAME evpp_unittest_concurrentqueue COMMAND evpp_unittest_concurrentqueue) 35 | add_test(NAME evpp_unittest_boost_lockfree COMMAND evpp_unittest_boost_lockfree) 36 | endif (UNIX) 37 | 38 | add_subdirectory (stability) 39 | add_subdirectory (more_tests) 40 | -------------------------------------------------------------------------------- /test/any_test.cc: -------------------------------------------------------------------------------- 1 | #include "test_common.h" 2 | 3 | #include 4 | #include 5 | 6 | TEST_UNIT(testAny1) { 7 | evpp::Buffer* buf(new evpp::Buffer()); 8 | evpp::Any any(buf); 9 | 10 | evpp::Buffer* b1 = evpp::any_cast(any); 11 | H_TEST_ASSERT(buf == b1); 12 | 13 | delete buf; 14 | } 15 | 16 | TEST_UNIT(testAny2) { 17 | std::shared_ptr buf(new evpp::Buffer()); 18 | evpp::Any any(buf); 19 | 20 | std::shared_ptr b1 = evpp::any_cast>(any); 21 | H_TEST_ASSERT(buf.get() == b1.get()); 22 | } 23 | 24 | TEST_UNIT(testAny3) { 25 | std::shared_ptr buf(new evpp::Buffer()); 26 | evpp::Any any(buf); 27 | 28 | std::shared_ptr b1 = any.Get>(); 29 | H_TEST_ASSERT(buf.get() == b1.get()); 30 | } 31 | 32 | -------------------------------------------------------------------------------- /test/event_loop_thread_test.cc: -------------------------------------------------------------------------------- 1 | #include "test_common.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace { 11 | static bool g_timeout = false; 12 | static std::atomic g_count; 13 | static void OnTimeout() { 14 | g_timeout = true; 15 | } 16 | 17 | static void OnCount() { 18 | g_count++; 19 | } 20 | } 21 | 22 | 23 | TEST_UNIT(testEventLoopThread) { 24 | evpp::Duration delay(double(1.0)); // 1s 25 | g_count.store(0); 26 | std::unique_ptr t(new evpp::EventLoopThread); 27 | t->Start(true); 28 | usleep(1000); 29 | evpp::Timestamp begin = evpp::Timestamp::Now(); 30 | t->loop()->RunAfter(delay, &OnTimeout); 31 | 32 | while (!g_timeout) { 33 | usleep(1); 34 | } 35 | 36 | evpp::Duration cost = evpp::Timestamp::Now() - begin; 37 | H_TEST_ASSERT(delay <= cost); 38 | t->loop()->RunInLoop(&OnCount); 39 | t->loop()->RunInLoop(&OnCount); 40 | t->loop()->RunInLoop(&OnCount); 41 | t->loop()->RunInLoop(&OnCount); 42 | t->Stop(true); 43 | t.reset(); 44 | H_TEST_ASSERT(g_count == 4); 45 | H_TEST_ASSERT(evpp::GetActiveEventCount() == 0); 46 | } 47 | -------------------------------------------------------------------------------- /test/glog_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "test_common.h" 4 | 5 | TEST_UNIT(testglog) { 6 | google::InitGoogleLogging("xxx"); 7 | FLAGS_stderrthreshold = 0; 8 | LOG(INFO) << "INFO"; 9 | LOG(WARNING) << "WARNING"; 10 | LOG(ERROR) << "ERROR"; 11 | } -------------------------------------------------------------------------------- /test/invoke_timer_test.cc: -------------------------------------------------------------------------------- 1 | 2 | #include "test_common.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace evloop { 12 | static std::shared_ptr loop; 13 | static evpp::Duration delay(1.0); 14 | static evpp::Duration cancel_delay(0.5); 15 | static bool event_handler_called = false; 16 | static void Close() { 17 | loop->Stop(); 18 | } 19 | 20 | static void Handle() { 21 | event_handler_called = true; 22 | } 23 | 24 | static void MyEventThread() { 25 | LOG_INFO << "EventLoop is running ..."; 26 | loop = std::shared_ptr(new evpp::EventLoop); 27 | loop->Run(); 28 | } 29 | } 30 | 31 | TEST_UNIT(testInvokerTimerCancel) { 32 | using namespace evloop; 33 | std::thread th(MyEventThread); 34 | usleep(delay.Microseconds()); 35 | evpp::Timestamp start = evpp::Timestamp::Now(); 36 | loop->RunAfter(delay, &Close); 37 | evpp::InvokeTimerPtr timer = loop->RunAfter(delay, &Handle); 38 | usleep(cancel_delay.Microseconds()); 39 | timer->Cancel(); 40 | th.join(); 41 | timer.reset(); 42 | loop.reset(); 43 | evpp::Duration cost = evpp::Timestamp::Now() - start; 44 | H_TEST_ASSERT(delay <= cost); 45 | H_TEST_ASSERT(!event_handler_called); 46 | H_TEST_ASSERT(evpp::GetActiveEventCount() == 0); 47 | } 48 | 49 | -------------------------------------------------------------------------------- /test/more_tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory (fork) 2 | -------------------------------------------------------------------------------- /test/more_tests/fork/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB SROUCES *.cc *.h) 2 | 3 | if (UNIX) 4 | add_executable(test_evpp_after_fork ${SROUCES}) 5 | target_link_libraries(test_evpp_after_fork evpp_static ${DEPENDENT_LIBRARIES}) 6 | endif (UNIX) 7 | 8 | -------------------------------------------------------------------------------- /test/stability/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #include_directories(${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/3rdparty/gtest ${PROJECT_SOURCE_DIR}/3rdparty) 2 | # 3 | #if (MSVC) 4 | #link_directories(${PROJECT_SOURCE_DIR}/vsprojects/bin/${CMAKE_BUILD_TYPE}/ 5 | # ${LIBRARY_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}/ 6 | # ${PROJECT_SOURCE_DIR}/3rdparty/glog-0.3.4/${CMAKE_BUILD_TYPE}) 7 | #endif (MSVC) 8 | 9 | file(GLOB SROUCES *.cc *.h) 10 | add_executable(test_evpp_stability ${SROUCES}) 11 | target_link_libraries(test_evpp_stability evpp_static ${DEPENDENT_LIBRARIES}) 12 | 13 | if (UNIX) 14 | add_executable(test_evpp_stability_boost_lockfree ${SROUCES}) 15 | target_link_libraries(test_evpp_stability_boost_lockfree evpp_boost_static ${DEPENDENT_LIBRARIES}) 16 | 17 | add_executable(test_evpp_stability_concurrentqueue ${SROUCES}) 18 | target_link_libraries(test_evpp_stability_concurrentqueue evpp_concurrentqueue_static ${DEPENDENT_LIBRARIES}) 19 | endif (UNIX) 20 | 21 | -------------------------------------------------------------------------------- /test/stability/run_stability.sh: -------------------------------------------------------------------------------- 1 | 2 | for port in 7081 7082 7083 7084 7085 7086 7087 7088 7089; do 3 | mkdir -p $port && cd $port 4 | nohup ../../../build-debug/bin/test_evpp_stability $port & 5 | cd .. 6 | done 7 | 8 | for port in 8081 8082 8083 8084 8085 8086 8087 8088 8089; do 9 | mkdir -p $port && cd $port 10 | nohup ../../../build-debug/bin/test_evpp_stability_boost_lockfree $port & 11 | cd .. 12 | done 13 | 14 | for port in 9081 9082 9083 9084 9085 9086 9087 9088 9089; do 15 | mkdir -p $port && cd $port 16 | nohup ../../../build-debug/bin/test_evpp_stability_concurrentqueue $port & 17 | cd .. 18 | done 19 | 20 | -------------------------------------------------------------------------------- /test/stability/stability.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | 10 | static std::vector g_listening_port; 11 | 12 | std::string GetListenAddr() { 13 | return std::string("127.0.0.1:") + std::to_string(g_listening_port[0]); 14 | } 15 | 16 | -------------------------------------------------------------------------------- /test/stability/stability_dns.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "../../examples/winmain-inl.h" 12 | 13 | void TestDNSResolver() { 14 | for (int i = 0; i < 40; i++) { 15 | bool resolved = false; 16 | bool deleted = false; 17 | auto fn_resolved = [&resolved](const std::vector & addrs) { 18 | LOG_INFO << "Entering fn_resolved"; 19 | resolved = true; 20 | }; 21 | 22 | evpp::Duration delay(double(3.0)); // 3s 23 | std::unique_ptr t(new evpp::EventLoopThread); 24 | t->Start(true); 25 | std::shared_ptr dns_resolver(new evpp::DNSResolver(t->loop(), "www.so.com", evpp::Duration(1.0), fn_resolved)); 26 | dns_resolver->Start(); 27 | 28 | while (!resolved) { 29 | usleep(1); 30 | } 31 | 32 | auto fn_deleter = [&deleted, dns_resolver]() { 33 | LOG_INFO << "Entering fn_deleter"; 34 | deleted = true; 35 | }; 36 | 37 | t->loop()->QueueInLoop(fn_deleter); 38 | dns_resolver.reset(); 39 | while (!deleted) { 40 | usleep(1); 41 | } 42 | 43 | t->Stop(true); 44 | t.reset(); 45 | if (evpp::GetActiveEventCount() != 0) { 46 | assert(evpp::GetActiveEventCount() == 0); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /test/time_test.cc: -------------------------------------------------------------------------------- 1 | 2 | #include "./test_common.h" 3 | #include "evpp/duration.h" 4 | #include "evpp/timestamp.h" 5 | #include "evpp/gettimeofday.h" 6 | 7 | TEST_UNIT(testDuration) { 8 | evpp::Duration d0(0); 9 | evpp::Duration d1(1); 10 | evpp::Duration d2(2); 11 | evpp::Duration d3(2); 12 | H_TEST_ASSERT(d0 < d1); 13 | H_TEST_ASSERT(d1 < d2); 14 | H_TEST_ASSERT(d2 == d3); 15 | H_TEST_ASSERT(d0.IsZero()); 16 | H_TEST_ASSERT(d0 <= d1); 17 | H_TEST_ASSERT(d1 <= d2); 18 | H_TEST_ASSERT(d2 <= d3); 19 | H_TEST_ASSERT(d2 >= d3); 20 | H_TEST_ASSERT(d1 > d0); 21 | H_TEST_ASSERT(d2 > d1); 22 | H_TEST_ASSERT(d1 >= d0); 23 | H_TEST_ASSERT(d2 >= d1); 24 | } 25 | 26 | TEST_UNIT(testTimestamp) { 27 | int64_t c_s = time(nullptr); 28 | int64_t c_us = evpp::utcmicrosecond(); 29 | int64_t ts_ns = evpp::Timestamp::Now().UnixNano(); 30 | int64_t c11_us = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); 31 | H_TEST_ASSERT(c_us / 1000000 == c11_us / 1000000); 32 | H_TEST_ASSERT(c_s == c11_us / 1000000); 33 | H_TEST_ASSERT(c_s == ts_ns / evpp::Duration::kSecond); 34 | } 35 | 36 | -------------------------------------------------------------------------------- /test/trivial_test.cc: -------------------------------------------------------------------------------- 1 | #include "test_common.h" 2 | 3 | #include 4 | #include 5 | 6 | TEST_UNIT(Teststrerror) { 7 | LOG_ERROR << evpp::strerror(EAGAIN); 8 | } 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/utility_test.cc: -------------------------------------------------------------------------------- 1 | #include "test_common.h" 2 | 3 | #include 4 | 5 | TEST_UNIT(testStringSplit1) { 6 | std::string s = "a,b,c,d"; 7 | std::vector v; 8 | evpp::StringSplit(s, ',', 0, v); 9 | H_TEST_ASSERT(v.size() == 4); 10 | H_TEST_ASSERT(v[0] == "a"); 11 | H_TEST_ASSERT(v[1] == "b"); 12 | H_TEST_ASSERT(v[2] == "c"); 13 | H_TEST_ASSERT(v[3] == "d"); 14 | } 15 | 16 | TEST_UNIT(testStringSplit2) { 17 | std::string s = "a,b,c,d"; 18 | std::vector v; 19 | evpp::StringSplit(s, ",", 0, v); 20 | H_TEST_ASSERT(v.size() == 4); 21 | H_TEST_ASSERT(v[0] == "a"); 22 | H_TEST_ASSERT(v[1] == "b"); 23 | H_TEST_ASSERT(v[2] == "c"); 24 | H_TEST_ASSERT(v[3] == "d"); 25 | } 26 | -------------------------------------------------------------------------------- /test/winmain.cc: -------------------------------------------------------------------------------- 1 | #include "test_common.h" 2 | 3 | #include "evpp/libevent.h" 4 | 5 | namespace { 6 | #ifdef WIN32 7 | struct OnApp { 8 | OnApp() { 9 | // Initialize net work. 10 | WSADATA wsaData; 11 | // Initialize Winsock 2.2 12 | int nError = WSAStartup(MAKEWORD(2, 2), &wsaData); 13 | 14 | if (nError) { 15 | std::cout << "WSAStartup() failed with error: %d" << nError; 16 | } 17 | 18 | } 19 | ~OnApp() { 20 | system("pause"); 21 | } 22 | } __s_onexit_pause; 23 | #endif 24 | } 25 | 26 | 27 | 28 | // main function is defined on gtest_main.cc -------------------------------------------------------------------------------- /tools/astyle_format_code.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Run this script at the directory which holds it. 4 | 5 | cd ../ 6 | 7 | SUBDIRS="evpp evpp/http evpp/httpc evpp/udp test examples/echo/httpecho examples/echo/udpecho examples/echo/tcpecho examples/pingpong/client examples/pingpong/server apps/evmc/test apps/evmc apps/evnsq apps/evnsq/test " 8 | FILETYPES="*.cc *.h" 9 | ASTYLE_BIN="3rdparty/astyle/build/gcc/bin/astyle" 10 | ASTYLE="${ASTYLE_BIN} -A2 -HtUwpj -M80 -c -s4 --pad-header --align-pointer=type " 11 | 12 | if test -f ${ASTYLE_BIN} 13 | then 14 | echo "use astyle" 15 | else 16 | tar zxvf 3rdparty/astyle_2.06_linux.tar.gz -C 3rdparty 17 | make -j -C 3rdparty/astyle/build/gcc 18 | if test -f ${ASTYLE_BIN} 19 | then 20 | echo "${ASTYLE_BIN} generated successfully." 21 | else 22 | echo "ERROR: astyle compiled failed!!!" 23 | exit 1 24 | fi 25 | fi 26 | 27 | for d in ${SUBDIRS} 28 | do 29 | echo "astyle format subdir: $d " 30 | for t in ${FILETYPES} 31 | do 32 | for file in $d/$t 33 | do 34 | echo ">>>>>>>>>> format file: $file " 35 | if test -f $file 36 | then 37 | ${ASTYLE} $file 38 | rm -f ${file}.orig 39 | fi 40 | done 41 | done 42 | done 43 | 44 | -------------------------------------------------------------------------------- /tools/benchmark-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Run this script at the directory which holds it. 4 | 5 | set -x 6 | 7 | SOURCE_DIR=`pwd`/.. 8 | BUILD_TYPE=release 9 | BUILD_DIR=${SOURCE_DIR}/build-${BUILD_TYPE} 10 | 11 | mkdir -p $BUILD_DIR \ 12 | && cd $BUILD_DIR \ 13 | && cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_BENCHMARK_TESTING=1 $SOURCE_DIR\ 14 | && make -j\ 15 | && cp -rf $BUILD_DIR/bin/benchmark_pingpong* ../benchmark/throughput/evpp \ 16 | && cp -rf $BUILD_DIR/bin/benchmark_tcp_asio_* ../benchmark/throughput/asio \ 17 | && cp -rf $BUILD_DIR/bin/benchmark_tcp_libevent_* ../benchmark/throughput/libevent \ 18 | && cp -rf $BUILD_DIR/bin/benchmark_ioevent_* ../benchmark/ioevent/libevent \ 19 | 20 | -------------------------------------------------------------------------------- /tools/debug-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Run this script at the directory which holds it. 4 | 5 | set -x 6 | 7 | SOURCE_DIR=`pwd`/.. 8 | BUILD_TYPE=debug 9 | BUILD_DIR=${SOURCE_DIR}/build-${BUILD_TYPE} 10 | 11 | mkdir -p $BUILD_DIR \ 12 | && cd $BUILD_DIR \ 13 | && cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE $SOURCE_DIR \ 14 | && make -j 15 | -------------------------------------------------------------------------------- /tools/release-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Run this script at the directory which holds it. 4 | 5 | #Try to checkout to the lastest TAG and compile it 6 | # 7 | #VERSION=`grep PACKAGE_VERSION ../cmake/packages.cmake | head -1 | awk -F\" '{print $2}' | awk -F"$" '{print $1}'` 8 | #VERSION=`echo -n ${VERSION}` 9 | # 10 | # git checkout $VERSION 11 | # 12 | 13 | set -x 14 | 15 | SOURCE_DIR=`pwd`/.. 16 | BUILD_TYPE=release 17 | BUILD_DIR=${SOURCE_DIR}/build-${BUILD_TYPE} 18 | 19 | rm -rf $BUILD_DIR 20 | mkdir -p $BUILD_DIR \ 21 | && cd $BUILD_DIR \ 22 | && cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE $SOURCE_DIR \ 23 | && make \ 24 | && make package 25 | -------------------------------------------------------------------------------- /tools/win32-build.sh: -------------------------------------------------------------------------------- 1 | 2 | # Run this script at the directory which holds it. 3 | 4 | mkdir -p ../build 5 | cd ../build 6 | cmake .. 7 | -------------------------------------------------------------------------------- /vsprojects/bin/Debug/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qihoo360/evpp/477033f938fd47dfecde43c82257cd286d9fa38e/vsprojects/bin/Debug/.placeholder -------------------------------------------------------------------------------- /vsprojects/bin/Release/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qihoo360/evpp/477033f938fd47dfecde43c82257cd286d9fa38e/vsprojects/bin/Release/.placeholder -------------------------------------------------------------------------------- /vsprojects/echo.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /vsprojects/pingpong_client.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 127.0.0.1 9099 2 1024 1 5 5 | WindowsLocalDebugger 6 | 7 | --------------------------------------------------------------------------------