├── .gitignore ├── AUTHORS ├── CMakeLists.txt ├── COPYING ├── ChangeLog ├── Config.h ├── Config.h.in ├── INSTALL ├── LICENSE ├── Makefile.am ├── NEWS ├── README ├── README.md ├── TODO ├── aclocal.m4 ├── autogen_test.sh ├── bootstrap ├── configure.ac ├── docs ├── (Part 1 of 2)The Reactor An Object-Oriented Wrapper for Event-Driven Port Monitoring and Service Demultiplexing.pdf ├── (Part 2 of 2)The Design and Implementation of the Reactor An Object-Oriented Framework for Event Demultiplexing.pdf ├── Comparing Two High-Performance I_O Design Patterns.pdf ├── Proactor : An Object Behavioral Pattern for Demultiplexing and Dispatching Handlers for Asynchronous Events.pdf ├── Proactor.pdf ├── README.md ├── Reactor : An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events.pdf ├── Scalable IO in Java(DougLea).pdf └── proactor.png ├── dos2unix.sh ├── examples ├── CMakeLists.txt ├── Makefile.am ├── echo │ ├── EchoClient.cpp │ ├── EchoClient.h │ ├── EchoServer.cpp │ ├── EchoServer.h │ ├── Makefile.am │ └── main.cpp ├── idleconnection │ ├── Makefile.am │ └── idleconnection.cpp ├── maxconnection │ ├── Makefile.am │ └── MaxConnection.cpp ├── reader_writer │ ├── Makefile.am │ └── reader_writer.cpp ├── roundtriptime │ ├── Makefile.am │ └── RoundTripTime.cpp ├── simpleServers │ ├── Makefile.am │ └── simpleServers.cpp ├── test_httpserver │ ├── Makefile.am │ └── test_httpserver.cpp ├── test_websocketclient │ ├── Makefile.am │ └── test_websocketclient.cpp ├── test_websocketserver │ ├── Makefile.am │ └── test_websocketserver.cpp ├── thread_bench │ ├── Makefile.am │ └── thread_bench.cpp └── twisted_finger │ ├── Makefile.am │ └── twisted_finger.cpp ├── install-sh ├── sln ├── libzlreactor │ ├── libzlreactor.vcxproj │ └── libzlreactor.vcxproj.filters └── zl_reactor.sln ├── stamp-h1 ├── tests ├── CMakeLists.txt ├── Makefile.am ├── PipePairFactory │ ├── Makefile.am │ └── pipePairTest.cpp ├── backtrace_test │ ├── Makefile.am │ ├── backtrace_test.cpp │ └── makefile_alone ├── bind_tcp_udp │ ├── Makefile.am │ └── bind_tcp_udp.cpp ├── c1000k │ ├── .gitignore │ ├── Makefile │ ├── README.md │ ├── client.c │ └── server.c ├── epoll_echoclient │ ├── EchoClient.cpp │ ├── EchoClient.h │ ├── EchoClientTest.cpp │ ├── EpollPoller.cpp │ ├── EpollPoller.h │ └── Makefile.am ├── epoll_echoserver │ ├── EchoServer.cpp │ ├── EchoServer.h │ ├── EchoServerTest.cpp │ ├── EpollPoller.cpp │ ├── EpollPoller.h │ └── Makefile.am ├── master_worker_process │ ├── Makefile.am │ └── master_worker_process.cpp ├── pingpong │ ├── Makefile.am │ ├── pingpong_client.cpp │ └── pingpong_server.cpp ├── proxy_server │ ├── Makefile.am │ ├── ProxyServerByEpoll.cpp │ └── ProxyServerByFork.cpp ├── server_aio │ ├── Makefile.am │ └── server_aio.cpp ├── signal_handler │ ├── Makefile.am │ └── signal_handler.cpp ├── socketAcceptThunderingHerd │ ├── Makefile.am │ └── socketAcceptThunderingHerd.cpp ├── stress_client │ ├── Makefile.am │ └── stress_client.cpp ├── tcpselfconnect1 │ ├── Makefile.am │ └── tcpselfconnect1.cpp ├── tcpselfconnect2 │ ├── Makefile.am │ └── tcpselfconnect2.cpp ├── timerqueue │ ├── Makefile.am │ ├── Timer.cpp │ ├── Timer.h │ ├── TimerQueue.cpp │ ├── TimerQueue.h │ └── Timer_Test.cpp └── universal_timer │ ├── Makefile.am │ ├── TriggerTimer.cpp │ ├── TriggerTimer.h │ └── TriggerTimerTest.cpp └── zlreactor ├── CMakeLists.txt ├── Define.h ├── Makefile.am ├── OsDefine.h ├── base ├── AsyncLogger.cpp ├── AsyncLogger.h ├── Closure.h ├── ConfigFile.h ├── Daemonize.cpp ├── Daemonize.h ├── Date.cpp ├── Date.h ├── DateTimeUtil.cpp ├── DateTimeUtil.h ├── Demangle.cpp ├── Demangle.h ├── Exception.cpp ├── Exception.h ├── File.cpp ├── File.h ├── FileUtil.cpp ├── FileUtil.h ├── HighPrecisionTime.h ├── LogFile.cpp ├── LogFile.h ├── Logger.cpp ├── Logger.h ├── Makefile.am ├── MasterWorkerProcess.cpp ├── MasterWorkerProcess.h ├── MathUtil.h ├── NonCopy.h ├── ObjectPool.h ├── Preprocess.h ├── ProcessTimeCounter.h ├── ProcessUtil.cpp ├── ProcessUtil.h ├── Random.h ├── ScopeExitGuard.h ├── Singleton.h ├── SmartAssert.h ├── StlUtil.h ├── StopWatch.h ├── StringPiece.cpp ├── StringPiece.h ├── StringUtil.cpp ├── StringUtil.h ├── Timestamp.cpp ├── Timestamp.h └── tests │ ├── AsyncLogger_test.cpp │ ├── CMakeLists.txt │ ├── ConfigFile_test.cpp │ ├── Daemon_test.cpp │ ├── Demangle_test.cpp │ ├── Exception_test.cpp │ ├── Logger_test.cpp │ ├── Makefile.am │ ├── MasterWorkerProcess_test.cpp │ ├── ObjectPool_test.cpp │ ├── Preprocess_test.cpp │ ├── ProcessUtil_test.cpp │ ├── ScopeExitGuard_test.cpp │ ├── Singleton_test.cpp │ ├── SmartAssert_test.cpp │ ├── StlUtil_test.cpp │ ├── StringPiece_test.cpp │ ├── StringUtil_test.cpp │ └── Timestamp_test.cpp ├── meta └── meta_util.hpp ├── net ├── ByteBuffer.cpp ├── ByteBuffer.h ├── CallBacks.h ├── Channel.cpp ├── Channel.h ├── DomainResolver.cpp ├── DomainResolver.h ├── EventLoop.cpp ├── EventLoop.h ├── EventLoopThreadPool.cpp ├── EventLoopThreadPool.h ├── Eventfd.cpp ├── Eventfd.h ├── InetAddress.cpp ├── InetAddress.h ├── Makefile.am ├── NetUtil.cpp ├── NetUtil.h ├── PipePairFactory.h ├── Signalfd.cpp ├── Signalfd.h ├── Socket.cpp ├── Socket.h ├── SocketUtil.cpp ├── SocketUtil.h ├── TcpAcceptor.cpp ├── TcpAcceptor.h ├── TcpClient.cpp ├── TcpClient.h ├── TcpConnection.cpp ├── TcpConnection.h ├── TcpConnector.cpp ├── TcpConnector.h ├── TcpServer.cpp ├── TcpServer.h ├── Timer.h ├── TimerQueue.cpp ├── TimerQueue.h ├── Timerfd.cpp ├── Timerfd.h ├── http │ ├── HttpContext.cpp │ ├── HttpContext.h │ ├── HttpKeyValue.cpp │ ├── HttpKeyValue.h │ ├── HttpProtocol.h │ ├── HttpRequest.cpp │ ├── HttpRequest.h │ ├── HttpResponse.cpp │ ├── HttpResponse.h │ ├── HttpServer.cpp │ ├── HttpServer.h │ ├── UriQueryParams.cpp │ ├── UriQueryParams.h │ ├── UriUtil.cpp │ └── UriUtil.h ├── poller │ ├── EpollPoller.cpp │ ├── EpollPoller.h │ ├── PollPoller.cpp │ ├── PollPoller.h │ ├── Poller.cpp │ ├── Poller.h │ ├── SelectPoller.cpp │ └── SelectPoller.h ├── tests │ ├── ByteBuffer_test.cpp │ ├── CMakeLists.txt │ ├── DomainResolver_test.cpp │ ├── EventLoopThreadPool_test.cpp │ ├── EventLoop_test.cpp │ ├── Eventfd_test.cpp │ ├── HttpRequestParser_test.cpp │ ├── InetAddress_test.cpp │ ├── Makefile.am │ ├── Signalfd_test.cpp │ ├── Socket_test.cpp │ ├── TcpAcceptor_test.cpp │ ├── TcpClient_test.cpp │ ├── Timer_test.cpp │ ├── Timerfd_test.cpp │ ├── UriDecode_gbk.h │ ├── UriDecode_test.cpp │ ├── UriDecode_utf8.h │ └── UriQueryParams_test.cpp └── websocket │ ├── WebSocket.cpp │ ├── WebSocket.h │ ├── WebSocketClient.cpp │ ├── WebSocketClient.h │ ├── WebSocketServer.cpp │ └── WebSocketServer.h ├── stl ├── any.h ├── array.h ├── range.h └── tests │ ├── any_test.cpp │ ├── array_test.cpp │ └── range_test.cpp ├── thread ├── Atomic.h ├── BlockingQueue.h ├── BlockingQueueWorker.h ├── BoundedBlockingQueue.h ├── ConcurrentHashMap.h ├── ConcurrentQueue.h ├── Condition.h ├── CountDownLatch.h ├── CyclicBarrier.h ├── Event.h ├── FastMutex.h ├── Makefile.am ├── Mutex.h ├── RWMutex.h ├── Semaphore.h ├── Thread.cpp ├── Thread.h ├── ThreadGroup.cpp ├── ThreadGroup.h ├── ThreadLocal.h ├── ThreadPool.cpp ├── ThreadPool.h └── tests │ ├── Atomic_test.cpp │ ├── BlockingQueueWorker_test.cpp │ ├── BlockingQueue_bench.cpp │ ├── BlockingQueue_test.cpp │ ├── CMakeLists.txt │ ├── ConcurrentHashMap_test.cpp │ ├── ConcurrentQueue_bench.cpp │ ├── ConcurrentQueue_test.cpp │ ├── CountDownLatch_test.cpp │ ├── CyclicBarrier_test.cpp │ ├── Event_test.cpp │ ├── Makefile.am │ ├── Mutex_test.cpp │ ├── ThreadGroup_test.cpp │ ├── ThreadId_test.cpp │ ├── ThreadLocal_test.cpp │ └── Thread_test.cpp └── utility ├── Base64.cpp ├── Base64.h ├── Hex2String.h ├── Md5.cpp ├── Md5.h ├── SHA1.cpp ├── SHA1.h ├── StringHash.cpp ├── StringHash.h ├── UUID.h ├── jenkins_hash.c ├── jenkins_hash.h ├── murmur3_hash.c └── murmur3_hash.h /.gitignore: -------------------------------------------------------------------------------- 1 | #ignore specificity dirs 2 | Debug 3 | bin 4 | log 5 | Release 6 | .deps 7 | 8 | # Compiled Object files 9 | *.slo 10 | *.lo 11 | *.o 12 | *.obj 13 | *.Makefile 14 | *.Makefile.in 15 | 16 | # Compiled Dynamic libraries 17 | *.so 18 | *.dylib 19 | *.dll 20 | 21 | # Compiled Static libraries 22 | *.lai 23 | *.la 24 | *.a 25 | *.lib 26 | 27 | # Executables 28 | *.exe 29 | *.out 30 | *.app 31 | 32 | #VisualStudio temp files 33 | *.obj 34 | *.user 35 | *.sdf 36 | *.suo 37 | *.ipch 38 | *.tlog 39 | *.pdb 40 | *.error 41 | *.ilk 42 | *.res 43 | *cache 44 | *.manifest 45 | *.log 46 | *.lastbuildstate 47 | *.idb 48 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | ______ ____ _____ _ ____ _____ ___ ____ 2 | |__ / | | _ \| ____| / \ / ___|_ _/ _ \| _ \ 3 | / /| | | |_) | _| / _ \| | | || | | | |_) | 4 | / /_| |___| _ <| |___ / ___ \ |___ | || |_| | _ < 5 | /____|_____|_| \_\_____/_/ \_\____| |_| \___/|_| \_\ 6 | 7 | AUTHORS 8 | =========== 9 | lizhenghn@gmail.com -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | ################################################################################### 3 | 4 | project(libzlreactor) 5 | 6 | if (CMAKE_BUILD_TYPE) 7 | else() 8 | set(CMAKE_BUILD_TYPE RELEASE) 9 | endif() 10 | 11 | set(CXX_FLAGS 12 | -g 13 | # -DVALGRIND 14 | -DCHECK_PTHREAD_RETURN_VALUE 15 | -D_FILE_OFFSET_BITS=64 16 | -Wall 17 | -Wextra 18 | -Werror 19 | -Wconversion 20 | -Wno-unused-parameter 21 | -Wold-style-cast 22 | -Woverloaded-virtual 23 | -Wpointer-arith 24 | -Wshadow 25 | -Wwrite-strings 26 | -march=native 27 | -std=c++0x 28 | -rdynamic 29 | ) 30 | if(CMAKE_BUILD_BITS EQUAL 32) 31 | list(APPEND CXX_FLAGS "-m32") 32 | endif() 33 | string(REPLACE ";" " " CMAKE_CXX_FLAGS "${CXX_FLAGS}") 34 | 35 | set(CMAKE_CXX_COMPILER "g++") 36 | set(CMAKE_CXX_FLAGS_DEBUG "-O0") 37 | set(CMAKE_CXX_FLAGS_RELEASE "-O2 -finline-limit=1000 -DNDEBUG") 38 | set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) 39 | set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) 40 | 41 | message("------------ Options -------------") 42 | message(" CMAKE_PROJECT: ${PROJECT_NAME}") 43 | message(" CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}") 44 | message(" CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") 45 | message(" CMAKE_BUILD_BITS: ${CMAKE_BUILD_BITS}") 46 | message(" CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") 47 | message(" EXECUTABLE_OUTPUT_PATH: ${EXECUTABLE_OUTPUT_PATH}") 48 | message(" LIBRARY_OUTPUT_PATH: ${LIBRARY_OUTPUT_PATH}") 49 | string(TOUPPER ${CMAKE_BUILD_TYPE} BUILD_TYPE) 50 | message(STATUS "CXX_FLAGS = " ${CMAKE_CXX_FLAGS} " " ${CMAKE_CXX_FLAGS_${BUILD_TYPE}}) 51 | 52 | find_package(CURL) 53 | if(CURL_FOUND) 54 | message(STATUS "found curl") 55 | endif() 56 | 57 | add_subdirectory(zlreactor) 58 | add_subdirectory(examples) 59 | add_subdirectory(tests) 60 | 61 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/ChangeLog -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 lizheng 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | CXXFLAGS = -Wall -Werror -g 2 | 3 | SUBDIRS = 4 | 5 | SUBDIRS += zlreactor 6 | 7 | if ZL_TEST_SUITES 8 | SUBDIRS += examples 9 | 10 | SUBDIRS += tests 11 | endif 12 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/NEWS -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/README -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ========== 2 | 3 | 学习C++,学习windows/linux编程,学习网络编程,学习reactor模型,自己实现一遍练手; 4 | 5 | 包含(以下实现是Windows/Linux平台通用的,美名其曰**跨平台**) 6 | 7 | * **基本工具库**: 8 | * 日志工具(日志优先级、同步日志、异步日志、带色彩的屏幕输出) 9 | * 模板单例类 10 | * 时间戳类 11 | * 计时器类 12 | * 日期类 13 | * 智能断言(静态断言、动态断言) 14 | * ScopeGuard RAII类 15 | * STL辅助工具 16 | * 字符串辅助工具 17 | * File类(本地文件读取、内存数据映像文件操作) 18 | * 文件及目录操作工具 19 | * 异常类及命名重整还原实现 20 | * 进程属性工具(Linux特有) 21 | * 多进程master-worker实现(Linux特有) 22 | * **线程库**: 23 | * 信号量 24 | * 锁(互斥、读写、独占、旋转) 25 | * 原子计数器 26 | * 同步waiter 27 | * (固定大小、不限大小)同步队列(先进先出、先进后出、按优先级出入) 28 | * TLS 29 | * 线程池(组) 30 | * **网络库**: 31 | * 网络相关工具 32 | * socket api的跨平台包装 33 | * socket RAII类 34 | * socket address类 35 | * EventLoop、EventLoopThreadPool 36 | * IO MultiPlexing(select\poll\epoll\iocp) 37 | * TimerQueue 38 | * TcpAcceptor、TcpConnector、TcpConnection、TcpServer 39 | * eventfd、signalfd、timerfd(Linux特有) 40 | * simple httpserver 41 | * **通用工具** 42 | * base64 编解码 43 | * md5 44 | * UUID 45 | * 字符串多种hash实现 46 | 47 | 48 | 感谢 49 | 50 | * [c++11](http://www.cplusplus.com/reference/) 51 | 52 | * [TinyThread++](http://tinythreadpp.bitsnbites.eu/) 53 | 54 | * [Muduo](https://github.com/chenshuo/muduo) 55 | 56 | * [libevent](http://libevent.org/) 57 | 58 | * [lighttpd](https://github.com/lizhenghn123/lighttpd1.4) 59 | 60 | * [redis](https://github.com/antirez/redis) 61 | 62 | * [Schmidt的三篇reactor文献] 63 | * [Reactor : An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events](http://www.cs.wustl.edu/~schmidt/PDF/reactor-siemens.pdf) 64 | * [The Reactor : An Object-Oriented Wrapper for Event-Driven Port Monitoring and Service Demultiplexing](https://www.dre.vanderbilt.edu/~schmidt/PDF/Reactor1-93.pdf) 65 | * [The Reactor 2 : The Design and Implementation of the Reactor An Object-Oriented Framework for Event Demultiplexing](https://www.dre.vanderbilt.edu/~schmidt/PDF/Reactor2-93.pdf) 66 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Add examples 2 | Add Benchmark 3 | Cancel log mutex(strace -T -r -c -p pid 发现日志输出时的锁调用过于频繁) 4 | 5 | -------------------------------------------------------------------------------- /autogen_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | case `uname` in 5 | Darwin) libtoolize=glibtoolize ;; 6 | *) libtoolize=libtoolize ;; 7 | esac 8 | 9 | INSTALL_DIR=$(cd "$(dirname "$0")"; pwd) 10 | 11 | #make distclean 12 | set -x 13 | $libtoolize --force --automake --copy 14 | aclocal -I build/acmacros 15 | automake --foreign --add-missing --copy 16 | autoconf 17 | CFLAGS=-m64 CXXFLAGS=-m64 LDFLAGS=-m64 ./configure --prefix=$INSTALL_DIR enable_test_suites=yes 18 | make 19 | make install 20 | -------------------------------------------------------------------------------- /bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | dos2unix config* INSTALL libtool ltmain.sh depcomp install-sh stamp-h1 4 | chmod +x config* INSTALL libtool ltmain.sh depcomp install-sh stamp-h1 5 | 6 | case `uname` in 7 | Darwin) libtoolize=glibtoolize ;; 8 | *) libtoolize=libtoolize ;; 9 | esac 10 | 11 | INSTALL_DIR=$(cd "$(dirname "$0")"; pwd) #将安装目录设置为当前脚本执行目录 12 | 13 | make distclean 14 | set -x 15 | $libtoolize --force --automake --copy 16 | aclocal -I build/acmacros 17 | automake --foreign --add-missing --copy 18 | autoconf 19 | CFLAGS=-m64 CXXFLAGS=-m64 LDFLAGS=-m64 ./configure --prefix=$INSTALL_DIR 20 | make 21 | make install 22 | -------------------------------------------------------------------------------- /docs/(Part 1 of 2)The Reactor An Object-Oriented Wrapper for Event-Driven Port Monitoring and Service Demultiplexing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/docs/(Part 1 of 2)The Reactor An Object-Oriented Wrapper for Event-Driven Port Monitoring and Service Demultiplexing.pdf -------------------------------------------------------------------------------- /docs/(Part 2 of 2)The Design and Implementation of the Reactor An Object-Oriented Framework for Event Demultiplexing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/docs/(Part 2 of 2)The Design and Implementation of the Reactor An Object-Oriented Framework for Event Demultiplexing.pdf -------------------------------------------------------------------------------- /docs/Comparing Two High-Performance I_O Design Patterns.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/docs/Comparing Two High-Performance I_O Design Patterns.pdf -------------------------------------------------------------------------------- /docs/Proactor : An Object Behavioral Pattern for Demultiplexing and Dispatching Handlers for Asynchronous Events.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/docs/Proactor : An Object Behavioral Pattern for Demultiplexing and Dispatching Handlers for Asynchronous Events.pdf -------------------------------------------------------------------------------- /docs/Proactor.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/docs/Proactor.pdf -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | * [Schmidt的几篇关于reactor和proactor的文献] 4 | * [Reactor : An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events](http://www.cs.wustl.edu/~schmidt/PDF/reactor-siemens.pdf) 5 | * [The Reactor 1: An Object-Oriented Wrapper for Event-Driven Port Monitoring and Service Demultiplexing](https://www.dre.vanderbilt.edu/~schmidt/PDF/Reactor1-93.pdf) 6 | * [The Reactor 2 : The Design and Implementation of the Reactor An Object-Oriented Framework for Event Demultiplexing](https://www.dre.vanderbilt.edu/~schmidt/PDF/Reactor2-93.pdf) 7 | * [Proactor : An Object Behavioral Pattern for Demultiplexing and Dispatching Handlers for Asynchronous Events](http://www.cs.wustl.edu/~schmidt/PDF/proactor.pdf) 8 | * [Proactor 1999](http://www.laputan.org/pub/sag/proactor.pdf) -------------------------------------------------------------------------------- /docs/Reactor : An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/docs/Reactor : An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events.pdf -------------------------------------------------------------------------------- /docs/Scalable IO in Java(DougLea).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/docs/Scalable IO in Java(DougLea).pdf -------------------------------------------------------------------------------- /docs/proactor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/docs/proactor.png -------------------------------------------------------------------------------- /dos2unix.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | makes=`find ./ -name "*.am" -type f` 4 | header=`find ./ -name "*.h" -type f` 5 | source=`find ./ -name "*.cpp" -type f` 6 | 7 | for file in $makes 8 | do 9 | dos2unix $file 10 | done 11 | 12 | for file in $header 13 | do 14 | dos2unix $file 15 | done 16 | 17 | for file in $source 18 | do 19 | dos2unix $file 20 | done 21 | 22 | echo "######### Done! #########" 23 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${PROJECT_SOURCE_DIR}) 2 | 3 | set(CMAKE_CXX_FLAGS "-std=c++0x -Wall -pthread -lrt") 4 | 5 | link_directories(${CMAKE_INSTALL_PREFIX}/lib/ 6 | ${PROJECT_SOURCE_DIR}/lib/ 7 | ${PROJECT_BINARY_DIR}/lib/ 8 | ) 9 | 10 | add_executable(reader_writer reader_writer/reader_writer.cpp) 11 | target_link_libraries(reader_writer zlreactor) 12 | 13 | add_executable(simpleServers simpleServers/simpleServers.cpp) 14 | target_link_libraries(simpleServers zlreactor) 15 | 16 | add_executable(roundtriptime roundtriptime/RoundTripTime.cpp) 17 | target_link_libraries(roundtriptime zlreactor) 18 | 19 | add_executable(twisted_finger twisted_finger/twisted_finger.cpp) 20 | target_link_libraries(twisted_finger zlreactor) 21 | 22 | add_executable(test_httpserver test_httpserver/test_httpserver.cpp) 23 | target_link_libraries(test_httpserver zlreactor) 24 | 25 | add_executable(maxconnection maxconnection/MaxConnection.cpp) 26 | target_link_libraries(maxconnection zlreactor) 27 | 28 | add_executable(idleconnection idleconnection/idleconnection.cpp) 29 | target_link_libraries(idleconnection zlreactor) 30 | 31 | add_executable(echo_test echo/main.cpp echo/EchoServer.cpp echo/EchoClient.cpp) 32 | target_link_libraries(echo_test zlreactor) 33 | 34 | add_executable(thread_bench thread_bench/thread_bench.cpp) 35 | target_link_libraries(thread_bench zlreactor) 36 | 37 | add_executable(test_websocketserver test_websocketserver/test_websocketserver.cpp) 38 | target_link_libraries(test_websocketserver zlreactor) 39 | -------------------------------------------------------------------------------- /examples/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = Makefile.in 2 | 3 | SUBDIRS = 4 | 5 | SUBDIRS += reader_writer 6 | 7 | SUBDIRS += simpleServers 8 | 9 | SUBDIRS += roundtriptime 10 | 11 | SUBDIRS += twisted_finger 12 | 13 | SUBDIRS += test_httpserver 14 | 15 | SUBDIRS += maxconnection 16 | 17 | SUBDIRS += idleconnection 18 | 19 | SUBDIRS += echo 20 | 21 | SUBDIRS += thread_bench 22 | 23 | SUBDIRS += test_websocketserver 24 | 25 | SUBDIRS += test_websocketclient 26 | -------------------------------------------------------------------------------- /examples/echo/EchoClient.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | File Name : EchoClient.cpp 3 | Author : LIZHENG 4 | Mail : lizhenghn@gmail.com 5 | Created Time: 2015年05月12日 星期二 20时19分55秒 6 | ************************************************************************/ 7 | #include "EchoClient.h" 8 | #include "zlreactor/net/TcpClient.h" 9 | #include "zlreactor/net/EventLoop.h" 10 | #include "zlreactor/net/InetAddress.h" 11 | #include "zlreactor/net/ByteBuffer.h" 12 | #include "zlreactor/net/TcpConnection.h" 13 | #include "zlreactor/base/Timestamp.h" 14 | #include "zlreactor/base/Logger.h" 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | using namespace zl; 20 | using namespace zl::base; 21 | using namespace zl::net; 22 | 23 | 24 | EchoClient::EchoClient(EventLoop *loop, const InetAddress& serverAddr, const std::string& name/* = "EchoClient"*/) 25 | : loop_(loop) 26 | { 27 | client_ = new TcpClient(loop, serverAddr, name); 28 | client_->setConnectionCallback(std::bind(&EchoClient::onConnection, this, std::placeholders::_1)); 29 | client_->setMessageCallback(std::bind(&EchoClient::onMessage, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); 30 | } 31 | 32 | EchoClient::~EchoClient() 33 | { 34 | delete client_; 35 | } 36 | 37 | void EchoClient::connect() 38 | { 39 | client_->enableRetry(); 40 | client_->connect(); 41 | running_ = true; 42 | } 43 | 44 | int EchoClient::fd() const 45 | { 46 | return client_->fd(); 47 | } 48 | 49 | void EchoClient::stop() 50 | { 51 | running_ = false; 52 | } 53 | 54 | void EchoClient::onConnection(const TcpConnectionPtr& conn) 55 | { 56 | LOG_INFO("%s <-> %s is %s", conn->peerAddress().ipPort().c_str(), conn->localAddress().ipPort().c_str(), (conn->connected() ? "UP" : "DOWN")); 57 | 58 | if (conn->connected()) 59 | { 60 | conn->send("hello world\n"); 61 | } 62 | else 63 | { 64 | conn->shutdown(); 65 | } 66 | } 67 | 68 | void EchoClient::onMessage(const TcpConnectionPtr& conn, ByteBuffer *buf, const Timestamp& time) 69 | { 70 | string msg(buf->retrieveAllAsString()); 71 | LOG_INFO("[%d] recv %d bytes[%s]", conn->fd(), msg.size(), msg.c_str()); 72 | 73 | if (running_ == false) 74 | { 75 | conn->send("bye\n"); 76 | } 77 | else if (msg == "ok\n") 78 | { 79 | conn->shutdown(); 80 | } 81 | else 82 | { 83 | conn->send(msg); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /examples/echo/EchoClient.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | File Name : EchoClient.h 3 | Author : LIZHENG 4 | Mail : lizhenghn@gmail.com 5 | Created Time: 2015年05月12日 星期二 20时19分49秒 6 | ************************************************************************/ 7 | #include 8 | #include "zlreactor/net/CallBacks.h" 9 | namespace zl 10 | { 11 | namespace base 12 | { 13 | class Timestamp; 14 | } 15 | namespace net 16 | { 17 | class EventLoop; 18 | class InetAddress; 19 | class TcpClient; 20 | class Channel; 21 | class Socket; 22 | class ByteBuffer; 23 | } 24 | } 25 | using namespace zl; 26 | using namespace zl::net; 27 | 28 | class EchoClient 29 | { 30 | public: 31 | EchoClient(EventLoop *loop, const InetAddress& serverAddr, const std::string& name = "EchoClient"); 32 | ~EchoClient(); 33 | 34 | int fd() const; 35 | 36 | void connect(); 37 | void stop(); 38 | 39 | private: 40 | void onConnection(const TcpConnectionPtr& conn); 41 | void onMessage(const TcpConnectionPtr& conn, ByteBuffer *buf, const Timestamp& time); 42 | 43 | private: 44 | EventLoop *loop_; 45 | TcpClient *client_; 46 | bool running_; // unsafe, use atomic 47 | }; 48 | -------------------------------------------------------------------------------- /examples/echo/EchoServer.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | File Name : EchoServer.h 3 | Author : LIZHENG 4 | Mail : lizhenghn@gmail.com 5 | Created Time: 2015年05月12日 星期二 19时43分29秒 6 | ************************************************************************/ 7 | #ifndef ZL_ECHOSERVER_H 8 | #define ZL_ECHOSERVER_H 9 | #include "zlreactor/net/CallBacks.h" 10 | namespace zl 11 | { 12 | namespace base 13 | { 14 | class Timestamp; 15 | } 16 | namespace net 17 | { 18 | class EventLoop; 19 | class InetAddress; 20 | class TcpServer; 21 | class Channel; 22 | class Socket; 23 | class ByteBuffer; 24 | } 25 | } 26 | 27 | using zl::net::EventLoop; 28 | using zl::net::InetAddress; 29 | using zl::net::TcpServer; 30 | using zl::net::Channel; 31 | using zl::net::Socket; 32 | using zl::net::ByteBuffer; 33 | 34 | using namespace zl; 35 | using namespace zl::net; 36 | 37 | class EchoServer 38 | { 39 | public: 40 | EchoServer(EventLoop *loop, const InetAddress& listenAddr, int numReactors = 0); 41 | ~EchoServer(); 42 | 43 | void start(); 44 | 45 | private: 46 | void onConnection(const TcpConnectionPtr& conn); 47 | void onMessage(const TcpConnectionPtr& conn, ByteBuffer *buf, const Timestamp& time); 48 | 49 | private: 50 | EventLoop *loop_; 51 | TcpServer *server_; 52 | }; 53 | 54 | #endif /* ZL_ECHOSERVER_H */ 55 | -------------------------------------------------------------------------------- /examples/echo/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = echo_test 4 | 5 | INCLUDES = -I../../zlreactor 6 | CPPFLAGS = -std=c++0x 7 | LDFLAGS = -L../../lib -lzlreactor 8 | 9 | #echoserver_test_CPPFLAGS = $(CPPFLAGS) 10 | #echoserver_test_LDFLAGS = $(CPPFLAGS) 11 | #echoserver_test_SOURCES = main.cpp EchoServer.cpp EchoClient.cpp 12 | #echoclient_test_SOURCES = main.cpp EchoServer.cpp EchoClient.cpp 13 | 14 | echo_test_SOURCES = main.cpp EchoServer.cpp EchoClient.cpp -------------------------------------------------------------------------------- /examples/idleconnection/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = idleconnection 4 | 5 | INCLUDES = -I../../zlreactor 6 | 7 | idleconnection_CPPFLAGS = -std=c++0x 8 | idleconnection_LDFLAGS = -L../../lib -lzlreactor 9 | 10 | idleconnection_SOURCES = idleconnection.cpp 11 | -------------------------------------------------------------------------------- /examples/maxconnection/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = maxconnection 4 | 5 | INCLUDES = -I../../zlreactor 6 | 7 | maxconnection_CPPFLAGS = -std=c++0x 8 | maxconnection_LDFLAGS = -L../../lib -lzlreactor 9 | 10 | maxconnection_SOURCES = MaxConnection.cpp 11 | -------------------------------------------------------------------------------- /examples/reader_writer/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = reader_writer 4 | 5 | INCLUDES = -I../../zlreactor 6 | 7 | reader_writer_CPPFLAGS = -std=c++0x 8 | reader_writer_LDFLAGS = -L../../lib -lzlreactor 9 | 10 | reader_writer_SOURCES = reader_writer.cpp 11 | -------------------------------------------------------------------------------- /examples/roundtriptime/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = RTT 4 | 5 | INCLUDES = -I../../zlreactor 6 | 7 | RTT_CPPFLAGS = -std=c++0x 8 | RTT_LDFLAGS = -L../../lib -lzlreactor 9 | 10 | RTT_SOURCES = RoundTripTime.cpp 11 | -------------------------------------------------------------------------------- /examples/simpleServers/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = simpleServers 4 | 5 | INCLUDES = -I../../zlreactor 6 | 7 | simpleServers_CPPFLAGS = -std=c++0x 8 | simpleServers_LDFLAGS = -L../../lib -lzlreactor 9 | 10 | simpleServers_SOURCES = simpleServers.cpp 11 | -------------------------------------------------------------------------------- /examples/test_httpserver/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = httpserver 4 | 5 | INCLUDES = -I../../zlreactor 6 | 7 | httpserver_CPPFLAGS = -std=c++0x -O2 8 | httpserver_LDFLAGS = -O2 -L../../lib -lzlreactor 9 | 10 | httpserver_SOURCES = test_httpserver.cpp 11 | -------------------------------------------------------------------------------- /examples/test_websocketclient/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = websocketclient 4 | 5 | INCLUDES = -I../../zlreactor 6 | 7 | websocketclient_CPPFLAGS = -std=c++0x -O2 8 | websocketclient_LDFLAGS = -O2 -L../../lib -lzlreactor 9 | 10 | websocketclient_SOURCES = test_websocketclient.cpp 11 | -------------------------------------------------------------------------------- /examples/test_websocketserver/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = websocketserver 4 | 5 | INCLUDES = -I../../zlreactor 6 | 7 | websocketserver_CPPFLAGS = -std=c++0x -O2 8 | websocketserver_LDFLAGS = -O2 -L../../lib -lzlreactor 9 | 10 | websocketserver_SOURCES = test_websocketserver.cpp 11 | -------------------------------------------------------------------------------- /examples/test_websocketserver/test_websocketserver.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "zlreactor/net/websocket/WebSocketServer.h" 4 | #include "zlreactor/net/EventLoop.h" 5 | #include "zlreactor/net/TcpConnection.h" 6 | #include "zlreactor/base/FileUtil.h" 7 | #include "zlreactor/base/Logger.h" 8 | using namespace std; 9 | using namespace zl::net; 10 | using namespace zl::net::ws; 11 | 12 | class EchoWebServer 13 | { 14 | public: 15 | EchoWebServer(EventLoop *loop, const InetAddress& listenAddr) 16 | : server_(loop, listenAddr, "EchoWebServer") 17 | { 18 | server_.setOnOpen(std::bind(&EchoWebServer::onopen, this, std::placeholders::_1)); 19 | server_.setOnClose(std::bind(&EchoWebServer::onclose, this, std::placeholders::_1)); 20 | server_.setOnMessage(std::bind(&EchoWebServer::onmessage, this, std::placeholders::_1, 21 | std::placeholders::_2, std::placeholders::_3)); 22 | } 23 | 24 | void start() 25 | { 26 | server_.start(); 27 | } 28 | 29 | private: 30 | void onopen(const TcpConnectionPtr& conn) 31 | { 32 | assert(conn->connected()); 33 | cout << "EchoWebServer " << conn->fd() << " connected\n"; 34 | } 35 | 36 | void onclose(const TcpConnectionPtr& conn) 37 | { 38 | cout << "EchoWebServer " << conn->fd() << " disconnected\n"; 39 | } 40 | 41 | void onmessage(const TcpConnectionPtr& conn, const std::vector& buf, Timestamp) 42 | { 43 | cout << "EchoWebServer onmessage : " << buf.data() << "\n"; 44 | //WsConnection *wsconn = zl::stl::any_cast(conn->getMutableContext()); 45 | //server->sendText(buf.data(), buf.size()); 46 | server_.send(conn, buf.data(), buf.size()); 47 | } 48 | 49 | private: 50 | zl::net::ws::WsServer server_; 51 | }; 52 | 53 | 54 | int main() 55 | { 56 | LOG_SET_DEBUG_MODE; 57 | 58 | EventLoop loop; 59 | EchoWebServer server(&loop, InetAddress("0.0.0.0", 8888)); 60 | 61 | server.start(); 62 | loop.loop(); 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /examples/thread_bench/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = thread_bench 4 | 5 | INCLUDES = -I../../zlreactor 6 | 7 | thread_bench_CPPFLAGS = -std=c++0x 8 | thread_bench_LDFLAGS = -L../../lib -lzlreactor 9 | 10 | thread_bench_SOURCES = thread_bench.cpp 11 | -------------------------------------------------------------------------------- /examples/thread_bench/thread_bench.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | File Name : thread_bench.cpp 3 | Author : LIZHENG 4 | Mail : lizhenghn@gmail.com 5 | Created Time: 2015年05月26日 星期二 20时24分29秒 6 | ************************************************************************/ 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "zlreactor/thread/Thread.h" 13 | #include "zlreactor/base/Timestamp.h" 14 | using namespace zl; 15 | using namespace zl::base; 16 | using namespace zl::thread; 17 | using namespace std; 18 | 19 | // 事实证明: 线程的创建速度还是远远快于进程的创建速度 20 | // see https://computing.llnl.gov/tutorials/pthreads/#WhyPthreads 21 | // see https://computing.llnl.gov/tutorials/pthreads/fork_vs_thread.txt 22 | void threadFunc() 23 | { 24 | //printf("this thread : %d\n", this_thread::get_id().tid()); 25 | } 26 | 27 | void thread_bench(int thread_num) 28 | { 29 | Timestamp start = Timestamp::now(); 30 | for(int i = 0; i < thread_num; ++i) 31 | { 32 | Thread trd(threadFunc); 33 | trd.join(); 34 | //trd.detach(); 35 | } 36 | Timestamp end = Timestamp::now(); 37 | printf("create %d threads costs %f s\n", thread_num, Timestamp::timeDiff(end, start)); 38 | } 39 | 40 | void process_bench(int process_num) 41 | { 42 | Timestamp start = Timestamp::now(); 43 | for(int i = 0; i < process_num; ++i) 44 | { 45 | pid_t p = ::fork(); 46 | if(p == 0) // child 47 | { 48 | exit(0); 49 | } 50 | else 51 | { 52 | ::waitpid(p, NULL, 0); 53 | } 54 | } 55 | Timestamp end = Timestamp::now(); 56 | printf("create %d process costs %f s\n", process_num, Timestamp::timeDiff(end, start)); 57 | 58 | } 59 | 60 | int main(int argc, char *argv[]) 61 | { 62 | printf("usage: \n %s\n %s \n", argv[0], argv[0]); 63 | 64 | int max_thread_num = 1000; 65 | if(argc > 1) 66 | { 67 | max_thread_num = atoi(argv[1]); 68 | } 69 | 70 | printf("###### thread ######\n"); 71 | thread_bench(max_thread_num); 72 | 73 | printf("###### process ######\n"); 74 | process_bench(max_thread_num); 75 | 76 | printf("###### GAME OVER ######"); 77 | } 78 | -------------------------------------------------------------------------------- /examples/twisted_finger/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = twisted_finger 4 | 5 | INCLUDES = -I../../zlreactor 6 | 7 | twisted_finger_CPPFLAGS = -std=c++0x 8 | twisted_finger_LDFLAGS = -L../../lib -lzlreactor 9 | 10 | twisted_finger_SOURCES = twisted_finger.cpp 11 | -------------------------------------------------------------------------------- /sln/zl_reactor.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libzlreactor", "libzlreactor\libzlreactor.vcxproj", "{83CD406D-277D-4C9E-B1AD-07C42D36AD40}" 5 | EndProject 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{47C97639-6D83-4E94-88B7-A00BDC989246}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test_httpserver", "test_httpserver", "{35B3B23D-BE2F-4796-952E-EC0A6D989B5D}" 9 | ProjectSection(SolutionItems) = preProject 10 | ..\examples\test_httpserver\test_httpserver.cpp = ..\examples\test_httpserver\test_httpserver.cpp 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|Win32 = Debug|Win32 16 | Release|Win32 = Release|Win32 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {83CD406D-277D-4C9E-B1AD-07C42D36AD40}.Debug|Win32.ActiveCfg = Debug|Win32 20 | {83CD406D-277D-4C9E-B1AD-07C42D36AD40}.Debug|Win32.Build.0 = Debug|Win32 21 | {83CD406D-277D-4C9E-B1AD-07C42D36AD40}.Release|Win32.ActiveCfg = Release|Win32 22 | {83CD406D-277D-4C9E-B1AD-07C42D36AD40}.Release|Win32.Build.0 = Release|Win32 23 | EndGlobalSection 24 | GlobalSection(SolutionProperties) = preSolution 25 | HideSolutionNode = FALSE 26 | EndGlobalSection 27 | GlobalSection(NestedProjects) = preSolution 28 | {35B3B23D-BE2F-4796-952E-EC0A6D989B5D} = {47C97639-6D83-4E94-88B7-A00BDC989246} 29 | EndGlobalSection 30 | EndGlobal 31 | -------------------------------------------------------------------------------- /stamp-h1: -------------------------------------------------------------------------------- 1 | timestamp for Config.h 2 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${PROJECT_SOURCE_DIR}) 2 | 3 | set(CMAKE_CXX_FLAGS "-std=c++0x -Wall -pthread -lrt") 4 | 5 | link_directories(${CMAKE_INSTALL_PREFIX}/lib/ 6 | ${PROJECT_SOURCE_DIR}/lib/ 7 | ${PROJECT_BINARY_DIR}/lib/ 8 | ) 9 | 10 | add_executable(universal_timer universal_timer/TriggerTimerTest.cpp universal_timer/TriggerTimer.cpp) 11 | target_link_libraries(universal_timer zlreactor) 12 | 13 | add_executable(stress_client stress_client/stress_client.cpp) 14 | target_link_libraries(stress_client zlreactor) 15 | 16 | add_executable(timerqueue timerqueue/Timer_Test.cpp timerqueue/TimerQueue.cpp timerqueue/Timer.cpp) 17 | target_link_libraries(timerqueue zlreactor) 18 | 19 | add_executable(epoll_echoclient epoll_echoclient/EchoClientTest.cpp epoll_echoclient/EchoClient.cpp epoll_echoclient/EpollPoller.cpp) 20 | target_link_libraries(epoll_echoclient) 21 | 22 | add_executable(epoll_echoserver epoll_echoserver/EchoServerTest.cpp 23 | epoll_echoserver/EchoServer.cpp epoll_echoserver/EpollPoller.cpp) 24 | target_link_libraries(epoll_echoserver) 25 | 26 | add_executable(signal_handler signal_handler/signal_handler.cpp) 27 | target_link_libraries(signal_handler) 28 | 29 | add_executable(tcpselfconnect1 tcpselfconnect1/tcpselfconnect1.cpp) 30 | target_link_libraries(tcpselfconnect1) 31 | 32 | add_executable(tcpselfconnect2 tcpselfconnect2/tcpselfconnect2.cpp) 33 | target_link_libraries(tcpselfconnect2) 34 | 35 | add_executable(pipePairTest PipePairFactory/pipePairTest.cpp) 36 | target_link_libraries(pipePairTest zlreactor) 37 | 38 | add_executable(master_worker_process master_worker_process/master_worker_process.cpp) 39 | target_link_libraries(master_worker_process zlreactor) 40 | 41 | add_executable(socketAcceptThunderingHerd socketAcceptThunderingHerd/socketAcceptThunderingHerd.cpp) 42 | target_link_libraries(socketAcceptThunderingHerd zlreactor) 43 | 44 | add_executable(bind_tcp_udp bind_tcp_udp/bind_tcp_udp.cpp) 45 | target_link_libraries(bind_tcp_udp) 46 | 47 | add_executable(backtrace_test backtrace_test/backtrace_test.cpp) 48 | target_link_libraries(backtrace_test) 49 | 50 | add_executable(ProxyServerByFork proxy_server/ProxyServerByFork.cpp) 51 | target_link_libraries(ProxyServerByFork) 52 | 53 | add_executable(ProxyServerByEpoll proxy_server/ProxyServerByEpoll.cpp) 54 | target_link_libraries(ProxyServerByEpoll) 55 | 56 | add_executable(server_aio server_aio/server_aio.cpp) 57 | target_link_libraries(server_aio) 58 | 59 | add_executable(pingpong_server pingpong/pingpong_server.cpp) 60 | target_link_libraries(pingpong_server zlreactor) 61 | 62 | add_executable(pingpong_client pingpong/pingpong_client.cpp) 63 | target_link_libraries(pingpong_client zlreactor) -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = Makefile.in 2 | 3 | SUBDIRS = 4 | 5 | SUBDIRS += universal_timer 6 | 7 | SUBDIRS += stress_client 8 | 9 | SUBDIRS += timerqueue 10 | 11 | SUBDIRS += epoll_echoclient 12 | 13 | SUBDIRS += epoll_echoserver 14 | 15 | SUBDIRS += signal_handler 16 | 17 | SUBDIRS += tcpselfconnect1 18 | 19 | SUBDIRS += tcpselfconnect2 20 | 21 | SUBDIRS += PipePairFactory 22 | 23 | SUBDIRS += master_worker_process 24 | 25 | SUBDIRS += socketAcceptThunderingHerd 26 | 27 | SUBDIRS += bind_tcp_udp 28 | 29 | SUBDIRS += backtrace_test 30 | 31 | SUBDIRS += server_aio 32 | 33 | SUBDIRS += proxy_server 34 | 35 | SUBDIRS += pingpong 36 | 37 | -------------------------------------------------------------------------------- /tests/PipePairFactory/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = pipePairTest 4 | 5 | INCLUDES = -I../../zlreactor 6 | 7 | pipePairTest_CPPFLAGS = -std=c++0x 8 | pipePairTest_LDFLAGS = -L../../lib -lzlreactor 9 | 10 | pipePairTest_SOURCES = pipePairTest.cpp -------------------------------------------------------------------------------- /tests/backtrace_test/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = backtrace_test 4 | 5 | #backtrace_test_CFLAGS = -g -O0 6 | backtrace_test_CPPFLAGS = -g -O0 7 | backtrace_test_LDFLAGS = -rdynamic 8 | 9 | backtrace_test_SOURCES = backtrace_test.cpp 10 | -------------------------------------------------------------------------------- /tests/backtrace_test/makefile_alone: -------------------------------------------------------------------------------- 1 | CC=g++ 2 | CFLAGS=-g -O0 3 | LDFLAGS=-rdynamic 4 | 5 | backtrace_test:backtrace_test.o 6 | $(CC) $(LDFLAGS) -o $@ $^ 7 | 8 | %.o:%.cpp 9 | $(CC) $(CFLAGS) -c -o $@ $^ 10 | 11 | clean: 12 | rm -f backtrace_test *.o 13 | -------------------------------------------------------------------------------- /tests/bind_tcp_udp/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = bind_tcp_udp 4 | 5 | #INCLUDES = -I../../zlreactor 6 | 7 | bind_tcp_udp_SOURCES = bind_tcp_udp.cpp 8 | -------------------------------------------------------------------------------- /tests/c1000k/.gitignore: -------------------------------------------------------------------------------- 1 | server 2 | client 3 | 4 | -------------------------------------------------------------------------------- /tests/c1000k/Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: 3 | gcc -O2 -o server server.c 4 | gcc -O2 -o client client.c 5 | 6 | -------------------------------------------------------------------------------- /tests/c1000k/README.md: -------------------------------------------------------------------------------- 1 | https://github.com/ideawu/c1000k 2 | This is the TCP server-client suit to help you test if your OS supports c1000k(1 million connections). 3 | 4 | ## Usage 5 | 6 | ### Download and compile 7 | 8 | wget --no-check-certificate https://github.com/ideawu/c1000k/archive/master.zip 9 | unzip master.zip 10 | cd c1000k-master 11 | make 12 | 13 | ### start the server, listen on port 7000~7099 14 | 15 | ./server 7000 16 | 17 | ### run the client 18 | 19 | ./client 127.0.0.1 7000 20 | 21 | The server will ouput message like this and quit: 22 | 23 | connections: 153 24 | error: Too many open files 25 | 26 | It says the server can only accept 153 connections, it reaches the max-open-files limitation so it quit. 27 | 28 | The client will output message like this: 29 | 30 | connections: 154 31 | error: Connection refused 32 | 33 | 34 | ######## http://idning.github.io/icomet-cr.html 35 | ideawu 提供了一个 c1000k 代码: https://github.com/ideawu/c1000k 36 | 37 | 要测试c1000k 主要两个问题: 38 | 39 | 是server 端, 每个sokcet 大约需要占用0.5M内存(内核sokcet缓冲区内存), 所以总共需要500G内存. 40 | client端, client 只能开大约3w-5w个client端口(对每个server ip+port, 只能有3w-5w连接) 41 | ideawu是这样解决的: 1. server 端每accept一个连接, 都设置它的缓冲区大小为5k: 42 | 43 | bufsize = 5000; 44 | setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)); 45 | setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)); 46 | 47 | 这样1000k连接只需要10G内存. 48 | server 端开100个port, 这样每个客户端3w端口, 就可以开300w个连接. 49 | 50 | 这时候, 限制就只有fd个数限制了. 51 | 52 | 我启动的时候设置好limit就可以 53 | 54 | $ ulimit -n 1024000 55 | $ ./server 6000 56 | $ ulimit -n 1024000 57 | $ ./client 127.0.0.1 6000 58 | 59 | 可以一直跑到: 60 | connections: 1023897 61 | error: Too many open files 62 | -------------------------------------------------------------------------------- /tests/c1000k/client.c: -------------------------------------------------------------------------------- 1 | /***************************************************** 2 | * The TCP socket client to help you to test if your 3 | * OS supports c1000k(1 million connections). 4 | * @author: ideawu 5 | * @link: http://www.ideawu.com/ 6 | *****************************************************/ 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define MAX_PORTS 100 16 | 17 | int main(int argc, char **argv){ 18 | if(argc <= 2){ 19 | printf("Usage: %s ip port\n", argv[0]); 20 | exit(0); 21 | } 22 | 23 | struct sockaddr_in addr; 24 | const char *ip = argv[1]; 25 | int base_port = atoi(argv[2]); 26 | int opt = 1; 27 | int bufsize; 28 | socklen_t optlen; 29 | int connections = 0; 30 | 31 | bzero(&addr, sizeof(addr)); 32 | addr.sin_family = AF_INET; 33 | inet_pton(AF_INET, ip, &addr.sin_addr); 34 | 35 | char tmp_data[10]; 36 | int index = 0; 37 | while(1){ 38 | if(++index >= MAX_PORTS){ 39 | index = 0; 40 | } 41 | int port = base_port + index; 42 | //printf("connect to %s:%d\n", ip, port); 43 | 44 | addr.sin_port = htons((short)port); 45 | 46 | int sock; 47 | if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1){ 48 | goto sock_err; 49 | } 50 | if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1){ 51 | goto sock_err; 52 | } 53 | 54 | connections ++; 55 | 56 | if(connections % 1000 == 999){ 57 | //printf("press Enter to continue: "); 58 | //getchar(); 59 | printf("connections: %d, fd: %d\n", connections, sock); 60 | } 61 | usleep(1 * 1000); 62 | 63 | bufsize = 5000; 64 | setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)); 65 | setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)); 66 | } 67 | 68 | return 0; 69 | sock_err: 70 | printf("connections: %d\n", connections); 71 | printf("error: %s\n", strerror(errno)); 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /tests/epoll_echoclient/EchoClient.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/tests/epoll_echoclient/EchoClient.h -------------------------------------------------------------------------------- /tests/epoll_echoclient/EchoClientTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "EchoClient.h" 5 | 6 | EchoClient *pollclient = NULL; 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | if (argc != 4) 11 | { 12 | printf("usage : [%s] serverip serverport max_client_sockets; example: [%s] 127.0.0.1 5000 1000 \n", argv[0], argv[0]); 13 | return 0; 14 | } 15 | 16 | pollclient = new EchoClient(argv[1], atoi(argv[2]), atoi(argv[3])); 17 | pollclient->start(); 18 | 19 | pollclient->runLoop(); 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /tests/epoll_echoclient/EpollPoller.cpp: -------------------------------------------------------------------------------- 1 | #include "EpollPoller.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | EpollPoller::EpollPoller(bool one_shot/* = false*/, int maxevents/* = 4096*/) 8 | { 9 | one_shot_ = one_shot; 10 | maxEvnets_ = maxevents; 11 | epollFd_ = ::epoll_create(maxevents); 12 | events_ = new epoll_event[maxevents]; 13 | assert(epollFd_ > 0); 14 | assert(events_); 15 | } 16 | 17 | EpollPoller::~EpollPoller() 18 | { 19 | ::close(epollFd_); 20 | delete[] events_; 21 | } 22 | 23 | 24 | int EpollPoller::add(int fd) 25 | { 26 | struct epoll_event ev = { 0, { 0 } }; 27 | ev.data.fd = fd; 28 | ev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP/* | EPOLLET*/; 29 | if (one_shot_) 30 | ev.events |= EPOLLONESHOT; 31 | return ::epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &ev); 32 | } 33 | 34 | int EpollPoller::mod(int fd, bool write/* = true*/, bool read/* = false*/) 35 | { 36 | struct epoll_event ev = { 0, { 0 } }; 37 | ev.data.fd = fd; 38 | ev.events = EPOLLRDHUP | EPOLLERR | EPOLLHUP; 39 | if (one_shot_) 40 | ev.events |= EPOLLONESHOT; 41 | if (write) 42 | ev.events |= EPOLLOUT; 43 | if (read) 44 | ev.events |= EPOLLIN; 45 | 46 | return ::epoll_ctl(epollFd_, EPOLL_CTL_MOD, fd, &ev); 47 | } 48 | 49 | int EpollPoller::del(int fd) 50 | { 51 | struct epoll_event ev = { 0, { 0 } }; 52 | ev.data.fd = fd; 53 | return ::epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, &ev); 54 | } 55 | 56 | int EpollPoller::poll(int timeoutMs) 57 | { 58 | //nextEventIdx_ = 0; 59 | return ::epoll_wait(epollFd_, events_, maxEvnets_, timeoutMs); 60 | } 61 | -------------------------------------------------------------------------------- /tests/epoll_echoclient/EpollPoller.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | struct epoll_event; 4 | 5 | class EpollPoller 6 | { 7 | public: 8 | explicit EpollPoller(bool one_shot = false, int maxevents = 4096); 9 | ~EpollPoller(); 10 | 11 | public: 12 | int add(int fd); 13 | int mod(int fd, bool write = true, bool read = false); 14 | int del(int fd); 15 | 16 | int poll(int timeoutMs); 17 | 18 | const epoll_event* events() const 19 | { 20 | return events_; 21 | } 22 | 23 | const epoll_event& nextEvent(int idx) 24 | { 25 | return events_[idx]; 26 | } 27 | //const epoll_event& operator[](int index) 28 | //{ 29 | // return events_[index]; 30 | //} 31 | //int nextFd() 32 | //{ 33 | // return events_[nextEventIdx_++].data.fd; 34 | //} 35 | 36 | private: 37 | bool one_shot_; 38 | int epollFd_; 39 | int maxEvnets_; 40 | //int nextEventIdx_; 41 | epoll_event* events_; 42 | }; -------------------------------------------------------------------------------- /tests/epoll_echoclient/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = epoll_echoclient 4 | 5 | epoll_echoclient_SOURCES = EchoClientTest.cpp EchoClient.cpp EpollPoller.cpp 6 | -------------------------------------------------------------------------------- /tests/epoll_echoserver/EchoServer.h: -------------------------------------------------------------------------------- 1 | #ifndef ZL_ECHOSERVER_H 2 | #define ZL_ECHOSERVER_H 3 | #include 4 | class EpollPoller; 5 | 6 | class EchoServer 7 | { 8 | public: 9 | EchoServer(const char *serverIP, int serverPort); 10 | 11 | ~EchoServer(); 12 | 13 | void runLoop(); 14 | 15 | private: 16 | bool initServer(); 17 | void setNonBlock(int sock); 18 | 19 | static void listenThread(void *args); 20 | 21 | private: 22 | int srvSocket_; 23 | char srvIP_[64]; 24 | short srvPort_; 25 | pthread_t listenThread_; 26 | EpollPoller* epoller_; 27 | }; 28 | 29 | #endif /* ZL_ECHOSERVER_H */ -------------------------------------------------------------------------------- /tests/epoll_echoserver/EchoServerTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "EchoServer.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | EchoServer *server; 8 | 9 | if(argc != 3) 10 | { 11 | printf("usage : [%s] serverip serverport; example: [%s] 127.0.0.1 5000\n", argv[0], argv[0]); 12 | printf("now use default settings : 127.0.0.1:8888\n"); 13 | server = new EchoServer("127.0.0.1", 8888); 14 | } 15 | else 16 | { 17 | server = new EchoServer(argv[1], atoi(argv[2])); 18 | } 19 | 20 | server->runLoop(); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /tests/epoll_echoserver/EpollPoller.cpp: -------------------------------------------------------------------------------- 1 | #include "EpollPoller.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | EpollPoller::EpollPoller(bool one_shot/* = false*/, int maxevents/* = 4096*/) 8 | { 9 | one_shot_ = one_shot; 10 | maxEvnets_ = maxevents; 11 | epollFd_ = ::epoll_create(maxevents); 12 | events_ = new epoll_event[maxevents]; 13 | assert(epollFd_ > 0); 14 | assert(events_); 15 | } 16 | 17 | EpollPoller::~EpollPoller() 18 | { 19 | ::close(epollFd_); 20 | delete[] events_; 21 | } 22 | 23 | 24 | int EpollPoller::add(int fd) 25 | { 26 | struct epoll_event ev = { 0, { 0 } }; 27 | ev.data.fd = fd; 28 | ev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP/* | EPOLLET*/; 29 | if (one_shot_) 30 | ev.events |= EPOLLONESHOT; 31 | return ::epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &ev); 32 | } 33 | 34 | int EpollPoller::mod(int fd, bool write/* = true*/, bool read/* = false*/) 35 | { 36 | struct epoll_event ev = { 0, { 0 } }; 37 | ev.data.fd = fd; 38 | ev.events = EPOLLRDHUP | EPOLLERR | EPOLLHUP; 39 | if (one_shot_) 40 | ev.events |= EPOLLONESHOT; 41 | if (write) 42 | ev.events |= EPOLLOUT; 43 | if (read) 44 | ev.events |= EPOLLIN; 45 | 46 | return ::epoll_ctl(epollFd_, EPOLL_CTL_MOD, fd, &ev); 47 | } 48 | 49 | int EpollPoller::del(int fd) 50 | { 51 | struct epoll_event ev = { 0, { 0 } }; 52 | ev.data.fd = fd; 53 | return ::epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, &ev); 54 | } 55 | 56 | int EpollPoller::poll(int timeoutMs) 57 | { 58 | //nextEventIdx_ = 0; 59 | return ::epoll_wait(epollFd_, events_, maxEvnets_, timeoutMs); 60 | } 61 | -------------------------------------------------------------------------------- /tests/epoll_echoserver/EpollPoller.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | struct epoll_event; 4 | 5 | class EpollPoller 6 | { 7 | public: 8 | explicit EpollPoller(bool one_shot = false, int maxevents = 4096); 9 | ~EpollPoller(); 10 | 11 | public: 12 | int add(int fd); 13 | int mod(int fd, bool write = true, bool read = false); 14 | int del(int fd); 15 | 16 | int poll(int timeoutMs); 17 | 18 | const epoll_event* events() const 19 | { 20 | return events_; 21 | } 22 | 23 | const epoll_event& nextEvent(int idx) 24 | { 25 | return events_[idx]; 26 | } 27 | //const epoll_event& operator[](int index) 28 | //{ 29 | // return events_[index]; 30 | //} 31 | //int nextFd() 32 | //{ 33 | // return events_[nextEventIdx_++].data.fd; 34 | //} 35 | 36 | private: 37 | bool one_shot_; 38 | int epollFd_; 39 | int maxEvnets_; 40 | //int nextEventIdx_; 41 | epoll_event* events_; 42 | }; -------------------------------------------------------------------------------- /tests/epoll_echoserver/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = epoll_echoserver 4 | 5 | epoll_echoserver_LDFLAGS = -lpthread 6 | 7 | epoll_echoserver_SOURCES = EchoServerTest.cpp EchoServer.cpp EpollPoller.cpp 8 | -------------------------------------------------------------------------------- /tests/master_worker_process/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = master_worker_process 4 | 5 | #INCLUDES = -I../../zlreactor 6 | 7 | master_worker_process_SOURCES = master_worker_process.cpp 8 | -------------------------------------------------------------------------------- /tests/pingpong/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = pingpong_server pingpong_client 4 | 5 | INCLUDES = -I../../zlreactor 6 | CPPFLAGS = -std=c++0x 7 | LDFLAGS = -L../../lib -lzlreactor 8 | 9 | pingpong_server_SOURCES = pingpong_server.cpp 10 | 11 | pingpong_client_SOURCES = pingpong_client.cpp -------------------------------------------------------------------------------- /tests/pingpong/pingpong_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "zlreactor/net/TcpServer.h" 14 | #include "zlreactor/net/TcpConnection.h" 15 | #include "zlreactor/net/EventLoop.h" 16 | #include "zlreactor/net/ByteBuffer.h" 17 | #include "zlreactor/base/Logger.h" 18 | #include "zlreactor/thread/Atomic.h" 19 | using namespace std; 20 | using namespace zl::net; 21 | using namespace zl::thread; 22 | 23 | void onConnection(const TcpConnectionPtr& conn) 24 | { 25 | if(conn->connected()) 26 | { 27 | conn->setNoDelay(true); 28 | } 29 | } 30 | 31 | const char* message = "ping pong server"; 32 | void onMessage(const TcpConnectionPtr& conn, ByteBuffer *buf, Timestamp) 33 | { 34 | //conn->send(message); 35 | conn->send(buf); 36 | } 37 | 38 | int main(int argc, char *argv[]) 39 | { 40 | if(argc < 4) 41 | { 42 | fprintf(stderr, "Usage: server
\n"); 43 | } 44 | else 45 | { 46 | LOG_SET_PRIORITY(zl::base::ZL_LOG_PRIO_WARNING); 47 | 48 | const char *ip = argv[1]; 49 | uint16_t port = static_cast(atoi(argv[2])); 50 | InetAddress listenAddr(ip, port); 51 | int threadCount = atoi(argv[3]); 52 | 53 | EventLoop loop; 54 | TcpServer server(&loop, listenAddr, "PingPong"); 55 | server.setConnectionCallback(onConnection); 56 | server.setMessageCallback(onMessage); 57 | 58 | if(threadCount > 1) 59 | { 60 | server.setMultiReactorThreads(threadCount); 61 | } 62 | 63 | server.start(); 64 | 65 | loop.loop(); 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /tests/proxy_server/Makefile.am: -------------------------------------------------------------------------------- 1 | CXXFLAGS += -Wall -g -lrt 2 | 3 | bin_PROGRAMS = ProxyServerByFork ProxyServerByEpoll 4 | 5 | ProxyServerByFork_SOURCES = ProxyServerByFork.cpp 6 | 7 | ProxyServerByEpoll_SOURCES = ProxyServerByEpoll.cpp 8 | -------------------------------------------------------------------------------- /tests/proxy_server/ProxyServerByEpoll.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/tests/proxy_server/ProxyServerByEpoll.cpp -------------------------------------------------------------------------------- /tests/proxy_server/ProxyServerByFork.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/tests/proxy_server/ProxyServerByFork.cpp -------------------------------------------------------------------------------- /tests/server_aio/Makefile.am: -------------------------------------------------------------------------------- 1 | CXXFLAGS += -Wall -g -lrt 2 | 3 | bin_PROGRAMS = server_aio 4 | 5 | server_aio_SOURCES = server_aio.cpp 6 | -------------------------------------------------------------------------------- /tests/signal_handler/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = signal_handler 4 | 5 | #signal_handler_CPPFLAGS = -std=c++0x 6 | #signal_handler_LDFLAGS = -lrt 7 | 8 | signal_handler_SOURCES = signal_handler.cpp 9 | -------------------------------------------------------------------------------- /tests/signal_handler/signal_handler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include // for waitpid 7 | 8 | void signal_handler(int signo) 9 | { 10 | printf("#%d : get a signal: %d ", getpid(), signo); 11 | 12 | bool do_exit = false; 13 | switch(signo) 14 | { 15 | case SIGCHLD: 16 | printf("SIGCHLD\n"); 17 | int status; 18 | while(waitpid(0, &status, WNOHANG) > 0); 19 | break; 20 | case SIGALRM: 21 | printf("SIGALRM\n"); 22 | break; 23 | case SIGIO: 24 | printf("SIGIO\n"); 25 | break; 26 | case SIGINT: 27 | printf("SIGINT\n"); 28 | do_exit = true; 29 | break; 30 | case SIGHUP: 31 | printf("SIGHUP\n"); 32 | do_exit = true; 33 | break; 34 | case SIGTERM: 35 | printf("SIGTERM\n"); 36 | do_exit = true; 37 | break; 38 | case SIGQUIT: 39 | printf("SIGQUIT\n"); 40 | do_exit = true; 41 | break; 42 | case SIGUSR1: 43 | printf("SIGUSR1\n"); 44 | break; 45 | case SIGUSR2: 46 | printf("SIGUSR2\n"); 47 | break; 48 | } 49 | 50 | if(do_exit) 51 | { 52 | exit(0); 53 | } 54 | } 55 | 56 | void register_signal_handler_imp(int signum, void (*handler)(int)) 57 | { 58 | struct sigaction action; 59 | 60 | action.sa_handler = handler; 61 | sigemptyset(&action.sa_mask); 62 | //action.sa_flags = 0; 63 | 64 | if(sigaction(signum, &action, NULL) == -1) 65 | { 66 | printf("register signal handler failed!\n"); 67 | } 68 | } 69 | 70 | void register_signal_handler() 71 | { 72 | register_signal_handler_imp(SIGCHLD, signal_handler); 73 | register_signal_handler_imp(SIGALRM, signal_handler); 74 | register_signal_handler_imp(SIGIO, signal_handler); 75 | register_signal_handler_imp(SIGINT, signal_handler); 76 | register_signal_handler_imp(SIGHUP, signal_handler); 77 | register_signal_handler_imp(SIGTERM, signal_handler); 78 | register_signal_handler_imp(SIGQUIT, signal_handler); 79 | register_signal_handler_imp(SIGUSR1, signal_handler); 80 | register_signal_handler_imp(SIGUSR2, signal_handler); 81 | printf("register signal handler success!\n"); 82 | } 83 | 84 | int main() 85 | { 86 | register_signal_handler(); 87 | while(1); 88 | } 89 | -------------------------------------------------------------------------------- /tests/socketAcceptThunderingHerd/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = socketAcceptThunderingHerd 4 | 5 | #INCLUDES = -I../../zlreactor 6 | 7 | socketAcceptThunderingHerd_SOURCES = socketAcceptThunderingHerd.cpp 8 | -------------------------------------------------------------------------------- /tests/stress_client/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = stress_client 4 | 5 | #INCLUDES = -I../../zlreactor 6 | 7 | #test_buffer_CPPFLAGS = -std=c++0x 8 | #excep_mangle_LDFLAGS = -L../../lib -lzlreactor 9 | 10 | stress_client_SOURCES = stress_client.cpp 11 | -------------------------------------------------------------------------------- /tests/tcpselfconnect1/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = tcpselfconnect1 4 | 5 | #INCLUDES = -I../../zlreactor 6 | 7 | tcpselfconnect1_SOURCES = tcpselfconnect1.cpp 8 | -------------------------------------------------------------------------------- /tests/tcpselfconnect2/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = tcpselfconnect2 4 | 5 | #INCLUDES = -I../../zlreactor 6 | 7 | tcpselfconnect2_SOURCES = tcpselfconnect2.cpp 8 | -------------------------------------------------------------------------------- /tests/timerqueue/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = timerqueue 4 | 5 | INCLUDES = -I../../zlreactor 6 | 7 | timerqueue_CPPFLAGS = -std=c++0x 8 | timerqueue_LDFLAGS = -L../../lib -lzlreactor 9 | 10 | timerqueue_SOURCES = Timer_Test.cpp \ 11 | TimerQueue.cpp \ 12 | Timer.cpp 13 | -------------------------------------------------------------------------------- /tests/timerqueue/Timer.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/tests/timerqueue/Timer.cpp -------------------------------------------------------------------------------- /tests/timerqueue/Timer.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : Timer.h 3 | // Author : LIZHENG 4 | // Created : 2014-10-26 5 | // Description : 6 | // 7 | // Last Modified By : LIZHENG 8 | // Last Modified On : 2014-11-23 9 | // 10 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 11 | // *********************************************************************** 12 | #ifndef ZL_TIMER_H 13 | #define ZL_TIMER_H 14 | #include "zlreactor/Define.h" 15 | #include "zlreactor/base/Timestamp.h" 16 | #include "zlreactor/base/NonCopy.h" 17 | NAMESPACE_ZL_NET_START 18 | 19 | using zl::base::Timestamp; 20 | class TimerQueue; 21 | 22 | class Timer 23 | { 24 | friend class TimerQueue; 25 | public: 26 | typedef std::function TimerCallBack; 27 | 28 | public: 29 | explicit Timer(TimerQueue *tqueue); 30 | Timer(TimerQueue *tqueue, const Timestamp& when); 31 | Timer(TimerQueue *tqueue, size_t millsec); 32 | ~Timer(); 33 | 34 | void wait(); 35 | void async_wait(TimerCallBack callback); 36 | size_t cancel(); 37 | 38 | Timestamp expires_at(const Timestamp& expiry_time); 39 | Timestamp expires_at() const; 40 | Timestamp expires_from_now(size_t millsec_time); 41 | size_t expires_from_now() const; 42 | 43 | private: 44 | void trigger(); 45 | 46 | private: 47 | TimerQueue *timerQueue_; 48 | Timestamp when_; 49 | TimerCallBack callback_; 50 | }; 51 | 52 | inline bool operator<(const Timer& lhs, const Timer& rhs) 53 | { 54 | return lhs.expires_at() < rhs.expires_at(); 55 | } 56 | 57 | NAMESPACE_ZL_NET_END 58 | #endif /* ZL_TIMER_H */ -------------------------------------------------------------------------------- /tests/timerqueue/TimerQueue.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : TimerQueue.h 3 | // Author : LIZHENG 4 | // Created : 2014-10-126 5 | // Description : һ��ͨ�õĶ�ʱ������ 6 | // 7 | // Last Modified By : LIZHENG 8 | // Last Modified On : 2014-10-26 9 | // 10 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 11 | // *********************************************************************** 12 | #ifndef ZL_TIMERQUEUE_H 13 | #define ZL_TIMERQUEUE_H 14 | #include "zlreactor/Define.h" 15 | #include "zlreactor/base/NonCopy.h" 16 | #include "zlreactor/thread/Mutex.h" 17 | #include "zlreactor/thread/Thread.h" 18 | #include "zlreactor/base/Timestamp.h" 19 | using zl::base::Timestamp; 20 | NAMESPACE_ZL_NET_START 21 | 22 | class Timer; 23 | 24 | class TimerQueue 25 | { 26 | public: 27 | TimerQueue(); 28 | ~TimerQueue(); 29 | 30 | void stop(); 31 | void addTimer(Timer *vtimer); 32 | void deleteTimer(Timer *vtimer); 33 | 34 | private: 35 | void addTimerWithHold(Timer *vtimer); 36 | void deleteTimerWithHold(Timer *vtimer); 37 | void processThread(); //��ʱ���ӳ��߳� 38 | 39 | private: 40 | typedef std::multimap TimerList; 41 | 42 | bool running_; 43 | bool checkTimer_; 44 | 45 | TimerList timers_; 46 | std::vector addTimes_; 47 | std::vector delTimes_; 48 | 49 | zl::thread::Mutex mutex_; 50 | zl::thread::Thread thread_; 51 | }; 52 | 53 | NAMESPACE_ZL_NET_END 54 | #endif /* ZL_TIMERQUEUE_H */ 55 | -------------------------------------------------------------------------------- /tests/timerqueue/Timer_Test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Timer.h" 3 | #include "TimerQueue.h" 4 | #include "zlreactor/base/Timestamp.h" 5 | using namespace std; 6 | using namespace zl; 7 | using namespace zl::base; 8 | using namespace zl::net; 9 | 10 | void print(Timer *self) 11 | { 12 | Timestamp now = Timestamp::now(); 13 | printf("[%s][%0x]async timer trigger : print\n", now.toString().c_str(), self); 14 | printf("hello world\n"); 15 | } 16 | 17 | void print_num(Timer *self, int num) 18 | { 19 | Timestamp now = Timestamp::now(); 20 | printf("[%s][%0x]async timer trigger : print_num\n", now.toString().c_str(), self); 21 | printf("hello world[%d]\n", num); 22 | 23 | num ++; 24 | if(num > 3) 25 | { 26 | self->cancel(); 27 | } 28 | else 29 | { 30 | self->expires_from_now(1200); 31 | self->async_wait(std::bind(print_num, self, num)); 32 | } 33 | } 34 | 35 | void test_sync_timer() 36 | { 37 | cout << "-----------test_sync_timer-----------\n"; 38 | Timestamp now = Timestamp::now(); 39 | printf("%s\n", now.toString().c_str()); 40 | Timer t1(NULL, 3000); 41 | 42 | t1.wait(); 43 | now = Timestamp::now(); 44 | printf("%s\n", now.toString().c_str()); 45 | } 46 | 47 | void test_async_timer() 48 | { 49 | cout << "-----------test_async_timer-----------\n"; 50 | TimerQueue tqueue ; 51 | Timer t1(&tqueue, 1000); 52 | Timer t2(&tqueue, 2300); 53 | 54 | Timestamp now = Timestamp::now(); 55 | printf("[%s]async timer start\n", now.toString().c_str()); 56 | 57 | t1.async_wait(std::bind(print, &t1)); 58 | t2.async_wait(std::bind(print_num, &t2, 1)); 59 | 60 | zl::thread::this_thread::sleep_for(zl::thread::chrono::seconds(15)); 61 | printf("================\n"); 62 | } 63 | 64 | int main() 65 | { 66 | test_sync_timer(); 67 | test_async_timer(); 68 | 69 | TimerQueue tqueue ; 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /tests/universal_timer/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = universal_timer 4 | 5 | #INCLUDES = -I../../zlreactor 6 | universal_timer_LDFLAGS = -lpthread 7 | 8 | universal_timer_SOURCES = TriggerTimerTest.cpp \ 9 | TriggerTimer.cpp 10 | -------------------------------------------------------------------------------- /tests/universal_timer/TriggerTimer.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : TriggerTimer.h 3 | // Author : LIZHENG 4 | // Created : 2014-07-26 5 | // Description : 定时器类 6 | // 7 | // Last Modified By : LIZHENG 8 | // Last Modified On : 2014-07-26 9 | // 10 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 11 | // *********************************************************************** 12 | #ifndef TRIGGERTIMER_H 13 | #define TRIGGERTIMER_H 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | class TriggerTimer 21 | { 22 | friend class TriggerTimerManager; 23 | public: 24 | enum TimerState 25 | { 26 | TIMER_IDLE=0, //start前以及手动调用stop后的状态 27 | TIMER_ALIVE, //在manager的list里时候的状态 28 | TIMER_TIMEOUT //超时后被移除的状态,循环型的没有 29 | }; 30 | enum TimerType 31 | { 32 | TIMER_ONCE=0, //一次型 33 | TIMER_CIRCLE //循环型 34 | }; 35 | 36 | public: 37 | TriggerTimer(unsigned int interval,void (*func)(TriggerTimer *,void *),void *args,TimerType type = TIMER_ONCE); 38 | ~TriggerTimer(); 39 | 40 | void Start(); // 开始定时器 41 | void Stop(); // 停止定时器 42 | void Reset(unsigned int interval); // 重置定时器 43 | bool Trigger(); // 触发定时器 44 | 45 | private: 46 | TimerState timer_state_; //状态 47 | TimerType timer_type_; //类型 48 | unsigned int timer_interval_; //定时间隔 49 | unsigned int timer_duration_; //开始设置为interval,随延迟时间到,减少 50 | unsigned long trigger_sum_; //触发计数 51 | 52 | void *args_; //回调函数参数 53 | void (*callback_)(TriggerTimer *,void *); //回调函数 54 | }; 55 | 56 | 57 | class TriggerTimerManager 58 | { 59 | public: 60 | static TriggerTimerManager * instance(); 61 | 62 | void Start(); 63 | void Stop(); 64 | void AddTimer(TriggerTimer * vtimer); 65 | void DeleteTimer(TriggerTimer * vtimer); 66 | 67 | private: 68 | void AddTimer_(TriggerTimer * vtimer); 69 | void DeleteTimer_(TriggerTimer * vtimer); 70 | 71 | private: 72 | static void* ProcessThread(void *); //定时器延迟线程 73 | 74 | static pthread_mutex_t m_mutex; 75 | static TriggerTimerManager * m_instance; 76 | TriggerTimerManager(); 77 | 78 | bool running_; 79 | std::list timers_; 80 | }; 81 | 82 | #endif /* TRIGGERTIMER_H */ 83 | 84 | -------------------------------------------------------------------------------- /tests/universal_timer/TriggerTimerTest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * File: main.cpp 3 | * Author: lizheng 4 | * 5 | * Created on 2014年7月26日, 上午11:03 6 | */ 7 | #include 8 | #include 9 | #include "TriggerTimer.h" 10 | using namespace std; 11 | 12 | void func(TriggerTimer * timer, void *data) 13 | { 14 | printf("hi,%d\n",*((int*)(data))); 15 | } 16 | 17 | int main(int argc, char** argv) 18 | { 19 | TriggerTimerManager::instance()->Start(); 20 | int i = 1, j=2,m=3,n=4; 21 | TriggerTimer a(1000,func,(void *)&i,TriggerTimer::TIMER_CIRCLE); 22 | TriggerTimer a1(2000,func,(void *)&j,TriggerTimer::TIMER_ONCE); 23 | TriggerTimer a2(3000,func,(void *)&m,TriggerTimer::TIMER_ONCE); 24 | TriggerTimer a3(1000,func,(void *)&n,TriggerTimer::TIMER_CIRCLE); 25 | 26 | a.Start(); 27 | a1.Start(); 28 | a2.Start(); 29 | a3.Start(); 30 | //a.Start(); 31 | //a1.Start(); 32 | //a2.Start(); 33 | //a3.Start(); 34 | 35 | a.Reset(2000); 36 | a1.Stop(); 37 | a3.Stop(); 38 | //while(1); 39 | sleep(20); 40 | a.Stop(); 41 | printf("stop timer over\n"); 42 | 43 | exit(0); 44 | return 0; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /zlreactor/OsDefine.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : OsDefine.h 3 | // Author : LIZHENG 4 | // Created : 2014-07-01 5 | // Description : 平台定义 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_OSDEFINE_H 10 | #define ZL_OSDEFINE_H 11 | 12 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) 13 | #define OS_WINDOWS 14 | #define OS_X86 15 | #elif defined(WIN64) || defined(_WIN64) || defined(__WIN64__) 16 | #define OS_WINDOWS 17 | #define OS_X64 18 | #elif defined(__CYGWIN__) || defined(__CYGWIN32__) 19 | #define OS_CYGWIN 20 | #elif defined(linux) || defined(__linux) || defined(__linux__) 21 | #define OS_LINUX 22 | #if defined(__x86_64__) 23 | #define OS_X64 24 | #else 25 | #define OS_X86 26 | #endif 27 | #elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) 28 | #define OS_MACOSX 29 | #elif defined(__FreeBSD__) 30 | #define OS_FREEBSD 31 | #elif defined(__NetBSD__) 32 | #define OS_NETBSD 33 | #elif defined(__OpenBSD__) 34 | #define OS_OPENBSD 35 | #else 36 | #error "You Must Be Choose One Platform" 37 | #endif 38 | 39 | #if defined(OS_WINDOWS) 40 | #if (_MSC_VER >= 1300) && (_MSC_VER < 1400) // Visual Studio 2003, MSVC++ 7.1 41 | #define ZL_MSVS_VERSION 2003 42 | #define ZL_MSVC_VERSION 71 43 | #elif (_MSC_VER >= 1400) && (_MSC_VER < 1500) // Visual Studio 2005, MSVC++ 8.0 44 | #define ZL_MSVS_VERSION 2005 45 | #define ZL_MSVC_VERSION 80 46 | #elif (_MSC_VER >= 1500) && (_MSC_VER < 1600) // Visual Studio 2008, MSVC++ 9.0 47 | #define ZL_MSVS_VERSION 2008 48 | #define ZL_MSVC_VERSION 90 49 | #elif (_MSC_VER >= 1600) && (_MSC_VER < 1700) // Visual Studio 2010, MSVC++ 10.0 50 | #define ZL_MSVS_VERSION 2010 51 | #define ZL_MSVC_VERSION 100 52 | #elif (_MSC_VER >= 1700) && (_MSC_VER < 1800) // Visual Studio 2012, MSVC++ 11.0 53 | #define ZL_MSVS_VERSION 2012 54 | #define ZL_MSVC_VERSION 110 55 | #endif 56 | #endif 57 | 58 | #endif /* ZL_OSDEFINE_H */ 59 | -------------------------------------------------------------------------------- /zlreactor/base/Daemonize.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : Daemonize.h 3 | // Author : LIZHENG 4 | // Created : 2015-01-05 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_DAEMONIZE_H 10 | #define ZL_DAEMONIZE_H 11 | namespace zl 12 | { 13 | namespace base 14 | { 15 | /// 创建守护进程(设置同台机器是否允许多个进程启动) 16 | /// nochdir : 为0改变当前进程工作目录,否则不改变 17 | /// noclose : 为0重定向输入输出到/dev/null,否则不会改变, nochdir, noclose 参数意义同 man 3 daemon 参数 18 | /// pidfile : 为NULL时允许多个进程启动,否则禁止系统重复启动进程 19 | /// 成功返回当前进程pid,失败返回-1 20 | int createDaemonize(int nochdir = 1, int noclose = 0, const char *pidfile = 0); 21 | 22 | int exitDaemonize(const char *pidfile); 23 | 24 | } 25 | } 26 | #endif /* ZL_DAEMONIZE_H */ 27 | -------------------------------------------------------------------------------- /zlreactor/base/Demangle.cpp: -------------------------------------------------------------------------------- 1 | #include "zlreactor/base/Demangle.h" 2 | #ifdef OS_WINDOWS 3 | #include 4 | #include 5 | #pragma comment(lib,"DbgHelp.lib") 6 | #elif defined(OS_LINUX) 7 | #include 8 | #else 9 | #error "You must be include OsDefine.h firstly if you want to demangle name" 10 | #endif 11 | 12 | NAMESPACE_ZL_BASE_START 13 | 14 | bool demangleName(const char *mangled, char *unmangled, size_t buf_size) 15 | { 16 | // static const size_t max_size = 1024; 17 | #ifdef OS_WINDOWS 18 | if (::UnDecorateSymbolName(mangled, unmangled, buf_size, UNDNAME_COMPLETE) == 0) 19 | { 20 | 21 | return false; 22 | } 23 | else 24 | { 25 | 26 | return true; 27 | } 28 | #else 29 | int status; 30 | //size_t n = max_size; 31 | abi::__cxa_demangle(mangled, unmangled, &buf_size, &status); 32 | if(status == 0) 33 | { 34 | //printf("Name after Mangled : %s ; Name before Mangled : %s\n", unmangled, mangled); 35 | return true; 36 | } 37 | //printf("Name after Mangled fail: %s Name before Mangled : %s\n", unmangled, mangled); 38 | return false; 39 | #endif 40 | } 41 | 42 | bool demangleName(const char *mangled, std::string& unmangled) 43 | { 44 | static const size_t max_size = 1024; 45 | char result[max_size]; 46 | if(demangleName(mangled, result, max_size)) 47 | { 48 | unmangled = result; 49 | return true; 50 | } 51 | return false; 52 | } 53 | 54 | NAMESPACE_ZL_BASE_END -------------------------------------------------------------------------------- /zlreactor/base/Demangle.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : Demangle.h 3 | // Author : LIZHENG 4 | // Created : 2014-11-05 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_DEMANGLE_H 10 | #define ZL_DEMANGLE_H 11 | #include "zlreactor/Define.h" 12 | NAMESPACE_ZL_BASE_START 13 | 14 | // 根据重整后的名字解析出原函数原型名字 15 | // 如果则返回true, 并将解析后的名字保存在unmangled 16 | // Demangle "mangled". On success, return true and write the 17 | // demangled symbol name to "unmangled". Otherwise, return false. 18 | // "unmangled" is modified even if demangling is unsuccessful. 19 | bool demangleName(const char *mangled, char *unmangled, size_t buf_size); 20 | 21 | bool demangleName(const char *mangled, std::string& unmangled); 22 | 23 | NAMESPACE_ZL_BASE_END 24 | #endif /* ZL_DEMANGLE_H */ 25 | -------------------------------------------------------------------------------- /zlreactor/base/Exception.cpp: -------------------------------------------------------------------------------- 1 | #include "zlreactor/base/Exception.h" 2 | #include 3 | #ifdef OS_WINDOWS 4 | #else 5 | #include 6 | #define DO_NAME_DEMANGLE 7 | #endif 8 | #ifdef DO_NAME_DEMANGLE 9 | #include "zlreactor/base/Demangle.h" 10 | #endif 11 | NAMESPACE_ZL_BASE_START 12 | 13 | Exception::Exception(const char* errinfo) 14 | : line_(0) 15 | , filename_("unknown filename") 16 | , errmsg_(errinfo) 17 | { 18 | trace_stack(); 19 | } 20 | 21 | Exception::Exception(const char *filename, int linenumber, const char* errinfo) 22 | : line_(linenumber), 23 | filename_(filename), 24 | errmsg_(errinfo) 25 | 26 | { 27 | trace_stack(); 28 | } 29 | 30 | Exception::Exception(const char *filename, int linenumber, const std::string& errinfo) 31 | : line_(linenumber) 32 | , filename_(filename) 33 | , errmsg_(errinfo) 34 | { 35 | trace_stack(); 36 | } 37 | 38 | Exception::~Exception() throw () 39 | { 40 | } 41 | 42 | void Exception::trace_stack() 43 | { 44 | #ifdef OS_WINDOWS 45 | #else 46 | static const int len = 256; 47 | void* buffer[len]; 48 | int nptrs = ::backtrace(buffer, len); 49 | char** strings = ::backtrace_symbols(buffer, nptrs); 50 | if (!strings) 51 | return; 52 | 53 | for (int i = 0; i < nptrs; ++i) 54 | { 55 | #ifndef DO_NAME_DEMANGLE 56 | callStack_.append(strings[i]); 57 | #else 58 | std::string line(strings[i]); // ./test(_ZN6detail12c_do_nothingEfi+0x44) [0x401974] 59 | size_t pos1 = line.find("("); 60 | size_t pos2 = line.find("+"); 61 | if (pos1 > 0 && pos2 > 0) 62 | line = line.substr(pos1, pos2); 63 | 64 | std::string unmangle; 65 | if (demangleName(line.c_str(), unmangle)) 66 | { 67 | callStack_.append(unmangle); 68 | } 69 | else 70 | { 71 | callStack_.append(strings[i]); 72 | } 73 | #endif 74 | callStack_.push_back('\n'); 75 | } 76 | free(strings); 77 | #endif 78 | } 79 | 80 | NAMESPACE_ZL_BASE_END 81 | -------------------------------------------------------------------------------- /zlreactor/base/Exception.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : Exception.h 3 | // Author : LIZHENG 4 | // Created : 2014-11-05 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_EXCEPTION_H 10 | #define ZL_EXCEPTION_H 11 | #include "zlreactor/Define.h" 12 | #include 13 | NAMESPACE_ZL_BASE_START 14 | 15 | class Exception : public std::exception 16 | { 17 | public: 18 | explicit Exception(const char *errinfo); 19 | Exception(const char *filename, int linenumber, const char *errinfo); 20 | Exception(const char *filename, int linenumber, const std::string& errinfo); 21 | virtual ~Exception() throw(); 22 | 23 | virtual const char *what() const throw() 24 | { 25 | return errmsg_.c_str(); 26 | } 27 | 28 | const char* stackTrace() const throw() 29 | { 30 | return callStack_.c_str(); 31 | } 32 | 33 | const char* filename() const throw() 34 | { 35 | return filename_.c_str(); 36 | } 37 | 38 | int line() const throw() 39 | { 40 | return line_; 41 | } 42 | private: 43 | void trace_stack(); 44 | 45 | int line_; 46 | std::string filename_; 47 | std::string errmsg_; 48 | std::string callStack_; 49 | }; 50 | 51 | NAMESPACE_ZL_BASE_END 52 | #endif /* */ 53 | -------------------------------------------------------------------------------- /zlreactor/base/FileUtil.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : FileUtil.h 3 | // Author : LIZHENG 4 | // Created : 2014-07-01 5 | // Description : 文件、目录相关工具函数 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_FILEUTIL_H 10 | #define ZL_FILEUTIL_H 11 | #include "zlreactor/Define.h" 12 | #include 13 | NAMESPACE_ZL_START 14 | 15 | namespace FileUtil 16 | { 17 | string getBinaryPath(); 18 | string getBinaryName(); 19 | string getBinaryDir(); 20 | 21 | bool isDirectory(const char *dir); 22 | bool createRecursionDir(const char *dir); 23 | 24 | bool isFileExist(const char *filepath); 25 | long getFileSize(FILE *file); 26 | long getFileSize(const char *filepath); 27 | size_t readFile(const char *filepath, std::string& buf); 28 | }; 29 | 30 | using namespace FileUtil; 31 | 32 | NAMESPACE_ZL_END 33 | #endif /* ZL_FILEUTIL_H */ 34 | -------------------------------------------------------------------------------- /zlreactor/base/HighPrecisionTime.h: -------------------------------------------------------------------------------- 1 | #ifndef HIGHPRECISIONTIME_FILE_H 2 | #define HIGHPRECISIONTIME_FILE_H 3 | #include "zlreactor/Define.h" 4 | #ifdef OS_WINDOWS 5 | #include 6 | #endif 7 | NAMESPACE_ZL_BASE_START 8 | 9 | class HighPrecisionTime 10 | { 11 | public: 12 | HighPrecisionTime() 13 | { 14 | ::QueryPerformanceFrequency(&m_liPerfFreq); 15 | start(); 16 | } 17 | 18 | void reset() 19 | { 20 | LARGE_INTEGER liPerfNow; 21 | ::QueryPerformanceCounter(&liPerfNow); 22 | m_liPerfStart = liPerfNow; 23 | } 24 | 25 | long long now() 26 | { 27 | LARGE_INTEGER liPerfNow; 28 | ::QueryPerformanceCounter(&liPerfNow); 29 | return liPerfNow.QuadPart; 30 | } 31 | 32 | long long getFreq() 33 | { 34 | return m_liPerfFreq.QuadPart; 35 | } 36 | 37 | double elapsedTime() 38 | { 39 | LARGE_INTEGER liPerfNow; 40 | ::QueryPerformanceCounter(&liPerfNow); 41 | 42 | return ((liPerfNow.QuadPart - m_liPerfStart.QuadPart) * 1.0) / m_liPerfFreq.QuadPart ; 43 | } 44 | 45 | double elapsedTimeInMill() 46 | { 47 | LARGE_INTEGER liPerfNow; 48 | ::QueryPerformanceCounter(&liPerfNow); 49 | 50 | return ((liPerfNow.QuadPart - m_liPerfStart.QuadPart) * 1000.0) / m_liPerfFreq.QuadPart ; 51 | } 52 | double elapsedTimeInMicro() 53 | { 54 | LARGE_INTEGER liPerfNow; 55 | ::QueryPerformanceCounter(&liPerfNow); 56 | 57 | return ((liPerfNow.QuadPart - m_liPerfStart.QuadPart) * 1000000.0) / m_liPerfFreq.QuadPart ; 58 | } 59 | private: 60 | void start() 61 | { 62 | ::QueryPerformanceCounter(&m_liPerfStart); 63 | } 64 | 65 | private: 66 | LARGE_INTEGER m_liPerfFreq; //Conuts per second 67 | LARGE_INTEGER m_liPerfStart; //Starting count 68 | }; 69 | 70 | NAMESPACE_ZL_BASE_END 71 | #endif /* HIGHPRECISIONTIME_FILE_H */ -------------------------------------------------------------------------------- /zlreactor/base/LogFile.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : LogFile.h 3 | // Author : LIZHENG 4 | // Created : 2015-06-12 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_LOGFILE_H 10 | #define ZL_LOGFILE_H 11 | #include "zlreactor/Define.h" 12 | #include "zlreactor/thread/Mutex.h" 13 | NAMESPACE_ZL_BASE_START 14 | 15 | #define MAX_LOG_FILE_SIZE (100 * 1024 * 1024) /** 默认每个日志文件大小(MB)*/ 16 | #define MAX_LOG_FILE_COUNT (10) /** 默认循环日志文件数量 */ 17 | #define MAX_FILE_PATH_LEN (1024) /* 日志文件路径最大长度 */ 18 | 19 | class LogFile 20 | { 21 | public: 22 | LogFile(const char *log_name = NULL, const char *log_dir = NULL, size_t max_file_size = MAX_LOG_FILE_SIZE, 23 | bool threadSafe = true, int flushInterval = 3/*second*/, int flushCount = 1024, 24 | size_t max_file_count = MAX_LOG_FILE_COUNT, bool append = true); 25 | 26 | ~LogFile(); 27 | 28 | void setThreadSafe(bool safe); 29 | 30 | void dumpLog(const char *log_entry, size_t size); 31 | 32 | void flush(); 33 | 34 | private: 35 | void init(const char *log_name, const char *log_dir, bool append); 36 | void dumpLogWithHold(const char *log_entry, size_t size); 37 | const char *makeLogFilePath(); 38 | 39 | private: 40 | char logDir_[MAX_FILE_PATH_LEN]; 41 | char logFileName_[MAX_FILE_PATH_LEN]; 42 | char currLogFileName_[MAX_FILE_PATH_LEN]; 43 | const int flushInterval_; /// seconds 44 | const int flushCount_; 45 | const size_t maxFileSize_; 46 | const int maxFileCount_; 47 | 48 | FILE *file_; 49 | int count_; 50 | size_t curSize_; 51 | int curFileIndex_; 52 | bool isThreadSafe_; 53 | time_t lastFlush_; 54 | zl::thread::Mutex *mutex_; 55 | }; 56 | 57 | NAMESPACE_ZL_BASE_END 58 | #endif /* ZL_LOGFILE_H */ 59 | -------------------------------------------------------------------------------- /zlreactor/base/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = Makefile.in 2 | 3 | SUBDIRS = 4 | 5 | SUBDIRS += tests 6 | -------------------------------------------------------------------------------- /zlreactor/base/MasterWorkerProcess.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : Process.h 3 | // Author : LIZHENG 4 | // Description : 一个通用的、固定数目的watcher-woker多进程模型(亦称prefork模型) 5 | // 6 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 7 | // ***********************************************************************# 8 | #ifndef ZL_MASTERWORKER_PROCESS_H 9 | #define ZL_MASTERWORKER_PROCESS_H 10 | #include 11 | #include 12 | 13 | // 一个通用的watcher-woker多进程模型,亦称 prefork模型 14 | // 15 | // see : https://github.com/lighttpd/lighttpd1.4/blob/master/src/server.c 16 | // 主进程创建固定数目的子进程用于进行任务处理,创建完成后主进程阻塞等待子进程退出 17 | // 如果子进程完成任务则退出,此时主进程会再次创建子进程,以使子进程数目维持固定 18 | // 19 | // while(主进程 and 程序继续运行) 20 | // { 21 | // if(还有未创建的子进程) 22 | // { 23 | // 创建一个新的子进程 24 | // if 是子进程, 退出循环. 25 | // if 是父进程, 将未创建的子进程数量减 1 26 | // } 27 | // else //所有子进程都创建完成 28 | // { 29 | // 阻塞等待子进程的退出, 30 | // 一旦有退出,主进程就得到消息, 并将未创建的子进程数量加 1 31 | // } 32 | // } 33 | // 34 | // if(子进程) //子进程入口点,用于处理任务 35 | // { 36 | // // do some work 37 | // } 38 | // else //主进程退出点,此处杀掉全部子进程,清理资源 39 | // { 40 | // // killall children process and cleanup 41 | // } 42 | 43 | namespace zl 44 | { 45 | class MasterWorkerProcess; 46 | //typedef std::function ProcessCallback; 47 | typedef void(*ProcessCallback)(MasterWorkerProcess* master, int jodid, void *arg); 48 | 49 | 50 | class MasterWorkerProcess 51 | { 52 | public: 53 | MasterWorkerProcess(); 54 | ~MasterWorkerProcess(); 55 | 56 | static pid_t mainProcessPid() { return mainProcessPid_; } 57 | 58 | public: 59 | void createWorkProcess(int workProcessNum, const ProcessCallback& callback, void* arg); 60 | 61 | bool isMainProcess() const { return mainProcessPid() == ::getpid(); } 62 | 63 | bool hasChild() const { return !childenPids_.empty(); } 64 | 65 | pid_t pid() const { return pid_; } 66 | 67 | bool shutdown() const; 68 | 69 | void stop(); 70 | 71 | private: 72 | pid_t createOneProcess(); 73 | 74 | private: 75 | static pid_t mainProcessPid_; 76 | 77 | volatile bool running_; 78 | pid_t pid_; 79 | std::list childenPids_; 80 | }; 81 | } 82 | 83 | #endif /* ZL_MASTERWORKER_PROCESS_H */ 84 | -------------------------------------------------------------------------------- /zlreactor/base/MathUtil.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : MathUtil.h 3 | // Author : LIZHENG 4 | // Created : 2014-11-02 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_STOPWTACH_H 10 | #define ZL_STOPWTACH_H 11 | #include "Define.h" 12 | NAMESPACE_ZL_BASE_START 13 | 14 | /// 判断一个整数是否是2的幂次方 15 | inline bool is_pow2(uint32_t num) 16 | { 17 | return !(num & (num - 1)); 18 | } 19 | 20 | /// 返回一个整数,其值不小于参数num,且为2的幂次方 21 | inline uint32_t num_of_pow2(uint32_t num) 22 | { 23 | if(is_pow2(num)) 24 | return num; 25 | num = num-1; 26 | num = num | (num>>1); 27 | num = num | (num>>2); 28 | num = num | (num>>4); 29 | num = num | (num>>8); 30 | num = num | (num>>16); 31 | return num + 1; 32 | } 33 | 34 | /// 返回一个不小于参数num的整数的关于2的幂次 35 | inline uint8_t get_pow2(uint32_t num) 36 | { 37 | uint8_t pow2 = 0; 38 | if(!is_pow2(num)) 39 | num = (num << 1); 40 | while(num > 1) 41 | { 42 | pow2++; 43 | num = num >> 1; 44 | } 45 | return pow2; 46 | } 47 | 48 | NAMESPACE_ZL_BASE_END 49 | -------------------------------------------------------------------------------- /zlreactor/base/NonCopy.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : NonCopy.h 3 | // Author : LIZHENG 4 | // Created : 2014-05-16 5 | // Description : 禁止拷贝构造、赋值构造,建议private继承 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_NONCOPY_H 10 | #define ZL_NONCOPY_H 11 | 12 | namespace zl 13 | { 14 | namespace base 15 | { 16 | class NonCopy 17 | { 18 | protected: 19 | NonCopy() {} 20 | ~NonCopy() {} 21 | private: 22 | NonCopy(const NonCopy&); 23 | const NonCopy& operator=(const NonCopy&); 24 | }; 25 | } 26 | 27 | using base::NonCopy; 28 | } 29 | 30 | #endif /* ZL_NONCOPY_H */ 31 | -------------------------------------------------------------------------------- /zlreactor/base/Preprocess.h: -------------------------------------------------------------------------------- 1 | #ifndef ZL_BASE_PREPROCESS_H 2 | #define ZL_BASE_PREPROCESS_H 3 | 4 | /// Helper macro to join 2 tokens 5 | #define ZL_PP_JOIN(X, Y) ZL_PP_DO_JOIN(X, Y) 6 | #define ZL_PP_DO_JOIN(X, Y) ZL_PP_DO_JOIN2(X, Y) 7 | #define ZL_PP_DO_JOIN2(X, Y) X##Y 8 | 9 | /// Converts the parameter X to a string after macro replacement 10 | /// on X has been performed. 11 | /// example: ZL_PP_STRINGIZE(UCHAR_MAX) -> "255" 12 | #define ZL_PP_STRINGIZE(X) ZL_PP_DO_STRINGIZE(X) 13 | #define ZL_PP_DO_STRINGIZE(X) #X 14 | 15 | 16 | #endif /* ZL_BASE_PREPROCESS_H */ -------------------------------------------------------------------------------- /zlreactor/base/Random.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. See the AUTHORS file for names of contributors. 4 | 5 | #ifndef ZL_BASE_RANDOM_H 6 | #define ZL_BASE_RANDOM_H 7 | 8 | #include 9 | 10 | namespace zl { namespace base { 11 | 12 | // A very simple random number generator. Not especially good at 13 | // generating truly random bits, but good enough for our needs in this 14 | // package. 15 | class Random 16 | { 17 | public: 18 | explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) { } 19 | 20 | uint32_t next() 21 | { 22 | static const uint32_t M = 2147483647L; // 2^31-1 23 | static const uint64_t A = 16807; // bits 14, 8, 7, 5, 2, 1, 0 24 | // We are computing 25 | // seed_ = (seed_ * A) % M, where M = 2^31-1 26 | // 27 | // seed_ must not be zero or M, or else all subsequent computed values 28 | // will be zero or M respectively. For all other values, seed_ will end 29 | // up cycling through every number in [1,M-1] 30 | uint64_t product = seed_ * A; 31 | 32 | // Compute (product % M) using the fact that ((x << 31) % M) == x. 33 | seed_ = static_cast((product >> 31) + (product & M)); 34 | // The first reduction may overflow by 1 bit, so we may need to 35 | // repeat. mod == M is not possible; using > allows the faster 36 | // sign-bit-based test. 37 | if (seed_ > M) 38 | { 39 | seed_ -= M; 40 | } 41 | return seed_; 42 | } 43 | 44 | // Returns a uniformly distributed value in the range [0..n-1] 45 | // REQUIRES: n > 0 46 | uint32_t uniform(int n) { return next() % n; } 47 | 48 | // Randomly returns true ~"1/n" of the time, and false otherwise. 49 | // REQUIRES: n > 0 50 | bool oneIn(int n) { return (next() % n) == 0; } 51 | 52 | // Skewed: pick "base" uniformly from range [0,max_log] and then 53 | // return "base" random bits. The effect is to pick a number in the 54 | // range [0,2^max_log-1] with exponential bias towards smaller numbers. 55 | uint32_t skewed(int max_log) 56 | { 57 | return uniform(1 << uniform(max_log + 1)); 58 | } 59 | 60 | private: 61 | uint32_t seed_; 62 | }; 63 | 64 | } } // namespace zl namespace base 65 | 66 | #endif // ZL_BASE_RANDOM_H 67 | -------------------------------------------------------------------------------- /zlreactor/base/ScopeExitGuard.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : ScopeExitGuard.h 3 | // Author : LIZHENG 4 | // Created : 2014-10-01 5 | // Description : RAII类,用于资源释放、清理 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_SCOPEEXITGUARD_H 10 | #define ZL_SCOPEEXITGUARD_H 11 | #include 12 | 13 | #define SCOPEGUARD_LINENAME_CAT(name, line) name##line 14 | #define SCOPEGUARD_LINENAME(name, line) SCOPEGUARD_LINENAME_CAT(name, line) 15 | #define ON_SCOPE_EXIT(callback) zl::base::ScopeExitGuard SCOPEGUARD_LINENAME(EXIT, __LINE__)(callback) 16 | 17 | namespace zl 18 | { 19 | namespace base 20 | { 21 | 22 | class ScopeExitGuard 23 | { 24 | public: 25 | explicit ScopeExitGuard(std::function onExitCallback) 26 | : onExitCb_(onExitCallback) 27 | , dismissed_(false) 28 | { 29 | } 30 | 31 | ScopeExitGuard(ScopeExitGuard&& rhs) 32 | : onExitCb_(std::move(rhs.onExitCb_)) 33 | , dismissed_(rhs.dismissed_) 34 | { 35 | } 36 | 37 | ~ScopeExitGuard() 38 | { 39 | if(!dismissed_) 40 | { 41 | onExitCb_(); 42 | } 43 | } 44 | 45 | void dismiss() 46 | { 47 | dismissed_ = true; 48 | } 49 | 50 | private: 51 | std::function onExitCb_; 52 | bool dismissed_; 53 | 54 | private: 55 | ScopeExitGuard(ScopeExitGuard const&); 56 | ScopeExitGuard& operator=(ScopeExitGuard const&); 57 | }; 58 | 59 | template 60 | ScopeExitGuard makeScopeExitGuard(F&& f) 61 | { 62 | return ScopeExitGuard(std::forward(f)); 63 | } 64 | 65 | } 66 | } 67 | #endif /* ZL_SCOPEEXITGUARD_H */ -------------------------------------------------------------------------------- /zlreactor/base/StringUtil.cpp: -------------------------------------------------------------------------------- 1 | #include "zlreactor/base/StringUtil.h" 2 | #include "zlreactor/Define.h" 3 | #include 4 | 5 | namespace zl 6 | { 7 | namespace base 8 | { 9 | 10 | #ifdef OS_WINDOWS 11 | #define VADUP(aq, ap) (backup_ap = ap) 12 | #else 13 | #define VADUP(aq, ap) va_copy(backup_ap, ap) 14 | #endif 15 | 16 | size_t stringFormatAppendImpl(std::string *dst, const char *format, va_list ap) 17 | { 18 | char space[1024]; // just try with a small fixed size buffer 19 | 20 | va_list backup_ap; // see "man va_start" 21 | VADUP(backup_ap, ap); 22 | 23 | int result = vsnprintf(space, sizeof(space), format, backup_ap); 24 | va_end(backup_ap); 25 | if ((result >= 0) && (result < static_cast(sizeof(space)))) 26 | { 27 | dst->append(space, result); 28 | return result; 29 | } 30 | 31 | int length = sizeof(space); 32 | while (true) // Repeatedly increase buffer size until it fits 33 | { 34 | if (result < 0) 35 | { 36 | length *= 2; 37 | } 38 | else 39 | { 40 | length = result + 1; 41 | } 42 | 43 | char* buf = new char[length]; 44 | VADUP(backup_ap, ap); // Restore the va_list before we use it again 45 | result = vsnprintf(buf, length, format, backup_ap); 46 | va_end(backup_ap); 47 | if ((result >= 0) && (result < length)) 48 | { 49 | dst->append(buf, result); 50 | delete[] buf; 51 | break; 52 | } 53 | delete[] buf; 54 | } 55 | 56 | return result; 57 | } 58 | 59 | size_t stringFormatAppend(std::string *dst, const char *format, ...) 60 | { 61 | va_list ap; 62 | va_start(ap, format); 63 | size_t result = stringFormatAppendImpl(dst, format, ap); 64 | va_end(ap); 65 | return result; 66 | } 67 | 68 | size_t stringFormat(std::string *dst, const char *format, ...) 69 | { 70 | va_list ap; 71 | va_start(ap, format); 72 | dst->clear(); 73 | size_t result = stringFormatAppendImpl(dst, format, ap); 74 | va_end(ap); 75 | return result; 76 | } 77 | 78 | std::string stringFormat(const char *format, ...) 79 | { 80 | va_list ap; 81 | va_start(ap, format); 82 | std::string result; 83 | stringFormatAppendImpl(&result, format, ap); 84 | va_end(ap); 85 | return result; 86 | } 87 | 88 | } // namespace base 89 | } // namespace zl 90 | -------------------------------------------------------------------------------- /zlreactor/base/Timestamp.cpp: -------------------------------------------------------------------------------- 1 | #include "zlreactor/base/Timestamp.h" 2 | #include 3 | #include "zlreactor/Define.h" 4 | #include 5 | #ifdef OS_WINDOWS 6 | #include 7 | #define ZL_LOCALTIME(a, b) localtime_s(b, a) 8 | #define ZL_GMTIME(a, b) gmtime_s(b, a) 9 | #else 10 | #include 11 | #define ZL_LOCALTIME(a, b) localtime_r(a, b) 12 | #define ZL_GMTIME(a, b) gmtime_r(a, b) 13 | #endif 14 | 15 | namespace zl 16 | { 17 | namespace base 18 | { 19 | 20 | Timestamp::Timestamp() : microSeconds_(0) 21 | { 22 | 23 | } 24 | 25 | Timestamp::Timestamp(int64_t ms) : microSeconds_(ms) 26 | { 27 | 28 | } 29 | 30 | /*static*/ Timestamp Timestamp::invalid() 31 | { 32 | return Timestamp(); 33 | } 34 | 35 | /*static*/ Timestamp Timestamp::now() 36 | { 37 | #ifdef OS_WINDOWS 38 | //Number of micro-seconds between the beginning of the Windows epoch (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970) 39 | const long long win_epoch_filetime = 116444736000000000ULL; 40 | 41 | FILETIME ft; 42 | LARGE_INTEGER li; 43 | GetSystemTimeAsFileTime(&ft); 44 | li.LowPart = ft.dwLowDateTime; 45 | li.HighPart = ft.dwHighDateTime; 46 | 47 | int64_t tt = (li.QuadPart - win_epoch_filetime) / 10; 48 | return Timestamp(tt); 49 | #else 50 | struct timeval tv; 51 | gettimeofday(&tv, NULL); 52 | return Timestamp(tv.tv_sec * ZL_USEC_PER_SEC + tv.tv_usec); 53 | #endif 54 | } 55 | 56 | struct tm Timestamp::getTm(bool showlocaltime/* = true*/) const 57 | { 58 | struct tm tm_time; 59 | time_t seconds = static_cast(microSeconds_ / ZL_USEC_PER_SEC); 60 | if(showlocaltime) 61 | ZL_LOCALTIME(&seconds, &tm_time); 62 | else 63 | ZL_GMTIME(&seconds, &tm_time); 64 | return tm_time; 65 | } 66 | 67 | std::string Timestamp::toString(bool showlocaltime/* = true*/) const 68 | { 69 | struct tm tm_time; 70 | time_t seconds = static_cast(microSeconds_ / ZL_USEC_PER_SEC); 71 | int microseconds = microSeconds_ % (ZL_USEC_PER_SEC); 72 | 73 | if(showlocaltime) 74 | ZL_LOCALTIME(&seconds, &tm_time); 75 | else 76 | ZL_GMTIME(&seconds, &tm_time); 77 | 78 | char buf[32] = { 0 }; 79 | ZL_SNPRINTF(buf, sizeof(buf), "%4d-%02d-%02d %02d:%02d:%02d:%06d", tm_time.tm_year + 1900, 80 | tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, microseconds); 81 | 82 | return buf; 83 | } 84 | 85 | } // namespace base 86 | } // namespace zl 87 | -------------------------------------------------------------------------------- /zlreactor/base/tests/AsyncLogger_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "zlreactor/base/Logger.h" 5 | #include "zlreactor/base/LogFile.h" 6 | #include "zlreactor/base/Timestamp.h" 7 | #include "zlreactor/base/AsyncLogger.h" 8 | #include "zlreactor/thread/Thread.h" 9 | #include 10 | using namespace std; 11 | using namespace zl::base; 12 | using namespace zl::thread; 13 | 14 | void test_asynclogger() 15 | { 16 | AsyncLogger logger; 17 | logger.start(); 18 | 19 | //LOG_CONSOLE_OUTPUT(false); 20 | LOG_DEBUG("This is a LOG_DEBUG msg!"); 21 | LOG_INFO("This is a LOG_INFO msg!"); 22 | LOG_NOTICE("This is a LOG_NOTICE msg!"); 23 | LOG_WARN("This is a LOG_WARN msg!"); 24 | LOG_ERROR("This is a LOG_ERROR msg!"); 25 | LOG_CRITICA("This is a LOG_CRITICA msg!"); 26 | LOG_ALERT("This is a LOG_ALERT msg!"); 27 | LOG_EMERGENCY("This is a LOG_EMERGENCY msg!"); 28 | // logger.stop(); 29 | cout << "####### test_log ########\n"; 30 | } 31 | 32 | void producer() 33 | { 34 | for (int i = 0; i < 5000; ++i) 35 | { 36 | LOG_DEBUG("[%d] This is a LOG_DEBUG msg!", this_thread::get_id().value()); 37 | LOG_INFO("[%d] This is a LOG_INFO msg!", this_thread::get_id().value()); 38 | LOG_NOTICE("[%d] This is a LOG_NOTICE msg!", this_thread::get_id().value()); 39 | LOG_WARN("[%d] This is a LOG_WARN msg!", this_thread::get_id().value()); 40 | LOG_ERROR("[%d] This is a LOG_ERROR msg!", this_thread::get_id().value()); 41 | LOG_CRITICA("[%d] This is a LOG_CRITICA msg!", this_thread::get_id().value()); 42 | LOG_ALERT("[%d] This is a LOG_ALERT msg!", this_thread::get_id().value()); 43 | LOG_EMERGENCY("[%d] This is a LOG_EMERGENCY msg!", this_thread::get_id().value()); 44 | } 45 | } 46 | 47 | void test_bench() 48 | { 49 | AsyncLogger logger; 50 | LOG_SET_LOGHANDLER(std::bind(&AsyncLogger::output, &logger, std::placeholders::_1, std::placeholders::_2)); 51 | logger.start(); 52 | 53 | int max_threads = 10; 54 | vector vec; 55 | for (int i = 0; i < max_threads; ++i) 56 | { 57 | vec.push_back(new Thread(producer)); 58 | } 59 | 60 | for (int i = 0; i < max_threads; ++i) 61 | { 62 | vec[i]->join(); 63 | delete vec[i]; 64 | } 65 | cout << "####### test_bench ########\n"; 66 | } 67 | 68 | int main() 69 | { 70 | test_asynclogger(); 71 | //test_bench(); 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /zlreactor/base/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${PROJECT_SOURCE_DIR}) 2 | 3 | set(CMAKE_CXX_FLAGS "-std=c++0x -Wall -pthread") 4 | 5 | link_directories(${CMAKE_INSTALL_PREFIX}/lib/ 6 | ${PROJECT_SOURCE_DIR}/lib/ 7 | ${PROJECT_BINARY_DIR}/lib/ 8 | ) 9 | 10 | add_executable(ConfigFile_test ConfigFile_test.cpp) 11 | target_link_libraries(ConfigFile_test zlreactor) 12 | 13 | add_executable(Daemon_test Daemon_test.cpp) 14 | target_link_libraries(Daemon_test zlreactor) 15 | 16 | add_executable(Exception_test Exception_test.cpp) 17 | target_link_libraries(Exception_test zlreactor) 18 | 19 | add_executable(AsyncLogger_test AsyncLogger_test.cpp) 20 | target_link_libraries(AsyncLogger_test zlreactor) 21 | 22 | add_executable(Logger_test Logger_test.cpp) 23 | target_link_libraries(Logger_test zlreactor) 24 | 25 | add_executable(MasterWorkerProcess_test MasterWorkerProcess_test.cpp) 26 | target_link_libraries(MasterWorkerProcess_test zlreactor) 27 | 28 | add_executable(ProcessUtil_test ProcessUtil_test.cpp) 29 | target_link_libraries(ProcessUtil_test zlreactor) 30 | 31 | add_executable(Singleton_test Singleton_test.cpp) 32 | target_link_libraries(Singleton_test zlreactor) 33 | 34 | add_executable(SmartAssert_test SmartAssert_test.cpp) 35 | target_link_libraries(SmartAssert_test zlreactor) 36 | 37 | add_executable(StringUtil_test StringUtil_test.cpp) 38 | target_link_libraries(StringUtil_test zlreactor) 39 | 40 | add_executable(Timestamp_test Timestamp_test.cpp) 41 | target_link_libraries(Timestamp_test zlreactor) 42 | 43 | -------------------------------------------------------------------------------- /zlreactor/base/tests/ConfigFile_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "zlreactor/base/ConfigFile.h" 4 | using namespace std; 5 | 6 | void test_ConfigFile() 7 | { 8 | zl::base::ConfigFile config("test.conf", "=", "#"); 9 | std::string serverIP = config.read("ServerIP", "127.0.0.1"); // if not exist, set default 127.0.0.1 10 | short serverPort = config.read("ServerPort", 80); // if not exist, set default 80 11 | std::cout << serverIP << " : " << serverPort << "\n"; 12 | 13 | int logsize = config.read("LogSize"); // if happen more than once, get the last one 14 | std::cout << logsize << "\n"; 15 | 16 | int threads = config.read("threads"); // if not exist, throw an exception 17 | } 18 | int main() 19 | { 20 | test_ConfigFile(); 21 | system("pause"); 22 | } -------------------------------------------------------------------------------- /zlreactor/base/tests/Daemon_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include // for exit 5 | #include 6 | #include // for O_CREAT 7 | #include 8 | #include 9 | #include "libTitCppKits/base/Daemonize.h" 10 | #include "libTitCppKits/base/Logger.h" 11 | #include "libTitCppKits/base/LogFile.h" 12 | 13 | void test_daemon_print_log(int nochdir = 1, int noclose = 0, const char *pidfile = 0) 14 | { 15 | LOG_INFO("test_daemon_print_log[%d] starting...", ::getpid()); 16 | 17 | int pid = zl::base::createDaemonize(nochdir, noclose, pidfile); 18 | if (pid < 0) 19 | { 20 | fprintf(stderr, "create daemon error. exit......\n"); 21 | exit(1); 22 | } 23 | else 24 | { 25 | printf("create daemon success, pid = [%d]\n", pid); 26 | assert(pid == ::getpid()); 27 | } 28 | 29 | 30 | LOG_INFO("test_daemon_print_log[%d] started...", ::getpid()); 31 | 32 | // 日志名,日志目录,日志回滚大小,线程安全,flush间隔0s, flush日志条数0条(也即是每次输出都flush) 33 | zl::base::LogFile* g_logFile = new zl::base::LogFile("Daemon_test", "./", 4000, true, 0, 0); 34 | assert(g_logFile); 35 | LOG_INFO("init log"); 36 | 37 | time_t t; 38 | int fd; 39 | while (1) 40 | { 41 | // fd = open("daemon.log", O_WRONLY | O_CREAT | O_APPEND, 0644); 42 | // if (fd == -1) 43 | // { 44 | // perror("open daemon.log error"); 45 | // exit(EXIT_FAILURE); 46 | // } 47 | t = time(0); 48 | char *buf = asctime(localtime(&t)); 49 | //write(fd, buf, strlen(buf)); //向daemon.log文件中写入当前时间 50 | //printf("[%d] time: %s\n", pid, buf); 51 | LOG_INFO("[%d][%d] time: %s", pid, ::getpid(), buf); 52 | //close(fd); 53 | sleep(3); // 每隔3s写入一次 54 | } 55 | 56 | zl::base::exitDaemonize(pidfile); 57 | } 58 | 59 | int main() 60 | { 61 | LOG_INFO("main[%d] starting...", ::getpid()); 62 | 63 | //test_daemon_print_log(1, 1, "Daemon_test.pid"); // 不改变当前目录,不重定向输入输出,禁止进程重复启动 64 | //test_daemon_print_log(1, 0, "Daemon_test.pid"); // 不改变当前目录,重定向输入输出(/dev/null),禁止进程重复启动 65 | test_daemon_print_log(1, 0, "Daemon_test.pid"); // 不改变当前目录,不重定向输入输出(/dev/null),允许进程重复启动 66 | } 67 | -------------------------------------------------------------------------------- /zlreactor/base/tests/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = Logger_test SmartAssert_test StringUtil_test Daemon_test Demangle_test ProcessUtil_test Timestamp_test ScopeExitGuard_test \ 4 | StlUtil_test AsyncLogger_test Exception_test MasterWorkerProcess_test ConfigFile_test StringPiece_test ObjectPool_test \ 5 | Singleton_test Preprocess_test 6 | 7 | INCLUDES = -I../../../zlreactor 8 | CPPFLAGS = -std=c++0x -O2 9 | LDFLAGS = -O2 -L../../../lib -lzlreactor -lrt 10 | 11 | Logger_test_SOURCES = Logger_test.cpp 12 | 13 | AsyncLogger_test_SOURCES = AsyncLogger_test.cpp 14 | 15 | SmartAssert_test_SOURCES = SmartAssert_test.cpp 16 | 17 | StringUtil_test_SOURCES = StringUtil_test.cpp 18 | 19 | Daemon_test_SOURCES = Daemon_test.cpp 20 | 21 | Demangle_test_SOURCES = Demangle_test.cpp 22 | 23 | Exception_test_LDFLAGS = -rdynamic 24 | Exception_test_SOURCES = Exception_test.cpp 25 | 26 | ProcessUtil_test_CPPFLAGS = $(CPPFLAGS) 27 | ProcessUtil_test_LDFLAGS = $(CPPFLAGS) 28 | ProcessUtil_test_SOURCES = ProcessUtil_test.cpp 29 | 30 | MasterWorkerProcess_test_SOURCES = MasterWorkerProcess_test.cpp 31 | 32 | Timestamp_test_LDFLAGS = $(CPPFLAGS) -lrt 33 | Timestamp_test_SOURCES = Timestamp_test.cpp 34 | 35 | ScopeExitGuard_test_LDFLAGS = $(CPPFLAGS) -std=c++1y 36 | ScopeExitGuard_test_SOURCES = ScopeExitGuard_test.cpp 37 | 38 | StlUtil_test_SOURCES = StlUtil_test.cpp 39 | 40 | ConfigFile_test_SOURCES = ConfigFile_test.cpp 41 | 42 | StringPiece_test_SOURCES = StringPiece_test.cpp 43 | 44 | ObjectPool_test_SOURCES = ObjectPool_test.cpp 45 | 46 | Singleton_test_SOURCES = Singleton_test.cpp 47 | 48 | Preprocess_test_SOURCES = Preprocess_test.cpp 49 | -------------------------------------------------------------------------------- /zlreactor/base/tests/MasterWorkerProcess_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "zlreactor/base/MasterWorkerProcess.h" 6 | using namespace zl; 7 | 8 | class Test 9 | { 10 | public: 11 | Test() : num_(0) {} 12 | 13 | int num_; 14 | }; 15 | 16 | //#define TEST_SUB_PROCESS_EXIT 17 | 18 | void child_process_work(zl::MasterWorkerProcess* main_process, int jobid, void* arg) 19 | { 20 | assert(main_process->pid() == MasterWorkerProcess::mainProcessPid()); 21 | assert(MasterWorkerProcess::mainProcessPid() != ::getpid()); 22 | 23 | FILE* file = fopen("one.log", "a+"); 24 | assert(file); 25 | while (!main_process->shutdown()) 26 | { 27 | char buffer[1024]; 28 | sprintf(buffer, "[%d][%d][%d]=======[%d]======\n", main_process->pid(), MasterWorkerProcess::mainProcessPid(), ::getpid(), main_process->shutdown()); 29 | printf("%s", buffer); 30 | fwrite(buffer, strlen(buffer), 1, file); 31 | fflush(file); 32 | sprintf(buffer, "child process[%d], jobid[%d], just sleep 6s\n", ::getpid(), jobid); 33 | printf("%s", buffer); 34 | fwrite(buffer, strlen(buffer), 1, file); 35 | fflush(file); 36 | ::sleep(6); 37 | #if defined(TEST_SUB_PROCESS_EXIT) 38 | break; 39 | #endif 40 | } 41 | printf("child process[%d] [%d]: exit the work\n", ::getpid(), main_process->shutdown()); 42 | fclose(file); 43 | } 44 | 45 | int main(int argc, char *argv[]) 46 | { 47 | if (argc != 2) 48 | { 49 | printf("error, should run as : bin child_num, ex : %s 3\n", argv[0]); 50 | return 0; 51 | } 52 | 53 | printf("main process[%d] starting...\n", ::getpid()); 54 | 55 | zl::MasterWorkerProcess process; 56 | process.createWorkProcess(atoi(argv[1]), child_process_work, NULL); 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /zlreactor/base/tests/ObjectPool_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "zlreactor/base/ObjectPool.h" 4 | #include "zlreactor/base/Singleton.h" 5 | #include "zlreactor/thread/Mutex.h" 6 | #include "zlreactor/thread/FastMutex.h" 7 | using namespace std; 8 | 9 | class TO 10 | { 11 | char c; 12 | int i; 13 | float t; 14 | double d; 15 | string s; 16 | }; 17 | 18 | class TO1 19 | { 20 | char c; 21 | int i; 22 | float t; 23 | double d; 24 | string s; 25 | TO *to; 26 | }; 27 | 28 | template 29 | void dump(const OP& pool) 30 | { 31 | cout << "------ dump objectpool ------\n"; 32 | cout << "max alloc : " << pool.max_alloc() << "\n"; 33 | cout << "total alloc : " << pool.total() << "\n"; 34 | cout << "avail : " << pool.avail() << "\n"; 35 | //cout << "------ --------------- ------\n"; 36 | } 37 | 38 | void test_maxalloc(int preAllocNum, int maxAllocNum) 39 | { 40 | cout << "test_maxalloc: " << preAllocNum << " " << maxAllocNum << "= = = = = = = = = \n"; 41 | 42 | zl::base::ObjectPool pool(preAllocNum, maxAllocNum); 43 | dump(pool); 44 | 45 | TO1* p = NULL; 46 | for(int i = 0; i < maxAllocNum; ++i) 47 | { 48 | p = pool.alloc(); 49 | assert(p); 50 | dump(pool); 51 | } 52 | 53 | TO1* p1 = pool.alloc(); 54 | assert(!p1); 55 | dump(pool); 56 | 57 | pool.free(p); 58 | TO1* p2 = pool.alloc(); 59 | assert(p2); 60 | dump(pool); 61 | } 62 | 63 | template 64 | void test_mutexlock() 65 | { 66 | cout << "test_mutexlock: " << "= = = = = = = = = \n"; 67 | zl::base::ObjectPool pool; 68 | T* t1 = pool.alloc(); 69 | pool.free(t1); 70 | cout << t1 << "\n"; 71 | T* t2 = pool.alloc(); 72 | cout << t2 << "\n"; 73 | T* t3 = pool.alloc(); 74 | cout << t2 << "\t" << t3 << "\t" << t3 - t2 << "\t" << sizeof(T) << "\n"; 75 | cout << "---------------\n"; 76 | } 77 | int main() 78 | { 79 | test_maxalloc(10, 2); 80 | test_maxalloc(1, 3); 81 | test_maxalloc(0, 4); 82 | 83 | test_mutexlock(); 84 | test_mutexlock(); 85 | test_mutexlock(); 86 | 87 | } -------------------------------------------------------------------------------- /zlreactor/base/tests/Preprocess_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "zlreactor/base/Preprocess.h" 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | int i = 123; 9 | assert(string("ABC") == ZL_PP_STRINGIZE(ABC)); 10 | assert(1234 == ZL_PP_JOIN(1, 234)); 11 | 12 | cout << ZL_PP_STRINGIZE(i) << "\n"; // cout i, not 123 13 | cout << ZL_PP_JOIN(123, 47) << "\n"; // 12347 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /zlreactor/base/tests/Singleton_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "zlreactor/base/Singleton.h" 4 | using namespace std; 5 | //using namespace zl; 6 | 7 | class Manager : public zl::Singleton 8 | { 9 | DECLARE_SINGLETON_CLASS(Manager); 10 | public: 11 | void start() 12 | { 13 | cout << "start\n"; 14 | } 15 | 16 | private: 17 | Manager() { cout << "Ctor\n"; } 18 | ~Manager() { cout << "Dtor\n"; } 19 | int id; 20 | }; 21 | 22 | int main() 23 | { 24 | zl::Singleton::getInstancePtr()->start(); 25 | 26 | Manager *m1 = zl::Singleton::getInstancePtr(); 27 | Manager *m2 = zl::Singleton::getInstancePtr(); 28 | Manager *m3 = zl::Singleton::getInstancePtr(); 29 | 30 | assert(m1 == m2); 31 | assert(m1 == m3); 32 | 33 | cout << "GAME OVER\n"; 34 | } 35 | -------------------------------------------------------------------------------- /zlreactor/base/tests/SmartAssert_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "zlreactor/base/SmartAssert.h" 5 | using namespace std; 6 | //using namespace zl::base; 7 | 8 | ZL_STATIC_ASSERT(SIGINT == 2, "SIGINT == 2 must be true"); 9 | 10 | int main() 11 | { 12 | { 13 | const static int i = 2; 14 | ZL_STATIC_ASSERT(i>0); 15 | ZL_STATIC_ASSERT(i>0, "i must greater than 0"); 16 | //ZL_STATIC_ASSERT(i>3); // complie failure 17 | //ZL_STATIC_ASSERT(i>3, "must i>3"); // complie failure 18 | } 19 | { 20 | int i = 2; 21 | 22 | std::vector vec; 23 | vec.push_back(5); 24 | ZL_ASSERT_LOG(vec.size() >= i)(i)(vec.size()); 25 | printf("---------------------------------\n"); 26 | ZL_ASSERT_LOG(vec.size() >= i)(i)(vec.size()); 27 | printf("---------------------------------\n"); 28 | 29 | ZL_ASSERT(i != 2); 30 | printf("---------------------------------\n"); 31 | ZL_ASSERTEX(i != 2, "sdfs", 342, "zxcvbnm"); 32 | printf("---------------------------------\n"); 33 | //ZL_STATIC_ASSERT(sizeof(i)>=8); 34 | ZL_ASSERT(i ==2 )(i); 35 | ZL_ASSERT(i != 2)(i); 36 | printf("---------------------------------\n"); 37 | 38 | } 39 | 40 | system("pause"); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /zlreactor/meta/meta_util.hpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/zlreactor/meta/meta_util.hpp -------------------------------------------------------------------------------- /zlreactor/net/ByteBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "zlreactor/net/ByteBuffer.h" 2 | NAMESPACE_ZL_NET_START 3 | 4 | const char ByteBuffer::kCRLF[] = "\r\n"; 5 | const char ByteBuffer::kDoubleCRLF[] = "\r\n\r\n"; 6 | 7 | //const size_t ByteBuffer::kCheapPrepend; 8 | //const size_t ByteBuffer::kInitialSize; 9 | 10 | NAMESPACE_ZL_NET_END -------------------------------------------------------------------------------- /zlreactor/net/CallBacks.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : CallBacks.h 3 | // Author : LIZHENG 4 | // Created : 2014-10-31 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_CALLBACKS_H 10 | #define ZL_CALLBACKS_H 11 | #include //for std::shared_ptr 12 | #include "zlreactor/base/Timestamp.h" 13 | NAMESPACE_ZL_NET_START 14 | 15 | class ByteArray; 16 | class EventLoop; 17 | class TcpConnection; 18 | class InetAddress; 19 | class TcpAcceptor; 20 | class ByteBuffer; 21 | using zl::base::Timestamp; 22 | 23 | //typedef std::string Buffer; 24 | typedef std::shared_ptr TcpConnectionPtr; 25 | 26 | void defaultConnectionCallback(const TcpConnectionPtr& conn); 27 | void defaultMessageCallback(const TcpConnectionPtr& conn, ByteBuffer* buffer, Timestamp receiveTime); 28 | 29 | typedef std::function ConnectionCallback; 30 | typedef std::function CloseCallback; 31 | typedef std::function WriteCompleteCallback; 32 | typedef std::function MessageCallback; 33 | 34 | 35 | typedef int TimerId; 36 | typedef std::function TimerCallback; 37 | 38 | typedef std::function SignalCallback; 39 | 40 | NAMESPACE_ZL_NET_END 41 | #endif /* ZL_CALLBACKS_H */ 42 | -------------------------------------------------------------------------------- /zlreactor/net/Channel.cpp: -------------------------------------------------------------------------------- 1 | #include "zlreactor/net/Channel.h" 2 | #include 3 | #include 4 | #include "zlreactor/base/Logger.h" 5 | #include "zlreactor/net/EventLoop.h" 6 | NAMESPACE_ZL_NET_START 7 | 8 | Channel::Channel(EventLoop* loop, int fd) 9 | : loop_(loop) 10 | , fd_(fd) 11 | , events_(0) 12 | , revents_(0) 13 | { 14 | } 15 | 16 | Channel::~Channel() 17 | { 18 | if (loop_->isInLoopThread()) 19 | { 20 | // assert(!loop_->hasChannel(this)); // ԭ��ͬTcpConnection����ʱ��ע�� 21 | } 22 | } 23 | 24 | void Channel::update() 25 | { 26 | loop_->updateChannel(this); 27 | } 28 | 29 | void Channel::remove() 30 | { 31 | assert(isNoneEvent()); 32 | loop_->removeChannel(this); 33 | } 34 | 35 | void Channel::handleEvent(Timestamp receiveTime) 36 | { 37 | handleEventWithHold(receiveTime); 38 | } 39 | 40 | void Channel::handleEventWithHold(Timestamp receiveTime) 41 | { 42 | if ((revents_ & FDEVENT_HUP) && !(revents_ & FDEVENT_IN)) 43 | { 44 | LOG_INFO("Channel::handleEventWithHold closeCallback, fd[%d]", fd_); 45 | if (closeCallback_) 46 | closeCallback_(); 47 | } 48 | 49 | if (revents_ & FDEVENT_NVAL) 50 | { 51 | LOG_WARN("Channel::handle_event() POLLNVAL, fd[%d]", fd_); 52 | } 53 | 54 | if (revents_ & (FDEVENT_ERR | FDEVENT_NVAL)) 55 | { 56 | LOG_INFO("Channel::handleEventWithHold closeCallback, fd[%d]", fd_); 57 | if (errorCallback_) 58 | errorCallback_(); 59 | } 60 | if (revents_ & kEventRead) 61 | { 62 | if (readCallback_) 63 | readCallback_(receiveTime); 64 | } 65 | if (revents_ & FDEVENT_OUT) 66 | { 67 | if (writeCallback_) 68 | writeCallback_(); 69 | } 70 | } 71 | 72 | std::string Channel::reventsToString() const 73 | { 74 | std::ostringstream oss; 75 | oss << fd_ << ": "; 76 | if (revents_ & FDEVENT_IN) 77 | oss << "IN "; 78 | if (revents_ & FDEVENT_PRI) 79 | oss << "PRI "; 80 | if (revents_ & FDEVENT_OUT) 81 | oss << "OUT "; 82 | if (revents_ & FDEVENT_HUP) 83 | oss << "HUP "; 84 | if (revents_ & FDEVENT_RDHUP) 85 | oss << "RDHUP "; 86 | if (revents_ & FDEVENT_ERR) 87 | oss << "ERR "; 88 | if (revents_ & FDEVENT_NVAL) 89 | oss << "NVAL "; 90 | 91 | return oss.str().c_str(); 92 | } 93 | 94 | NAMESPACE_ZL_NET_END 95 | -------------------------------------------------------------------------------- /zlreactor/net/DomainResolver.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : DomainResolver.h 3 | // Author : LIZHENG 4 | // Created : 2015-04-09 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_DOMAINRESOLVER_H 10 | #define ZL_DOMAINRESOLVER_H 11 | #include "zlreactor/Define.h" 12 | #include "zlreactor/net/InetAddress.h" 13 | struct hostent; 14 | struct addrinfo; 15 | NAMESPACE_ZL_NET_START 16 | 17 | class DomainResolver; 18 | 19 | /// 存储主机名、别名、ip地址 20 | class HostEntry 21 | { 22 | public: 23 | typedef std::vector AliasList; 24 | typedef std::vector AddressList; 25 | 26 | public: 27 | void initialize(const struct hostent* entry); 28 | 29 | void initialize(const struct addrinfo* info); 30 | 31 | const std::string& name() const { return hostName_; } 32 | 33 | const AliasList aliases() const { return aliases_; } 34 | 35 | const AddressList& addresses() const { return addresses_; } 36 | 37 | void clear() 38 | { 39 | hostName_.clear(); 40 | aliases_.clear(); 41 | addresses_.clear(); 42 | } 43 | 44 | void swap(HostEntry& other) 45 | { 46 | std::swap(hostName_, other.hostName_); 47 | std::swap(aliases_, other.aliases_); 48 | std::swap(addresses_, other.addresses_); 49 | } 50 | 51 | private: 52 | void add(const InetAddress& address); 53 | 54 | private: 55 | std::string hostName_; 56 | AliasList aliases_; /// alias names 57 | AddressList addresses_; 58 | }; 59 | 60 | class DomainResolver 61 | { 62 | public: 63 | static bool query(const std::string& hostname, HostEntry* host, int *error = NULL); 64 | 65 | static bool resolveInetAddress(const std::string& hostname, std::vector* ips, int *error = NULL); 66 | 67 | static bool isError(int error); 68 | 69 | static std::string errorString(int error); 70 | }; 71 | 72 | #endif /* ZL_DOMAINRESOLVER_H */ 73 | NAMESPACE_ZL_NET_END 74 | -------------------------------------------------------------------------------- /zlreactor/net/EventLoopThreadPool.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : EventLoopThreadPool.h 3 | // Author : LIZHENG 4 | // Created : 2014-11-07 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_EVENTLOOPTHREADPOOL_H 10 | #define ZL_EVENTLOOPTHREADPOOL_H 11 | #include "zlreactor/Define.h" 12 | #include "zlreactor/base/NonCopy.h" 13 | #include "zlreactor/net/SocketUtil.h" 14 | #include "zlreactor/net/InetAddress.h" 15 | #include "zlreactor/thread/Mutex.h" 16 | namespace zl 17 | { 18 | namespace thread 19 | { 20 | class Thread; 21 | class CountDownLatch; 22 | } 23 | } 24 | NAMESPACE_ZL_NET_START 25 | class EventLoop; 26 | 27 | class EventLoopThreadPool : zl::NonCopy 28 | { 29 | public: 30 | EventLoopThreadPool(EventLoop* baseLoop); 31 | ~EventLoopThreadPool(); 32 | 33 | std::vector getAllLoops() { return loops_; } 34 | 35 | /// 设置EventLoopThreadPool的threads大小;if numThreads 36 | /// < 0 : 设置该值为当前系统CPU并发数; 37 | /// == 0 : 不使用EventLoopThreadPool,所有Channel都在同一个EventLoop中运行,默认值; 38 | /// > 0 : 设置numThreads个线程,也即numThreads个EventLoop,每个连接选择其中一个 39 | void setMultiReactorThreads(int numThreads); 40 | 41 | void start(); 42 | bool isStart() { return started_; } 43 | EventLoop* getNextLoop(); 44 | 45 | private: 46 | void runLoop(); 47 | 48 | private: 49 | EventLoop *baseLoop_; 50 | bool started_; 51 | int numThreads_; 52 | size_t next_; 53 | zl::thread::Mutex mutex_; 54 | zl::thread::CountDownLatch *latch_; 55 | std::vector loops_; 56 | std::vector threads_; 57 | }; 58 | 59 | NAMESPACE_ZL_NET_END 60 | #endif /* EVENTLOOPTHREADPOOL */ 61 | -------------------------------------------------------------------------------- /zlreactor/net/Eventfd.cpp: -------------------------------------------------------------------------------- 1 | #include "zlreactor/net/Eventfd.h" 2 | #include 3 | #include 4 | #include "zlreactor/base/Logger.h" 5 | #include "zlreactor/net/SocketUtil.h" 6 | NAMESPACE_ZL_NET_START 7 | 8 | EventfdHandler::EventfdHandler(unsigned int initval/* = 0 */, int flags/* = EFD_NONBLOCK | EFD_CLOEXEC */) 9 | { 10 | eventfd_ = -1; 11 | createEventfd(initval, flags); 12 | } 13 | 14 | EventfdHandler::~EventfdHandler() 15 | { 16 | if(eventfd_ != -1) 17 | { 18 | ::close(eventfd_); 19 | eventfd_ = -1; 20 | } 21 | } 22 | 23 | int EventfdHandler::createEventfd(unsigned int initval, int flags) 24 | { 25 | int efd = ::eventfd(initval, flags); 26 | if (efd < 0) 27 | { 28 | LOG_ALERT("create eventfd failed in EventfdHandler::createEventfd()"); 29 | return efd; 30 | } 31 | LOG_INFO("EventfdHandler::createEventfd [%d]", efd); 32 | 33 | eventfd_ = efd; 34 | return efd; 35 | } 36 | 37 | ssize_t EventfdHandler::write(uint64_t value/* = 1 */) 38 | { 39 | ssize_t n = ::write(eventfd_, &value, sizeof(value)); 40 | if (n != sizeof(value)) // just write one uint64_t 41 | { 42 | LOG_ERROR("EventfdHandler::write(): write error[%d][%d][%d]", eventfd_, n, errno); 43 | } 44 | return n; 45 | } 46 | 47 | ssize_t EventfdHandler::read(uint64_t *value/* = NULL*/) 48 | { 49 | ssize_t n; 50 | if (value == NULL) 51 | { 52 | uint64_t tmp; 53 | n = ::read(eventfd_, &tmp, sizeof(uint64_t)); 54 | } 55 | else 56 | { 57 | n = ::read(eventfd_, value, sizeof(uint64_t)); 58 | } 59 | 60 | if (n != sizeof(value)) //always return 8 byte 61 | { 62 | LOG_ERROR("EventfdHandler::read(): read error[%d][%d][%d][%s]", eventfd_, n, errno, strerror(errno)); 63 | } 64 | 65 | return n; 66 | } 67 | 68 | NAMESPACE_ZL_NET_END -------------------------------------------------------------------------------- /zlreactor/net/Eventfd.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : Eventfd.h 3 | // Author : LIZHENG 4 | // Created : 2015-01-14 5 | // Description : 进程及线程间的事件通知,need linux kernel > 2.6.22 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_EVENTFD_H 10 | #define ZL_EVENTFD_H 11 | #include "zlreactor/Define.h" 12 | #include 13 | #include 14 | NAMESPACE_ZL_NET_START 15 | 16 | // eventfd的缓冲区大小是sizeof(uint64_t), 也即是8字节. 17 | // 它是一个64位计数器, 计数器不为零是有可读事件发生. 18 | // 写入一次增加计数器值,读取将获取计数器值,并清零. 19 | 20 | class EventfdHandler 21 | { 22 | public: 23 | EventfdHandler(unsigned int initval = 0, int flags = EFD_NONBLOCK | EFD_CLOEXEC); 24 | ~EventfdHandler(); 25 | 26 | public: 27 | int fd() { return eventfd_; } 28 | 29 | void notify() { write(1); } 30 | 31 | ssize_t write(uint64_t value = 1); 32 | 33 | ssize_t read(uint64_t *value = NULL); 34 | 35 | private: 36 | /// iff success, return eventfd_, else return -1; 37 | int createEventfd(unsigned int initval, int flags); 38 | 39 | private: 40 | int eventfd_; 41 | }; 42 | 43 | NAMESPACE_ZL_NET_END 44 | #endif /* ZL_EVENTFD_H */ 45 | -------------------------------------------------------------------------------- /zlreactor/net/InetAddress.cpp: -------------------------------------------------------------------------------- 1 | #include "zlreactor/net/InetAddress.h" 2 | #include 3 | NAMESPACE_ZL_NET_START 4 | 5 | InetAddress::InetAddress(uint16_t port/* = 0*/) 6 | { 7 | ::memset(&addr_, 0, sizeof(addr_)); 8 | addr_.sin_family = AF_INET; 9 | addr_.sin_port = htons(port); 10 | addr_.sin_addr.s_addr = INADDR_ANY; 11 | } 12 | 13 | InetAddress::InetAddress(const char *ip, uint16_t port) 14 | { 15 | ::memset(&addr_, 0, sizeof(addr_)); 16 | addr_.sin_family = AF_INET; 17 | addr_.sin_port = htons(port); 18 | int nIP = 0; 19 | if (!ip || '\0' == *ip || 0 == strcmp(ip, "0") 20 | || 0 == strcmp(ip, "0.0.0.0") || 0 == strcmp(ip, "*")) 21 | { 22 | nIP = htonl(INADDR_ANY); 23 | } 24 | else 25 | { 26 | nIP = inet_addr(ip); 27 | } 28 | addr_.sin_addr.s_addr = nIP; 29 | } 30 | 31 | InetAddress::InetAddress(const ZL_SOCKADDR_IN& addr) : addr_(addr) 32 | { 33 | 34 | } 35 | 36 | std::string InetAddress::ip() const 37 | { 38 | char ip[256], tmp[256]; 39 | ZL_SNPRINTF(ip, 128, "%s", inet_ntop(AF_INET, (void*)&addr_.sin_addr, tmp, 256)); 40 | return ip; 41 | } 42 | 43 | uint16_t InetAddress::port() const 44 | { 45 | return ntohs(addr_.sin_port); 46 | } 47 | 48 | std::string InetAddress::ipPort() const 49 | { 50 | char host[256], ip[256]; 51 | ZL_SNPRINTF(host, 256, "%s:%d", inet_ntop(AF_INET, (void*)&addr_.sin_addr, ip, 256), ntohs(addr_.sin_port)); 52 | return host; 53 | } 54 | 55 | /*static*/ bool InetAddress::resolve(const char *hostname, InetAddress *addr) 56 | { 57 | #ifdef OS_LINUX 58 | static __thread char g_resolveBuffer[64 * 1024]; 59 | struct hostent hent; 60 | struct hostent* he = NULL; 61 | int herrno = 0; 62 | bzero(&hent, sizeof(hent)); 63 | 64 | int ret = gethostbyname_r(hostname, &hent, g_resolveBuffer, sizeof(g_resolveBuffer), &he, &herrno); 65 | if (ret == 0 && he != NULL) 66 | { 67 | assert(he->h_addrtype == AF_INET && he->h_length == sizeof(uint32_t)); 68 | addr->addr_.sin_addr = *reinterpret_cast(he->h_addr); 69 | return true; 70 | } 71 | else 72 | { 73 | return false; 74 | } 75 | #elif defined(OS_WINDOWS) 76 | //static __declspec(thread) char g_resolveBuffer[64 * 1024]; 77 | hostent *hent = gethostbyname(hostname); 78 | if (hent == 0) 79 | return false; 80 | addr->addr_.sin_addr.S_un.S_addr = ntohl(*(u_long *)hent->h_addr_list[0]); 81 | //addr.addr_.S_un.S_addr = ntohl(*(u_long *)hent->h_addr_list[0]); 82 | return true; 83 | #endif 84 | } 85 | 86 | NAMESPACE_ZL_NET_END -------------------------------------------------------------------------------- /zlreactor/net/InetAddress.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : InetAddress.h 3 | // Author : LIZHENG 4 | // Created : 2014-09-06 5 | // Description : InetAddress的跨平台包装 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_INETADDRESS_H 10 | #define ZL_INETADDRESS_H 11 | #include "zlreactor/Define.h" 12 | #include "zlreactor/base/NonCopy.h" 13 | #include "zlreactor/net/SocketUtil.h" 14 | #ifdef OS_WINDOWS 15 | #include 16 | #include 17 | #else 18 | #include 19 | #include 20 | #endif 21 | NAMESPACE_ZL_NET_START 22 | 23 | class InetAddress 24 | { 25 | public: 26 | explicit InetAddress(uint16_t port = 0); 27 | InetAddress(const char *ip, uint16_t port); 28 | InetAddress(const ZL_SOCKADDR_IN& addr); 29 | 30 | static bool resolve(const char *hostname, InetAddress *addr); 31 | 32 | public: 33 | uint16_t port() const; 34 | std::string ip() const; 35 | std::string ipPort() const; 36 | 37 | size_t addressLength() const { return sizeof(addr_); } 38 | operator struct sockaddr *() const{ return (struct sockaddr*)&addr_; } 39 | 40 | const ZL_SOCKADDR_IN& getSockAddrInet() const { return addr_; } 41 | void setSockAddrInet(const ZL_SOCKADDR_IN& addr) { addr_ = addr; } 42 | 43 | uint32_t ipNetEndian() const { return addr_.sin_addr.s_addr; } 44 | uint16_t portNetEndian() const { return addr_.sin_port; } 45 | 46 | private: 47 | ZL_SOCKADDR_IN addr_; 48 | }; 49 | 50 | NAMESPACE_ZL_NET_END 51 | #endif /* ZL_INETADDRESS_H */ 52 | -------------------------------------------------------------------------------- /zlreactor/net/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = Makefile.in 2 | 3 | SUBDIRS = 4 | 5 | SUBDIRS += tests 6 | -------------------------------------------------------------------------------- /zlreactor/net/Signalfd.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : Signalfd.h 3 | // Author : LIZHENG 4 | // Created : 2015-01-07 5 | // Description : signalfd need linux kernel > 2.6.25 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_SIGNALFD_H 10 | #define ZL_SIGNALFD_H 11 | #include "zlreactor/Define.h" 12 | #include "zlreactor/net/CallBacks.h" 13 | #include 14 | #include 15 | NAMESPACE_ZL_NET_START 16 | 17 | typedef int Signalfd; 18 | 19 | class SignalfdHandler 20 | { 21 | public: 22 | SignalfdHandler(); 23 | ~SignalfdHandler(); 24 | 25 | public: 26 | Signalfd fd() { return signalFd_; } 27 | 28 | void addSigHandler(int sig, const SignalCallback& handler); 29 | 30 | void removeSig(int sig); 31 | 32 | bool haveSignal(int sig); 33 | 34 | /// must call registerAll after addSigHandler 35 | void registerAll(int flags = SFD_NONBLOCK | SFD_CLOEXEC); 36 | 37 | /// read signalno and return 38 | int readSig(); 39 | 40 | /// sync loop-read 41 | void wait(); 42 | 43 | void stop() { isReady_ = false; } 44 | 45 | private: 46 | Signalfd createSignalfd(int flags); 47 | 48 | private: 49 | typedef std::unordered_map SigHandlerMap; 50 | 51 | bool isReady_; 52 | Signalfd signalFd_; 53 | sigset_t mask_; 54 | SigHandlerMap sigHanhlers_; 55 | }; 56 | 57 | NAMESPACE_ZL_NET_END 58 | #endif /* ZL_SIGNALFD_H */ 59 | -------------------------------------------------------------------------------- /zlreactor/net/TcpAcceptor.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : TcpAcceptor.h 3 | // Author : LIZHENG 4 | // Created : 2014-10-26 5 | // Description : 服务端接受器,监听在某一端口上,接受远程Socket连接 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_TCPACCEPTOR_H 10 | #define ZL_TCPACCEPTOR_H 11 | #include "zlreactor/Define.h" 12 | #include "zlreactor/base/Timestamp.h" 13 | #include "zlreactor/base/NonCopy.h" 14 | NAMESPACE_ZL_NET_START 15 | class Socket; 16 | class InetAddress; 17 | class Channel; 18 | class EventLoop; 19 | using zl::base::Timestamp; 20 | 21 | class TcpAcceptor : zl::NonCopy 22 | { 23 | public: 24 | //typedef std::function NewConnectionCallback; 25 | typedef std::function NewConnectionCallback; 26 | public: 27 | TcpAcceptor(EventLoop *loop, const InetAddress& listenAddr); 28 | ~TcpAcceptor(); 29 | 30 | void setNewConnectionCallback(const NewConnectionCallback& callback) 31 | { 32 | newConnCallBack_ = callback; 33 | } 34 | 35 | void listen(); 36 | 37 | private: 38 | void onAccept(Timestamp now); 39 | 40 | private: 41 | EventLoop *loop_; 42 | Socket *accept_socket; 43 | Channel *accept_channel_; 44 | NewConnectionCallback newConnCallBack_; 45 | }; 46 | 47 | NAMESPACE_ZL_NET_END 48 | #endif /* ZL_TCPACCEPTOR_H */ 49 | -------------------------------------------------------------------------------- /zlreactor/net/TcpClient.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : TcpClient.h 3 | // Author : LIZHENG 4 | // Created : 2014-11-06 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_TCPCLIENT_H 10 | #define ZL_TCPCLIENT_H 11 | #include "zlreactor/Define.h" 12 | #include "zlreactor/base/Timestamp.h" 13 | #include "zlreactor/thread/Mutex.h" 14 | #include "zlreactor/net/CallBacks.h" 15 | #include "zlreactor/net/InetAddress.h" 16 | #include "zlreactor/base/NonCopy.h" 17 | #include "zlreactor/net/TcpConnection.h" 18 | using zl::base::Timestamp; 19 | using zl::thread::Mutex; 20 | 21 | NAMESPACE_ZL_NET_START 22 | 23 | class EventLoop; 24 | class InetAddress; 25 | class TcpConnector; 26 | class ByteBuffer; 27 | class Tcpconnection; 28 | 29 | class TcpClient 30 | { 31 | public: 32 | TcpClient(EventLoop* loop, const InetAddress& serverAddr, const std::string& clientname = "TcpClient"); 33 | ~TcpClient(); 34 | 35 | public: 36 | EventLoop* getLoop() const { return loop_; } 37 | ZL_SOCKET fd() const 38 | { 39 | assert(connection_); 40 | return connection_->fd(); 41 | } 42 | 43 | void setConnectionCallback(const ConnectionCallback& cb) 44 | { connectionCallback_ = cb; } 45 | 46 | void setMessageCallback(const MessageCallback& cb) 47 | { messageCallback_ = cb; } 48 | 49 | void setWriteCompleteCallback(const WriteCompleteCallback& cb) 50 | { writeCompleteCallback_ = cb; } 51 | 52 | public: 53 | void connect(); 54 | void disconnect(); 55 | void stop(); 56 | 57 | bool retry() const; 58 | void enableRetry() { retry_ = true; } 59 | 60 | private: 61 | void newConnection(int sockfd); 62 | void removeConnection(const TcpConnectionPtr& conn); 63 | 64 | private: 65 | EventLoop *loop_; 66 | TcpConnector *connector_; 67 | ConnectionCallback connectionCallback_; 68 | MessageCallback messageCallback_; 69 | WriteCompleteCallback writeCompleteCallback_; 70 | bool retry_; 71 | bool connect_; 72 | TcpConnectionPtr connection_; 73 | const std::string clientName_; 74 | }; 75 | 76 | NAMESPACE_ZL_NET_END 77 | #endif /* ZL_TCPCLIENT_H */ 78 | -------------------------------------------------------------------------------- /zlreactor/net/TcpConnector.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : TcpConnector.h 3 | // Author : LIZHENG 4 | // Created : 2014-10-26 5 | // Description : 客户端连接器,连接远程Socket 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_TCPCONNECTOR_H 10 | #define ZL_TCPCONNECTOR_H 11 | #include "zlreactor/Define.h" 12 | #include "zlreactor/base/NonCopy.h" 13 | #include "zlreactor/net/SocketUtil.h" 14 | #include "zlreactor/net/InetAddress.h" 15 | NAMESPACE_ZL_NET_START 16 | class Socket; 17 | class Channel; 18 | class EventLoop; 19 | class InetAddress; 20 | 21 | class TcpConnector : zl::NonCopy 22 | { 23 | public: 24 | typedef std::function NewConnectionCallback; 25 | 26 | public: 27 | TcpConnector(EventLoop *loop, const InetAddress& serverAddr); 28 | ~TcpConnector(); 29 | 30 | void setNewConnectionCallback(const NewConnectionCallback& callback) 31 | { 32 | newConnCallBack_ = callback; 33 | } 34 | 35 | const InetAddress& serverAddress() const 36 | { 37 | return serverAddr_; 38 | } 39 | 40 | void connect(); 41 | void stop(); 42 | 43 | private: 44 | void connectInLoop(); 45 | void connectServer(); 46 | void connectEstablished(ZL_SOCKET sock); 47 | void stopInLoop(); 48 | 49 | void handleWrite(); 50 | void handleError(); 51 | ZL_SOCKET disableChannel(); 52 | void retry(ZL_SOCKET sockfd); 53 | 54 | enum States { kDisconnected, kConnecting, kConnected }; 55 | void setState(States s) { state_ = s; } 56 | 57 | private: 58 | States state_; 59 | bool connect_; 60 | EventLoop *loop_; 61 | const InetAddress& serverAddr_; 62 | Channel *connChannel_; 63 | NewConnectionCallback newConnCallBack_; 64 | }; 65 | 66 | typedef TcpConnector* TcpConnectorPtr; 67 | 68 | NAMESPACE_ZL_NET_END 69 | #endif /* ZL_TCPCONNECTOR_H */ 70 | -------------------------------------------------------------------------------- /zlreactor/net/Timer.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : Timer.h 3 | // Author : LIZHENG 4 | // Created : 2014-12-22 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_TIMER_H 10 | #define ZL_TIMER_H 11 | #include "zlreactor/Define.h" 12 | #include "zlreactor/base/NonCopy.h" 13 | #include "zlreactor/thread/Mutex.h" 14 | #include "zlreactor/net/CallBacks.h" 15 | NAMESPACE_ZL_NET_START 16 | class EventLoop; 17 | 18 | 19 | class Timer 20 | { 21 | public: 22 | Timer(TimerId id, const TimerCallback& cb, const Timestamp& when, double interval) 23 | : id_(id) 24 | , callback_(cb) 25 | , when_(when) 26 | , interval_(interval) 27 | { 28 | } 29 | 30 | TimerId id() const { return id_; } 31 | 32 | Timestamp expires_at() const { return when_; } 33 | 34 | bool repeat() const { return interval_ > 0; } 35 | 36 | void trigger() const { callback_(); } 37 | 38 | void restart(const Timestamp& now) 39 | { 40 | if(repeat()) 41 | { 42 | when_ = now + interval_; 43 | } 44 | else 45 | { 46 | when_ = Timestamp::invalid(); 47 | } 48 | } 49 | 50 | private: 51 | TimerId id_; 52 | TimerCallback callback_; 53 | Timestamp when_; 54 | double interval_; // second 55 | }; 56 | 57 | inline bool operator<(const Timer& lhs, const Timer& rhs) 58 | { 59 | return lhs.expires_at() < rhs.expires_at(); 60 | } 61 | 62 | NAMESPACE_ZL_NET_END 63 | #endif /* ZL_TIMER_H */ 64 | -------------------------------------------------------------------------------- /zlreactor/net/TimerQueue.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : TimerQueue.h 3 | // Author : LIZHENG 4 | // Created : 2014-12-22 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_TIMERQUEUE_H 10 | #define ZL_TIMERQUEUE_H 11 | #include "zlreactor/Define.h" 12 | #include "zlreactor/base/NonCopy.h" 13 | #include "zlreactor/thread/Mutex.h" 14 | #include "zlreactor/thread/Atomic.h" 15 | #include "zlreactor/net/Timer.h" 16 | #include "zlreactor/net/CallBacks.h" 17 | #include 18 | #include 19 | #include 20 | using zl::base::Timestamp; 21 | NAMESPACE_ZL_NET_START 22 | 23 | class Timer; 24 | class EventLoop; 25 | 26 | class TimerQueue 27 | { 28 | typedef std::pair Entry; 29 | typedef std::set TimerList; 30 | typedef std::unordered_map TimerMap; 31 | typedef std::unordered_set CancelTimerList; 32 | 33 | public: 34 | explicit TimerQueue(EventLoop* loop); 35 | ~TimerQueue(); 36 | 37 | public: 38 | TimerId addTimer(const TimerCallback& cb, const Timestamp& when, double interval); 39 | void cancelTimer(TimerId id); 40 | Timestamp getNearestExpiration() const; 41 | void runTimer(const Timestamp& now); 42 | 43 | private: 44 | void addTimerInLoop(Timer* timer); 45 | void cancelTimerInLoop(TimerId id); 46 | void addTimer(Timer* timer); 47 | std::vector getExpiredTimers(const Timestamp& now); 48 | 49 | private: 50 | TimerList timers_; 51 | TimerMap activeTimers_; 52 | CancelTimerList cancelTimers_; 53 | 54 | EventLoop *loop_; 55 | zl::thread::Atomic atomic_; 56 | zl::thread::Atomic callingTimesFunctor_; 57 | }; 58 | 59 | NAMESPACE_ZL_NET_END 60 | #endif /* ZL_TIMERQUEUE_H */ 61 | -------------------------------------------------------------------------------- /zlreactor/net/Timerfd.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : Timerfd.h 3 | // Author : LIZHENG 4 | // Created : 2014-11-23 5 | // Description : timerfd need linux kernel > 2.6.25 6 | // Linux下基于基于文件描述符的定时器接口,通过fd的可读事件进行超时通知,能够用于select/poll 7 | // 8 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 9 | // *********************************************************************** 10 | #ifndef ZL_TIMERFD_H 11 | #define ZL_TIMERFD_H 12 | #include "zlreactor/Define.h" 13 | #include "zlreactor/base/Timestamp.h" 14 | #include 15 | using zl::base::Timestamp; 16 | NAMESPACE_ZL_NET_START 17 | 18 | typedef int Timerfd; 19 | 20 | class TimerfdHandler 21 | { 22 | public: 23 | TimerfdHandler(int clockid = CLOCK_MONOTONIC, int flags = TFD_NONBLOCK | TFD_CLOEXEC); 24 | ~TimerfdHandler(); 25 | 26 | public: 27 | /// 返回定时器描述符 28 | Timerfd fd() { return timerfd_; } 29 | 30 | /// 设置新的超时时间(绝对时间)以及定时器循环间隔(<=0 表示只定时一次), 单位:微秒 31 | void resetTimerfd(Timestamp expiration, int interval_us = 0); 32 | 33 | /// 设置新的超时时间(相对时间)以及定时器循环间隔(<=0 表示只定时一次), 单位:微秒 34 | void resetTimerfd(uint64_t next_expire_us, int interval_us = 0); 35 | 36 | /// 获得当前有多少个定时器超时 37 | uint64_t read(uint64_t *howmany); 38 | 39 | /// 停止定时器 40 | void stop(); 41 | 42 | private: 43 | Timerfd timerfd_; 44 | }; 45 | 46 | NAMESPACE_ZL_NET_END 47 | #endif /* ZL_TIMERFD_H */ 48 | -------------------------------------------------------------------------------- /zlreactor/net/http/HttpContext.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : HttpContext.h 3 | // Author : LIZHENG 4 | // Created : 2015-03-18 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_HTTPCONTEXT_H 10 | #define ZL_HTTPCONTEXT_H 11 | #include "zlreactor/Define.h" 12 | #include "zlreactor/base/NonCopy.h" 13 | #include "zlreactor/net/TcpServer.h" 14 | #include "zlreactor/net/CallBacks.h" 15 | #include "zlreactor/net/http/HttpProtocol.h" 16 | #include "zlreactor/net/http/HttpRequest.h" 17 | #include "zlreactor/base/Timestamp.h" 18 | using zl::base::Timestamp; 19 | NAMESPACE_ZL_NET_START 20 | class EventLoop; 21 | class HttpRequest; 22 | class HttpResponse; 23 | class InetAddress; 24 | class ByteBuffer; 25 | 26 | class HttpContext// : public zl::NonCopy 27 | { 28 | public: 29 | enum HttpRequestParseState 30 | { 31 | kExpectRequestLine, 32 | kExpectHeaders, 33 | kExpectBody, 34 | kGotAll, 35 | }; 36 | 37 | HttpContext() 38 | : state_(kExpectRequestLine) 39 | { 40 | } 41 | 42 | public: 43 | bool parseRequest(ByteBuffer *buf, Timestamp receiveTime); 44 | 45 | public: 46 | bool expectRequestLine() const { return state_ == kExpectRequestLine; } 47 | bool expectHeaders() const { return state_ == kExpectHeaders; } 48 | bool expectBody() const { return state_ == kExpectBody; } 49 | bool gotAll() const { return state_ == kGotAll; } 50 | void receiveRequestLine() { state_ = kExpectHeaders; } 51 | void receiveHeaders() 52 | { 53 | if(request_.method() == HttpGet) 54 | state_ = kGotAll; 55 | else if(request_.method() == HttpPost) 56 | state_ = kExpectBody; 57 | } 58 | void receiveBody() { state_ = kGotAll; } 59 | 60 | HttpRequest& request() { return request_; } 61 | const HttpRequest& request() const { return request_; } 62 | 63 | void reset() 64 | { 65 | state_ = kExpectRequestLine; 66 | HttpRequest dummy; 67 | request_.swap(dummy); 68 | } 69 | 70 | private: 71 | bool processRequestLine(const char *begin, const char *end); 72 | bool processReqestHeader(const char *begin, const char *end); 73 | 74 | private: 75 | HttpRequestParseState state_; 76 | HttpRequest request_; 77 | }; 78 | 79 | NAMESPACE_ZL_NET_END 80 | #endif /* ZL_HTTPCONTEXT_H */ 81 | -------------------------------------------------------------------------------- /zlreactor/net/http/HttpKeyValue.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : HttpKeyValue.h 3 | // Author : LIZHENG 4 | // Created : 2014-07-02 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_HTTPKEYVALUE_H 10 | #define ZL_HTTPKEYVALUE_H 11 | #include "zlreactor/Define.h" 12 | #include "zlreactor/base/Singleton.h" 13 | #include "zlreactor/net/http/HttpProtocol.h" 14 | NAMESPACE_ZL_NET_START 15 | 16 | class HttpKeyValue : public zl::Singleton < HttpKeyValue > 17 | { 18 | DECLARE_SINGLETON_CLASS(HttpKeyValue); 19 | 20 | public: 21 | std::string getStatusDesc(HttpStatusCode code) const; 22 | std::string getContentType(const std::string& file_type) const; 23 | std::string getMethodStr(HttpMethod method) const; 24 | 25 | private: 26 | std::map code_desc_; 27 | std::map content_type_; 28 | std::map method_str_; 29 | 30 | private: 31 | HttpKeyValue(); 32 | void initialise(); 33 | }; 34 | 35 | NAMESPACE_ZL_NET_END 36 | #endif /* ZL_HTTPKEYVALUE_H */ 37 | -------------------------------------------------------------------------------- /zlreactor/net/http/HttpResponse.cpp: -------------------------------------------------------------------------------- 1 | #include "zlreactor/net/http/HttpResponse.h" 2 | #include "zlreactor/net/http/HttpKeyValue.h" 3 | #include "zlreactor/base/FileUtil.h" 4 | #include "zlreactor/net/ByteBuffer.h" 5 | NAMESPACE_ZL_NET_START 6 | 7 | HttpResponse::HttpResponse(bool closeConn/* = true*/) 8 | : statusCode_(HttpStatusOk), closeConnection_(closeConn) 9 | { 10 | } 11 | HttpResponse::~HttpResponse() 12 | { 13 | } 14 | 15 | /// complie: 16 | /// status line \r\n 17 | /// response header \r\n 18 | /// \r\n 19 | /// response body 20 | void HttpResponse::compileToBuffer(ByteBuffer* output) const 21 | { 22 | HttpKeyValue *ptable = HttpKeyValue::getInstancePtr(); 23 | 24 | //status line : HttpVer / StatusCode / ReasonPhrase 25 | char buf[128] = {0}; 26 | snprintf(buf, sizeof(buf), "HTTP/1.1 %d %s\r\n", statusCode_, 27 | ptable->getStatusDesc(statusCode_).c_str()); 28 | 29 | output->write(buf, strlen(buf)); 30 | 31 | // respone headers 32 | if(!serverName_.empty()) 33 | { 34 | output->write("Server: "); output->write(serverName_); output->write("\r\n"); 35 | } 36 | if(!contentType_.empty()) 37 | { 38 | output->write("Content-Type: "); output->write(contentType_); output->write("\r\n"); 39 | } 40 | 41 | if (closeConnection_) 42 | { 43 | output->write("Connection: close\r\n"); 44 | } 45 | else 46 | { 47 | output->write("Connection: Keep-Alive\r\n"); 48 | } 49 | 50 | for (std::map::const_iterator it = headers_.begin(); it != headers_.end(); ++it) 51 | { 52 | if(it->second.empty()) 53 | continue; 54 | output->write(it->first); 55 | output->write(": "); 56 | output->write(it->second); 57 | output->write("\r\n"); 58 | } 59 | 60 | output->write("\r\n"); //消息头和消息体之间有一个空行 61 | // response body, maybe 62 | if(!body_.empty()) 63 | { 64 | memset(buf, 0, 128); 65 | snprintf(buf, sizeof buf, "Content-Length: %d\r\n", static_cast(body_.size())); 66 | output->write(buf, strlen(buf)); 67 | output->write(body_); 68 | } 69 | 70 | //const string& s = output->toString(); 71 | //printf("[[%d][\n%s]]\n", (int)s.size(), s.c_str()); 72 | } 73 | 74 | NAMESPACE_ZL_NET_END 75 | -------------------------------------------------------------------------------- /zlreactor/net/http/HttpResponse.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : HttpResponse.h 3 | // Author : LIZHENG 4 | // Created : 2015-03-16 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_HTTPRESPONSE_H 10 | #define ZL_HTTPRESPONSE_H 11 | #include "zlreactor/Define.h" 12 | #include "zlreactor/net/http/HttpProtocol.h" 13 | NAMESPACE_ZL_NET_START 14 | 15 | class ByteBuffer; 16 | class HttpRequest; 17 | 18 | class HttpResponse 19 | { 20 | public: 21 | explicit HttpResponse(bool closeConn = true); 22 | ~HttpResponse(); 23 | 24 | public: 25 | void setStatusCode(HttpStatusCode code) { statusCode_ = code; } 26 | void setVersion(HttpVersion ver) { version_ = ver; } 27 | void setServerName(const string& name) { serverName_ = name; } 28 | void setContentType(const string& type) { contentType_ = type; } 29 | void setCloseConnection(bool on) { closeConnection_ = on; } 30 | bool closeConnection() const { return closeConnection_; } 31 | void setBody(const string& body) { body_ = body; } 32 | void addHeader(const string& key, const string& value) { headers_[key] = value; } 33 | 34 | void compileToBuffer(ByteBuffer* output) const; 35 | 36 | private: 37 | HttpStatusCode statusCode_; 38 | HttpVersion version_; 39 | string serverName_; 40 | string contentType_; 41 | bool closeConnection_; 42 | string body_; 43 | map headers_; 44 | }; 45 | 46 | NAMESPACE_ZL_NET_END 47 | 48 | # endif /* ZL_HTTPRESPONSE_H */ 49 | -------------------------------------------------------------------------------- /zlreactor/net/http/HttpServer.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : HttpServer.h 3 | // Author : LIZHENG 4 | // Created : 2015-03-16 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_HTTPSERVER_H 10 | #define ZL_HTTPSERVER_H 11 | #include "zlreactor/Define.h" 12 | #include "zlreactor/net/TcpServer.h" 13 | #include "zlreactor/net/CallBacks.h" 14 | #include "zlreactor/net/http/HttpProtocol.h" 15 | NAMESPACE_ZL_NET_START 16 | class EventLoop; 17 | class HttpRequest; 18 | class HttpResponse; 19 | class InetAddress; 20 | 21 | class HttpServer : public TcpServer 22 | { 23 | public: 24 | typedef std::function HttpCallback; 25 | public: 26 | HttpServer(EventLoop *loop, const InetAddress& listenAddr, const string& servername = "HttpServer"); 27 | ~HttpServer(); 28 | 29 | public: 30 | void setRootDir(const string& dir) { docRootDir_ = dir; } 31 | string rootDir() { return docRootDir_; } 32 | 33 | void setDefaultPage(const string& page){ defaultPage_ = page; } 34 | string defaultPage() { return defaultPage_; } 35 | 36 | void setCallback(HttpMethod m, const HttpCallback& cb) 37 | { 38 | methodCallback_[m] = cb; 39 | } 40 | 41 | private: 42 | void onConnection(const TcpConnectionPtr& conn); 43 | void onMessage(const TcpConnectionPtr& conn, ByteBuffer *buf, Timestamp receiveTime); 44 | void response(const TcpConnectionPtr& conn, const HttpRequest& req); 45 | void methodCallback(const HttpRequest& req, HttpResponse *resp); 46 | 47 | private: 48 | HttpServer(const HttpServer&); 49 | HttpServer& operator = (const HttpServer&); 50 | 51 | private: 52 | std::string docRootDir_; 53 | std::string defaultPage_; 54 | std::map methodCallback_; 55 | }; 56 | 57 | NAMESPACE_ZL_NET_END 58 | #endif /* ZL_HTTPSERVER_H */ 59 | -------------------------------------------------------------------------------- /zlreactor/net/http/UriQueryParams.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : UriQueryParams.h 3 | // Author : LIZHENG 4 | // Description : 5 | // 6 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 7 | // *********************************************************************** 8 | #ifndef ZL_URIQUERYPARAMS_H 9 | #define ZL_URIQUERYPARAMS_H 10 | #include 11 | #include 12 | 13 | namespace zl 14 | { 15 | namespace net 16 | { 17 | struct UriQueryParam 18 | { 19 | public: 20 | UriQueryParam() {} 21 | UriQueryParam(const std::string& name, const std::string& value) 22 | : name_(name) 23 | , value_(value) 24 | { 25 | } 26 | 27 | void name(const std::string& n) { name_ = n; } 28 | void value(const std::string& v) { value_ = v; } 29 | const std::string name() const { return name_; } 30 | const std::string value() const { return value_; } 31 | 32 | public: 33 | std::string name_; 34 | std::string value_; 35 | }; 36 | 37 | class UriQueryParams 38 | { 39 | public: 40 | bool parse(const std::string& params); 41 | void appendToString(std::string* target) const; 42 | void writeToString(std::string* target) const; 43 | std::string toString() const; 44 | 45 | const UriQueryParam* find(const std::string& name) const; 46 | UriQueryParam* find(const std::string& name); 47 | 48 | UriQueryParam& get(size_t index); 49 | const UriQueryParam& get(size_t index) const; 50 | 51 | bool getValue(const std::string& name, std::string* value) const; 52 | bool getValue(const std::string& name, int* value) const; 53 | const std::string& getOrDefaultValue(const std::string& name, const std::string& default_value) const; 54 | 55 | size_t count() const; 56 | void clear(); 57 | bool isEmpty() const; 58 | void add(const UriQueryParam& param); 59 | void add(const std::string& name, const std::string& value); 60 | void set(const std::string& name, const std::string& value); 61 | bool remove(const std::string& name); 62 | 63 | private: 64 | std::vector params_; 65 | }; 66 | } 67 | } 68 | #endif /* ZL_URIQUERYPARAMS_H */ 69 | 70 | -------------------------------------------------------------------------------- /zlreactor/net/http/UriUtil.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : UriUtil.h 3 | // Author : LIZHENG 4 | // Created : 2015 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_HTTP_URIUTIL_H 10 | #define ZL_HTTP_URIUTIL_H 11 | #include "zlreactor/Define.h" 12 | #include 13 | NAMESPACE_ZL_NET_START 14 | 15 | size_t uriEncode(const char* unencoded, size_t len, char* encoded); 16 | std::string uriEncode(const char* unencoded, size_t len); 17 | std::string uriEncode(const std::string& unencoded); 18 | 19 | 20 | size_t uriDecode(const char* encoded, size_t len, char* dst); 21 | std::string uriDecode(const char* encoded, size_t len); 22 | std::string uriDecode(const std::string& encoded); 23 | 24 | NAMESPACE_ZL_NET_END 25 | #endif /* ZL_HTTP_URIUTIL_H */ 26 | -------------------------------------------------------------------------------- /zlreactor/net/poller/EpollPoller.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : EpollPoller.h 3 | // Author : LIZHENG 4 | // Created : 2014-09-26 5 | // Description : I/O MultiPlexing 的 epoll 实现 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_EPOLLPOLLER_H 10 | #define ZL_EPOLLPOLLER_H 11 | #include "zlreactor/net/poller/Poller.h" 12 | struct epoll_event; 13 | NAMESPACE_ZL_NET_START 14 | 15 | class EpollPoller : public Poller 16 | { 17 | public: 18 | explicit EpollPoller(EventLoop *loop, bool enableET = false); 19 | 20 | ~EpollPoller(); 21 | 22 | public: 23 | virtual bool updateChannel(Channel *channel); 24 | 25 | virtual bool removeChannel(Channel *channel); 26 | 27 | virtual Timestamp pollOnce(int timeoutMs, ChannelList& activeChannels); 28 | 29 | virtual const char* ioMultiplexerName() const { return "linux_epoll"; } 30 | 31 | private: 32 | bool update(Channel *channel, int operation); 33 | 34 | void fireActiveChannels(int numEvents, ChannelList& activeChannels) const; 35 | 36 | private: 37 | typedef std::vector EpollEventList; 38 | 39 | int epollfd_; 40 | bool enableET_; 41 | EpollEventList events_; 42 | }; 43 | 44 | NAMESPACE_ZL_NET_END 45 | #endif /* ZL_EPOLLPOLLER_H */ 46 | -------------------------------------------------------------------------------- /zlreactor/net/poller/PollPoller.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : PollPoller.h 3 | // Author : LIZHENG 4 | // Created : 2014-12-22 5 | // Description : I/O MultiPlexing 的 poll 实现 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_POLLPOLLER_H 10 | #define ZL_POLLPOLLER_H 11 | #include "zlreactor/net/poller/Poller.h" 12 | #include 13 | //#ifdef __GNUC__ 14 | //#include 15 | //#else 16 | //#include 17 | //#endif 18 | //namespace std 19 | //{ 20 | // using namespace __gnu_cxx; 21 | //} 22 | NAMESPACE_ZL_NET_START 23 | 24 | class PollPoller : public Poller 25 | { 26 | public: 27 | explicit PollPoller(EventLoop *loop); 28 | 29 | ~PollPoller(); 30 | 31 | public: 32 | virtual bool updateChannel(Channel *channel); 33 | 34 | virtual bool removeChannel(Channel *channel); 35 | 36 | virtual Timestamp pollOnce(int timeoutMs, ChannelList& activeChannels); 37 | 38 | virtual const char* ioMultiplexerName() const { return "linux_poll"; } 39 | 40 | private: 41 | void fireActiveChannels(int numEvents, ChannelList& activeChannels) const; 42 | 43 | private: 44 | typedef std::vector PollFdList; 45 | typedef std::unordered_map ChannelIter; 46 | 47 | PollFdList pollfds_; 48 | ChannelIter channelIter_; 49 | }; 50 | 51 | NAMESPACE_ZL_NET_END 52 | #endif /* ZL_POLLPOLLER_H */ 53 | -------------------------------------------------------------------------------- /zlreactor/net/poller/Poller.cpp: -------------------------------------------------------------------------------- 1 | #include "zlreactor/net/poller/Poller.h" 2 | #include "zlreactor/net/Channel.h" 3 | #include "zlreactor/net/poller/EpollPoller.h" 4 | #include "zlreactor/net/poller/PollPoller.h" 5 | #include "zlreactor/net/poller/SelectPoller.h" 6 | NAMESPACE_ZL_NET_START 7 | 8 | Poller::Poller(EventLoop *loop) : loop_(loop) 9 | { 10 | } 11 | 12 | Poller::~Poller() 13 | { 14 | } 15 | 16 | bool Poller::hasChannel(const Channel* channel) const 17 | { 18 | ChannelMap::const_iterator itr = channelMap_.find(channel->fd()); 19 | return itr != channelMap_.end() && itr->second == channel; 20 | } 21 | 22 | Channel* Poller::getChannel(ZL_SOCKET sock) const 23 | { 24 | ChannelMap::const_iterator itr = channelMap_.find(sock); 25 | if(itr == channelMap_.end()) 26 | return NULL; 27 | return itr->second; 28 | } 29 | 30 | /*static*/ Poller* Poller::createPoller(EventLoop *loop) 31 | { 32 | #if defined(USE_POLLER_EPOLL) 33 | return new EpollPoller(loop); 34 | #elif defined(USE_POLLER_SELECT) 35 | return new SelectPoller(loop); 36 | #elif defined(USE_POLLER_POLL) 37 | return new PollPoller(loop); 38 | #else 39 | return NULL; 40 | #endif 41 | } 42 | 43 | NAMESPACE_ZL_NET_END -------------------------------------------------------------------------------- /zlreactor/net/poller/SelectPoller.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : SelectPoller.h 3 | // Author : LIZHENG 4 | // Created : 2015-01-13 5 | // Description : I/O MultiPlexing 的 select 实现 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_SELECTPOLLER_H 10 | #define ZL_SELECTPOLLER_H 11 | #include "zlreactor/net/poller/Poller.h" 12 | #include 13 | #ifdef OS_LINUX 14 | #include 15 | #endif 16 | NAMESPACE_ZL_NET_START 17 | 18 | class SelectPoller : public Poller 19 | { 20 | public: 21 | explicit SelectPoller(EventLoop *loop); 22 | 23 | ~SelectPoller(); 24 | 25 | public: 26 | virtual bool updateChannel(Channel *channel); 27 | 28 | virtual bool removeChannel(Channel *channel); 29 | 30 | virtual Timestamp pollOnce(int timeoutMs, ChannelList& activeChannels); 31 | 32 | virtual const char* ioMultiplexerName() const { return "select"; } 33 | 34 | private: 35 | void fireActiveChannels(int numEvents, ChannelList& activeChannels) const; 36 | 37 | private: 38 | fd_set readfds_; /// select返回的所有可读事件 39 | fd_set writefds_; /// select返回的所有可写事件 40 | fd_set exceptfds_; /// select返回的所有错误事件 41 | 42 | fd_set select_readfds_; /// 加入到select中的感兴趣的所有可读事件 43 | fd_set select_writefds_; /// 加入到select中的感兴趣的所有可写事件 44 | fd_set select_exceptfds_; /// 加入到select中的感兴趣的所有错误事件 45 | 46 | std::set< int, std::greater > fdlist_; 47 | }; 48 | 49 | NAMESPACE_ZL_NET_END 50 | #endif /* ZL_SELECTPOLLER_H */ 51 | -------------------------------------------------------------------------------- /zlreactor/net/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${PROJECT_SOURCE_DIR}) 2 | 3 | set(CMAKE_CXX_FLAGS "-std=c++0x -Wall -pthread") 4 | 5 | link_directories(${CMAKE_INSTALL_PREFIX}/lib/ 6 | ${PROJECT_SOURCE_DIR}/lib/ 7 | ${PROJECT_BINARY_DIR}/lib/ 8 | ) 9 | 10 | add_executable(ByteBuffer_test ByteBuffer_test.cpp) 11 | target_link_libraries(ByteBuffer_test zlreactor) 12 | 13 | add_executable(DomainResolver_test DomainResolver_test.cpp) 14 | target_link_libraries(DomainResolver_test zlreactor) 15 | 16 | add_executable(Eventfd_test Eventfd_test.cpp) 17 | target_link_libraries(Eventfd_test zlreactor) 18 | 19 | add_executable(EventLoopThreadPool_test EventLoopThreadPool_test.cpp) 20 | target_link_libraries(EventLoopThreadPool_test zlreactor) 21 | 22 | add_executable(EventLoop_test EventLoop_test.cpp) 23 | target_link_libraries(EventLoop_test zlreactor) 24 | 25 | add_executable(HttpRequestParser_test HttpRequestParser_test.cpp) 26 | target_link_libraries(HttpRequestParser_test zlreactor) 27 | 28 | add_executable(InetAddress_test InetAddress_test.cpp) 29 | target_link_libraries(InetAddress_test zlreactor) 30 | 31 | add_executable(Signalfd_test Signalfd_test.cpp) 32 | target_link_libraries(Signalfd_test zlreactor) 33 | 34 | add_executable(Socket_test Socket_test.cpp) 35 | target_link_libraries(Socket_test zlreactor) 36 | 37 | add_executable(TcpAcceptor_test TcpAcceptor_test.cpp) 38 | target_link_libraries(TcpAcceptor_test zlreactor) 39 | 40 | add_executable(TcpClient_test TcpClient_test.cpp) 41 | target_link_libraries(TcpClient_test zlreactor) 42 | 43 | add_executable(Timerfd_test Timerfd_test.cpp) 44 | target_link_libraries(Timerfd_test zlreactor) 45 | 46 | add_executable(Timer_test Timer_test.cpp) 47 | target_link_libraries(Timer_test zlreactor) 48 | 49 | add_executable(UriDecode_test UriDecode_test.cpp) 50 | target_link_libraries(UriDecode_test zlreactor) 51 | 52 | add_executable(UriQueryParams_test UriQueryParams_test.cpp) 53 | target_link_libraries(UriQueryParams_test zlreactor) 54 | -------------------------------------------------------------------------------- /zlreactor/net/tests/DomainResolver_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "zlreactor/net/DomainResolver.h" 3 | using namespace std; 4 | using namespace zl; 5 | using namespace zl::net; 6 | 7 | void test_query1() 8 | { 9 | HostEntry host; 10 | int error; 11 | if (DomainResolver::query("www.baidu.com", &host, &error)) 12 | { 13 | std::cout << "Query success:\n" << "name: " << host.name() << "\n"; 14 | 15 | std::cout << "Alias:"; 16 | for (size_t i = 0; i < host.aliases().size(); ++i) 17 | std::cout << " " << host.aliases()[i]; 18 | std::cout << "\n"; 19 | 20 | std::cout << "IP:"; 21 | for (size_t i = 0; i < host.addresses().size(); ++i) 22 | std::cout << " " << host.addresses()[i].ipPort(); 23 | std::cout << "\n"; 24 | } 25 | else 26 | { 27 | std::cout << "Query error: " << DomainResolver::errorString(error) << '\n'; 28 | } 29 | } 30 | 31 | void test_query2() 32 | { 33 | std::vector addresses; 34 | int error; 35 | if (DomainResolver::resolveInetAddress("www.qq.com", &addresses, &error)) 36 | { 37 | std::cout << "Query success:\nIP:"; 38 | for (size_t i = 0; i < addresses.size(); ++i) 39 | std::cout << " " << addresses[i].ipPort(); 40 | std::cout << "\n"; 41 | } 42 | else 43 | { 44 | std::cout << "Query error: " << DomainResolver::errorString(error) << '\n'; 45 | } 46 | } 47 | 48 | void test_query3() 49 | { 50 | std::vector addresses; 51 | int error; 52 | if(DomainResolver::resolveInetAddress("non-exist.domain...", &addresses, &error)) 53 | { 54 | 55 | } 56 | else 57 | { 58 | std::cout << "error code = " << error << "\n"; 59 | std::cout << "Query error: " << DomainResolver::errorString(error) << '\n'; 60 | } 61 | } 62 | 63 | int main() 64 | { 65 | test_query1(); 66 | std::cout << "******************************************\n"; 67 | test_query2(); 68 | std::cout << "******************************************\n"; 69 | test_query3(); 70 | std::cout << "******************************************\n"; 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /zlreactor/net/tests/EventLoopThreadPool_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | File Name : EventLoopThreadPool_test.cpp 3 | Author : LIZHENG 4 | Mail : lizhenghn@gmail.com 5 | Created Time: 2015年05月11日 星期一 22时36分31秒 6 | ************************************************************************/ 7 | #include 8 | #include "zlreactor/net/EventLoop.h" 9 | #include "zlreactor/net/EventLoopThreadPool.h" 10 | using namespace std; 11 | using namespace zl; 12 | using namespace zl::net; 13 | 14 | void test_eltp() 15 | { 16 | EventLoop loop; 17 | loop.addTimer(std::bind(&EventLoop::quit, &loop), 10, false); 18 | 19 | EventLoopThreadPool eltp1(&loop); 20 | eltp1.setMultiReactorThreads(0); // no multi-reactor, only one EventLoop(loop), eltp1 create none. 21 | eltp1.start(); 22 | assert(eltp1.getNextLoop() == &loop); 23 | assert(eltp1.getNextLoop() == &loop); 24 | assert(eltp1.getNextLoop() == &loop); 25 | 26 | EventLoopThreadPool eltp2(&loop); 27 | eltp2.setMultiReactorThreads(1); // multi-reactor(two), one (loop) for accept, one(eltp2 create) for other. 28 | eltp2.start(); 29 | assert(eltp2.getNextLoop() != &loop); 30 | EventLoop *lp2 = eltp2.getNextLoop(); 31 | assert(eltp2.getNextLoop() != &loop); 32 | assert(eltp2.getNextLoop() == lp2); 33 | 34 | EventLoopThreadPool eltp3(&loop); 35 | eltp3.setMultiReactorThreads(2); // multi-reactor(three), one (loop) for accept, two(eltp3 create) for other. 36 | eltp3.start(); 37 | EventLoop *lp3 = eltp3.getNextLoop(); 38 | assert(lp3 != &loop); 39 | assert(lp3 != eltp3.getNextLoop()); 40 | assert(lp3 == eltp3.getNextLoop()); 41 | assert(lp3 != eltp3.getNextLoop()); 42 | 43 | loop.loop(); 44 | } 45 | 46 | int main() 47 | { 48 | test_eltp(); 49 | cout << Timestamp::now().toString() << "\n"; 50 | cout << "###### GAME OVER ######\n"; 51 | } 52 | -------------------------------------------------------------------------------- /zlreactor/net/tests/InetAddress_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "zlreactor/net/InetAddress.h" 5 | #include "zlreactor/net/Socket.h" 6 | #include "zlreactor/net/SocketUtil.h" 7 | using namespace std; 8 | using namespace zl; 9 | using namespace zl::net; 10 | 11 | void test_InetAddress() 12 | { 13 | { 14 | InetAddress addr(8888); 15 | assert(addr.port()== 8888); 16 | assert(addr.ip() == string("0.0.0.0")); 17 | assert(addr.ipPort() == string("0.0.0.0:8888")); 18 | } 19 | { 20 | InetAddress addr("192.168.14.7", 8888); 21 | assert(addr.ip() == string("192.168.14.7")); 22 | assert(addr.ipPort() == string("192.168.14.7:8888")); 23 | } 24 | { 25 | InetAddress addr("192.168.14.7", 8888); 26 | Socket socket(SocketUtil::createSocket()); 27 | assert(socket.fd() > 0); 28 | bool ret = socket.bind(addr); 29 | assert(ret); 30 | ret = socket.listen(1024); 31 | assert(ret); 32 | cout << "server listening on " << addr.ipPort() << ", waiting for incoming....\n"; 33 | while(true) 34 | { 35 | InetAddress clientAddr; 36 | ZL_SOCKET clientFd = socket.accept(&clientAddr); // test: nc 192.168.14.7 8888 37 | cout << "accept one client from " << clientAddr.ipPort() << "\n"; 38 | SocketUtil::closeSocket(clientFd); 39 | } 40 | } 41 | } 42 | 43 | int main() 44 | { 45 | test_InetAddress(); 46 | printf("###### GAME OVER ######"); 47 | } 48 | 49 | -------------------------------------------------------------------------------- /zlreactor/net/tests/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = Timer_test ByteBuffer_test DomainResolver_test HttpRequestParser_test Socket_test\ 4 | Eventfd_test Timerfd_test Signalfd_test \ 5 | TcpAcceptor_test TcpClient_test EventLoop_test EventLoopThreadPool_test InetAddress_test \ 6 | UriQueryParams_test UriDecode_test 7 | 8 | INCLUDES = -I../../../zlreactor 9 | CPPFLAGS = -std=c++0x 10 | LDFLAGS = -L../../../lib -lzlreactor 11 | 12 | Timer_test_CPPFLAGS = $(CPPFLAGS) 13 | Timer_test_LDFLAGS = $(CPPFLAGS) 14 | Timer_test_SOURCES = Timer_test.cpp 15 | 16 | ByteBuffer_test_SOURCES = ByteBuffer_test.cpp 17 | 18 | DomainResolver_test_SOURCES = DomainResolver_test.cpp 19 | 20 | HttpRequestParser_test_SOURCES = HttpRequestParser_test.cpp 21 | 22 | Socket_test_SOURCES = Socket_test.cpp 23 | 24 | InetAddress_test_SOURCES = InetAddress_test.cpp 25 | 26 | Eventfd_test_SOURCES = Eventfd_test.cpp 27 | Timerfd_test_SOURCES = Timerfd_test.cpp 28 | Signalfd_test_SOURCES = Signalfd_test.cpp 29 | 30 | TcpAcceptor_test_SOURCES = TcpAcceptor_test.cpp 31 | 32 | TcpClient_test_SOURCES = TcpClient_test.cpp 33 | 34 | EventLoop_test_SOURCES = EventLoop_test.cpp 35 | 36 | EventLoopThreadPool_test_SOURCES = EventLoopThreadPool_test.cpp 37 | 38 | UriQueryParams_test_SOURCES = UriQueryParams_test.cpp 39 | 40 | UriDecode_test_SOURCES = UriDecode_test.cpp 41 | -------------------------------------------------------------------------------- /zlreactor/net/tests/TcpAcceptor_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | File Name : TcpAcceptor_test.cpp 3 | Author : LIZHENG 4 | Mail : lizhenghn@gmail.com 5 | Created Time: 2015年05月25日 星期一 20时45分36秒 6 | ************************************************************************/ 7 | #include 8 | #include 9 | #include "zlreactor/net/TcpAcceptor.h" 10 | #include "zlreactor/net/InetAddress.h" 11 | #include "zlreactor/net/EventLoop.h" 12 | using namespace std; 13 | using namespace zl; 14 | using namespace zl::net; 15 | 16 | void accept_callback(int fd, const InetAddress& addr) 17 | { 18 | cout << "get " << fd << ", and close it.\n"; 19 | ::close(fd); 20 | } 21 | 22 | void test_tcpacceptor() 23 | { 24 | EventLoop loop; 25 | InetAddress serverAddr(8888); 26 | TcpAcceptor acceptor(&loop, serverAddr); 27 | acceptor.setNewConnectionCallback(accept_callback); 28 | acceptor.listen(); 29 | 30 | loop.loop(); 31 | } 32 | 33 | int main() 34 | { 35 | test_tcpacceptor(); 36 | } 37 | -------------------------------------------------------------------------------- /zlreactor/net/tests/Timer_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "zlreactor/net/EventLoop.h" 5 | #include "zlreactor/thread/Thread.h" 6 | #include "zlreactor/base/StopWatch.h" 7 | #include "zlreactor/base/Logger.h" 8 | using namespace zl; 9 | using namespace zl::net; 10 | 11 | // see https://github.com/chenshuo/muduo/blob/master/muduo/net/tests/TimerQueue_unittest.cc 12 | // chenshuo真是大牛,自己水平高,写出来的代码也能让大家读懂,技术文章也很好,高山仰止 13 | // 本项目代码即是参照chenshuo及其他开源项目而自己练手写的 14 | 15 | int cnt = 0; 16 | EventLoop *g_loop; 17 | 18 | void printTid() 19 | { 20 | printf("pid = %d, tid = %ld\n", getpid(), thread::this_thread::get_id().value()); 21 | printf("now %s\n", Timestamp::now().toString().c_str()); 22 | } 23 | 24 | void print(const char *msg) 25 | { 26 | printf("msg %s %s\n", Timestamp::now().toString().c_str(), msg); 27 | if (++cnt == 20) 28 | { 29 | g_loop->quit(); 30 | } 31 | } 32 | 33 | void cancel(TimerId timer) 34 | { 35 | g_loop->cancelTimer(timer); 36 | printf("cancelled at %s\n", Timestamp::now().toString().c_str()); 37 | } 38 | 39 | void bench() 40 | { 41 | EventLoop loop; 42 | zl::base::StopWatch sw; 43 | for(int i = 0; i < 100000; ++i) 44 | { 45 | loop.addTimer(printTid, 1, false); 46 | } 47 | std::cout << sw.elapsedTimeInMill() << " ms\n"; 48 | } 49 | 50 | bool dobench = false; 51 | int main() 52 | { 53 | printTid(); 54 | if(dobench) 55 | { 56 | LOG_DISABLE_ALL; 57 | bench(); 58 | } 59 | else 60 | { 61 | EventLoop loop; 62 | g_loop = &loop; 63 | 64 | print("main"); 65 | loop.addTimer(std::bind(print, "once1"), 1, false); 66 | loop.addTimer(std::bind(print, "once1"), 1.5, false); 67 | loop.addTimer(std::bind(print, "once2.5"), 2.5, false); 68 | loop.addTimer(std::bind(print, "once3.5"), 3.5, false); 69 | TimerId t45 = loop.addTimer(std::bind(print, "once4.5"), 4.5, false); 70 | loop.addTimer(std::bind(cancel, t45), 4.0, false); 71 | loop.addTimer(std::bind(cancel, t45), 4.8, false); 72 | loop.addTimer(std::bind(print, "every2"), 2, true); 73 | TimerId t3 = loop.addTimer(std::bind(print, "every3"), 3, true); 74 | loop.addTimer(std::bind(cancel, t3), 9.001, false); 75 | 76 | loop.loop(); 77 | print("main loop exits"); 78 | } 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /zlreactor/net/tests/Timerfd_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "zlreactor/net/EventLoop.h" 6 | #include "zlreactor/net/Timerfd.h" 7 | #include "zlreactor/base/Timestamp.h" 8 | using namespace std; 9 | using namespace zl; 10 | using namespace zl::base; 11 | using namespace zl::net; 12 | /****** 13 | #include 14 | 15 | int timerfd_create(int clockid, int flags); 16 | 用来创建一个定时器描述符timerfd 17 | 第一个参数:clockid指定时间类型,有两个值: 18 | CLOCK_REALTIME :Systemwide realtime clock. 系统范围内的实时时钟 19 | CLOCK_MONOTONIC:以固定的速率运行,从不进行调整和复位 ,它不受任何系统time-of-day时钟修改的影响 20 | 第二个参数:flags可以是0或者O_CLOEXEC/O_NONBLOCK。 21 | 返回值:timerfd(文件描述符) 22 | 23 | int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value); 24 | 启动或关闭有fd指定的定时器 25 | 参数: 26 | fd:timerfd,有timerfd_create函数返回 27 | fnew_value:指定新的超时时间,设定new_value.it_value非零则启动定时器,否则关闭定时器,如果new_value.it_interval为0,则定时器只定时一次,即初始那次,否则之后每隔设定时间超时一次 28 | old_value:不为null,则返回定时器这次设置之前的超时时间 29 | flags:1代表设置的是绝对时间;为0代表相对时间。 30 | 31 | int timerfd_gettime(int fd, struct itimerspec *curr_value); 32 | 用于获得定时器距离下次超时还剩下的时间。如果调用时定时器已经到期, 33 | 并且该定时器处于循环模式(设置超时时间时struct itimerspec::it_interval不为0), 34 | 那么调用此函数之后定时器重新开始计时。 35 | 36 | read(2) 37 | read读取timefd超时事件通知 38 | 当定时器超时,read读事件发生即可读,返回超时次数(从上次调用timerfd_settime()启动开始或上次read成功读取开始), 39 | 它是一个8字节的unit64_t类型整数,如果定时器没有发生超时事件,则read将阻塞若timerfd为阻塞模式, 40 | 否则返回EAGAIN 错误(O_NONBLOCK模式),如果read时提供的缓冲区小于8字节将以EINVAL错误返回。 41 | ******/ 42 | #define handle_error(msg) do { perror(msg); exit(0); } while(0) 43 | 44 | void printTime() 45 | { 46 | struct timeval tv; 47 | gettimeofday(&tv, NULL); 48 | printf("current time:%ld.%ld ", tv.tv_sec, tv.tv_usec); 49 | } 50 | 51 | void test_timerfd() 52 | { 53 | printTime(); 54 | printf("test_timerfd start\n"); 55 | 56 | TimerfdHandler tfd(CLOCK_MONOTONIC, 0); 57 | Timestamp exp(Timestamp::now() + 3); 58 | tfd.resetTimerfd(exp, 1000000); // 在第3s后触发定时器,以后每隔1s触发一次 59 | 60 | int total = 0; 61 | int count = 0; 62 | while(count++ < 10) 63 | { 64 | uint64_t many; 65 | ssize_t s = tfd.read(&many); 66 | if (s != sizeof(uint64_t)) 67 | handle_error("read"); 68 | 69 | total += many; 70 | printTime(); 71 | printf("read: %llu; total=%llu\n", many, total); 72 | 73 | if(count > 5) 74 | { 75 | tfd.stop(); 76 | printf("stop the timerfd\n"); 77 | } 78 | } 79 | } 80 | 81 | int main() 82 | { 83 | test_timerfd(); 84 | printf("###### GAME OVER ######"); 85 | } 86 | 87 | -------------------------------------------------------------------------------- /zlreactor/net/tests/UriDecode_gbk.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/zlreactor/net/tests/UriDecode_gbk.h -------------------------------------------------------------------------------- /zlreactor/net/tests/UriDecode_utf8.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | const char kTigerUtf8[] = "老虎棒子鸡"; 4 | const char kTigerUtf8Encoded[] = "%E8%80%81%E8%99%8E%E6%A3%92%E5%AD%90%E9%B8%A1"; 5 | -------------------------------------------------------------------------------- /zlreactor/net/tests/UriQueryParams_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "zlreactor/net/http/UriQueryParams.h" 4 | using namespace std; 5 | using namespace zl; 6 | using namespace zl::net; 7 | 8 | void test1() 9 | { 10 | UriQueryParams params; 11 | assert(params.parse("a=1&b=2&c=%FF%FE&d")); 12 | assert(4 == params.count()); 13 | assert("a" == params.get(0).name()); 14 | assert("1" == params.get(0).value()); 15 | 16 | assert("b" == params.get(1).name()); 17 | assert("2" == params.get(1).value()); 18 | 19 | assert("c" == params.get(2).name()); 20 | assert("%FF%FE" == params.get(2).value()); 21 | 22 | assert("d" == params.get(3).name()); 23 | assert("" == params.get(3).value()); 24 | 25 | assert("123" == params.getOrDefaultValue("key", "123")); 26 | } 27 | 28 | void test2() 29 | { 30 | UriQueryParams params; 31 | params.add(UriQueryParam("len", "124")); 32 | 33 | UriQueryParam param; 34 | param.name("idx"); 35 | param.value("10"); 36 | params.add(param); 37 | 38 | params.add("islast", "false"); 39 | params.add("key", "123456"); 40 | params.set("key", "555555"); 41 | cout << params.toString() << "\n"; 42 | } 43 | int main() 44 | { 45 | test1(); 46 | test2(); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /zlreactor/stl/any.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/zlreactor/stl/any.h -------------------------------------------------------------------------------- /zlreactor/stl/range.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/zlreactor/stl/range.h -------------------------------------------------------------------------------- /zlreactor/stl/tests/any_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "stl/any.h" 5 | using namespace std; 6 | 7 | class A 8 | { 9 | public: 10 | A() : i(0) 11 | { 12 | 13 | } 14 | void print() 15 | { 16 | cout << "hello, A, " << ++i << "\n"; 17 | } 18 | int i ; 19 | }; 20 | 21 | class B 22 | { 23 | public: 24 | void setContext(const zl::stl::any & an1) 25 | { 26 | context_ = an1; 27 | } 28 | const zl::stl::any& get() const 29 | { 30 | return context_; 31 | } 32 | 33 | zl::stl::any* getMutableContext() 34 | { 35 | return &context_; 36 | } 37 | 38 | zl::stl::any context_; 39 | }; 40 | int main() 41 | { 42 | { 43 | B *b = new B; 44 | b->setContext(A()); 45 | 46 | A *context = zl::stl::any_cast(b->getMutableContext()); 47 | context->print(); 48 | context->print(); 49 | assert(context); 50 | } 51 | { 52 | zl::stl::any an1; 53 | an1 = 123; 54 | int num = zl::stl::any_cast(an1); 55 | cout << num << "\n"; 56 | } 57 | { 58 | zl::stl::any an1; 59 | an1 = (string)"wwwww"; 60 | string str = zl::stl::any_cast(an1); 61 | cout << str << "\n"; 62 | } 63 | { 64 | zl::stl::any an; 65 | an = 111; 66 | int num = zl::stl::any_cast(an); 67 | cout << num << "\n"; 68 | 69 | an = (string)"wer"; 70 | string str = zl::stl::any_cast(an); 71 | cout << str << "\n"; 72 | } 73 | { 74 | const zl::stl::any an1 = "1"; 75 | int i = zl::stl::any_cast(an1); // throw exception 76 | zl::stl::any_cast(&an1); 77 | const zl::stl::any *p1 = &an1; 78 | zl::stl::any_cast(p1); 79 | 80 | zl::stl::any an2 = "1"; 81 | zl::stl::any_cast(an2); 82 | zl::stl::any_cast(&an2); 83 | zl::stl::any *p2 = &an2; 84 | zl::stl::any_cast(p2); 85 | } 86 | system("pause"); 87 | } -------------------------------------------------------------------------------- /zlreactor/stl/tests/array_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "stl/array.h" 4 | using namespace zl::stl; 5 | 6 | int main() 7 | { 8 | zl::stl::array a, b; 9 | b.fill(1); 10 | 11 | b.back() += 1; 12 | b.front() -= 20; 13 | 14 | for (size_t i = 0; i < b.size(); ++i) 15 | { 16 | std::cout << ((i % 2 == 0) ? b[i] : b.at(i)) << ", "; 17 | } 18 | std::cout << "\n"; 19 | 20 | a == b; 21 | a != b; 22 | a < b; 23 | a <= b; 24 | a > b; 25 | a >= b; 26 | 27 | //zl::stl::array az; // 'az' uses undefined class 'zl::stl::array' 28 | 29 | system("pause"); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /zlreactor/stl/tests/range_test.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/zlreactor/stl/tests/range_test.cpp -------------------------------------------------------------------------------- /zlreactor/thread/BlockingQueueWorker.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : BlockingQueueWorker.h 3 | // Author : LIZHENG 4 | // Created : 2014-05-16 5 | // Description : 工作调度,工作在阻塞队列(BlockingQueue 或者 BoundedBlockingQueue)上面 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_BLOCKQUEUEWORKER_H 10 | #define ZL_BLOCKQUEUEWORKER_H 11 | #include "zlreactor/thread/BlockingQueue.h" 12 | #include "zlreactor/thread/ThreadGroup.h" 13 | NAMESPACE_ZL_THREAD_START 14 | 15 | template 16 | class BlockingQueueWorker 17 | { 18 | public: 19 | typedef Queue QueueType; 20 | typedef typename Queue::JobType JobType; 21 | typedef std::function FunctionType; 22 | 23 | template 24 | BlockingQueueWorker(QueueType& queue, const FunctionType& function, int thread_num = 1) 25 | : queue_(queue) 26 | , function_(function) 27 | , threadNum_(thread_num) 28 | { 29 | } 30 | 31 | BlockingQueueWorker(QueueType& queue, int thread_num = 1) 32 | : queue_(queue) 33 | , function_(NULL) 34 | , threadNum_(thread_num) 35 | { 36 | } 37 | 38 | ~BlockingQueueWorker() 39 | { 40 | stop(); 41 | } 42 | 43 | void start() 44 | { 45 | if(threads_.size() > 0) return; 46 | for (int i = 0; i < threadNum_; ++i) 47 | { 48 | threads_.create_thread(std::bind(&BlockingQueueWorker::doWork, this)); 49 | } 50 | } 51 | 52 | template 53 | void start(const FunctionType& function) 54 | { 55 | function_ = function; 56 | start(); 57 | } 58 | 59 | void stop() 60 | { 61 | function_ = 0; 62 | queue_.stop(); 63 | threads_.join_all(); 64 | } 65 | 66 | private: 67 | void doWork() 68 | { 69 | for(;;) 70 | { 71 | JobType job; 72 | bool bret = queue_.pop(job); 73 | if (!bret) break; 74 | if (function_) 75 | { 76 | function_(job); 77 | } 78 | } 79 | } 80 | 81 | private: 82 | QueueType& queue_; 83 | FunctionType function_; 84 | int threadNum_; 85 | ThreadGroup threads_; 86 | }; 87 | 88 | NAMESPACE_ZL_THREAD_END 89 | #endif /* ZL_BLOCKQUEUEWORKER_H */ 90 | -------------------------------------------------------------------------------- /zlreactor/thread/CountDownLatch.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : CountDownLatch.h 3 | // Author : LIZHENG 4 | // Created : 2014-06-08 5 | // Description : 同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_COUNTDOWNLATCH_H 10 | #define ZL_COUNTDOWNLATCH_H 11 | #include "zlreactor/base/NonCopy.h" 12 | #include "zlreactor/thread/Mutex.h" 13 | #include "zlreactor/thread/Condition.h" 14 | NAMESPACE_ZL_THREAD_START 15 | 16 | class CountDownLatch : zl::NonCopy 17 | { 18 | public: 19 | explicit CountDownLatch(int count) 20 | : count_(count) 21 | , mutex_() 22 | , condition_(mutex_) 23 | { 24 | } 25 | 26 | void wait() 27 | { 28 | LockGuard lock(mutex_); 29 | while(count_ > 0) 30 | { 31 | condition_.wait(); 32 | } 33 | } 34 | 35 | void countDown() 36 | { 37 | LockGuard lock(mutex_); 38 | --count_; 39 | if(count_ == 0) 40 | { 41 | condition_.notify_all(); 42 | } 43 | } 44 | 45 | int getCount() const 46 | { 47 | LockGuard lock(mutex_); 48 | return count_; 49 | } 50 | 51 | private: 52 | int count_; 53 | mutable Mutex mutex_; 54 | Condition condition_; 55 | }; 56 | 57 | NAMESPACE_ZL_THREAD_END 58 | 59 | #endif /* ZL_BLOCKINGQUEUE_H */ 60 | -------------------------------------------------------------------------------- /zlreactor/thread/Event.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : Event.h 3 | // Author : LIZHENG 4 | // Description : 同步原语,可用于一个线程在某一事件发生时通知其他(多个)线程 5 | // 6 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 7 | // *********************************************************************** 8 | #ifndef ZL_EVENT_H 9 | #define ZL_EVENT_H 10 | #include "zlreactor/Define.h" 11 | #include "zlreactor/base/NonCopy.h" 12 | #include "zlreactor/thread/Mutex.h" 13 | #include "zlreactor/thread/Condition.h" 14 | NAMESPACE_ZL_THREAD_START 15 | 16 | class Event : public zl::NonCopy 17 | { 18 | public: 19 | /// signal为false表示除非调用set, 否则当前事件状态就是non-signal的; 20 | /// autoreset为true时表示该事件在wait成功返回时会自动重置; 21 | explicit Event(bool signal = false, bool autoreset = true) 22 | : mutex_() 23 | , condition_(mutex_) 24 | , signaled_(signal) 25 | , autoReset_(autoreset) 26 | { 27 | 28 | } 29 | 30 | ~Event() 31 | { 32 | 33 | } 34 | 35 | public: 36 | /// block until signaled_ == true 37 | void wait() 38 | { 39 | LockGuard lock(mutex_); 40 | while (!signaled_) 41 | { 42 | condition_.wait(); 43 | } 44 | 45 | if(autoReset_) 46 | { 47 | signaled_ = false; 48 | } 49 | } 50 | 51 | bool timed_wait(int millisecond) 52 | { 53 | LockGuard lock(mutex_); 54 | if (!signaled_) 55 | { 56 | condition_.timed_wait(millisecond); 57 | } 58 | 59 | if (!signaled_) 60 | { 61 | return false; 62 | } 63 | 64 | if(autoReset_) 65 | { 66 | signaled_ = false; 67 | } 68 | return true; 69 | } 70 | 71 | bool try_wait() 72 | { 73 | return timed_wait(0); 74 | } 75 | 76 | void set() 77 | { 78 | LockGuard lock(mutex_); 79 | signaled_ = true; 80 | condition_.notify_all(); 81 | } 82 | 83 | void reset() 84 | { 85 | LockGuard lock(mutex_); 86 | signaled_ = false; 87 | } 88 | 89 | bool autoReset() const 90 | { 91 | return autoReset_; 92 | } 93 | 94 | private: 95 | zl::thread::Mutex mutex_; 96 | zl::thread::Condition condition_; 97 | bool signaled_; 98 | const bool autoReset_; 99 | }; 100 | 101 | NAMESPACE_ZL_THREAD_END 102 | #endif /* ZL_CONTDITION_H */ 103 | -------------------------------------------------------------------------------- /zlreactor/thread/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = Makefile.in 2 | 3 | SUBDIRS = 4 | 5 | SUBDIRS += tests 6 | -------------------------------------------------------------------------------- /zlreactor/thread/ThreadGroup.cpp: -------------------------------------------------------------------------------- 1 | #include "zlreactor/thread/ThreadGroup.h" 2 | #include "zlreactor/thread/Thread.h" 3 | #include 4 | NAMESPACE_ZL_THREAD_START 5 | 6 | ThreadGroup::ThreadGroup() 7 | { 8 | 9 | } 10 | 11 | ThreadGroup::~ThreadGroup() 12 | { 13 | for(auto it=threads_.begin(),end=threads_.end(); it!=end; ++it) 14 | { 15 | delete *it; 16 | } 17 | threads_.clear(); 18 | } 19 | 20 | bool ThreadGroup::is_this_thread_in() 21 | { 22 | Thread::id id = this_thread::get_id(); 23 | LockGuard lock(mutex_); 24 | for(auto it=threads_.begin(),end=threads_.end(); it!=end; ++it) 25 | { 26 | if ((*it)->get_id() == id) 27 | return true; 28 | } 29 | return false; 30 | } 31 | 32 | bool ThreadGroup::is_thread_in(Thread* thrd) 33 | { 34 | if(thrd) 35 | { 36 | Thread::id id = thrd->get_id(); 37 | LockGuard lock(mutex_); 38 | for(auto it=threads_.begin(),end=threads_.end(); it!=end; ++it) 39 | { 40 | if ((*it)->get_id() == id) 41 | return true; 42 | } 43 | return false; 44 | } 45 | 46 | return false; 47 | } 48 | 49 | void ThreadGroup::add_thread(Thread *thrd) 50 | { 51 | if(thrd) 52 | { 53 | assert(!is_thread_in(thrd) && "must not add a duplicated thread"); 54 | LockGuard lock(mutex_); 55 | threads_.push_back(thrd); 56 | } 57 | } 58 | 59 | void ThreadGroup::remove_thread(Thread *thd) 60 | { 61 | LockGuard lock(mutex_); 62 | std::vector::iterator it = std::find(threads_.begin(), threads_.end(), thd); 63 | if(it != threads_.end()) 64 | { 65 | threads_.erase(it); 66 | } 67 | } 68 | 69 | void ThreadGroup::join_all() 70 | { 71 | assert(!is_this_thread_in() && "trying joining itself"); 72 | LockGuard lock(mutex_); 73 | //for_each(threads_.begin(), threads_.end(), std::bind(&Thread::join, std::placeholders::_1)); 74 | for(auto it=threads_.begin(),end=threads_.end(); it!=end; ++it) 75 | { 76 | if ((*it)->joinable()) 77 | (*it)->join(); 78 | } 79 | } 80 | 81 | size_t ThreadGroup::size() const 82 | { 83 | LockGuard lock(mutex_); 84 | return threads_.size(); 85 | } 86 | 87 | NAMESPACE_ZL_THREAD_END -------------------------------------------------------------------------------- /zlreactor/thread/ThreadGroup.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : ThreadGroup.h 3 | // Author : LIZHENG 4 | // Created : 2014-10-13 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_THREADGROU_H 10 | #define ZL_THREADGROU_H 11 | #include "zlreactor/Define.h" 12 | #include "zlreactor/base/NonCopy.h" 13 | #include "zlreactor/thread/Thread.h" 14 | #include "zlreactor/thread/Mutex.h" 15 | NAMESPACE_ZL_THREAD_START 16 | class Thread; 17 | 18 | class ThreadGroup : zl::NonCopy 19 | { 20 | public: 21 | ThreadGroup(); 22 | ~ThreadGroup(); 23 | 24 | public: 25 | template 26 | Thread* create_thread(F threadfunc, const std::string& thrd_name="") 27 | { 28 | Thread *trd = new Thread(threadfunc, thrd_name); 29 | add_thread(trd); 30 | return trd; 31 | } 32 | 33 | void add_thread(Thread *thd); 34 | void remove_thread(Thread *thd); 35 | void join_all(); 36 | size_t size() const; 37 | 38 | private: 39 | bool is_this_thread_in(); 40 | bool is_thread_in(Thread* thrd); 41 | 42 | private: 43 | mutable Mutex mutex_; 44 | std::vector threads_; 45 | }; 46 | 47 | NAMESPACE_ZL_THREAD_END 48 | #endif /* ZL_THREADGROU_H */ 49 | -------------------------------------------------------------------------------- /zlreactor/thread/ThreadPool.cpp: -------------------------------------------------------------------------------- 1 | #include "zlreactor/thread/ThreadPool.h" 2 | #include 3 | #include 4 | #include "zlreactor/thread/Thread.h" 5 | #include "zlreactor/base/Exception.h" 6 | NAMESPACE_ZL_THREAD_START 7 | 8 | ThreadPool::ThreadPool(const std::string& name/* = "ThreadPool"*/) 9 | : name_(name), running_(false) 10 | { 11 | } 12 | 13 | ThreadPool::~ThreadPool() 14 | { 15 | if (running_) 16 | { 17 | stop(); 18 | } 19 | } 20 | 21 | void ThreadPool::start(int numThreads) 22 | { 23 | if (running_) 24 | return; 25 | running_ = true; 26 | assert(threads_.empty()); 27 | threads_.reserve(numThreads); 28 | for (int i = 0; i < numThreads; ++i) 29 | { 30 | char id[32]; 31 | ZL_SNPRINTF(id, sizeof id, "%d", i); 32 | threads_.push_back(new Thread(std::bind(&ThreadPool::executeThread, this), name_ + id)); 33 | } 34 | } 35 | 36 | void ThreadPool::stop() 37 | { 38 | running_ = false; 39 | queue_.stop(); 40 | for_each(threads_.begin(), threads_.end(), std::bind(&Thread::join, std::placeholders::_1)); 41 | } 42 | 43 | void ThreadPool::run(const Task& task) 44 | { 45 | if (threads_.empty()) 46 | { 47 | task(); 48 | } 49 | else 50 | { 51 | queue_.push(task); 52 | } 53 | } 54 | 55 | void ThreadPool::executeThread() 56 | { 57 | try 58 | { 59 | while (running_) 60 | { 61 | Task task(queue_.pop()); 62 | if (task) 63 | { 64 | /*bool ret = */task(); 65 | } 66 | } 67 | } 68 | catch (const zl::base::Exception& ex) 69 | { 70 | fprintf(stderr, "exception caught in ThreadPool %s\n", name_.c_str()); 71 | fprintf(stderr, "reason: %s\n", ex.what()); 72 | fprintf(stderr, "stack trace: %s\n", ex.stackTrace()); 73 | std::abort(); 74 | } 75 | catch (const std::exception& ex) 76 | { 77 | fprintf(stderr, "exception caught in ThreadPool %s\n", name_.c_str()); 78 | fprintf(stderr, "reason: %s\n", ex.what()); 79 | std::abort(); 80 | } 81 | catch (...) 82 | { 83 | fprintf(stderr, "unknown exception caught in ThreadPool %s\n", name_.c_str()); 84 | throw; // rethrow 85 | } 86 | } 87 | 88 | NAMESPACE_ZL_THREAD_END 89 | -------------------------------------------------------------------------------- /zlreactor/thread/ThreadPool.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : ThreadPool.h 3 | // Author : LIZHENG 4 | // Created : 2014-10-06 5 | // Description : 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_THREADPOOL_H 10 | #define ZL_THREADPOOL_H 11 | #include "zlreactor/Define.h" 12 | #include "zlreactor/base/NonCopy.h" 13 | #include "zlreactor/thread/BlockingQueue.h" 14 | NAMESPACE_ZL_THREAD_START 15 | 16 | class Thread; 17 | 18 | class ThreadPool : zl::NonCopy 19 | { 20 | public: 21 | typedef std::function Task; 22 | 23 | public: 24 | explicit ThreadPool(const std::string& name = "ThreadPool"); 25 | ~ThreadPool(); 26 | 27 | public: 28 | void start(int numThreads); 29 | void stop(); 30 | void run(const Task& f); 31 | size_t size() const { return queue_.size(); } 32 | 33 | private: 34 | void executeThread(); 35 | 36 | private: 37 | std::string name_; 38 | volatile bool running_; 39 | BlockingQueue queue_; 40 | std::vector threads_; 41 | }; 42 | 43 | NAMESPACE_ZL_THREAD_END 44 | #endif /* ZL_THREADPOOL_H */ 45 | -------------------------------------------------------------------------------- /zlreactor/thread/tests/Atomic_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "zlreactor/thread/Atomic.h" 4 | using namespace std; 5 | 6 | 7 | void test_usage() 8 | { 9 | { 10 | zl::thread::Atomic ato; 11 | ato++; 12 | ++ato; 13 | ato.getAndAdd(10); 14 | ato += 100; 15 | ato -= 3; 16 | std::cout << ato.value() << "\n"; 17 | 18 | long t = ato.subAndGet(3); 19 | std::cout << ato << "\t" << t << "\n"; 20 | } 21 | { 22 | std::cout << "========================================\n"; 23 | //zl::thread::Atomic ato; 24 | zl::thread::AtomicInt32 ato; 25 | 26 | std::cout << ato.getAndAdd(2) << "\t"; 27 | std::cout << ato.value() << "\n"; 28 | 29 | std::cout << ato.addAndGet(3) << "\t"; 30 | std::cout << ato.value() << "\n"; 31 | } 32 | { 33 | std::cout << "========================================\n"; 34 | zl::thread::Atomic ato; 35 | cout << ato << "\n"; 36 | cout << ato.test_and_set() << "\n"; 37 | cout << ato << "\n"; 38 | 39 | ato = true; 40 | cout << ato << "\n"; 41 | ato = false; 42 | cout << ato << "\n"; 43 | 44 | ato = false; 45 | ato = false; 46 | cout << ato << "\n"; 47 | 48 | ato = true; 49 | ato.clear(); 50 | cout << ato << "\n"; 51 | } 52 | } 53 | 54 | template < typename T> 55 | void test_atomic() 56 | { 57 | zl::thread::Atomic ato; 58 | 59 | ato = (T)0; 60 | ato++; 61 | assert(ato.value() == 1); 62 | 63 | ato += 3; 64 | assert(ato.value() == 4); 65 | 66 | ato--; 67 | --ato; 68 | assert(ato.value() == 2); 69 | } 70 | 71 | template <> 72 | void test_atomic() 73 | { 74 | zl::thread::AtomicBool ato; 75 | ato = true; 76 | assert(ato.value() == true); 77 | ato.clear(); 78 | assert(ato.value() == false); 79 | assert(ato.test_and_set() == false); 80 | assert(ato.value() == true); 81 | } 82 | 83 | int main() 84 | { 85 | test_usage(); 86 | 87 | test_atomic(); 88 | test_atomic(); 89 | test_atomic(); 90 | test_atomic(); 91 | test_atomic(); 92 | test_atomic(); 93 | test_atomic(); 94 | test_atomic(); 95 | 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /zlreactor/thread/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${PROJECT_SOURCE_DIR}) 2 | 3 | set(CMAKE_CXX_FLAGS "-std=c++0x -Wall -pthread") 4 | 5 | link_directories(${CMAKE_INSTALL_PREFIX}/lib/ 6 | ${PROJECT_SOURCE_DIR}/lib/ 7 | ${PROJECT_BINARY_DIR}/lib/ 8 | ) 9 | 10 | add_executable(Atomic_test Atomic_test.cpp) 11 | target_link_libraries(Atomic_test zlreactor) 12 | 13 | add_executable(BlockingQueue_test BlockingQueue_test.cpp) 14 | target_link_libraries(BlockingQueue_test zlreactor) 15 | 16 | add_executable(CountDownLatch_test CountDownLatch_test.cpp) 17 | target_link_libraries(CountDownLatch_test zlreactor) 18 | 19 | add_executable(CyclicBarrier_test CyclicBarrier_test.cpp) 20 | target_link_libraries(CyclicBarrier_test zlreactor) 21 | 22 | add_executable(Mutex_test Mutex_test.cpp) 23 | target_link_libraries(Mutex_test zlreactor) 24 | 25 | add_executable(Event_test Event_test.cpp) 26 | target_link_libraries(Event_test zlreactor) 27 | 28 | add_executable(Thread_test Thread_test.cpp) 29 | target_link_libraries(Thread_test zlreactor) 30 | 31 | add_executable(ThreadGroup_test ThreadGroup_test.cpp) 32 | target_link_libraries(ThreadGroup_test zlreactor) 33 | 34 | add_executable(ThreadLocal_test ThreadLocal_test.cpp) 35 | target_link_libraries(ThreadLocal_test zlreactor) 36 | -------------------------------------------------------------------------------- /zlreactor/thread/tests/ConcurrentQueue_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "zlreactor/thread/ConcurrentQueue.h" 5 | using namespace std; 6 | using namespace zl::thread; 7 | 8 | // 模仿java.util.concurrent库并发容器及Mircosoft的并发容器而写的一个简单并发队列 9 | // http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html 10 | // http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/LinkedBlockingQueue.html 11 | // http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html 12 | // http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/PriorityBlockingQueue.html 13 | int main() 14 | { 15 | { 16 | FifoConcurrentQueue cq; 17 | cq.push(3); 18 | cq.push(1); 19 | cq.push(2); 20 | 21 | int i; 22 | cq.pop(i); 23 | assert(i == 3); 24 | cq.pop(i); 25 | assert(i == 1); 26 | cq.pop(i); 27 | assert(i == 2); 28 | } 29 | 30 | { 31 | FiloConcurrentQueue cq; 32 | cq.push(3); 33 | cq.push(1); 34 | cq.push(2); 35 | 36 | int i; 37 | cq.pop(i); 38 | assert(i == 2); 39 | cq.pop(i); 40 | assert(i == 1); 41 | cq.pop(i); 42 | assert(i == 3); 43 | } 44 | 45 | { 46 | PrioConcurrentQueue cq; 47 | cq.push(3); 48 | cq.push(1); 49 | cq.push(2); 50 | 51 | int i; 52 | cq.pop(i); 53 | assert(i == 3); 54 | cq.pop(i); 55 | assert(i == 2); 56 | cq.pop(i); 57 | assert(i == 1); 58 | } 59 | { 60 | ConcurrentQueue, std::greater >, ConcurrentQueueTraits::tagPRIO> cq; 61 | cq.push(3); 62 | cq.push(1); 63 | cq.push(2); 64 | 65 | int i; 66 | cq.pop(i); 67 | assert(i == 1); 68 | cq.pop(i); 69 | assert(i == 2); 70 | cq.pop(i); 71 | assert(i == 3); 72 | } 73 | 74 | } -------------------------------------------------------------------------------- /zlreactor/thread/tests/Makefile.am: -------------------------------------------------------------------------------- 1 | #CXXFLAGS += -Wall -static -g -O2 -fPIC 2 | 3 | bin_PROGRAMS = Atomic_test BlockingQueue_test CountDownLatch_test CyclicBarrier_test Thread_test ThreadLocal_test \ 4 | Mutex_test Event_test ThreadGroup_test BlockingQueueWorker_test ThreadId_test BlockingQueue_bench \ 5 | ConcurrentQueue_test ConcurrentQueue_bench ConcurrentHashMap_test 6 | 7 | INCLUDES = -I../../../zlreactor 8 | CPPFLAGS = -std=c++0x 9 | LDFLAGS = -L../../../lib -lzlreactor 10 | 11 | #Atomic_test_CPPFLAGS = $(CPPFLAGS) 12 | #Atomic_test_LDFLAGS = $(CPPFLAGS) 13 | Atomic_test_SOURCES = Atomic_test.cpp 14 | 15 | Mutex_test_CPPFLAGS = $(CPPFLAGS) -O2 16 | Mutex_test_SOURCES = Mutex_test.cpp 17 | 18 | Event_test_SOURCES = Event_test.cpp 19 | 20 | BlockingQueue_test_SOURCES = BlockingQueue_test.cpp 21 | 22 | BlockingQueue_bench_SOURCES = BlockingQueue_bench.cpp 23 | 24 | CountDownLatch_test_SOURCES = CountDownLatch_test.cpp 25 | 26 | CyclicBarrier_test_SOURCES = CyclicBarrier_test.cpp 27 | 28 | #Thread_test_CPPFLAGS = $(CPPFLAGS) 29 | #Thread_test_LDFLAGS = $(CPPFLAGS) 30 | Thread_test_SOURCES = Thread_test.cpp 31 | 32 | ThreadId_test_SOURCES = ThreadId_test.cpp 33 | 34 | ThreadLocal_test_SOURCES = ThreadLocal_test.cpp 35 | 36 | ThreadGroup_test_SOURCES = ThreadGroup_test.cpp 37 | 38 | BlockingQueueWorker_test_SOURCES = BlockingQueueWorker_test.cpp 39 | 40 | ConcurrentQueue_test_SOURCES = ConcurrentQueue_test.cpp 41 | 42 | ConcurrentQueue_bench_LDFLAGS = $(CPPFLAGS) -O2 -DNDEBUG 43 | ConcurrentQueue_bench_SOURCES = ConcurrentQueue_bench.cpp 44 | 45 | ConcurrentHashMap_test_SOURCES = ConcurrentHashMap_test.cpp 46 | -------------------------------------------------------------------------------- /zlreactor/thread/tests/ThreadGroup_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | File Name : ThreadLocal_test.cpp 3 | Author : LIZHENG 4 | Mail : lizhenghn@gmail.com 5 | Created Time: 2015年06月23日 星期二 23时26分50秒 6 | ************************************************************************/ 7 | #include 8 | #include "zlreactor/thread/Thread.h" 9 | #include "zlreactor/thread/Mutex.h" 10 | #include "zlreactor/thread/Condition.h" 11 | #include "zlreactor/thread/ThreadPool.h" 12 | #include "zlreactor/thread/ThreadGroup.h" 13 | using namespace std; 14 | using namespace zl; 15 | using namespace zl::thread; 16 | 17 | void printI(int i) 18 | { 19 | printf("this thread[%ld] print %d\n", this_thread::get_id().value(), i); 20 | this_thread::sleep_for(chrono::milliseconds(1000)); 21 | } 22 | void printString(const char* data) 23 | { 24 | printf("this thread[%ld] print %s\n", this_thread::get_id().value(), data); 25 | } 26 | 27 | void test_ThreadGroup() 28 | { 29 | ThreadGroup tg; 30 | Thread *trd; 31 | for (int i = 1; i < 10; i++) 32 | { 33 | if (i%2 == 0) 34 | { 35 | trd = tg.create_thread(std::bind(printI, i)); 36 | } 37 | else if(i%3 == 0) 38 | { 39 | tg.create_thread(std::bind(printString, "hello world")); 40 | } 41 | else 42 | { 43 | tg.add_thread(new Thread(std::bind(printI, i))); 44 | } 45 | } 46 | 47 | tg.remove_thread(trd); // 该接口并不能使已加入的线程停止运行(创建时即运行),仅仅使该线程不再由ThreadGroup负责删除 48 | 49 | tg.create_thread(std::bind(printString, "ThreadGroup")); 50 | 51 | tg.join_all(); 52 | 53 | delete trd; 54 | } 55 | 56 | int main() 57 | { 58 | cout << "###### test ThreadGroup ######\n"; 59 | test_ThreadGroup(); 60 | 61 | cout << "###### GAME OVER ######\n"; 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /zlreactor/thread/tests/ThreadLocal_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "zlreactor/thread/Thread.h" 3 | #include "zlreactor/thread/Mutex.h" 4 | #include "zlreactor/thread/Condition.h" 5 | #include "zlreactor/thread/ThreadPool.h" 6 | #include "zlreactor/thread/ThreadLocal.h" 7 | #include "zlreactor/thread/CountDownLatch.h" 8 | using namespace std; 9 | using namespace zl; 10 | using namespace zl::thread; 11 | 12 | // pod 类型的thread_local测试 13 | namespace thread_tls1 14 | { 15 | thread_local int gLocalVar = 0; 16 | 17 | void ThreadTLS(int op) 18 | { 19 | gLocalVar += op; 20 | cout << "[" << this_thread::tid() <<"]Thread gLocalVar is " << gLocalVar << ".\n"; 21 | } 22 | 23 | void test_threadtls() 24 | { 25 | gLocalVar = 1; // 主线程设置gLocalVar新值 26 | cout << "[" << this_thread::tid() << "]Main gLocalVar is " << gLocalVar << ".\n"; 27 | 28 | Thread t1(std::bind(ThreadTLS, 99)); // 子线程更新gLocalVar值, 注意输出 29 | t1.join(); // cout 99, not 99 + 1 30 | 31 | Thread t2(std::bind(ThreadTLS, 9999)); // 另一子线程更新gLocalVar值, 注意输出 32 | t2.join(); // cout 9999, not 9999+1 33 | 34 | assert(gLocalVar == 1); 35 | } 36 | } 37 | 38 | // class 类型的thread_local测试 39 | namespace thread_tls2 40 | { 41 | class TestTLS 42 | { 43 | public: 44 | TestTLS() 45 | { 46 | num = -1; 47 | cout << "TestTLS : [" << this << "] " << num << "\n"; 48 | } 49 | ~TestTLS() 50 | { 51 | cout << "~TestTLS : [" << this << "] " << num << "\n"; 52 | } 53 | void set(int n) { num = n; } 54 | void plus(int n) { num += n; } 55 | void print() { cout << "print : [" << this << "] " << num << "\n"; } 56 | private: 57 | int num; 58 | }; 59 | 60 | ThreadLocal g_tls; 61 | 62 | void testTLS(int i) 63 | { 64 | g_tls->plus(i); 65 | g_tls->print(); 66 | } 67 | void test_threadtls() 68 | { 69 | g_tls->set(10); 70 | g_tls->print(); 71 | 72 | Thread t1(std::bind(testTLS, 23)); 73 | t1.join(); 74 | 75 | Thread t2(std::bind(testTLS, 100)); 76 | t2.join(); 77 | 78 | g_tls->print(); 79 | } 80 | } 81 | 82 | void test() 83 | { 84 | cout << "#######################################\n"; 85 | thread_tls1::test_threadtls(); 86 | cout << "#######################################\n"; 87 | thread_tls2::test_threadtls(); 88 | } 89 | 90 | int main() 91 | { 92 | cout << "###### test thread local ######\n"; 93 | test(); 94 | 95 | cout << "###### GAME OVER ######\n"; 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /zlreactor/utility/Base64.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : Base64.h 3 | // Author : LIZHENG 4 | // Created : 2014-09-16 5 | // Description : Base64 ������ 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_BASE64_H 10 | #define ZL_BASE64_H 11 | #include "zlreactor/Define.h" 12 | #include 13 | NAMESPACE_ZL_UTIL_START 14 | 15 | // len == strlen(src), and strlen(dst) >= len * 4 / 3 16 | // ���ر��������ַ������� 17 | size_t base64Encode(const char *src, size_t len, char *dst); 18 | size_t base64Encode(const char *src, size_t len, std::string& dst); 19 | size_t base64Encode(const std::string& src, std::string& dst); 20 | std::string base64Encode(const char *src, size_t len); 21 | std::string base64Encode(const std::string& src); 22 | 23 | // len == strlen(src), and strlen(dst) >= len * 3 / 4 24 | // ���ؽ��������ַ������� 25 | size_t base64Decode(const char *src, size_t len, char *dst); 26 | size_t base64Decode(const char *src, size_t len, std::string& dst); 27 | size_t base64Decode(const std::string& src, std::string& dst); 28 | std::string base64Decode(const char *src, size_t len); 29 | std::string base64Decode(const std::string& src); 30 | 31 | NAMESPACE_ZL_UTIL_END 32 | #endif /* ZL_BASE64_H */ 33 | -------------------------------------------------------------------------------- /zlreactor/utility/Hex2String.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lizhenghn123/zl_reactor/2f40099b9f6a281bc8b51fb3c084117c5bbd60ad/zlreactor/utility/Hex2String.h -------------------------------------------------------------------------------- /zlreactor/utility/SHA1.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : SHA1.h 3 | // Author : LIZHENG 4 | // Created : 2015--27 5 | // Description : 安全哈希算法(Secure Hash Algorithm) 6 | // 7 | // Last Modified By : LIZHENG 8 | // Last Modified On : 2015-11-10 9 | // 10 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 11 | // *********************************************************************** 12 | #ifndef ZL_SHA1_H 13 | #define ZL_SHA1_H 14 | #include 15 | #include 16 | // 对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。 17 | // 在传输的过程中,数据很可能会发生变化,那么这时候就会产生不同的消息摘要。 18 | // SHA1特性:不可以从消息摘要中复原信息;两个不同的消息不会产生同样的消息摘要。 19 | 20 | namespace zl 21 | { 22 | namespace util 23 | { 24 | 25 | class SHA1 26 | { 27 | public: 28 | SHA1(); 29 | ~SHA1(); 30 | 31 | static std::string hexDigest(const std::string& src); 32 | 33 | public: 34 | void reset(); 35 | void update(const std::string& sp); 36 | // Finalizes the Sha1 operation and fills the buffer with the digest. 37 | // Data is uint8_t digest_[20] 38 | void final(void* digest); 39 | // Hex encoding for result 40 | std::string hexFinal(); 41 | 42 | private: 43 | void sha1Transform(uint32_t state[5], const uint8_t buffer[64]); 44 | void update(const uint8_t* data, size_t input_len); 45 | void finalInternal(); 46 | 47 | private: 48 | SHA1(const SHA1&); 49 | const SHA1& operator=(const SHA1&); 50 | 51 | struct SHA1_CTX 52 | { 53 | uint32_t state[5]; 54 | uint32_t count[2]; // Bit count of input. 55 | uint8_t buffer[64]; 56 | }; 57 | 58 | SHA1_CTX context_; 59 | uint8_t digest_[20]; 60 | }; 61 | 62 | } 63 | } 64 | #endif /* ZL_SHA1_H */ -------------------------------------------------------------------------------- /zlreactor/utility/StringHash.cpp: -------------------------------------------------------------------------------- 1 | #include "zlreactor/utility/StringHash.h" 2 | NAMESPACE_ZL_UTIL_START 3 | 4 | //SDBM Hash Function 5 | unsigned int SDBMHash(const char *str) 6 | { 7 | unsigned int hash = 0; 8 | while( *str ) 9 | { 10 | //equivalent to: hash = 65599*hash+(*str++); 11 | hash = (*str++) + (hash<<6) + (hash<<16) - hash; 12 | } 13 | 14 | return (hash&0x7FFFFFFF); 15 | } 16 | 17 | //RS Hash Function 18 | unsigned int RSHash(const char *str) 19 | { 20 | unsigned int b = 378551; 21 | unsigned int a = 63689; 22 | unsigned int hash = 0; 23 | 24 | while( *str ) 25 | { 26 | hash = hash * a + (*str++); 27 | a *= b; 28 | } 29 | 30 | return (hash&0x7FFFFFFF); 31 | } 32 | 33 | //JS Hash Function 34 | unsigned int JSHash(const char *str) 35 | { 36 | unsigned int hash = 1315423911; 37 | 38 | while( *str ) 39 | { 40 | hash ^= ( (hash<<5) + (*str++) + (hash>>2) ); 41 | } 42 | 43 | return (hash&0x7FFFFFFF); 44 | } 45 | 46 | //BKDR Hash Function 47 | unsigned int BKDRHash(const char *str) 48 | { 49 | //unsigned int seed = 131; //31 131 1313 13131 131313 50 | unsigned int hash = 0; 51 | 52 | while( *str ) 53 | { 54 | hash ^= ( (hash<<5) + (*str++) + (hash>>2) ); 55 | } 56 | 57 | return (hash&0x7FFFFFFF); 58 | } 59 | 60 | //DJB Hash Function 61 | unsigned int DJBHash(const char *str) 62 | { 63 | unsigned int hash = 5381; 64 | 65 | while( *str ) 66 | { 67 | hash += (hash<<5) + (*str++); 68 | } 69 | 70 | return (hash&0x7FFFFFFF); 71 | } 72 | 73 | unsigned int FNVHash(const char *str) 74 | { 75 | register unsigned int hash = 2166136261; 76 | while (unsigned int ch = (unsigned int )*str++) 77 | { 78 | hash *= 16777619; 79 | hash ^= ch; 80 | } 81 | return hash; 82 | } 83 | 84 | NAMESPACE_ZL_UTIL_END -------------------------------------------------------------------------------- /zlreactor/utility/StringHash.h: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Filename : StringHash.h 3 | // Author : LIZHENG 4 | // Created : 2014-09-23 5 | // Description : �ַ����Ķ���hash���� 6 | // 7 | // Copyright (c) lizhenghn@gmail.com. All rights reserved. 8 | // *********************************************************************** 9 | #ifndef ZL_STRINGHASH_H 10 | #define ZL_STRINGHASH_H 11 | #include "zlreactor/Define.h" 12 | NAMESPACE_ZL_UTIL_START 13 | 14 | //SDBM Hash Function 15 | unsigned int SDBMHash(const char *str); 16 | 17 | //RS Hash Function 18 | unsigned int RSHash(const char *str); 19 | 20 | //JS Hash Function 21 | unsigned int JSHash(const char *str); 22 | 23 | //BKDR Hash Function 24 | unsigned int BKDRHash(const char *str); 25 | 26 | //DJB Hash Function 27 | unsigned int DJBHash(const char *str); 28 | 29 | //FNV Hash Function 30 | unsigned int FNVHash(const char *str); 31 | 32 | NAMESPACE_ZL_UTIL_END 33 | #endif /* ZL_STRINGHASH_H */ 34 | -------------------------------------------------------------------------------- /zlreactor/utility/UUID.h: -------------------------------------------------------------------------------- 1 | #ifndef ZL_UUID_H 2 | #define ZL_UUID_H 3 | #include "zlreactor/Define.h" 4 | #ifdef OS_WINDOWS 5 | #include 6 | #else 7 | #include // need -luuid 8 | #endif 9 | 10 | NAMESPACE_ZL_UTIL_START 11 | 12 | std::string createUuid() 13 | { 14 | char buf[64] = {0}; 15 | #ifdef OS_WINDOWS 16 | GUID guid; 17 | if (CoCreateGuid(&guid) == S_OK){ 18 | ZL_SNPRINTF(buf, sizeof(buf), 19 | "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", 20 | guid.Data1, guid.Data2, guid.Data3, 21 | guid.Data4[0], guid.Data4[1], 22 | guid.Data4[2], guid.Data4[3], 23 | guid.Data4[4], guid.Data4[5], 24 | guid.Data4[6], guid.Data4[7]); 25 | } 26 | #else 27 | uuid_t uu; 28 | uuid_generate(uu); 29 | if (!uuid_is_null(uu)) { 30 | ZL_SNPRINTF(buf, sizeof(buf), 31 | "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", 32 | uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7], 33 | uu[8], uu[9], uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]); 34 | } 35 | #endif 36 | 37 | return buf; 38 | } 39 | 40 | NAMESPACE_ZL_UTIL_END 41 | #endif /* ZL_UUID_H */ -------------------------------------------------------------------------------- /zlreactor/utility/jenkins_hash.h: -------------------------------------------------------------------------------- 1 | #ifndef JENKINS_HASH_H 2 | #define JENKINS_HASH_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | uint32_t jenkins_hash(const void *key, size_t length); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif /* JENKINS_HASH_H */ 15 | 16 | -------------------------------------------------------------------------------- /zlreactor/utility/murmur3_hash.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // MurmurHash3 was written by Austin Appleby, and is placed in the public 3 | // domain. The author hereby disclaims copyright to this source code. 4 | 5 | #ifndef MURMURHASH3_H 6 | #define MURMURHASH3_H 7 | 8 | //----------------------------------------------------------------------------- 9 | // Platform-specific functions and macros 10 | #include 11 | #include 12 | 13 | //----------------------------------------------------------------------------- 14 | 15 | uint32_t MurmurHash3_x86_32(const void *key, size_t length); 16 | 17 | //----------------------------------------------------------------------------- 18 | 19 | #endif // MURMURHASH3_H 20 | --------------------------------------------------------------------------------