├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── Metazion ├── CMakeLists.txt ├── CoreInclude.hpp ├── Define.hpp ├── Function.hpp ├── Net │ ├── Address.hpp │ ├── AlternativeService.hpp │ ├── AlternativeStrategy.hpp │ ├── AlternativeThread.hpp │ ├── AppClientSocket.cpp │ ├── AppClientSocket.hpp │ ├── AppListenSocket.cpp │ ├── AppListenSocket.hpp │ ├── AppServerSocket.cpp │ ├── AppServerSocket.hpp │ ├── CMakeLists.txt │ ├── ComAccepter.cpp │ ├── ComAccepter.hpp │ ├── ComConnecter.cpp │ ├── ComConnecter.hpp │ ├── ComPacketer.cpp │ ├── ComPacketer.hpp │ ├── EpollIoThread.cpp │ ├── EpollIoThread.hpp │ ├── EpollListenStrategy.cpp │ ├── EpollListenStrategy.hpp │ ├── EpollOperation.hpp │ ├── EpollService.cpp │ ├── EpollService.hpp │ ├── EpollStrategy.hpp │ ├── EpollTransmitStrategy.cpp │ ├── EpollTransmitStrategy.hpp │ ├── Host.hpp │ ├── IocpIoThread.cpp │ ├── IocpIoThread.hpp │ ├── IocpListenStrategy.cpp │ ├── IocpListenStrategy.hpp │ ├── IocpOperation.hpp │ ├── IocpService.cpp │ ├── IocpService.hpp │ ├── IocpStrategy.hpp │ ├── IocpTransmitStrategy.cpp │ ├── IocpTransmitStrategy.hpp │ ├── ListenSocket.cpp │ ├── ListenSocket.hpp │ ├── MaintenanceThread.cpp │ ├── MaintenanceThread.hpp │ ├── NetInclude.hpp │ ├── Network.cpp │ ├── Network.hpp │ ├── NetworkService.cpp │ ├── NetworkService.hpp │ ├── PacketCodec.cpp │ ├── PacketCodec.hpp │ ├── PacketDefine.hpp │ ├── SelectIoThread.cpp │ ├── SelectIoThread.hpp │ ├── SelectListenStrategy.cpp │ ├── SelectListenStrategy.hpp │ ├── SelectOperation.hpp │ ├── SelectService.cpp │ ├── SelectService.hpp │ ├── SelectStrategy.hpp │ ├── SelectTransmitStrategy.cpp │ ├── SelectTransmitStrategy.hpp │ ├── Socket.cpp │ ├── Socket.hpp │ ├── SocketBuffer.cpp │ ├── SocketBuffer.hpp │ ├── SocketCtrl.hpp │ ├── SocketDefine.cpp │ ├── SocketDefine.hpp │ ├── TransmitSocket.cpp │ └── TransmitSocket.hpp ├── Overall.hpp ├── Platform.hpp ├── Share │ ├── Algorithm │ │ └── StringHash.hpp │ ├── Async │ │ ├── AsyncService.cpp │ │ ├── AsyncService.hpp │ │ ├── AsyncThread.cpp │ │ └── AsyncThread.hpp │ ├── CMakeLists.txt │ ├── Collection │ │ ├── ArrayList.hpp │ │ ├── DynamicArray.hpp │ │ ├── DynamicSortedArray.hpp │ │ ├── HashMap.hpp │ │ ├── Hasher.hpp │ │ ├── List.hpp │ │ ├── Map.hpp │ │ ├── PriorityQueue.hpp │ │ ├── RBTree.hpp │ │ ├── SelfArrayList.hpp │ │ ├── SelfList.hpp │ │ ├── StaticArray.hpp │ │ ├── StaticSortedArray.hpp │ │ ├── UDList.hpp │ │ └── UDSelfList.hpp │ ├── Log │ │ ├── LogDefine.hpp │ │ └── Logger.hpp │ ├── Memory │ │ ├── BlockAllocator.hpp │ │ ├── HeapAllocator.hpp │ │ ├── InputBuffer.hpp │ │ ├── MemoryPiece.hpp │ │ ├── MemoryRecordset.cpp │ │ ├── MemoryRecordset.hpp │ │ ├── ObjectPool.hpp │ │ ├── OutputBuffer.hpp │ │ ├── PieceBuffer.hpp │ │ ├── RingBuffer.hpp │ │ ├── ShrinkStepAllocator.hpp │ │ ├── StepAllocator.hpp │ │ └── StepBuffer.hpp │ ├── Misc │ │ ├── MemoryInputStream.hpp │ │ └── MemoryOutputStream.hpp │ ├── Pattern │ │ └── Singleton.hpp │ ├── ShareInclude.hpp │ ├── Sync │ │ └── NoneLock.hpp │ ├── Thread │ │ ├── Thread.cpp │ │ └── Thread.hpp │ ├── Time │ │ ├── Time.cpp │ │ └── Time.hpp │ └── Utility │ │ ├── Random.cpp │ │ ├── Random.hpp │ │ ├── StringFunction.cpp │ │ └── StringFunction.hpp └── Type.hpp ├── README.md ├── lcmake.sh ├── mcmake.sh └── wcmake.sh /.gitignore: -------------------------------------------------------------------------------- 1 | /Build 2 | /Bin 3 | /Lib 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | 3 | PROJECT(Metazion) 4 | SET(PRODUCT_VERSION 1.0) 5 | 6 | SET(SELF Metazion) 7 | SET(DEPENDENCE Dependence) 8 | SET(INC Inc) 9 | SET(LIB Lib) 10 | SET(BIN Bin) 11 | 12 | IF (CMAKE_SIZEOF_VOID_P MATCHES 8) 13 | SET(IS_64_BIT TRUE) 14 | ELSE() 15 | SET(IS_64_BIT FALSE) 16 | ENDIF() 17 | 18 | IF(IS_64_BIT) 19 | SET(PLATFORM x64) 20 | ELSE() 21 | SET(PLATFORM x86) 22 | ENDIF() 23 | 24 | SET(CMAKE_C_COMPILER cc) 25 | SET(CMAKE_CXX_COMPILER c++) 26 | 27 | IF(WIN32) 28 | SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MDd /Zi /Od /Ob0 /RTC1") 29 | SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MD /O2 /Ob2") 30 | SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd /Zi /Od /Ob0 /RTC1") 31 | SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD /O2 /Ob2") 32 | SET(CMAKE_EXE_LINKER_FLAGS "/MANIFEST:NO") 33 | ENDIF(WIN32) 34 | 35 | IF(UNIX) 36 | SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -std=c99 -g -Wall -D_DEBUG") 37 | SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -std=c99 -g -Wall") 38 | SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++14 -g -Wall -D_DEBUG") 39 | SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++14 -g -Wall") 40 | ENDIF(UNIX) 41 | 42 | SET(CMAKE_DEBUG_POSTFIX D) 43 | SET(CMAKE_BUILD_TYPE DEBUG) 44 | 45 | SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}) 46 | 47 | SET(SELF_DIR ${PROJECT_SOURCE_DIR}) 48 | SET(BUILD_DIR ${PROJECT_BINARY_DIR}) 49 | SET(INCLUDE_DIR ${SELF_DIR}) 50 | SET(SOURCE_DIR ${SELF_DIR}) 51 | SET(DEPENDENCE_DIR ${SELF_DIR}/${DEPENDENCE}) 52 | SET(INC_DIR ${SELF_DIR}/${INC}) 53 | SET(LIB_DIR ${SELF_DIR}/${LIB}/${PLATFORM}) 54 | SET(BIN_DIR ${SELF_DIR}/${BIN}/${PLATFORM}) 55 | 56 | OPTION(PRODUCT_INSTALL "Install libs, includes, and CMake scripts" ON) 57 | 58 | MESSAGE(STATUS "IS_64_BIT: ${IS_64_BIT}") 59 | MESSAGE(STATUS "PLATFORM: ${PLATFORM}") 60 | 61 | MESSAGE(STATUS "PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}") 62 | MESSAGE(STATUS "PROJECT_BINARY_DIR: ${PROJECT_BINARY_DIR}") 63 | MESSAGE(STATUS "PRODUCT_VERSION: ${PRODUCT_VERSION}") 64 | 65 | MESSAGE(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}") 66 | MESSAGE(STATUS "CMAKE_C_FLAGS_DEBUG: ${CMAKE_C_FLAGS_DEBUG}") 67 | MESSAGE(STATUS "CMAKE_C_FLAGS_RELEASE: ${CMAKE_C_FLAGS_RELEASE}") 68 | MESSAGE(STATUS "CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}") 69 | MESSAGE(STATUS "CMAKE_CXX_FLAGS_DEBUG: ${CMAKE_CXX_FLAGS_DEBUG}") 70 | MESSAGE(STATUS "CMAKE_CXX_FLAGS_RELEASE: ${CMAKE_CXX_FLAGS_RELEASE}") 71 | MESSAGE(STATUS "CMAKE_DEBUG_POSTFIX: ${CMAKE_DEBUG_POSTFIX}") 72 | MESSAGE(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") 73 | 74 | MESSAGE(STATUS "SELF_DIR: ${SELF_DIR}") 75 | MESSAGE(STATUS "BUILD_DIR: ${BUILD_DIR}") 76 | MESSAGE(STATUS "INCLUDE_DIR: ${INCLUDE_DIR}") 77 | MESSAGE(STATUS "SOURCE_DIR: ${SOURCE_DIR}") 78 | MESSAGE(STATUS "DEPENDENCE_DIR: ${DEPENDENCE_DIR}") 79 | MESSAGE(STATUS "LIB_DIR: ${LIB_DIR}") 80 | MESSAGE(STATUS "BIN_DIR: ${BIN_DIR}") 81 | 82 | ADD_SUBDIRECTORY(${SELF}) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-2016 Metazion 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 | -------------------------------------------------------------------------------- /Metazion/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | INCLUDE_DIRECTORIES(${INCLUDE_DIR}) 2 | 3 | IF(WIN32) 4 | ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) 5 | ENDIF(WIN32) 6 | 7 | ADD_DEFINITIONS(-D_UNICODE) 8 | 9 | FILE(GLOB METAZION_HEADERS "./*.hpp") 10 | FILE(GLOB METAZION_SOURCES "./*.cpp") 11 | 12 | ADD_SUBDIRECTORY(Share) 13 | ADD_SUBDIRECTORY(Net) -------------------------------------------------------------------------------- /Metazion/CoreInclude.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_CORE_INCLUDE_HPP_ 2 | #define _MZ_CORE_INCLUDE_HPP_ 3 | 4 | #include "Metazion/Platform.hpp" 5 | 6 | #define DECL_NAMESPACE_MZ_BEGIN namespace mz { 7 | #define DECL_NAMESPACE_MZ_END } 8 | #define USING_NAMESPACE_MZ using namespace mz; 9 | #define NS_MZ mz 10 | 11 | #endif // _MZ_CORE_INCLUDE_HPP_ 12 | -------------------------------------------------------------------------------- /Metazion/Define.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_DEFINE_HPP_ 2 | #define _MZ_DEFINE_HPP_ 3 | 4 | #include "Metazion/CoreInclude.hpp" 5 | 6 | #include 7 | 8 | DECL_NAMESPACE_MZ_BEGIN 9 | 10 | #if defined(MZ_PLATFORM_MACOS) 11 | # define thread_local 12 | #endif 13 | 14 | #if defined(MZ_MODE_DEBUG) 15 | # define MZ_ENABLE_STATISTIC 16 | #endif 17 | 18 | #define DECL_BLOCK_BEGIN { 19 | #define DECL_BLOCK_END } 20 | 21 | #define MZ_DISALLOW_COPY_AND_ASSIGN(CLASS) \ 22 | CLASS(const CLASS&) = delete; \ 23 | CLASS& operator =(const CLASS&) = delete; \ 24 | CLASS(const CLASS&&) = delete; \ 25 | CLASS& operator =(const CLASS&&) = delete; 26 | 27 | #define MZ_ADAPT_FOR_RANGE_TRAVERSAL() \ 28 | ConstIterator_t begin() const { \ 29 | return Begin(); \ 30 | } \ 31 | Iterator_t begin() { \ 32 | return Begin(); \ 33 | } \ 34 | ConstIterator_t end() const { \ 35 | return End(); \ 36 | } \ 37 | Iterator_t end() { \ 38 | return End(); \ 39 | } 40 | 41 | #define MZ_ASSERT_TRUE(exp) assert( (exp) ) 42 | #define MZ_ASSERT_FALSE(exp) assert( !(exp) ) 43 | 44 | #define MZ_RELEASE_ASSERT_TRUE(exp) do { if (!(exp)) __asm { int 3 } } while (false) 45 | #define MZ_RELEASE_ASSERT_FALSE(exp) do { if ((exp)) __asm { int 3 } } while (false) 46 | 47 | #define MZ_MAX(a, b) (((a) > (b)) ? (a) : (b)) 48 | #define MZ_MIN(a, b) (((a) < (b)) ? (a) : (b)) 49 | 50 | #define MZ_DEFAULT_ALIGNMENT (sizeof(void*)) 51 | #define MZ_ALIGN_LENGTH(length, align) (((length) + (align) - 1) & ~((align) - 1)) 52 | #define MZ_IS_LENGTH_ALIGN(length, align) (((length) & ((align) -1)) == 0) 53 | 54 | #define MZ_UNUSED_VARIABLE(v) (void)(v) 55 | #define MZ_UNUSED_PARAM(v) (void)(v) 56 | 57 | DECL_NAMESPACE_MZ_END 58 | 59 | #endif // _MZ_DEFINE_HPP_ 60 | -------------------------------------------------------------------------------- /Metazion/Function.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_FUNCTION_HPP_ 2 | #define _MZ_FUNCTION_HPP_ 3 | 4 | #include "Metazion/CoreInclude.hpp" 5 | 6 | #include 7 | 8 | DECL_NAMESPACE_MZ_BEGIN 9 | 10 | template 11 | inline void SafeDelete(T*& ptr) { 12 | enum { TYPE_MUST_BE_COMPLETE = sizeof(T) }; 13 | delete ptr; 14 | ptr = nullptr; 15 | } 16 | 17 | template 18 | inline void SafeDeleteArray(T*& ptr) { 19 | enum { TYPE_MUST_BE_COMPLETE = sizeof(T) }; 20 | delete[] ptr; 21 | ptr = nullptr; 22 | } 23 | 24 | template 25 | inline bool IsNull(const T* const ptr) { 26 | return nullptr == ptr; 27 | } 28 | 29 | template 30 | inline bool IsNull(const T& val) { 31 | return nullptr == val; 32 | } 33 | 34 | inline int AlignLength(int length, int align) { 35 | return (length + align - 1) & ~(align - 1); 36 | } 37 | 38 | inline bool IsLengthAlign(int length, int align) { 39 | return (length & (align - 1)) == 0; 40 | } 41 | 42 | inline int MzGetLastError() { 43 | #if defined(MZ_PLATFORM_WINDOWS) 44 | return GetLastError(); 45 | #endif 46 | 47 | #if defined(MZ_PLATFORM_LINUX) 48 | return errno; 49 | #endif 50 | 51 | #if defined(MZ_PLATFORM_MACOS) 52 | return errno; 53 | #endif 54 | 55 | } 56 | 57 | DECL_NAMESPACE_MZ_END 58 | 59 | #endif // _MZ_FUNCTION_HPP_ 60 | -------------------------------------------------------------------------------- /Metazion/Net/Address.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_ADDRESS_HPP_ 2 | #define _MZ_NET_ADDRESS_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | DECL_NAMESPACE_MZ_NET_BEGIN 7 | 8 | struct Address { 9 | uint32_t m_ip{ 0 }; 10 | uint16_t m_port{ 0 }; 11 | }; 12 | 13 | DECL_NAMESPACE_MZ_NET_END 14 | 15 | #endif // _MZ_NET_ADDRESS_HPP_ 16 | -------------------------------------------------------------------------------- /Metazion/Net/AlternativeService.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_ALTERNATIVESERVICE_HPP_ 2 | #define _MZ_NET_ALTERNATIVESERVICE_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include "Metazion/Net/EpollService.hpp" 7 | #include "Metazion/Net/IocpService.hpp" 8 | #include "Metazion/Net/SelectService.hpp" 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | #if defined(NETWORK_USE_EPOLL_MODEL) 13 | # define SocketService EpollService 14 | #endif 15 | 16 | #if defined(NETWORK_USE_IOCP_MODEL) 17 | # define SocketService IocpService 18 | #endif 19 | 20 | #if defined(NETWORK_USE_SELECT_MODEL) 21 | # define SocketService SelectService 22 | #endif 23 | 24 | DECL_NAMESPACE_MZ_NET_END 25 | 26 | #endif // _MZ_NET_ALTERNATIVESERVICE_HPP_ 27 | -------------------------------------------------------------------------------- /Metazion/Net/AlternativeStrategy.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_ALTERNATIVESTRATEGY_HPP_ 2 | #define _MZ_NET_ALTERNATIVESTRATEGY_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include "Metazion/Net/EpollListenStrategy.hpp" 7 | #include "Metazion/Net/EpollTransmitStrategy.hpp" 8 | #include "Metazion/Net/IocpListenStrategy.hpp" 9 | #include "Metazion/Net/IocpTransmitStrategy.hpp" 10 | #include "Metazion/Net/SelectListenStrategy.hpp" 11 | #include "Metazion/Net/SelectTransmitStrategy.hpp" 12 | 13 | DECL_NAMESPACE_MZ_NET_BEGIN 14 | 15 | #if defined(NETWORK_USE_EPOLL_MODEL) 16 | # define IoStrategy EpollStrategy 17 | # define ListenStrategy EpollListenStrategy 18 | # define TransmitStrategy EpollTransmitStrategy 19 | #endif 20 | 21 | #if defined(NETWORK_USE_IOCP_MODEL) 22 | # define IoStrategy IocpStrategy 23 | # define ListenStrategy IocpListenStrategy 24 | # define TransmitStrategy IocpTransmitStrategy 25 | #endif 26 | 27 | #if defined(NETWORK_USE_SELECT_MODEL) 28 | # define IoStrategy SelectStrategy 29 | # define ListenStrategy SelectListenStrategy 30 | # define TransmitStrategy SelectTransmitStrategy 31 | #endif 32 | 33 | DECL_NAMESPACE_MZ_NET_END 34 | 35 | #endif // _MZ_NET_ALTERNATIVESTRATEGY_HPP_ 36 | -------------------------------------------------------------------------------- /Metazion/Net/AlternativeThread.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_ALTERNATIVETHREAD_HPP_ 2 | #define _MZ_NET_ALTERNATIVETHREAD_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include "Metazion/Net/EpollIoThread.hpp" 7 | #include "Metazion/Net/IocpIoThread.hpp" 8 | #include "Metazion/Net/SelectIoThread.hpp" 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | #if defined(NETWORK_USE_EPOLL_MODEL) 13 | # define IoThread EpollIoThread 14 | #endif 15 | 16 | #if defined(NETWORK_USE_IOCP_MODEL) 17 | # define IoThread IocpIoThread 18 | #endif 19 | 20 | #if defined(NETWORK_USE_SELECT_MODEL) 21 | # define IoThread SelectIoThread 22 | #endif 23 | 24 | DECL_NAMESPACE_MZ_NET_END 25 | 26 | #endif // _MZ_NET_ALTERNATIVETHREAD_HPP_ 27 | -------------------------------------------------------------------------------- /Metazion/Net/AppClientSocket.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/AppClientSocket.hpp" 2 | 3 | DECL_NAMESPACE_MZ_NET_BEGIN 4 | 5 | AppClientSocket::AppClientSocket() 6 | : m_connecter(*this) 7 | , m_packeter(*this) {} 8 | 9 | AppClientSocket::~AppClientSocket() {} 10 | 11 | void AppClientSocket::Reset() { 12 | TransmitSocket::Reset(); 13 | 14 | m_connecter.Reset(); 15 | m_packeter.Reset(); 16 | 17 | DerivedReset(); 18 | } 19 | 20 | void AppClientSocket::Prepare() { 21 | TransmitSocket::Prepare(); 22 | 23 | DerivedPrepare(); 24 | } 25 | 26 | void AppClientSocket::Tick(int64_t now, int interval) { 27 | TransmitSocket::Tick(now, interval); 28 | 29 | m_connecter.Tick(now, interval); 30 | 31 | DerivedTick(now, interval); 32 | } 33 | 34 | void AppClientSocket::Dispatch() { 35 | TransmitSocket::Dispatch(); 36 | 37 | m_packeter.Dispatch(); 38 | 39 | DerivedDispatch(); 40 | } 41 | 42 | void AppClientSocket::OnConnected() { 43 | TransmitSocket::OnConnected(); 44 | 45 | DerivedOnConnected(); 46 | } 47 | 48 | void AppClientSocket::OnDisconnected() { 49 | TransmitSocket::OnDisconnected(); 50 | 51 | DerivedOnDisconnected(); 52 | } 53 | 54 | void AppClientSocket::OnSended(const void* data, int length) { 55 | TransmitSocket::OnSended(data, length); 56 | 57 | DerivedOnSended(data, length); 58 | } 59 | 60 | void AppClientSocket::OnRecved(const void* data, int length) { 61 | TransmitSocket::OnRecved(data, length); 62 | 63 | DerivedOnRecved(data, length); 64 | } 65 | 66 | DECL_NAMESPACE_MZ_NET_END 67 | -------------------------------------------------------------------------------- /Metazion/Net/AppClientSocket.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_APPCLIENTSOCKET_HPP_ 2 | #define _MZ_NET_APPCLIENTSOCKET_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include "Metazion/Net/TransmitSocket.hpp" 7 | #include "Metazion/Net/ComConnecter.hpp" 8 | #include "Metazion/Net/ComPacketer.hpp" 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | class AppClientSocket : public TransmitSocket { 13 | MZ_DISALLOW_COPY_AND_ASSIGN(AppClientSocket) 14 | 15 | public: 16 | ComConnecter m_connecter; 17 | ComPacketer m_packeter; 18 | 19 | public: 20 | AppClientSocket(); 21 | 22 | virtual ~AppClientSocket(); 23 | 24 | void Reset() override final; 25 | 26 | void Prepare() override final; 27 | 28 | void Tick(int64_t now, int interval) override final; 29 | 30 | void Dispatch() override final; 31 | 32 | int GetType() const override final; 33 | 34 | protected: 35 | void OnConnected() override final; 36 | 37 | void OnDisconnected() override final; 38 | 39 | void OnSended(const void* data, int length) override final; 40 | 41 | void OnRecved(const void* data, int length) override final; 42 | 43 | virtual void DerivedReset() {}; 44 | 45 | virtual void DerivedPrepare() {}; 46 | 47 | virtual void DerivedTick(int64_t now, int interval) {}; 48 | 49 | virtual void DerivedDispatch() {}; 50 | 51 | virtual void DerivedOnConnected() {}; 52 | 53 | virtual void DerivedOnDisconnected() {}; 54 | 55 | virtual void DerivedOnSended(const void* data, int length) {}; 56 | 57 | virtual void DerivedOnRecved(const void* data, int length) {}; 58 | }; 59 | 60 | inline int AppClientSocket::GetType() const { 61 | return SOCKET_TCP_CLIENT; 62 | } 63 | 64 | DECL_NAMESPACE_MZ_NET_END 65 | 66 | #endif // _MZ_NET_APPCLIENTSOCKET_HPP_ 67 | -------------------------------------------------------------------------------- /Metazion/Net/AppListenSocket.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/AppListenSocket.hpp" 2 | 3 | DECL_NAMESPACE_MZ_NET_BEGIN 4 | 5 | AppListenSocket::AppListenSocket() 6 | : m_accepter(*this) {} 7 | 8 | AppListenSocket::~AppListenSocket() {} 9 | 10 | void AppListenSocket::Reset() { 11 | ListenSocket::Reset(); 12 | 13 | m_accepter.Reset(); 14 | 15 | DerivedReset(); 16 | } 17 | 18 | void AppListenSocket::Prepare() { 19 | ListenSocket::Prepare(); 20 | 21 | DerivedPrepare(); 22 | } 23 | 24 | void AppListenSocket::Tick(int64_t now, int interval) { 25 | ListenSocket::Tick(now, interval); 26 | 27 | DerivedTick(now, interval); 28 | } 29 | 30 | void AppListenSocket::Dispatch() { 31 | ListenSocket::Dispatch(); 32 | 33 | DerivedDispatch(); 34 | } 35 | 36 | void AppListenSocket::OnWatched() { 37 | ListenSocket::OnWatched(); 38 | 39 | DerivedOnWatched(); 40 | } 41 | 42 | void AppListenSocket::OnUnwatched() { 43 | ListenSocket::OnUnwatched(); 44 | 45 | DerivedOnUnwatched(); 46 | } 47 | 48 | bool AppListenSocket::OnAccepted(const SockId_t& sockId, const Host& host) { 49 | auto ret = ListenSocket::OnAccepted(sockId, host); 50 | if (!ret) { 51 | return false; 52 | } 53 | 54 | ret = m_accepter.Accept(sockId, host); 55 | if (!ret) { 56 | return false; 57 | } 58 | 59 | return DerivedOnAccepted(sockId, host); 60 | } 61 | 62 | DECL_NAMESPACE_MZ_NET_END 63 | -------------------------------------------------------------------------------- /Metazion/Net/AppListenSocket.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_APPLISTENSOCKET_HPP_ 2 | #define _MZ_NET_APPLISTENSOCKET_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include "Metazion/Net/ListenSocket.hpp" 7 | #include "Metazion/Net/ComAccepter.hpp" 8 | 9 | DECL_NAMESPACE_MZ_NET_BEGIN 10 | 11 | class AppListenSocket : public ListenSocket { 12 | MZ_DISALLOW_COPY_AND_ASSIGN(AppListenSocket) 13 | 14 | public: 15 | ComAccepter m_accepter; 16 | 17 | public: 18 | AppListenSocket(); 19 | 20 | virtual ~AppListenSocket(); 21 | 22 | void Reset() override final; 23 | 24 | void Prepare() override final; 25 | 26 | void Tick(int64_t now, int interval) override final; 27 | 28 | void Dispatch() override final; 29 | 30 | int GetType() const override final; 31 | 32 | protected: 33 | void OnWatched() override final; 34 | 35 | void OnUnwatched() override final; 36 | 37 | bool OnAccepted(const SockId_t& sockId, const Host& host) override final; 38 | 39 | virtual void DerivedReset() {}; 40 | 41 | virtual void DerivedPrepare() {}; 42 | 43 | virtual void DerivedTick(int64_t now, int interval) {}; 44 | 45 | virtual void DerivedDispatch() {}; 46 | 47 | virtual void DerivedOnWatched() {} 48 | 49 | virtual void DerivedOnUnwatched() {} 50 | 51 | virtual bool DerivedOnAccepted(const SockId_t& sockId, const Host& host) { return true; } 52 | }; 53 | 54 | inline int AppListenSocket::GetType() const { 55 | return SOCKET_TCP_LISTEN; 56 | } 57 | 58 | DECL_NAMESPACE_MZ_NET_END 59 | 60 | #endif // _MZ_NET_APPLISTENSOCKET_HPP_ 61 | -------------------------------------------------------------------------------- /Metazion/Net/AppServerSocket.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/AppServerSocket.hpp" 2 | 3 | DECL_NAMESPACE_MZ_NET_BEGIN 4 | 5 | AppServerSocket::AppServerSocket() 6 | : m_packeter(*this) {} 7 | 8 | AppServerSocket::~AppServerSocket() {} 9 | 10 | void AppServerSocket::Reset() { 11 | TransmitSocket::Reset(); 12 | 13 | m_packeter.Reset(); 14 | 15 | DerivedReset(); 16 | } 17 | 18 | void AppServerSocket::Prepare() { 19 | TransmitSocket::Prepare(); 20 | 21 | DerivedPrepare(); 22 | } 23 | 24 | void AppServerSocket::Tick(int64_t now, int interval) { 25 | TransmitSocket::Tick(now, interval); 26 | 27 | DerivedTick(now, interval); 28 | } 29 | 30 | void AppServerSocket::Dispatch() { 31 | TransmitSocket::Dispatch(); 32 | 33 | m_packeter.Dispatch(); 34 | 35 | DerivedDispatch(); 36 | } 37 | 38 | void AppServerSocket::Attach(const SockId_t& sockId) { 39 | AttachSockId(sockId); 40 | } 41 | 42 | void AppServerSocket::OnConnected() { 43 | TransmitSocket::OnConnected(); 44 | 45 | DerivedOnConnected(); 46 | } 47 | 48 | void AppServerSocket::OnDisconnected() { 49 | TransmitSocket::OnDisconnected(); 50 | 51 | DerivedOnDisconnected(); 52 | } 53 | 54 | void AppServerSocket::OnSended(const void* data, int length) { 55 | TransmitSocket::OnSended(data, length); 56 | 57 | DerivedOnSended(data, length); 58 | } 59 | 60 | void AppServerSocket::OnRecved(const void* data, int length) { 61 | TransmitSocket::OnRecved(data, length); 62 | 63 | DerivedOnRecved(data, length); 64 | } 65 | 66 | DECL_NAMESPACE_MZ_NET_END 67 | -------------------------------------------------------------------------------- /Metazion/Net/AppServerSocket.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_APPSERVERSOCKET_HPP_ 2 | #define _MZ_NET_APPSERVERSOCKET_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include "Metazion/Net/TransmitSocket.hpp" 7 | #include "Metazion/Net/ComPacketer.hpp" 8 | 9 | DECL_NAMESPACE_MZ_NET_BEGIN 10 | 11 | class AppServerSocket : public TransmitSocket { 12 | MZ_DISALLOW_COPY_AND_ASSIGN(AppServerSocket) 13 | 14 | public: 15 | ComPacketer m_packeter; 16 | 17 | public: 18 | AppServerSocket(); 19 | 20 | virtual ~AppServerSocket(); 21 | 22 | void Reset() override final; 23 | 24 | void Prepare() override final; 25 | 26 | void Tick(int64_t now, int interval) override final; 27 | 28 | void Dispatch() override final; 29 | 30 | int GetType() const override final; 31 | 32 | void Attach(const SockId_t& sockId); 33 | 34 | protected: 35 | void OnConnected() override final; 36 | 37 | void OnDisconnected() override final; 38 | 39 | void OnSended(const void* data, int length) override final; 40 | 41 | void OnRecved(const void* data, int length) override final; 42 | 43 | virtual void DerivedReset() {}; 44 | 45 | virtual void DerivedPrepare() {}; 46 | 47 | virtual void DerivedTick(int64_t now, int interval) {}; 48 | 49 | virtual void DerivedDispatch() {}; 50 | 51 | virtual void DerivedOnConnected() {}; 52 | 53 | virtual void DerivedOnDisconnected() {}; 54 | 55 | virtual void DerivedOnSended(const void* data, int length) {}; 56 | 57 | virtual void DerivedOnRecved(const void* data, int length) {}; 58 | }; 59 | 60 | inline int AppServerSocket::GetType() const { 61 | return SOCKET_TCP_SERVER; 62 | } 63 | 64 | DECL_NAMESPACE_MZ_NET_END 65 | 66 | #endif // _MZ_NET_APPSERVERSOCKET_HPP_ 67 | -------------------------------------------------------------------------------- /Metazion/Net/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | FILE(GLOB METAZION_NET_HEADERS "./*.hpp") 2 | FILE(GLOB METAZION_NET_SOURCES "./*.cpp") 3 | 4 | SET(LIBRARY_OUTPUT_PATH ${BUILD_DIR}/${LIB}/${PLATFORM}) 5 | SET(EXECUTABLE_OUTPUT_PATH ${BUILD_DIR}/${BIN}/${PLATFORM}) 6 | 7 | ADD_LIBRARY(Net STATIC 8 | ${METAZION_NET_HEADERS} 9 | ${METAZION_NET_SOURCES} 10 | ) 11 | 12 | SET_TARGET_PROPERTIES(Net PROPERTIES 13 | OUTPUT_NAME "MzNet" 14 | CLEAN_DIRECT_OUTPUT 1 15 | VERSION ${PRODUCT_VERSION} 16 | VERSION ${PRODUCT_VERSION} 17 | ) 18 | 19 | IF(PRODUCT_INSTALL) 20 | INSTALL(TARGETS Net 21 | RUNTIME DESTINATION ${BIN_DIR} 22 | LIBRARY DESTINATION ${LIB_DIR} 23 | ARCHIVE DESTINATION ${LIB_DIR}) 24 | ENDIF(PRODUCT_INSTALL) 25 | 26 | IF(WIN32) 27 | # create visual studio folders 28 | SOURCE_GROUP(Header FILES ${METAZION_NET_HEADERS}) 29 | SOURCE_GROUP(Source FILES ${METAZION_NET_SOURCES}) 30 | ENDIF(WIN32) -------------------------------------------------------------------------------- /Metazion/Net/ComAccepter.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/ComAccepter.hpp" 2 | 3 | #include "Metazion/Net/ListenSocket.hpp" 4 | #include "Metazion/Net/AppServerSocket.hpp" 5 | #include "Metazion/Net/NetworkService.hpp" 6 | 7 | DECL_NAMESPACE_MZ_NET_BEGIN 8 | 9 | ComAccepter::ComAccepter(ListenSocket& socket) 10 | : m_socket(socket) {} 11 | 12 | ComAccepter::~ComAccepter() {} 13 | 14 | void ComAccepter::Reset() { 15 | SetCreateSocketCallback(nullptr); 16 | } 17 | 18 | bool ComAccepter::Accept(const SockId_t& sockId, const Host& host) { 19 | NetworkService* networkService = m_socket.GetNetworkService(); 20 | MZ_ASSERT_TRUE(!IsNull(networkService)); 21 | 22 | auto socket = m_createServerSocketCallback(); 23 | MZ_ASSERT_TRUE(!IsNull(socket)); 24 | 25 | socket->SetRemoteHost(host); 26 | socket->Attach(sockId); 27 | 28 | const bool ret = networkService->Manage(socket); 29 | if (!ret) { 30 | socket->Destory(); 31 | return false; 32 | } 33 | 34 | return true; 35 | } 36 | 37 | DECL_NAMESPACE_MZ_NET_END 38 | -------------------------------------------------------------------------------- /Metazion/Net/ComAccepter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_COMACCEPTER_HPP_ 2 | #define _MZ_NET_COMACCEPTER_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include 7 | 8 | #include "Metazion/Net/SocketDefine.hpp" 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | class ListenSocket; 13 | class AppServerSocket; 14 | class Host; 15 | 16 | class ComAccepter { 17 | MZ_DISALLOW_COPY_AND_ASSIGN(ComAccepter) 18 | 19 | using CreateSocketCallback_t = std::function; 20 | 21 | private: 22 | ListenSocket& m_socket; 23 | 24 | CreateSocketCallback_t m_createServerSocketCallback; 25 | 26 | public: 27 | ComAccepter(ListenSocket& socket); 28 | 29 | ~ComAccepter(); 30 | 31 | void Reset(); 32 | 33 | bool Accept(const SockId_t& sockId, const Host& host); 34 | 35 | void SetCreateSocketCallback(CreateSocketCallback_t callback); 36 | }; 37 | 38 | inline void ComAccepter::SetCreateSocketCallback(CreateSocketCallback_t callback) { 39 | m_createServerSocketCallback = callback; 40 | } 41 | 42 | DECL_NAMESPACE_MZ_NET_END 43 | 44 | #endif // _MZ_NET_SOCKETACCEPTER_HPP_ 45 | -------------------------------------------------------------------------------- /Metazion/Net/ComConnecter.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/ComConnecter.hpp" 2 | 3 | #include 4 | 5 | #include "Metazion/Net/TransmitSocket.hpp" 6 | 7 | DECL_NAMESPACE_MZ_NET_BEGIN 8 | 9 | ComConnecter::ComConnecter(TransmitSocket& socket) 10 | : m_socket(socket) {} 11 | 12 | ComConnecter::~ComConnecter() {} 13 | 14 | void ComConnecter::Reset() { 15 | m_stage = STAGE_NONE; 16 | m_connectTime = 0; 17 | m_reconnectInterval = 0; 18 | m_tempSockId = INVALID_SOCKID; 19 | } 20 | 21 | void ComConnecter::Tick(int64_t now, int interval) { 22 | ConnectStage(); 23 | } 24 | 25 | bool ComConnecter::Connect() { 26 | SetStage(STAGE_WAITING); 27 | return true; 28 | } 29 | 30 | void ComConnecter::ConnectStage() { 31 | switch (m_stage) { 32 | case STAGE_WAITING: 33 | ConnectStageWaiting(); 34 | break; 35 | case STAGE_CONNECTING: 36 | ConnectStageConnecting(); 37 | break; 38 | case STAGE_CONNECTED: 39 | ConnectStageConnected(); 40 | break; 41 | case STAGE_CLOSED: 42 | ConnectStageClosed(); 43 | break; 44 | default: MZ_ASSERT_TRUE(false); break; 45 | } 46 | } 47 | 48 | void ComConnecter::ConnectStageWaiting() { 49 | const auto now = NS_SHARE::GetNowMillisecond(); 50 | if (now < m_connectTime) { 51 | return; 52 | } 53 | 54 | const auto ret = TryToConnect(); 55 | if (ret == 0) { 56 | SetStage(STAGE_CONNECTING); 57 | } 58 | else if (ret > 0) { 59 | m_socket.AttachSockId(m_tempSockId); 60 | SetStage(STAGE_CONNECTED); 61 | } 62 | else { 63 | m_connectFaildCallback(); 64 | Reconnect(m_reconnectInterval); 65 | } 66 | } 67 | 68 | void ComConnecter::ConnectStageConnecting() { 69 | const auto ret = CheckConnected(); 70 | if (ret == 0) { 71 | // Keep connecting. 72 | } 73 | else if (ret > 0) { 74 | m_socket.AttachSockId(m_tempSockId); 75 | SetStage(STAGE_CONNECTED); 76 | } 77 | else { 78 | DetachTempSockId(); 79 | m_connectFaildCallback(); 80 | Reconnect(m_reconnectInterval); 81 | } 82 | } 83 | 84 | void ComConnecter::ConnectStageConnected() { 85 | if (m_socket.IsActive()) { 86 | return; 87 | } 88 | 89 | if (m_socket.IsWannaClose()) { 90 | return; 91 | } 92 | 93 | Reconnect(1000); 94 | } 95 | 96 | void ComConnecter::ConnectStageClosed() { 97 | MZ_ASSERT_TRUE(!m_socket.IsActive()); 98 | } 99 | 100 | void ComConnecter::Reconnect(int milliseconds) { 101 | if (m_reconnectInterval < 0) { 102 | SetStage(STAGE_CLOSED); 103 | return; 104 | } 105 | 106 | ResetConnectTime(milliseconds); 107 | SetStage(STAGE_WAITING); 108 | } 109 | 110 | int ComConnecter::TryToConnect() { 111 | auto sockId = CreateSockId(TRANSPORT_TCP); 112 | if (sockId == INVALID_SOCKID) { 113 | return -1; 114 | } 115 | 116 | AttachTempSockId(sockId); 117 | 118 | auto sockAddr = m_socket.GetRemoteHost().SockAddr(); 119 | auto sockAddrLen = m_socket.GetRemoteHost().SockAddrLen(); 120 | const auto ret = connect(m_tempSockId, sockAddr, sockAddrLen); 121 | if (ret < 0) { 122 | const auto error = SAGetLastError(); 123 | if (!IsConnectWouldBlock(error)) { 124 | DetachTempSockId(); 125 | return -1; 126 | } 127 | 128 | return 0; 129 | } 130 | 131 | return 1; 132 | } 133 | 134 | int ComConnecter::CheckConnected() { 135 | const auto ret = CheckSockConnected(m_tempSockId); 136 | if (ret <= 0) { 137 | return ret; 138 | } 139 | 140 | // It doesn't work in some situations on linux platform. 141 | // For examle, when listen socket's backlog queue is full. 142 | // And also doesn't work on solaris platform. 143 | int optValue = 0; 144 | auto optLength = static_cast(sizeof(optValue)); 145 | GetSockOpt(m_tempSockId, SOL_SOCKET, SO_ERROR, &optValue, &optLength); 146 | if (optValue != 0) { 147 | return -1; 148 | } 149 | 150 | return 1; 151 | } 152 | 153 | void ComConnecter::ResetConnectTime(int milliseconds) { 154 | m_connectTime = NS_SHARE::GetNowMillisecond() + milliseconds; 155 | } 156 | 157 | DECL_NAMESPACE_MZ_NET_END 158 | -------------------------------------------------------------------------------- /Metazion/Net/ComConnecter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_COMCONNECTER_HPP_ 2 | #define _MZ_NET_COMCONNECTER_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include 7 | 8 | #include "Metazion/Net/Host.hpp" 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | class TransmitSocket; 13 | 14 | class ComConnecter { 15 | MZ_DISALLOW_COPY_AND_ASSIGN(ComConnecter) 16 | 17 | enum Stage { 18 | STAGE_NONE = 0, 19 | STAGE_WAITING, 20 | STAGE_CONNECTING, 21 | STAGE_CONNECTED, 22 | STAGE_CLOSED, 23 | }; 24 | 25 | using ConnectFailedCallback_t = std::function; 26 | 27 | private: 28 | TransmitSocket& m_socket; 29 | 30 | int m_stage{ STAGE_NONE }; 31 | int64_t m_connectTime{ 0 }; 32 | int m_reconnectInterval{ 0 }; 33 | SockId_t m_tempSockId{ INVALID_SOCKID }; 34 | 35 | ConnectFailedCallback_t m_connectFaildCallback; 36 | 37 | public: 38 | ComConnecter(TransmitSocket& socket); 39 | 40 | ~ComConnecter(); 41 | 42 | void Reset(); 43 | 44 | void Tick(int64_t now, int interval); 45 | 46 | bool Connect(); 47 | 48 | int GetReconnectInterval() const; 49 | 50 | void SetReconnectInterval(int milliseconds); 51 | 52 | void SetConnectFailedCallback(ConnectFailedCallback_t callback); 53 | 54 | private: 55 | void ConnectStage(); 56 | 57 | void ConnectStageWaiting(); 58 | 59 | void ConnectStageConnecting(); 60 | 61 | void ConnectStageConnected(); 62 | 63 | void ConnectStageClosed(); 64 | 65 | void Reconnect(int milliseconds); 66 | 67 | int TryToConnect(); 68 | 69 | int CheckConnected(); 70 | 71 | void ResetConnectTime(int milliseconds); 72 | 73 | bool IsStage(int stage) const; 74 | 75 | void SetStage(int stage); 76 | 77 | void AttachTempSockId(const SockId_t& sockId); 78 | 79 | void DetachTempSockId(); 80 | }; 81 | 82 | inline int ComConnecter::GetReconnectInterval() const { 83 | return m_reconnectInterval; 84 | } 85 | 86 | inline void ComConnecter::SetReconnectInterval(int milliseconds) { 87 | m_reconnectInterval = milliseconds; 88 | } 89 | 90 | inline void ComConnecter::SetConnectFailedCallback(ConnectFailedCallback_t callback) { 91 | m_connectFaildCallback = callback; 92 | } 93 | 94 | inline bool ComConnecter::IsStage(int stage) const { 95 | return m_stage == stage; 96 | } 97 | 98 | inline void ComConnecter::SetStage(int stage) { 99 | m_stage = stage; 100 | } 101 | 102 | inline void ComConnecter::AttachTempSockId(const SockId_t& sockId) { 103 | m_tempSockId = sockId; 104 | } 105 | 106 | inline void ComConnecter::DetachTempSockId() { 107 | if (m_tempSockId != INVALID_SOCKID) { 108 | DestroySockId(m_tempSockId); 109 | m_tempSockId = INVALID_SOCKID; 110 | } 111 | } 112 | 113 | DECL_NAMESPACE_MZ_NET_END 114 | 115 | #endif // _MZ_NET_COMCONNECTER_HPP_ 116 | -------------------------------------------------------------------------------- /Metazion/Net/ComPacketer.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/ComPacketer.hpp" 2 | 3 | #include "Metazion/Net/TransmitSocket.hpp" 4 | 5 | DECL_NAMESPACE_MZ_NET_BEGIN 6 | 7 | ComPacketer::ComPacketer(TransmitSocket& socket) 8 | : m_socket(socket) 9 | , m_packetCodec(socket) {} 10 | 11 | ComPacketer::~ComPacketer() {} 12 | 13 | void ComPacketer::Reset() { 14 | SetValidPacketCallback(nullptr); 15 | SetInvalidPacketCallback(nullptr); 16 | } 17 | 18 | void ComPacketer::Dispatch() { 19 | thread_local DecodeBuffer decodeBuffer; 20 | 21 | while (true) { 22 | int command = 0; 23 | decodeBuffer.m_resultBuffer.Reset(); 24 | const auto ret = m_packetCodec.Decode(command, decodeBuffer); 25 | if (ret == 0) { 26 | break; 27 | } 28 | else if (ret < 0) { 29 | m_invalidPacketCallback(); 30 | break; 31 | } 32 | 33 | const auto pullBuffer = decodeBuffer.m_resultBuffer.GetPullBuffer(); 34 | const auto pullLength = decodeBuffer.m_resultBuffer.GetPullLength(); 35 | m_validPacketCallback(command, pullBuffer, pullLength); 36 | } 37 | } 38 | 39 | bool ComPacketer::SendData(int command, const void* data, int length) { 40 | thread_local EncodeBuffer encodeBuffer; 41 | encodeBuffer.m_resultBuffer.Reset(); 42 | 43 | const auto ret = m_packetCodec.Encode(command, data, length, encodeBuffer); 44 | if (ret <= 0) { 45 | return false; 46 | } 47 | 48 | const auto pullBuffer = encodeBuffer.m_resultBuffer.GetPullBuffer(); 49 | const auto pullLength = encodeBuffer.m_resultBuffer.GetPullLength(); 50 | return m_socket.Send(pullBuffer, pullLength) == pullLength; 51 | } 52 | 53 | void ComPacketer::PostData(int command, const void* data, int length) { 54 | m_validPacketCallback(command, data, length); 55 | } 56 | 57 | DECL_NAMESPACE_MZ_NET_END 58 | -------------------------------------------------------------------------------- /Metazion/Net/ComPacketer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_COMPACKETER_HPP_ 2 | #define _MZ_NET_COMPACKETER_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include 7 | 8 | #include "Metazion/Net/PacketCodec.hpp" 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | class TransmitSocket; 13 | 14 | class ComPacketer { 15 | MZ_DISALLOW_COPY_AND_ASSIGN(ComPacketer) 16 | 17 | using ValidPacketCallback_t = std::function; 18 | using InvalidPacketCallback_t = std::function; 19 | 20 | private: 21 | TransmitSocket& m_socket; 22 | 23 | PacketCodec m_packetCodec; 24 | 25 | ValidPacketCallback_t m_validPacketCallback; 26 | InvalidPacketCallback_t m_invalidPacketCallback; 27 | 28 | public: 29 | ComPacketer(TransmitSocket& m_socket); 30 | 31 | ~ComPacketer(); 32 | 33 | void Reset(); 34 | 35 | void Dispatch(); 36 | 37 | bool SendData(int command, const void* data, int length); 38 | 39 | void PostData(int command, const void* data, int length); 40 | 41 | void SetValidPacketCallback(ValidPacketCallback_t callback); 42 | 43 | void SetInvalidPacketCallback(InvalidPacketCallback_t callback); 44 | }; 45 | 46 | inline void ComPacketer::SetValidPacketCallback(ValidPacketCallback_t callback) { 47 | m_validPacketCallback = callback; 48 | } 49 | 50 | inline void ComPacketer::SetInvalidPacketCallback(InvalidPacketCallback_t callback) { 51 | m_invalidPacketCallback = callback; 52 | } 53 | 54 | DECL_NAMESPACE_MZ_NET_END 55 | 56 | #endif // _MZ_NET_COMPACKETER_HPP_ 57 | -------------------------------------------------------------------------------- /Metazion/Net/EpollIoThread.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/EpollIoThread.hpp" 2 | 3 | #if defined(NETWORK_USE_EPOLL_MODEL) 4 | 5 | #include 6 | 7 | #include "Metazion/Net/NetworkService.hpp" 8 | #include "Metazion/Net/Socket.hpp" 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | EpollIoThread::EpollIoThread() {} 13 | 14 | EpollIoThread::~EpollIoThread() {} 15 | 16 | void EpollIoThread::Initialize(NetworkService* networkService, int index) { 17 | m_stopDesired = false; 18 | m_networkService = networkService; 19 | m_index = index; 20 | const auto startIndex = m_networkService->GetSocketService().GetStartIndex(m_index); 21 | m_socketCount = m_networkService->GetSocketService().GetSocketCount(m_index); 22 | m_socketCtrlList = &m_networkService->GetSocketCtrl(startIndex); 23 | m_epollfd = m_networkService->GetSocketService().GetEpollfd(m_index); 24 | m_eventList = &m_networkService->GetSocketService().GetEpollEvent(startIndex); 25 | } 26 | 27 | void EpollIoThread::Finalize() { 28 | m_stopDesired = true; 29 | Join(); 30 | } 31 | 32 | void EpollIoThread::Execute() { 33 | while (!m_stopDesired) { 34 | ProcessEvents(); 35 | ProcessIO(); 36 | } 37 | } 38 | 39 | void EpollIoThread::ProcessEvents() { 40 | const auto count = epoll_wait(m_epollfd, m_eventList, m_socketCount, 20); 41 | if (count == 0) { 42 | return; 43 | } 44 | 45 | if (count < 0) { 46 | const auto error = SAGetLastError(); 47 | if (error != EINTR) { 48 | NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Warning: epoll wait, error[%d]. [%s:%d]\n", error, __FILE__, __LINE__); 49 | } 50 | return; 51 | } 52 | 53 | for (auto index = 0; index < count; ++index) { 54 | const auto& event = m_eventList[index]; 55 | const auto socket = static_cast(event.data.ptr); 56 | 57 | if (event.events & EPOLLRDHUP) { 58 | NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Info: socket close. [%s:%d]\n", __FILE__, __LINE__); 59 | socket->Close(); 60 | continue; 61 | } 62 | 63 | if (event.events & EPOLLIN) { 64 | socket->TheIoStrategy().EnableInput(); 65 | } 66 | 67 | if (event.events & EPOLLOUT) { 68 | socket->TheIoStrategy().EnableOutput(); 69 | } 70 | } 71 | } 72 | 73 | void EpollIoThread::ProcessIO() { 74 | for (int index = 0; index < m_socketCount; ++index) { 75 | const auto& socketCtrl = m_socketCtrlList[index]; 76 | const auto socket = socketCtrl.m_socket; 77 | if (IsNull(socket)) { 78 | continue; 79 | } 80 | 81 | socket->TheIoStrategy().PostInput(); 82 | socket->TheIoStrategy().PostOutput(); 83 | } 84 | } 85 | 86 | DECL_NAMESPACE_MZ_NET_END 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /Metazion/Net/EpollIoThread.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_EPOLLIOTHREAD_HPP_ 2 | #define _MZ_NET_EPOLLIOTHREAD_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #if defined(NETWORK_USE_EPOLL_MODEL) 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include "Metazion/Net/SocketCtrl.hpp" 13 | #include "Metazion/Net/SocketDefine.hpp" 14 | 15 | DECL_NAMESPACE_MZ_NET_BEGIN 16 | 17 | class NetworkService; 18 | 19 | class EpollIoThread : public NS_SHARE::Thread { 20 | MZ_DISALLOW_COPY_AND_ASSIGN(EpollIoThread) 21 | 22 | private: 23 | std::atomic m_stopDesired{ false }; 24 | 25 | NetworkService* m_networkService{ nullptr }; 26 | int m_index{ 0 }; 27 | int m_socketCount{ 0 }; 28 | SocketCtrl* m_socketCtrlList{ nullptr }; 29 | int m_epollfd{ 0 }; 30 | epoll_event* m_eventList{ nullptr }; 31 | 32 | public: 33 | EpollIoThread(); 34 | 35 | ~EpollIoThread(); 36 | 37 | void Initialize(NetworkService* networkService, int index); 38 | 39 | void Finalize(); 40 | 41 | protected: 42 | void Execute() override final; 43 | 44 | private: 45 | void ProcessEvents(); 46 | 47 | void ProcessIO(); 48 | }; 49 | 50 | DECL_NAMESPACE_MZ_NET_END 51 | 52 | #endif 53 | 54 | #endif // _MZ_NET_EPOLLIOTHREAD_HPP_ 55 | -------------------------------------------------------------------------------- /Metazion/Net/EpollListenStrategy.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/EpollListenStrategy.hpp" 2 | 3 | #include 4 | 5 | #include "Metazion/Net/ListenSocket.hpp" 6 | 7 | #if defined(NETWORK_USE_EPOLL_MODEL) 8 | 9 | DECL_NAMESPACE_MZ_NET_BEGIN 10 | 11 | EpollListenStrategy::EpollListenStrategy(ListenSocket& listenSocket) 12 | : m_listenSocket(listenSocket) {} 13 | 14 | EpollListenStrategy::~EpollListenStrategy() {} 15 | 16 | void EpollListenStrategy::Reset() { 17 | // Nothing to do. 18 | } 19 | 20 | void EpollListenStrategy::Prepare() { 21 | Reset(); 22 | } 23 | 24 | void EpollListenStrategy::Start() { 25 | // Nothing to do. 26 | } 27 | 28 | void EpollListenStrategy::Launch() { 29 | // Nothing to do. 30 | } 31 | 32 | bool EpollListenStrategy::IsBusy() const { 33 | return false; 34 | } 35 | 36 | void EpollListenStrategy::PostInput() { 37 | if (!m_canInput) { 38 | return; 39 | } 40 | 41 | Host peerHost; 42 | auto sockAddr = peerHost.SockAddr(); 43 | auto sockAddrLen = peerHost.SockAddrLen(); 44 | const auto& listenSockId = m_listenSocket.GetSockId(); 45 | while (true) { 46 | auto sockId = accept(listenSockId, sockAddr, &sockAddrLen); 47 | if (sockId == INVALID_SOCKID) { 48 | const auto error = SAGetLastError(); 49 | if (IsInterrupted(error)) { 50 | continue; 51 | } 52 | 53 | if (IsWouldBlock(error)) { 54 | m_canInput = false; 55 | break; 56 | } 57 | 58 | switch(error) { 59 | case EMFILE: 60 | case ENFILE: 61 | case ENOBUFS: 62 | case ENOMEM: 63 | case EPERM: 64 | MZ_ASSERT_TRUE(false); 65 | break; 66 | default: break; 67 | }; 68 | 69 | NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Error: socket close, error[%d]. [%s:%d]\n", error, __FILE__, __LINE__); 70 | m_listenSocket.Close(); 71 | m_listenSocket.OnError(error); 72 | break; 73 | } 74 | 75 | SetNonBlock(sockId); 76 | 77 | if (!m_listenSocket.OnAccepted(sockId, peerHost)) { 78 | DestroySockId(sockId); 79 | } 80 | } 81 | } 82 | 83 | void EpollListenStrategy::PostOutput() { 84 | // Nothing to do. 85 | } 86 | 87 | void EpollListenStrategy::EnableInput() { 88 | m_canInput = true; 89 | } 90 | 91 | void EpollListenStrategy::EnableOutput() { 92 | m_canOutput = true; 93 | } 94 | 95 | DECL_NAMESPACE_MZ_NET_END 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /Metazion/Net/EpollListenStrategy.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_EPOLLLISTENSTRATEGY_HPP_ 2 | #define _MZ_NET_EPOLLLISTENSTRATEGY_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #if defined(NETWORK_USE_EPOLL_MODEL) 7 | 8 | #include "Metazion/Net/EpollStrategy.hpp" 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | class ListenSocket; 13 | 14 | class EpollListenStrategy final : public EpollStrategy { 15 | MZ_DISALLOW_COPY_AND_ASSIGN(EpollListenStrategy) 16 | 17 | private: 18 | ListenSocket& m_listenSocket; 19 | std::atomic m_canInput{ false }; 20 | std::atomic m_canOutput{ false }; 21 | 22 | public: 23 | EpollListenStrategy(ListenSocket& m_listenSocket); 24 | 25 | ~EpollListenStrategy(); 26 | 27 | void Reset() override final; 28 | 29 | void Prepare() override final; 30 | 31 | void Start() override final; 32 | 33 | void Launch() override final; 34 | 35 | bool IsBusy() const override final; 36 | 37 | void PostInput() override final; 38 | 39 | void PostOutput() override final; 40 | 41 | void EnableInput() override final; 42 | 43 | void EnableOutput() override final; 44 | }; 45 | 46 | DECL_NAMESPACE_MZ_NET_END 47 | 48 | #endif 49 | 50 | #endif // _MZ_NET_EPOLLLISTENSTRATEGY_HPP_ 51 | -------------------------------------------------------------------------------- /Metazion/Net/EpollOperation.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_EPOLLOPERATION_HPP_ 2 | #define _MZ_NET_EPOLLOPERATION_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #if defined(NETWORK_USE_EPOLL_MODEL) 7 | 8 | #include 9 | 10 | #include "Metazion/Net/SocketDefine.hpp" 11 | 12 | DECL_NAMESPACE_MZ_NET_BEGIN 13 | 14 | struct EpollOperation { 15 | enum Type { 16 | TYPE_ACCEPT = 1, 17 | TYPE_SEND, 18 | TYPE_RECV, 19 | }; 20 | 21 | Type m_type; 22 | std::atomic m_busy{ false }; 23 | 24 | EpollOperation(Type type) 25 | : m_type(type) {} 26 | 27 | void Reset() { 28 | m_busy = false; 29 | } 30 | 31 | bool IsBusy() const { 32 | return m_busy; 33 | } 34 | 35 | void SetBusy(bool busy) { 36 | m_busy = busy; 37 | } 38 | }; 39 | 40 | struct AcceptOperation final : public EpollOperation { 41 | char* m_buffer{ nullptr }; 42 | SockId_t m_sockId = INVALID_SOCKID; 43 | 44 | AcceptOperation() 45 | : EpollOperation(TYPE_ACCEPT) {} 46 | 47 | void Reset() { 48 | EpollOperation::Reset(); 49 | m_buffer = nullptr; 50 | m_sockId = INVALID_SOCKID; 51 | } 52 | }; 53 | 54 | struct SendOperation final : public EpollOperation { 55 | IOV_TYPE m_iov[NUMBER_SEND_IOV]; 56 | 57 | SendOperation() 58 | : EpollOperation(TYPE_SEND) {} 59 | 60 | void Reset() { 61 | EpollOperation::Reset(); 62 | memset(&m_iov, 0, sizeof(m_iov)); 63 | } 64 | }; 65 | 66 | struct RecvOperation final : public EpollOperation { 67 | IOV_TYPE m_iov[NUMBER_RECV_IOV]; 68 | 69 | RecvOperation() 70 | : EpollOperation(TYPE_RECV) {} 71 | 72 | void Reset() { 73 | EpollOperation::Reset(); 74 | memset(&m_iov, 0, sizeof(m_iov)); 75 | } 76 | }; 77 | 78 | DECL_NAMESPACE_MZ_NET_END 79 | 80 | #endif 81 | 82 | #endif // _MZ_NET_EPOLLOPERATION_HPP_ 83 | -------------------------------------------------------------------------------- /Metazion/Net/EpollService.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/EpollService.hpp" 2 | 3 | #include "Metazion/Net/Socket.hpp" 4 | 5 | #if defined(NETWORK_USE_EPOLL_MODEL) 6 | 7 | DECL_NAMESPACE_MZ_NET_BEGIN 8 | 9 | EpollService::EpollService() {} 10 | 11 | EpollService::~EpollService() {} 12 | 13 | bool EpollService::Initialize(int socketCapacity, int ioThreadNumber) { 14 | m_socketCapacity = socketCapacity; 15 | m_ioThreadNumber = ioThreadNumber; 16 | 17 | m_epollfdList = new int[m_ioThreadNumber]; 18 | for (auto index = 0; index < m_ioThreadNumber; ++index) { 19 | auto& epollfd = m_epollfdList[index]; 20 | const auto socketCount = GetSocketCount(index); 21 | epollfd = epoll_create(socketCount); 22 | if (epollfd < 0) { 23 | return false; 24 | } 25 | } 26 | 27 | m_epollEventList = new epoll_event[m_socketCapacity]; 28 | memset(m_epollEventList, 0, sizeof(epoll_event) * m_socketCapacity); 29 | return true; 30 | } 31 | 32 | void EpollService::Finalize() { 33 | SafeDeleteArray(m_epollEventList); 34 | 35 | for (auto index = 0; index < m_ioThreadNumber; ++index) { 36 | auto& epollfd = m_epollfdList[index]; 37 | if (epollfd >= 0) { 38 | close(epollfd); 39 | } 40 | } 41 | SafeDeleteArray(m_epollfdList); 42 | } 43 | 44 | bool EpollService::Associate(Socket* socket) { 45 | const auto& sockId = socket->GetSockId(); 46 | const auto socketIndex = socket->GetIndex(); 47 | const auto threadIndex = GetThreadIndex(socketIndex); 48 | 49 | epoll_event event; 50 | event.data.ptr = socket; 51 | event.events = EPOLLIN | EPOLLOUT | EPOLLET | EPOLLRDHUP; 52 | const auto ret = epoll_ctl(m_epollfdList[threadIndex], EPOLL_CTL_ADD 53 | , sockId, &event); 54 | return ret == 0; 55 | } 56 | 57 | int EpollService::GetThreadIndex(int socketIndex) { 58 | const auto eachCount = (m_socketCapacity + m_ioThreadNumber - 1) / m_ioThreadNumber; 59 | return socketIndex / eachCount; 60 | } 61 | 62 | int EpollService::GetStartIndex(int threadIndex) const { 63 | const auto eachCount = (m_socketCapacity + m_ioThreadNumber - 1) / m_ioThreadNumber; 64 | return eachCount * threadIndex; 65 | } 66 | 67 | int EpollService::GetSocketCount(int threadIndex) const { 68 | const auto eachCount = (m_socketCapacity + m_ioThreadNumber - 1) / m_ioThreadNumber; 69 | const auto startIndex = eachCount * threadIndex; 70 | const auto restCount = m_socketCapacity - startIndex; 71 | return restCount < eachCount ? restCount : eachCount; 72 | } 73 | 74 | DECL_NAMESPACE_MZ_NET_END 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /Metazion/Net/EpollService.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_EPOLLSERVICE_HPP_ 2 | #define _MZ_NET_EPOLLSERVICE_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include "Metazion/Net/SocketDefine.hpp" 7 | 8 | #if defined(NETWORK_USE_EPOLL_MODEL) 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | class Socket; 13 | 14 | class EpollService { 15 | MZ_DISALLOW_COPY_AND_ASSIGN(EpollService) 16 | 17 | private: 18 | int m_socketCapacity{ 0 }; 19 | int m_ioThreadNumber{ 0 }; 20 | int* m_epollfdList{ 0 }; 21 | epoll_event* m_epollEventList{ nullptr }; 22 | 23 | public: 24 | EpollService(); 25 | 26 | ~EpollService(); 27 | 28 | bool Initialize(int socketCapacity, int ioThreadNumber); 29 | 30 | void Finalize(); 31 | 32 | bool Associate(Socket* socket); 33 | 34 | int GetThreadIndex(int socketIndex); 35 | 36 | int GetStartIndex(int threadIndex) const; 37 | 38 | int GetSocketCount(int threadIndex) const; 39 | 40 | int GetEpollfd(int threadIndex) const; 41 | 42 | epoll_event& GetEpollEvent(int index); 43 | }; 44 | 45 | inline int EpollService::GetEpollfd(int threadIndex) const { 46 | return m_epollfdList[threadIndex]; 47 | } 48 | 49 | inline epoll_event& EpollService::GetEpollEvent(int index) { 50 | return m_epollEventList[index]; 51 | } 52 | 53 | DECL_NAMESPACE_MZ_NET_END 54 | 55 | #endif 56 | 57 | #endif // _MZ_NET_EPOLLSERVICE_HPP_ 58 | -------------------------------------------------------------------------------- /Metazion/Net/EpollStrategy.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_EPOLLSTRATEGY_HPP_ 2 | #define _MZ_NET_EPOLLSTRATEGY_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #if defined(NETWORK_USE_EPOLL_MODEL) 7 | 8 | #include "Metazion/Net/EpollOperation.hpp" 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | class EpollStrategy { 13 | MZ_DISALLOW_COPY_AND_ASSIGN(EpollStrategy) 14 | 15 | public: 16 | EpollStrategy() {} 17 | 18 | virtual ~EpollStrategy() {} 19 | 20 | virtual void Reset() = 0; 21 | 22 | virtual void Prepare() = 0; 23 | 24 | virtual void Start() = 0; 25 | 26 | virtual void Launch() = 0; 27 | 28 | virtual bool IsBusy() const = 0; 29 | 30 | virtual void PostInput() = 0; 31 | 32 | virtual void PostOutput() = 0; 33 | 34 | virtual void EnableInput() = 0; 35 | 36 | virtual void EnableOutput() = 0; 37 | }; 38 | 39 | DECL_NAMESPACE_MZ_NET_END 40 | 41 | #endif 42 | 43 | #endif // _MZ_NET_EPOLLSTRATEGY_HPP_ 44 | -------------------------------------------------------------------------------- /Metazion/Net/EpollTransmitStrategy.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/EpollTransmitStrategy.hpp" 2 | 3 | #include 4 | 5 | #include "Metazion/Net/TransmitSocket.hpp" 6 | 7 | #if defined(NETWORK_USE_EPOLL_MODEL) 8 | 9 | DECL_NAMESPACE_MZ_NET_BEGIN 10 | 11 | EpollTransmitStrategy::EpollTransmitStrategy(TransmitSocket& transmitSocket) 12 | : m_transmitSocket(transmitSocket) {} 13 | 14 | EpollTransmitStrategy::~EpollTransmitStrategy() {} 15 | 16 | void EpollTransmitStrategy::Reset() { 17 | m_sendOperation.Reset(); 18 | m_recvOperation.Reset(); 19 | m_canOutput = false; 20 | } 21 | 22 | void EpollTransmitStrategy::Prepare() { 23 | Reset(); 24 | } 25 | 26 | void EpollTransmitStrategy::Start() { 27 | // Nothing to do. 28 | } 29 | 30 | void EpollTransmitStrategy::Launch() { 31 | // Nothing to do. 32 | } 33 | 34 | bool EpollTransmitStrategy::IsBusy() const { 35 | return false; 36 | } 37 | 38 | void EpollTransmitStrategy::PostInput() { 39 | auto& socketBuffer = m_transmitSocket.TheSocketBuffer(); 40 | 41 | if (!m_canInput) { 42 | return; 43 | } 44 | 45 | const auto& transmitSockId = m_transmitSocket.GetSockId(); 46 | while (true) { 47 | const auto pushLength = socketBuffer.PrepareRecvPlan(); 48 | MZ_UNUSED_VARIABLE(pushLength); 49 | 50 | const auto count = socketBuffer.SetupRecvIov(m_recvOperation.m_iov); 51 | 52 | const auto recvLength = readv(transmitSockId, m_recvOperation.m_iov, count); 53 | if (recvLength == 0) { 54 | NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Info: socket close. [%s:%d]\n", __FILE__, __LINE__); 55 | m_transmitSocket.Close(); 56 | break; 57 | } 58 | else if (recvLength < 0) { 59 | const auto error = SAGetLastError(); 60 | if (IsInterrupted(error)) { 61 | continue; 62 | } 63 | 64 | if (IsWouldBlock(error)) { 65 | m_canInput = false; 66 | break; 67 | } 68 | 69 | NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Error: socket close, error[%d]. [%s:%d]\n", error, __FILE__, __LINE__); 70 | m_transmitSocket.Close(); 71 | m_transmitSocket.OnError(error); 72 | break; 73 | } 74 | 75 | m_transmitSocket.OnRecved(nullptr, recvLength); 76 | 77 | const auto restLength = socketBuffer.PreserveRecvPlan(recvLength); 78 | if (restLength > 0) { 79 | NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Trace: socket close. [%s:%d]\n", __FILE__, __LINE__); 80 | m_transmitSocket.Disconnect(); 81 | } 82 | } 83 | } 84 | 85 | void EpollTransmitStrategy::PostOutput() { 86 | auto& socketBuffer = m_transmitSocket.TheSocketBuffer(); 87 | 88 | if (!m_canOutput) { 89 | return; 90 | } 91 | 92 | if (!m_transmitSocket.IsWorking()) { 93 | return; 94 | } 95 | 96 | if (!socketBuffer.HasDataToSend()) { 97 | return; 98 | } 99 | 100 | const auto& transmitSockId = m_transmitSocket.GetSockId(); 101 | while (true) { 102 | const auto pullLength = socketBuffer.PrepareSendPlan(); 103 | if (pullLength < 1) { 104 | break; 105 | } 106 | 107 | const auto count = socketBuffer.SetupSendIov(m_sendOperation.m_iov); 108 | 109 | const auto sendLength = writev(transmitSockId, m_sendOperation.m_iov, count); 110 | if (sendLength < 0) { 111 | const auto error = SAGetLastError(); 112 | if (IsInterrupted(error)) { 113 | continue; 114 | } 115 | 116 | if (IsWouldBlock(error)) { 117 | m_canOutput = false; 118 | break; 119 | } 120 | 121 | NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Error: socket close, error[%d]. [%s:%d]\n", error, __FILE__, __LINE__); 122 | m_transmitSocket.Close(); 123 | m_transmitSocket.OnError(error); 124 | break; 125 | } 126 | 127 | m_transmitSocket.OnSended(nullptr, sendLength); 128 | 129 | const auto restLength = socketBuffer.PreserveSendPlan(sendLength); 130 | MZ_UNUSED_VARIABLE(restLength); 131 | } 132 | } 133 | 134 | void EpollTransmitStrategy::EnableInput() { 135 | m_canInput = true; 136 | } 137 | 138 | void EpollTransmitStrategy::EnableOutput() { 139 | m_canOutput = true; 140 | } 141 | 142 | DECL_NAMESPACE_MZ_NET_END 143 | 144 | #endif 145 | -------------------------------------------------------------------------------- /Metazion/Net/EpollTransmitStrategy.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_EPOLLTRANSMITSTRATEGY_HPP_ 2 | #define _MZ_NET_EPOLLTRANSMITSTRATEGY_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #if defined(NETWORK_USE_EPOLL_MODEL) 7 | 8 | #include 9 | 10 | #include "Metazion/Net/EpollStrategy.hpp" 11 | 12 | DECL_NAMESPACE_MZ_NET_BEGIN 13 | 14 | class TransmitSocket; 15 | 16 | class EpollTransmitStrategy final : public EpollStrategy { 17 | MZ_DISALLOW_COPY_AND_ASSIGN(EpollTransmitStrategy) 18 | 19 | private: 20 | TransmitSocket& m_transmitSocket; 21 | SendOperation m_sendOperation; 22 | RecvOperation m_recvOperation; 23 | std::atomic m_canInput{ false }; 24 | std::atomic m_canOutput{ false }; 25 | 26 | public: 27 | EpollTransmitStrategy(TransmitSocket& transmitSocket); 28 | 29 | ~EpollTransmitStrategy(); 30 | 31 | void Reset() override final; 32 | 33 | void Prepare() override final; 34 | 35 | void Start() override final; 36 | 37 | void Launch() override final; 38 | 39 | bool IsBusy() const override final; 40 | 41 | void PostInput() override final; 42 | 43 | void PostOutput() override final; 44 | 45 | void EnableInput() override final; 46 | 47 | void EnableOutput() override final; 48 | }; 49 | 50 | DECL_NAMESPACE_MZ_NET_END 51 | 52 | #endif 53 | 54 | #endif // _MZ_NET_EPOLLTRANSMITSTRATEGY_HPP_ 55 | -------------------------------------------------------------------------------- /Metazion/Net/Host.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_HOST_HPP_ 2 | #define _MZ_NET_HOST_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include "Metazion/Net/Address.hpp" 7 | #include "Metazion/Net/SocketDefine.hpp" 8 | 9 | DECL_NAMESPACE_MZ_NET_BEGIN 10 | 11 | class Host { 12 | 13 | private: 14 | SockAddrIn_t m_sockAddrIn; 15 | char m_buffer[64]{ '\0' }; 16 | 17 | public: 18 | Host() { 19 | memset(&m_sockAddrIn, 0, sizeof(m_sockAddrIn)); 20 | } 21 | 22 | ~Host() {} 23 | 24 | Host(const Host& other) { 25 | *this = other; 26 | } 27 | 28 | Host& operator =(const Host& other) { 29 | if(this != &other) { 30 | memcpy(&m_sockAddrIn, &other.m_sockAddrIn, sizeof(m_sockAddrIn)); 31 | } 32 | 33 | return *this; 34 | } 35 | 36 | void Reset() { 37 | memset(&m_sockAddrIn, 0, sizeof(m_sockAddrIn)); 38 | } 39 | 40 | void FromSockAddrIn(const SockAddrIn_t* sockAddrIn) { 41 | memcpy(&m_sockAddrIn, sockAddrIn, sizeof(m_sockAddrIn)); 42 | } 43 | 44 | void FromAddress(const Address& address, int family = AF_INET) { 45 | m_sockAddrIn.sin_family = family; 46 | m_sockAddrIn.sin_addr.s_addr = htonl(address.m_ip); 47 | m_sockAddrIn.sin_port = htons(address.m_port); 48 | } 49 | 50 | Address ToAddress() { 51 | Address address; 52 | address.m_ip = ntohl(m_sockAddrIn.sin_addr.s_addr); 53 | address.m_port = ntohs(m_sockAddrIn.sin_port); 54 | return address; 55 | } 56 | 57 | SockAddrIn_t* SockAddrIn() { 58 | return &m_sockAddrIn; 59 | } 60 | 61 | SockAddr_t* SockAddr() { 62 | return reinterpret_cast(&m_sockAddrIn); 63 | } 64 | 65 | SockLen_t SockAddrLen() const { 66 | return sizeof(m_sockAddrIn); 67 | } 68 | 69 | int GetFamily() const { 70 | return m_sockAddrIn.sin_family; 71 | } 72 | 73 | void SetFamily(int family) { 74 | m_sockAddrIn.sin_family = family; 75 | } 76 | 77 | const char* GetIp() { 78 | return inet_ntop(m_sockAddrIn.sin_family, &m_sockAddrIn.sin_addr, m_buffer, sizeof(m_buffer)); 79 | } 80 | 81 | void SetIp(const char* ip) { 82 | inet_pton(m_sockAddrIn.sin_family, ip, &m_sockAddrIn.sin_addr); 83 | } 84 | 85 | int GetPort() const { 86 | return ntohs(m_sockAddrIn.sin_port); 87 | } 88 | 89 | void SetPort(int port) { 90 | m_sockAddrIn.sin_port = htons(port); 91 | } 92 | }; 93 | 94 | DECL_NAMESPACE_MZ_NET_END 95 | 96 | #endif // _MZ_NET_HOST_HPP_ 97 | -------------------------------------------------------------------------------- /Metazion/Net/IocpIoThread.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/IocpIoThread.hpp" 2 | 3 | #if defined(NETWORK_USE_IOCP_MODEL) 4 | 5 | #include "Metazion/Net/NetworkService.hpp" 6 | #include "Metazion/Net/Socket.hpp" 7 | 8 | DECL_NAMESPACE_MZ_NET_BEGIN 9 | 10 | IocpIoThread::IocpIoThread() {} 11 | 12 | IocpIoThread::~IocpIoThread() {} 13 | 14 | void IocpIoThread::Initialize(NetworkService* networkService, int index) { 15 | m_stopDesired = false; 16 | m_networkService = networkService; 17 | m_index = index; 18 | } 19 | 20 | void IocpIoThread::Finalize() { 21 | m_stopDesired = true; 22 | Join(); 23 | } 24 | 25 | void IocpIoThread::Execute() { 26 | Socket* socket = nullptr; 27 | IocpOperation* iocpOperation = nullptr; 28 | DWORD numberOfBytes = 0; 29 | ULONG_PTR completionKey = 0; 30 | LPOVERLAPPED overlapped = nullptr; 31 | 32 | auto hIocp = m_networkService->GetSocketService().GetIocpHandle(); 33 | 34 | auto hThread = GetCurrentThread(); 35 | SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST); 36 | 37 | while (!m_stopDesired) { 38 | numberOfBytes = 0; 39 | completionKey = 0; 40 | overlapped = nullptr; 41 | 42 | auto ret = GetQueuedCompletionStatus(hIocp 43 | , &numberOfBytes 44 | , &completionKey 45 | , &overlapped 46 | , 20); 47 | 48 | socket = reinterpret_cast(completionKey); 49 | iocpOperation = CONTAINING_RECORD(overlapped, IocpOperation, m_overlapped); 50 | 51 | const auto error = WSAGetLastError(); 52 | const auto result = AnalyseStatusResult(ret 53 | , overlapped 54 | , numberOfBytes 55 | , error); 56 | 57 | switch (result) { 58 | case RESULT_SUCCESS: 59 | socket->TheIoStrategy().HandleSuccess(iocpOperation, numberOfBytes); 60 | break; 61 | case RESULT_FAILURE: 62 | socket->TheIoStrategy().HandleFailure(iocpOperation, numberOfBytes, error); 63 | break; 64 | case RESULT_CLOSE: 65 | socket->TheIoStrategy().HandleClose(iocpOperation, numberOfBytes); 66 | break; 67 | case RESULT_TIMEOUT: 68 | break; 69 | case RESULT_ERROR: 70 | break; 71 | default: MZ_ASSERT_TRUE(false); break; 72 | } 73 | } 74 | } 75 | 76 | int IocpIoThread::AnalyseStatusResult(BOOL ret 77 | , OVERLAPPED* overlapped 78 | , DWORD numberOfBytes 79 | , DWORD error) { 80 | if (ret == TRUE) { 81 | if (numberOfBytes == 0xFFFFFFFF) { 82 | return RESULT_CLOSE; 83 | } 84 | 85 | return RESULT_SUCCESS; 86 | } 87 | 88 | if (!IsNull(overlapped)) { 89 | return RESULT_FAILURE; 90 | } 91 | 92 | if (error == WAIT_TIMEOUT) { 93 | return RESULT_TIMEOUT; 94 | } 95 | 96 | return RESULT_ERROR; 97 | } 98 | 99 | DECL_NAMESPACE_MZ_NET_END 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /Metazion/Net/IocpIoThread.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_IOCPIOTHREAD_HPP_ 2 | #define _MZ_NET_IOCPIOTHREAD_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #if defined(NETWORK_USE_IOCP_MODEL) 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include "Metazion/Net/SocketCtrl.hpp" 13 | #include "Metazion/Net/SocketDefine.hpp" 14 | 15 | DECL_NAMESPACE_MZ_NET_BEGIN 16 | 17 | class NetworkService; 18 | 19 | class IocpIoThread : public NS_SHARE::Thread { 20 | MZ_DISALLOW_COPY_AND_ASSIGN(IocpIoThread) 21 | 22 | enum Result { 23 | RESULT_SUCCESS = 1, 24 | RESULT_FAILURE, 25 | RESULT_CLOSE, 26 | RESULT_TIMEOUT, 27 | RESULT_ERROR, 28 | }; 29 | 30 | private: 31 | NetworkService* m_networkService{ nullptr }; 32 | int m_index{ 0 }; 33 | std::atomic m_stopDesired{ false }; 34 | 35 | public: 36 | IocpIoThread(); 37 | 38 | ~IocpIoThread(); 39 | 40 | void Initialize(NetworkService* networkService, int index); 41 | 42 | void Finalize(); 43 | 44 | protected: 45 | void Execute() override final; 46 | 47 | private: 48 | int AnalyseStatusResult(BOOL ret 49 | , OVERLAPPED* overlapped 50 | , DWORD numberOfBytes 51 | , DWORD error); 52 | }; 53 | 54 | DECL_NAMESPACE_MZ_NET_END 55 | 56 | #endif 57 | 58 | #endif // _MZ_NET_IOCPIOTHREAD_HPP_ 59 | -------------------------------------------------------------------------------- /Metazion/Net/IocpListenStrategy.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/IocpListenStrategy.hpp" 2 | 3 | #include 4 | 5 | #include "Metazion/Net/ListenSocket.hpp" 6 | 7 | #if defined(NETWORK_USE_IOCP_MODEL) 8 | 9 | DECL_NAMESPACE_MZ_NET_BEGIN 10 | 11 | IocpListenStrategy::IocpListenStrategy(ListenSocket& listenSocket) 12 | : m_listenSocket(listenSocket) {} 13 | 14 | IocpListenStrategy::~IocpListenStrategy() {} 15 | 16 | void IocpListenStrategy::Reset() { 17 | m_acceptOperation.Reset(); 18 | memset(m_acceptBuffer, 0, sizeof(m_acceptBuffer)); 19 | } 20 | 21 | void IocpListenStrategy::Prepare() { 22 | Reset(); 23 | } 24 | 25 | void IocpListenStrategy::Start() { 26 | PostInput(); 27 | } 28 | 29 | void IocpListenStrategy::Launch() { 30 | PostOutput(); 31 | } 32 | 33 | bool IocpListenStrategy::IsBusy() const { 34 | return m_acceptOperation.IsBusy(); 35 | } 36 | 37 | bool IocpListenStrategy::PostInput() { 38 | if (!m_listenSocket.IsWorking()) { 39 | return false; 40 | } 41 | 42 | if (m_acceptOperation.IsBusy()) { 43 | return true; 44 | } 45 | 46 | m_acceptOperation.SetBusy(true); 47 | 48 | return PostAccept(); 49 | } 50 | 51 | bool IocpListenStrategy::PostOutput() { 52 | return true; 53 | } 54 | 55 | bool IocpListenStrategy::HandleSuccess(const IocpOperation* iocpOperation 56 | , DWORD byteNumber) { 57 | MZ_ASSERT_TRUE(&m_acceptOperation == iocpOperation); 58 | 59 | const auto& acceptBuffer = m_acceptOperation.m_buffer; 60 | const auto& acceptSockId = m_acceptOperation.m_sockId; 61 | 62 | const auto localBuffer = m_acceptOperation.m_buffer; 63 | const auto localAddr = reinterpret_cast(localBuffer); 64 | const auto remoteBuffer = m_acceptOperation.m_buffer + sizeof(SockAddrIn_t) + 16; 65 | const auto remoteAddr = reinterpret_cast(remoteBuffer); 66 | 67 | Host peerHost; 68 | peerHost.FromSockAddrIn(remoteAddr); 69 | 70 | const auto& listenSockId = m_listenSocket.GetSockId(); 71 | const auto ret = setsockopt(acceptSockId 72 | , SOL_SOCKET 73 | , SO_UPDATE_ACCEPT_CONTEXT 74 | , reinterpret_cast(&listenSockId) 75 | , sizeof(listenSockId)); 76 | if (ret != 0) { 77 | DestroySockId(acceptSockId); 78 | } 79 | 80 | if (!m_listenSocket.OnAccepted(acceptSockId, peerHost)) { 81 | DestroySockId(acceptSockId); 82 | } 83 | 84 | return PostAccept(); 85 | } 86 | 87 | bool IocpListenStrategy::HandleFailure(const IocpOperation* iocpOperation 88 | , DWORD byteNumber, int error) { 89 | MZ_ASSERT_TRUE(&m_acceptOperation == iocpOperation); 90 | 91 | NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Error: socket close. [%s:%d]\n", __FILE__, __LINE__); 92 | m_listenSocket.Close(); 93 | m_listenSocket.OnError(error); 94 | 95 | DestroySockId(m_acceptOperation.m_sockId); 96 | m_acceptOperation.m_sockId = INVALID_SOCKID; 97 | m_acceptOperation.SetBusy(false); 98 | return true; 99 | } 100 | 101 | bool IocpListenStrategy::HandleClose(const IocpOperation* iocpOperation 102 | , DWORD byteNumber){ 103 | MZ_ASSERT_TRUE(&m_acceptOperation == iocpOperation); 104 | 105 | NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Trace: socket close. [%s:%d]\n", __FILE__, __LINE__); 106 | m_listenSocket.Disconnect(); 107 | 108 | DestroySockId(m_acceptOperation.m_sockId); 109 | m_acceptOperation.m_sockId = INVALID_SOCKID; 110 | m_acceptOperation.SetBusy(false); 111 | return true; 112 | } 113 | 114 | bool IocpListenStrategy::PostAccept() { 115 | const auto sockId = CreateSockId(TRANSPORT_TCP); 116 | if (sockId == INVALID_SOCKID) { 117 | m_acceptOperation.SetBusy(false); 118 | return false; 119 | } 120 | 121 | m_acceptOperation.m_buffer = m_acceptBuffer; 122 | m_acceptOperation.m_sockId = sockId; 123 | 124 | DWORD bytesRecvd = 0; 125 | const auto& listenSockId = m_listenSocket.GetSockId(); 126 | const auto ret = AcceptEx(listenSockId 127 | , m_acceptOperation.m_sockId 128 | , m_acceptOperation.m_buffer 129 | , 0 130 | , sizeof(SockAddrIn_t) + 16 131 | , sizeof(SockAddrIn_t) + 16 132 | , &bytesRecvd 133 | , &m_acceptOperation.m_overlapped); 134 | if (ret == FALSE) { 135 | const DWORD error = WSAGetLastError(); 136 | if (error != ERROR_IO_PENDING) { 137 | HandleFailure(&m_acceptOperation, 0, error); 138 | return false; 139 | } 140 | } 141 | 142 | return true; 143 | } 144 | 145 | DECL_NAMESPACE_MZ_NET_END 146 | 147 | #endif 148 | -------------------------------------------------------------------------------- /Metazion/Net/IocpListenStrategy.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_IOCPLISTENSTRATEGY_HPP_ 2 | #define _MZ_NET_IOCPLISTENSTRATEGY_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #if defined(NETWORK_USE_IOCP_MODEL) 7 | 8 | #include 9 | #include 10 | 11 | #include "Metazion/Net/IocpStrategy.hpp" 12 | 13 | DECL_NAMESPACE_MZ_NET_BEGIN 14 | 15 | class ListenSocket; 16 | 17 | class IocpListenStrategy final : public IocpStrategy { 18 | MZ_DISALLOW_COPY_AND_ASSIGN(IocpListenStrategy) 19 | 20 | private: 21 | ListenSocket& m_listenSocket; 22 | AcceptOperation m_acceptOperation; 23 | char m_acceptBuffer[256]{ 0 }; 24 | 25 | public: 26 | IocpListenStrategy(ListenSocket& listenSocket); 27 | 28 | ~IocpListenStrategy(); 29 | 30 | void Reset() override final; 31 | 32 | void Prepare() override final; 33 | 34 | void Start() override final; 35 | 36 | void Launch() override final; 37 | 38 | bool IsBusy() const override final; 39 | 40 | bool PostInput() override final; 41 | 42 | bool PostOutput() override final; 43 | 44 | bool HandleSuccess(const IocpOperation* iocpOperation 45 | , DWORD byteNumber) override final; 46 | 47 | bool HandleFailure(const IocpOperation* iocpOperation 48 | , DWORD byteNumber, int error) override final; 49 | 50 | bool HandleClose(const IocpOperation* iocpOperation 51 | , DWORD byteNumber) override final; 52 | 53 | private: 54 | bool PostAccept(); 55 | }; 56 | 57 | DECL_NAMESPACE_MZ_NET_END 58 | 59 | #endif 60 | 61 | #endif // _MZ_NET_IOCPLISTENSTRATEGY_HPP_ 62 | -------------------------------------------------------------------------------- /Metazion/Net/IocpOperation.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_IOCPOPERATION_HPP_ 2 | #define _MZ_NET_IOCPOPERATION_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #if defined(NETWORK_USE_IOCP_MODEL) 7 | 8 | #include 9 | 10 | #include "Metazion/Net/SocketDefine.hpp" 11 | #include "Metazion/Net/Host.hpp" 12 | 13 | DECL_NAMESPACE_MZ_NET_BEGIN 14 | 15 | struct IocpOperation { 16 | enum Type { 17 | TYPE_ACCEPT = 1, 18 | TYPE_SEND, 19 | TYPE_RECV, 20 | }; 21 | 22 | Type m_type; 23 | OVERLAPPED m_overlapped; 24 | std::atomic m_busy{ false }; 25 | 26 | IocpOperation(Type type) 27 | : m_type(type) { memset(&m_overlapped, 0, sizeof(m_overlapped)); } 28 | 29 | void Reset() { 30 | memset(&m_overlapped, 0, sizeof(m_overlapped)); 31 | m_busy = false; 32 | } 33 | 34 | bool IsBusy() const { 35 | return m_busy; 36 | } 37 | 38 | void SetBusy(bool busy) { 39 | m_busy = busy; 40 | } 41 | }; 42 | 43 | struct AcceptOperation final : public IocpOperation { 44 | char* m_buffer{ nullptr }; 45 | SockId_t m_sockId = INVALID_SOCKID; 46 | 47 | AcceptOperation() 48 | : IocpOperation(TYPE_ACCEPT) {} 49 | 50 | void Reset() { 51 | IocpOperation::Reset(); 52 | m_buffer = nullptr; 53 | m_sockId = INVALID_SOCKID; 54 | } 55 | }; 56 | 57 | struct SendOperation final : public IocpOperation { 58 | IOV_TYPE m_iov[NUMBER_SEND_IOV]; 59 | 60 | SendOperation() 61 | : IocpOperation(TYPE_SEND) {} 62 | 63 | void Reset() { 64 | IocpOperation::Reset(); 65 | memset(&m_iov, 0, sizeof(m_iov)); 66 | } 67 | }; 68 | 69 | struct RecvOperation final : public IocpOperation { 70 | IOV_TYPE m_iov[NUMBER_RECV_IOV]; 71 | 72 | RecvOperation() 73 | : IocpOperation(TYPE_RECV) {} 74 | 75 | void Reset() { 76 | IocpOperation::Reset(); 77 | memset(&m_iov, 0, sizeof(m_iov)); 78 | } 79 | }; 80 | 81 | DECL_NAMESPACE_MZ_NET_END 82 | 83 | #endif 84 | 85 | #endif // _MZ_NET_IOCPOPERATION_HPP_ 86 | -------------------------------------------------------------------------------- /Metazion/Net/IocpService.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/IocpService.hpp" 2 | 3 | #include "Metazion/Net/Socket.hpp" 4 | 5 | #if defined(NETWORK_USE_IOCP_MODEL) 6 | 7 | DECL_NAMESPACE_MZ_NET_BEGIN 8 | 9 | IocpService::IocpService() {} 10 | 11 | IocpService::~IocpService() {} 12 | 13 | bool IocpService::Initialize(int socketCapacity, int ioThreadNumber) { 14 | m_socketCapacity = socketCapacity; 15 | m_ioThreadNumber = ioThreadNumber; 16 | 17 | auto hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, ioThreadNumber); 18 | if (hIocp == NULL) { 19 | return false; 20 | } 21 | 22 | m_hIocp = hIocp; 23 | return true; 24 | } 25 | 26 | void IocpService::Finalize() { 27 | CloseHandle(m_hIocp); 28 | } 29 | 30 | bool IocpService::Associate(Socket* socket) { 31 | const auto& sockId = socket->GetSockId(); 32 | auto sockHandle = reinterpret_cast(sockId); 33 | auto compKey = reinterpret_cast(socket); 34 | auto hIocp = CreateIoCompletionPort(sockHandle, m_hIocp, compKey, 0); 35 | return hIocp != NULL; 36 | } 37 | 38 | DECL_NAMESPACE_MZ_NET_END 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /Metazion/Net/IocpService.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_IOCPSERVICE_HPP_ 2 | #define _MZ_NET_IOCPSERVICE_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include "Metazion/Net/SocketDefine.hpp" 7 | 8 | #if defined(NETWORK_USE_IOCP_MODEL) 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | class Socket; 13 | 14 | class IocpService { 15 | MZ_DISALLOW_COPY_AND_ASSIGN(IocpService) 16 | 17 | private: 18 | int m_socketCapacity{ 0 }; 19 | int m_ioThreadNumber{ 0 }; 20 | HANDLE m_hIocp{ nullptr }; 21 | 22 | public: 23 | IocpService(); 24 | 25 | ~IocpService(); 26 | 27 | bool Initialize(int socketCapacity, int ioThreadNumber); 28 | 29 | void Finalize(); 30 | 31 | bool Associate(Socket* socket); 32 | 33 | HANDLE GetIocpHandle() const; 34 | }; 35 | 36 | inline HANDLE IocpService::GetIocpHandle() const { 37 | return m_hIocp; 38 | } 39 | 40 | DECL_NAMESPACE_MZ_NET_END 41 | 42 | #endif 43 | 44 | #endif // _MZ_NET_IOCPSERVICE_HPP_ 45 | -------------------------------------------------------------------------------- /Metazion/Net/IocpStrategy.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_IOCPSOCKET_HPP_ 2 | #define _MZ_NET_IOCPSOCKET_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #if defined(NETWORK_USE_IOCP_MODEL) 7 | 8 | #include "Metazion/Net/IocpOperation.hpp" 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | class IocpStrategy { 13 | MZ_DISALLOW_COPY_AND_ASSIGN(IocpStrategy) 14 | 15 | public: 16 | IocpStrategy() {} 17 | 18 | virtual ~IocpStrategy() {} 19 | 20 | virtual void Reset() = 0; 21 | 22 | virtual void Prepare() = 0; 23 | 24 | virtual void Start() = 0; 25 | 26 | virtual void Launch() = 0; 27 | 28 | virtual bool IsBusy() const = 0; 29 | 30 | virtual bool PostInput() = 0; 31 | 32 | virtual bool PostOutput() = 0; 33 | 34 | virtual bool HandleSuccess(const IocpOperation* iocpOperation 35 | , DWORD byteNumber) = 0; 36 | 37 | virtual bool HandleFailure(const IocpOperation* iocpOperation 38 | , DWORD byteNumber, int error) = 0; 39 | 40 | virtual bool HandleClose(const IocpOperation* iocpOperation 41 | , DWORD byteNumber) = 0; 42 | }; 43 | 44 | DECL_NAMESPACE_MZ_NET_END 45 | 46 | #endif 47 | 48 | #endif // _MZ_NET_IOCPSOCKET_HPP_ 49 | -------------------------------------------------------------------------------- /Metazion/Net/IocpTransmitStrategy.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_IOCPTRANSMITSTRATEGY_HPP_ 2 | #define _MZ_NET_IOCPTRANSMITSTRATEGY_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #if defined(NETWORK_USE_IOCP_MODEL) 7 | 8 | #include "Metazion/Net/IocpStrategy.hpp" 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | class TransmitSocket; 13 | 14 | class IocpTransmitStrategy final : public IocpStrategy { 15 | MZ_DISALLOW_COPY_AND_ASSIGN(IocpTransmitStrategy) 16 | 17 | private: 18 | TransmitSocket& m_transmitSocket; 19 | SendOperation m_sendOperation; 20 | RecvOperation m_recvOperation; 21 | 22 | public: 23 | IocpTransmitStrategy(TransmitSocket& transmitSocket); 24 | 25 | ~IocpTransmitStrategy(); 26 | 27 | void Reset() override final; 28 | 29 | void Prepare() override final; 30 | 31 | void Start() override final; 32 | 33 | void Launch() override final; 34 | 35 | bool IsBusy() const override final; 36 | 37 | bool PostInput() override final; 38 | 39 | bool PostOutput() override final; 40 | 41 | bool HandleSuccess(const IocpOperation* iocpOperation 42 | , DWORD byteNumber) override final; 43 | 44 | bool HandleFailure(const IocpOperation* iocpOperation 45 | , DWORD byteNumber, int error) override final; 46 | 47 | bool HandleClose(const IocpOperation* iocpOperation 48 | , DWORD byteNumber) override final; 49 | 50 | private: 51 | bool PostRecv(); 52 | 53 | bool PostSend(); 54 | 55 | bool HandleRecvSuccess(const IocpOperation* iocpOperation 56 | , DWORD byteNumber); 57 | 58 | bool HandleSendSuccess(const IocpOperation* iocpOperation 59 | , DWORD byteNumber); 60 | 61 | bool HandleRecvFailure(const IocpOperation* iocpOperation 62 | , DWORD byteNumber, int error); 63 | 64 | bool HandleSendFailure(const IocpOperation* iocpOperation 65 | , DWORD byteNumber, int error); 66 | 67 | bool HandleRecvClose(const IocpOperation* iocpOperation 68 | , DWORD byteNumber); 69 | 70 | bool HandleSendClose(const IocpOperation* iocpOperation 71 | , DWORD byteNumber); 72 | }; 73 | 74 | DECL_NAMESPACE_MZ_NET_END 75 | 76 | #endif 77 | 78 | #endif // _MZ_NET_IOCPTRANSMITSTRATEGY_HPP_ 79 | -------------------------------------------------------------------------------- /Metazion/Net/ListenSocket.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/ListenSocket.hpp" 2 | 3 | #include 4 | #include 5 | 6 | #include "Metazion/Net/NetworkService.hpp" 7 | 8 | DECL_NAMESPACE_MZ_NET_BEGIN 9 | 10 | ListenSocket::ListenSocket() 11 | : m_listenStrategy(*this) {} 12 | 13 | ListenSocket::~ListenSocket() {} 14 | 15 | void ListenSocket::Reset() { 16 | Socket::Reset(); 17 | 18 | m_listenStrategy.Reset(); 19 | m_localHost.Reset(); 20 | 21 | m_watchedTime = 0; 22 | m_unwatchedTime = 0; 23 | m_firstAcceptTime = 0; 24 | m_lastAcceptTime = 0; 25 | m_acceptedNumber = 0; 26 | } 27 | 28 | void ListenSocket::Prepare() { 29 | Socket::Prepare(); 30 | 31 | m_listenStrategy.Prepare(); 32 | } 33 | 34 | bool ListenSocket::IsAlive() const { 35 | auto ret = IsValid(); 36 | if (ret) { 37 | return true; 38 | } 39 | 40 | ret = m_listenStrategy.IsBusy(); 41 | if (ret) { 42 | return true; 43 | } 44 | 45 | return false; 46 | } 47 | 48 | bool ListenSocket::KeepEnough() const { 49 | return false; 50 | } 51 | 52 | void ListenSocket::OnAttached() {} 53 | 54 | void ListenSocket::OnDetached() {} 55 | 56 | void ListenSocket::OnStart() { 57 | m_listenStrategy.Start(); 58 | OnWatched(); 59 | } 60 | 61 | void ListenSocket::OnStop() { 62 | OnUnwatched(); 63 | } 64 | 65 | void ListenSocket::OnError(int error) {} 66 | 67 | void ListenSocket::SetLocalHost(const Host& host) { 68 | m_localHost = host; 69 | } 70 | 71 | bool ListenSocket::Listen(int backlog) { 72 | const auto sockId = CreateSockId(TRANSPORT_TCP); 73 | if (sockId == INVALID_SOCKID) { 74 | return false; 75 | } 76 | 77 | int optValue = 1; 78 | auto optLength = static_cast(sizeof(optValue)); 79 | auto ret = SetSockOpt(sockId, SOL_SOCKET, SO_REUSEADDR, &optValue, optLength); 80 | if (ret == SOCKET_ERROR) { 81 | DestroySockId(sockId); 82 | return false; 83 | } 84 | 85 | auto sockAddr = m_localHost.SockAddr(); 86 | auto sockAddrLen = m_localHost.SockAddrLen(); 87 | ret = bind(sockId, sockAddr, sockAddrLen); 88 | if (ret == SOCKET_ERROR) { 89 | DestroySockId(sockId); 90 | return false; 91 | } 92 | 93 | ret = listen(sockId, backlog); 94 | if (ret == SOCKET_ERROR) { 95 | DestroySockId(sockId); 96 | return false; 97 | } 98 | 99 | AttachSockId(sockId); 100 | return true; 101 | } 102 | 103 | void ListenSocket::OnWatched() { 104 | m_watchedTime = m_now; 105 | } 106 | 107 | void ListenSocket::OnUnwatched() { 108 | m_unwatchedTime = m_now; 109 | } 110 | 111 | bool ListenSocket::OnAccepted(const SockId_t& sockId, const Host& host) { 112 | const auto now = m_now; 113 | if (m_firstAcceptTime == 0) { 114 | m_firstAcceptTime = now; 115 | } 116 | 117 | m_lastAcceptTime = now; 118 | ++m_acceptedNumber; 119 | return true; 120 | } 121 | 122 | DECL_NAMESPACE_MZ_NET_END 123 | -------------------------------------------------------------------------------- /Metazion/Net/ListenSocket.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_LISTENSOCKET_HPP_ 2 | #define _MZ_NET_LISTENSOCKET_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include "Metazion/Net/Socket.hpp" 7 | 8 | DECL_NAMESPACE_MZ_NET_BEGIN 9 | 10 | class ListenSocket : public Socket { 11 | MZ_DISALLOW_COPY_AND_ASSIGN(ListenSocket) 12 | 13 | friend class ListenStrategy; 14 | 15 | protected: 16 | ListenStrategy m_listenStrategy; 17 | Host m_localHost; 18 | 19 | int64_t m_watchedTime{ 0 }; 20 | int64_t m_unwatchedTime{ 0 }; 21 | int64_t m_firstAcceptTime{ 0 }; 22 | int64_t m_lastAcceptTime{ 0 }; 23 | int64_t m_acceptedNumber{ 0 }; 24 | 25 | public: 26 | ListenSocket(); 27 | 28 | virtual ~ListenSocket(); 29 | 30 | void Reset() override; 31 | 32 | void Prepare() override; 33 | 34 | bool IsAlive() const override final; 35 | 36 | bool KeepEnough() const override final; 37 | 38 | IoStrategy& TheIoStrategy() override final; 39 | 40 | void OnAttached() override final; 41 | 42 | void OnDetached() override final; 43 | 44 | void OnStart() override final; 45 | 46 | void OnStop() override final; 47 | 48 | void OnError(int error) override final; 49 | 50 | void SetLocalHost(const Host& host); 51 | 52 | bool Listen(int backlog); 53 | 54 | protected: 55 | virtual void OnWatched(); 56 | 57 | virtual void OnUnwatched(); 58 | 59 | virtual bool OnAccepted(const SockId_t& sockId, const Host& host); 60 | }; 61 | 62 | inline IoStrategy& ListenSocket::TheIoStrategy() { 63 | return m_listenStrategy; 64 | } 65 | 66 | DECL_NAMESPACE_MZ_NET_END 67 | 68 | #endif // _MZ_NET_LISTENSOCKET_HPP_ 69 | -------------------------------------------------------------------------------- /Metazion/Net/MaintenanceThread.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/MaintenanceThread.hpp" 2 | 3 | #include 4 | 5 | #include "Metazion/Net/NetworkService.hpp" 6 | #include "Metazion/Net/Socket.hpp" 7 | 8 | DECL_NAMESPACE_MZ_NET_BEGIN 9 | 10 | MaintenanceThread::MaintenanceThread() {} 11 | 12 | MaintenanceThread::~MaintenanceThread() {} 13 | 14 | void MaintenanceThread::Init(NetworkService* networkService) { 15 | MZ_ASSERT_TRUE(!IsNull(networkService)); 16 | 17 | m_stopDesired = false; 18 | m_networkService = networkService; 19 | m_now = 0; 20 | m_interval = 0; 21 | } 22 | 23 | void MaintenanceThread::Finalize() { 24 | m_stopDesired = true; 25 | Join(); 26 | } 27 | 28 | void MaintenanceThread::Execute() { 29 | auto lastTime = NS_SHARE::GetNowMillisecond(); 30 | auto lastTickTime = lastTime; 31 | while (!m_stopDesired) { 32 | m_now = NS_SHARE::GetNowMillisecond(); 33 | if (m_now - lastTime < 10) { 34 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); 35 | continue; 36 | } 37 | 38 | m_interval = static_cast(m_now - lastTickTime); 39 | lastTickTime = m_now; 40 | 41 | ProcessSockets(); 42 | 43 | lastTime = m_now; 44 | } 45 | } 46 | 47 | void MaintenanceThread::ProcessSockets() { 48 | const auto socketCapacity = m_networkService->GetSocketCapacity(); 49 | for (auto index = 0; index < socketCapacity; ++index) { 50 | auto& socketCtrl = m_networkService->GetSocketCtrl(index); 51 | if (IsNull(socketCtrl.m_socket)) { 52 | continue; 53 | } 54 | 55 | socketCtrl.m_socket->Tick(m_now, m_interval); 56 | 57 | socketCtrl.m_active 58 | ? ProcessActiveSocket(socketCtrl.m_socket, index) 59 | : ProcessClosedSocket(socketCtrl.m_socket, index); 60 | } 61 | } 62 | 63 | void MaintenanceThread::ProcessActiveSocket(Socket* socket, int index) { 64 | if (socket->KeepEnough()) { 65 | socket->Disconnect(); 66 | } 67 | 68 | if (socket->IsGonnaClose()) { 69 | socket->Stop(); 70 | } 71 | 72 | if (!socket->IsActive()) { 73 | m_networkService->MarkSocketClosed(index); 74 | } 75 | } 76 | 77 | void MaintenanceThread::ProcessClosedSocket(Socket* socket, int index) { 78 | if (socket->IsActive()) { 79 | m_networkService->MarkSocketActive(index); 80 | return; 81 | } 82 | 83 | if (!socket->IsAlive()) { 84 | m_networkService->Lock(); 85 | if (socket->IsAlive()) { 86 | m_networkService->Unlock(); 87 | return; 88 | } 89 | 90 | m_networkService->RemoveSocketCtrl(index); 91 | m_networkService->Unlock(); 92 | 93 | socket->OnDetached(); 94 | socket->Destory(); 95 | } 96 | } 97 | 98 | DECL_NAMESPACE_MZ_NET_END 99 | -------------------------------------------------------------------------------- /Metazion/Net/MaintenanceThread.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_MAINTENANCETHREAD_HPP_ 2 | #define _MZ_NET_MAINTENANCETHREAD_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include 7 | 8 | #include 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | class Socket; 13 | class NetworkService; 14 | 15 | class MaintenanceThread : public NS_SHARE::Thread { 16 | MZ_DISALLOW_COPY_AND_ASSIGN(MaintenanceThread) 17 | 18 | private: 19 | std::atomic m_stopDesired{ false }; 20 | NetworkService* m_networkService{ nullptr }; 21 | int64_t m_now{ 0 }; 22 | int m_interval{ 0 }; 23 | 24 | public: 25 | MaintenanceThread(); 26 | 27 | ~MaintenanceThread(); 28 | 29 | void Init(NetworkService* networkService); 30 | 31 | void Finalize(); 32 | 33 | protected: 34 | void Execute() override final; 35 | 36 | private: 37 | void ProcessSockets(); 38 | 39 | void ProcessActiveSocket(Socket* socket, int index); 40 | 41 | void ProcessClosedSocket(Socket* socket, int index); 42 | }; 43 | 44 | DECL_NAMESPACE_MZ_NET_END 45 | 46 | #endif // _MZ_NET_MAINTENANCETHREAD_HPP_ 47 | -------------------------------------------------------------------------------- /Metazion/Net/NetInclude.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_INCLUDE_HPP_ 2 | #define _MZ_NET_INCLUDE_HPP_ 3 | 4 | #include "Metazion/Overall.hpp" 5 | 6 | #define DECL_NAMESPACE_MZ_NET_BEGIN namespace mz { namespace net { 7 | #define DECL_NAMESPACE_MZ_NET_END } } 8 | #define USING_NAMESPACE_MZ_NET using namespace mz::net; 9 | #define USING_NAMESPACE_NET using namespace net; 10 | #define NS_MZ_NET mz::net 11 | #define NS_NET net 12 | 13 | #if defined(MZ_PLATFORM_LINUX) 14 | # define NETWORK_USE_EPOLL_MODEL 15 | #elif defined(MZ_PLATFORM_WINDOWS) 16 | # define NETWORK_USE_IOCP_MODEL 17 | #else 18 | # define NETWORK_USE_SELECT_MODEL 19 | #endif 20 | 21 | #endif // _MZ_NET_INCLUDE_HPP_ 22 | -------------------------------------------------------------------------------- /Metazion/Net/Network.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/Network.hpp" 2 | 3 | #if defined(MZ_PLATFORM_WINDOWS) 4 | #include 5 | #pragma comment(lib, "ws2_32.lib") 6 | #endif 7 | 8 | DECL_NAMESPACE_MZ_NET_BEGIN 9 | 10 | int Network::Startup() { 11 | int ret = 0; 12 | #if defined(MZ_PLATFORM_WINDOWS) 13 | WSADATA wsaData; 14 | ret = WSAStartup(MAKEWORD(2, 2), &wsaData); 15 | #endif 16 | return ret; 17 | } 18 | 19 | int Network::Cleanup() { 20 | int ret = 0; 21 | #if defined(MZ_PLATFORM_WINDOWS) 22 | ret = WSACleanup(); 23 | #endif 24 | return ret; 25 | } 26 | 27 | DECL_NAMESPACE_MZ_NET_END 28 | -------------------------------------------------------------------------------- /Metazion/Net/Network.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_NETWORK_HPP_ 2 | #define _MZ_NET_NETWORK_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include "Metazion/Net/Host.hpp" 7 | 8 | DECL_NAMESPACE_MZ_NET_BEGIN 9 | 10 | class Network { 11 | 12 | public: 13 | static int Startup(); 14 | 15 | static int Cleanup(); 16 | }; 17 | 18 | DECL_NAMESPACE_MZ_NET_END 19 | 20 | #endif // _MZ_NET_NETWORK_HPP_ 21 | -------------------------------------------------------------------------------- /Metazion/Net/NetworkService.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_NETWORKSERVICE_HPP_ 2 | #define _MZ_NET_NETWORKSERVICE_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include "Metazion/Net/AlternativeService.hpp" 12 | #include "Metazion/Net/AlternativeThread.hpp" 13 | #include "Metazion/Net/MaintenanceThread.hpp" 14 | #include "Metazion/Net/Socket.hpp" 15 | #include "Metazion/Net/SocketBuffer.hpp" 16 | #include "Metazion/Net/SocketCtrl.hpp" 17 | 18 | DECL_NAMESPACE_MZ_NET_BEGIN 19 | 20 | class NetworkService { 21 | MZ_DISALLOW_COPY_AND_ASSIGN(NetworkService) 22 | 23 | friend class IoThread; 24 | friend class MaintenanceThread; 25 | 26 | using Lock_t = std::mutex; 27 | using LockGuard_t = std::lock_guard; 28 | 29 | public: 30 | using SocketArray_t = NS_SHARE::StaticArray; 31 | 32 | private: 33 | Lock_t m_lock; 34 | SocketService m_socketService; 35 | int m_socketCapacity{ 0 }; 36 | int m_socketNumber{ 0 }; 37 | SocketCtrl* m_socketCtrlList{ nullptr }; 38 | int m_ioThreadNumber{ 0 }; 39 | IoThread** m_ioThreadList{ nullptr }; 40 | MaintenanceThread* m_maintenanceThread{ nullptr }; 41 | SocketBuffer::SendCache_t::BufferPool_t m_sendCachePool; 42 | SocketBuffer::RecvCache_t::BufferPool_t m_recvCachePool; 43 | 44 | Socket** m_sockets{ nullptr }; 45 | SocketArray_t m_socketArray; 46 | 47 | public: 48 | NetworkService(); 49 | 50 | ~NetworkService(); 51 | 52 | bool Initialize(int socketCapacity, int ioThreadNumber); 53 | 54 | void Finalize(); 55 | 56 | void Tick(); 57 | 58 | bool Manage(Socket* socket); 59 | 60 | int AcquireSockets(std::function socketFilter, SocketArray_t& socketArray); 61 | 62 | void ReleaseSockets(SocketArray_t& socketArray); 63 | 64 | void Lock(); 65 | 66 | void Unlock(); 67 | 68 | int GetSocketCapacity() const; 69 | 70 | int GetSocketNumber() const; 71 | 72 | int GetIoThreadNumber() const; 73 | 74 | Socket* GetSocket(int index); 75 | 76 | SocketBuffer::SendCache_t::BufferPool_t& GetSendCachePool(); 77 | 78 | SocketBuffer::RecvCache_t::BufferPool_t& GetRecvCachePool(); 79 | 80 | private: 81 | SocketService& GetSocketService(); 82 | 83 | SocketCtrl& GetSocketCtrl(int index); 84 | 85 | void AddSocketCtrl(int index, Socket* socket); 86 | 87 | void RemoveSocketCtrl(int index); 88 | 89 | int GetVacantIndex() const; 90 | 91 | void MarkSocketActive(int index); 92 | 93 | void MarkSocketClosed(int index); 94 | }; 95 | 96 | inline void NetworkService::Lock() { 97 | m_lock.lock(); 98 | } 99 | 100 | inline void NetworkService::Unlock() { 101 | m_lock.unlock(); 102 | } 103 | 104 | inline int NetworkService::GetSocketCapacity() const { 105 | return m_socketCapacity; 106 | } 107 | 108 | inline int NetworkService::GetSocketNumber() const { 109 | return m_socketNumber; 110 | } 111 | 112 | inline int NetworkService::GetIoThreadNumber() const { 113 | return m_ioThreadNumber; 114 | } 115 | 116 | inline Socket* NetworkService::GetSocket(int index) { 117 | return m_socketCtrlList[index].m_socket; 118 | } 119 | 120 | inline SocketBuffer::SendCache_t::BufferPool_t& NetworkService::GetSendCachePool() { 121 | return m_sendCachePool; 122 | } 123 | 124 | inline SocketBuffer::RecvCache_t::BufferPool_t& NetworkService::GetRecvCachePool() { 125 | return m_recvCachePool; 126 | } 127 | 128 | inline SocketService& NetworkService::GetSocketService() { 129 | return m_socketService; 130 | } 131 | 132 | inline SocketCtrl& NetworkService::GetSocketCtrl(int index) { 133 | return m_socketCtrlList[index]; 134 | } 135 | 136 | DECL_NAMESPACE_MZ_NET_END 137 | 138 | #endif // _MZ_NET_NETWORKSERVICE_HPP_ 139 | -------------------------------------------------------------------------------- /Metazion/Net/PacketCodec.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/PacketCodec.hpp" 2 | 3 | #include "Metazion/Net/TransmitSocket.hpp" 4 | 5 | DECL_NAMESPACE_MZ_NET_BEGIN 6 | 7 | PacketCodec::PacketCodec(TransmitSocket& transmitSocket) 8 | : m_transmitSocket(transmitSocket) {} 9 | 10 | PacketCodec::~PacketCodec() {} 11 | 12 | int PacketCodec::Encode(int command, const void* data, int length, EncodeBuffer& encodeBuffer) { 13 | if (length < 0 || length > MAXAPPDATALENGTH) { 14 | MZ_ASSERT_TRUE(false); 15 | return -1; 16 | } 17 | 18 | PacketHeader header; 19 | header.m_command = command; 20 | header.m_length = length; 21 | 22 | encodeBuffer.m_resultBuffer.Push(&header, sizeof(header)); 23 | encodeBuffer.m_resultBuffer.Push(data, header.m_length); 24 | return sizeof(header) + header.m_length; 25 | } 26 | 27 | int PacketCodec::Decode(int& command, DecodeBuffer& decodeBuffer) { 28 | auto& socketBuffer = m_transmitSocket.TheSocketBuffer(); 29 | 30 | PacketHeader header; 31 | const auto headerLength = static_cast(sizeof(header)); 32 | const auto peekLength = socketBuffer.m_recvCache.Peek(&header, headerLength); 33 | if (peekLength != headerLength) { 34 | return 0; 35 | } 36 | 37 | const auto packetLength = static_cast(header.m_length); 38 | if (packetLength < 0 || packetLength > MAXAPPPACKETLENGTH) { 39 | return -1; 40 | } 41 | 42 | const auto cacheLength = socketBuffer.m_recvCache.GetCurLength(); 43 | if (cacheLength < headerLength + packetLength) { 44 | return 0; 45 | } 46 | 47 | auto pushBuffer = decodeBuffer.m_resultBuffer.GetPushBuffer(); 48 | const auto pushLength = decodeBuffer.m_resultBuffer.GetPushLength(); 49 | MZ_ASSERT_TRUE(pushLength >= packetLength); 50 | 51 | socketBuffer.m_recvLock.lock(); 52 | 53 | const auto pullHeaderLength = socketBuffer.m_recvCache.Pull(&header, headerLength); 54 | MZ_ASSERT_TRUE(pullHeaderLength == headerLength); 55 | 56 | const auto pullDataLength = socketBuffer.m_recvCache.Pull(pushBuffer, packetLength); 57 | MZ_ASSERT_TRUE(pullDataLength == packetLength); 58 | 59 | socketBuffer.m_recvLock.unlock(); 60 | 61 | command = header.m_command; 62 | decodeBuffer.m_resultBuffer.SetPushIndex(pullDataLength); 63 | return header.m_length; 64 | } 65 | 66 | DECL_NAMESPACE_MZ_NET_END 67 | -------------------------------------------------------------------------------- /Metazion/Net/PacketCodec.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_PACKETCODEC_HPP_ 2 | #define _MZ_NET_PACKETCODEC_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include 7 | 8 | #include "Metazion/Net/PacketDefine.hpp" 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | class TransmitSocket; 13 | 14 | class PacketCodec { 15 | MZ_DISALLOW_COPY_AND_ASSIGN(PacketCodec) 16 | 17 | private: 18 | TransmitSocket& m_transmitSocket; 19 | 20 | public: 21 | PacketCodec(TransmitSocket& transmitSocket); 22 | 23 | ~PacketCodec(); 24 | 25 | int Encode(int command, const void* data, int length, EncodeBuffer& encodeBuffer); 26 | 27 | int Decode(int& command, DecodeBuffer& decodeBuffer); 28 | }; 29 | 30 | DECL_NAMESPACE_MZ_NET_END 31 | 32 | #endif // _MZ_NET_PACKETCODEC_HPP_ 33 | -------------------------------------------------------------------------------- /Metazion/Net/PacketDefine.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_PACKETDEFINE_HPP_ 2 | #define _MZ_NET_PACKETDEFINE_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | #pragma pack(push, 1) 13 | 14 | struct PacketHeader { 15 | int16_t m_command{ 0 }; 16 | int16_t m_length{ 0 }; 17 | }; 18 | 19 | #pragma pack(pop) 20 | 21 | enum PacketValue { 22 | MAXNETDATALENGTH = 1024, 23 | MAXNETPACKETLENGTH = MAXNETDATALENGTH + sizeof(PacketHeader), 24 | 25 | MAXAPPDATALENGTH = 1024 * 64, 26 | MAXAPPPACKETLENGTH = MAXAPPDATALENGTH + sizeof(PacketHeader), 27 | }; 28 | 29 | struct EncodeBuffer { 30 | enum { LENGTH = MAXAPPPACKETLENGTH }; 31 | 32 | using Buffer_t = NS_SHARE::PieceBuffer; 33 | 34 | Buffer_t m_resultBuffer; 35 | }; 36 | 37 | struct DecodeBuffer { 38 | enum { LENGTH = MAXAPPPACKETLENGTH }; 39 | 40 | using Buffer_t = NS_SHARE::PieceBuffer; 41 | 42 | Buffer_t m_resultBuffer; 43 | }; 44 | 45 | DECL_NAMESPACE_MZ_NET_END 46 | 47 | #endif // _MZ_NET_PACKETDEFINE_HPP_ 48 | -------------------------------------------------------------------------------- /Metazion/Net/SelectIoThread.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/SelectIoThread.hpp" 2 | 3 | #if defined(NETWORK_USE_SELECT_MODEL) 4 | 5 | #include 6 | 7 | #include "Metazion/Net/NetworkService.hpp" 8 | #include "Metazion/Net/Socket.hpp" 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | SelectIoThread::SelectIoThread() {} 13 | 14 | SelectIoThread::~SelectIoThread() {} 15 | 16 | void SelectIoThread::Initialize(NetworkService* networkService, int index) { 17 | m_stopDesired = false; 18 | m_networkService = networkService; 19 | m_index = index; 20 | const auto startIndex = m_networkService->GetSocketService().GetStartIndex(m_index); 21 | m_socketCount = m_networkService->GetSocketService().GetSocketCount(m_index); 22 | m_socketCtrlList = &m_networkService->GetSocketCtrl(startIndex); 23 | } 24 | 25 | void SelectIoThread::Finalize() { 26 | m_stopDesired = true; 27 | Join(); 28 | } 29 | 30 | void SelectIoThread::Execute() { 31 | while (!m_stopDesired) { 32 | ProcessEvents(); 33 | ProcessIO(); 34 | } 35 | } 36 | 37 | void SelectIoThread::ProcessEvents() { 38 | const auto maxFd = ResetFds(); 39 | if (maxFd < 0) { 40 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); 41 | return; 42 | } 43 | 44 | struct timeval timeout{ 0, 20 * 1000 }; 45 | const auto ret = select(maxFd + 1, &m_rfds, &m_wfds, &m_efds, &timeout); 46 | if (ret == 0) { 47 | return; 48 | } 49 | else if (ret < 0) { 50 | return; 51 | } 52 | 53 | for (auto index = 0; index < m_socketCount; ++index) { 54 | const auto& socketCtrl = m_socketCtrlList[index]; 55 | if (IsNull(socketCtrl.m_socket)) { 56 | continue; 57 | } 58 | 59 | if (!socketCtrl.m_active) { 60 | continue; 61 | } 62 | 63 | const auto socket = socketCtrl.m_socket; 64 | const auto sockId = socket->GetSockId(); 65 | if (FD_ISSET(sockId, &m_efds)) { 66 | NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Info: socket close. [%s:%d]\n", __FILE__, __LINE__); 67 | socket->Close(); 68 | continue; 69 | } 70 | 71 | if (FD_ISSET(sockId, &m_rfds)) { 72 | socket->TheIoStrategy().EnableInput(); 73 | } 74 | 75 | if (FD_ISSET(sockId, &m_wfds)) { 76 | socket->TheIoStrategy().EnableOutput(); 77 | } 78 | } 79 | } 80 | 81 | void SelectIoThread::ProcessIO() { 82 | for (int index = 0; index < m_socketCount; ++index) { 83 | const auto& socketCtrl = m_socketCtrlList[index]; 84 | const auto socket = socketCtrl.m_socket; 85 | if (IsNull(socket)) { 86 | continue; 87 | } 88 | 89 | socket->TheIoStrategy().PostInput(); 90 | socket->TheIoStrategy().PostOutput(); 91 | } 92 | } 93 | 94 | int SelectIoThread::ResetFds() { 95 | FD_ZERO(&m_rfds); 96 | FD_ZERO(&m_wfds); 97 | FD_ZERO(&m_efds); 98 | 99 | int maxFd = -1; 100 | for (auto index = 0; index < m_socketCount; ++index) { 101 | const auto& socketCtrl = m_socketCtrlList[index]; 102 | const auto socket = socketCtrl.m_socket; 103 | if (IsNull(socket)) { 104 | continue; 105 | } 106 | 107 | if (!socket->IsWorking()) { 108 | continue; 109 | } 110 | 111 | const auto sockId = socket->GetSockId(); 112 | FD_SET(sockId, &m_rfds); 113 | FD_SET(sockId, &m_efds); 114 | if (socket->TheIoStrategy().ShouldCareAboutOutput()) { 115 | FD_SET(sockId, &m_wfds); 116 | } 117 | 118 | const auto sockFd = static_cast(sockId); 119 | maxFd = sockFd > maxFd ? sockFd : maxFd; 120 | } 121 | 122 | return maxFd; 123 | } 124 | 125 | DECL_NAMESPACE_MZ_NET_END 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /Metazion/Net/SelectIoThread.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_SELECTIOTHREAD_HPP_ 2 | #define _MZ_NET_SELECTIOTHREAD_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #if defined(NETWORK_USE_SELECT_MODEL) 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include "Metazion/Net/SocketCtrl.hpp" 13 | #include "Metazion/Net/SocketDefine.hpp" 14 | 15 | DECL_NAMESPACE_MZ_NET_BEGIN 16 | 17 | class NetworkService; 18 | 19 | class SelectIoThread : public NS_SHARE::Thread { 20 | MZ_DISALLOW_COPY_AND_ASSIGN(SelectIoThread) 21 | 22 | private: 23 | std::atomic m_stopDesired{ false }; 24 | 25 | NetworkService* m_networkService{ nullptr }; 26 | int m_index{ 0 }; 27 | int m_socketCount{ 0 }; 28 | SocketCtrl* m_socketCtrlList{ nullptr }; 29 | fd_set m_rfds; 30 | fd_set m_wfds; 31 | fd_set m_efds; 32 | 33 | public: 34 | SelectIoThread(); 35 | 36 | ~SelectIoThread(); 37 | 38 | void Initialize(NetworkService* networkService, int index); 39 | 40 | void Finalize(); 41 | 42 | protected: 43 | void Execute() override final; 44 | 45 | private: 46 | void ProcessEvents(); 47 | 48 | void ProcessIO(); 49 | 50 | int ResetFds(); 51 | }; 52 | 53 | DECL_NAMESPACE_MZ_NET_END 54 | 55 | #endif 56 | 57 | #endif // _MZ_NET_SELECTIOTHREAD_HPP_ 58 | -------------------------------------------------------------------------------- /Metazion/Net/SelectListenStrategy.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/SelectListenStrategy.hpp" 2 | 3 | #include 4 | 5 | #include "Metazion/Net/ListenSocket.hpp" 6 | 7 | #if defined(NETWORK_USE_SELECT_MODEL) 8 | 9 | DECL_NAMESPACE_MZ_NET_BEGIN 10 | 11 | SelectListenStrategy::SelectListenStrategy(ListenSocket& listenSocket) 12 | : m_listenSocket(listenSocket) {} 13 | 14 | SelectListenStrategy::~SelectListenStrategy() {} 15 | 16 | void SelectListenStrategy::Reset() { 17 | // Nothing to do. 18 | } 19 | 20 | void SelectListenStrategy::Prepare() { 21 | Reset(); 22 | } 23 | 24 | void SelectListenStrategy::Start() { 25 | // Nothing to do. 26 | } 27 | 28 | void SelectListenStrategy::Launch() { 29 | // Nothing to do. 30 | } 31 | 32 | bool SelectListenStrategy::IsBusy() const { 33 | return false; 34 | } 35 | 36 | void SelectListenStrategy::PostInput() { 37 | if (!m_canInput) { 38 | return; 39 | } 40 | 41 | Host peerHost; 42 | auto sockAddr = peerHost.SockAddr(); 43 | auto sockAddrLen = peerHost.SockAddrLen(); 44 | const auto& listenSockId = m_listenSocket.GetSockId(); 45 | while (true) { 46 | auto sockId = accept(listenSockId, sockAddr, &sockAddrLen); 47 | if (sockId == INVALID_SOCKID) { 48 | const auto error = SAGetLastError(); 49 | if (IsInterrupted(error)) { 50 | continue; 51 | } 52 | 53 | if (IsWouldBlock(error)) { 54 | m_canInput = false; 55 | break; 56 | } 57 | 58 | NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Error: socket close, error[%d]. [%s:%d]\n", error, __FILE__, __LINE__); 59 | m_listenSocket.Close(); 60 | m_listenSocket.OnError(error); 61 | break; 62 | } 63 | 64 | SetNonBlock(sockId); 65 | 66 | if (!m_listenSocket.OnAccepted(sockId, peerHost)) { 67 | DestroySockId(sockId); 68 | } 69 | } 70 | } 71 | 72 | void SelectListenStrategy::PostOutput() { 73 | // Nothing to do. 74 | } 75 | 76 | void SelectListenStrategy::EnableInput() { 77 | m_canInput = true; 78 | } 79 | 80 | void SelectListenStrategy::EnableOutput() { 81 | m_canOutput = true; 82 | } 83 | 84 | DECL_NAMESPACE_MZ_NET_END 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /Metazion/Net/SelectListenStrategy.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_SELECTLISTENSTRATEGY_HPP_ 2 | #define _MZ_NET_SELECTLISTENSTRATEGY_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #if defined(NETWORK_USE_SELECT_MODEL) 7 | 8 | #include "Metazion/Net/SelectStrategy.hpp" 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | class ListenSocket; 13 | 14 | class SelectListenStrategy final : public SelectStrategy { 15 | MZ_DISALLOW_COPY_AND_ASSIGN(SelectListenStrategy) 16 | 17 | private: 18 | ListenSocket& m_listenSocket; 19 | std::atomic m_canInput{ false }; 20 | std::atomic m_canOutput{ false }; 21 | 22 | public: 23 | SelectListenStrategy(ListenSocket& m_listenSocket); 24 | 25 | ~SelectListenStrategy(); 26 | 27 | void Reset() override final; 28 | 29 | void Prepare() override final; 30 | 31 | void Start() override final; 32 | 33 | void Launch() override final; 34 | 35 | bool IsBusy() const override final; 36 | 37 | void PostInput() override final; 38 | 39 | void PostOutput() override final; 40 | 41 | void EnableInput() override final; 42 | 43 | void EnableOutput() override final; 44 | 45 | bool ShouldCareAboutOutput() const override final; 46 | }; 47 | 48 | inline bool SelectListenStrategy::ShouldCareAboutOutput() const { 49 | return false; 50 | } 51 | 52 | DECL_NAMESPACE_MZ_NET_END 53 | 54 | #endif 55 | 56 | #endif // _MZ_NET_SELECTLISTENSTRATEGY_HPP_ 57 | -------------------------------------------------------------------------------- /Metazion/Net/SelectOperation.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_SELECTOPERATION_HPP_ 2 | #define _MZ_NET_SELECTOPERATION_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #if defined(NETWORK_USE_SELECT_MODEL) 7 | 8 | #include 9 | 10 | #include "Metazion/Net/SocketDefine.hpp" 11 | 12 | DECL_NAMESPACE_MZ_NET_BEGIN 13 | 14 | struct SelectOperation { 15 | enum Type { 16 | TYPE_ACCEPT = 1, 17 | TYPE_SEND, 18 | TYPE_RECV, 19 | }; 20 | 21 | Type m_type; 22 | std::atomic m_busy{ false }; 23 | 24 | SelectOperation(Type type) 25 | : m_type(type) {} 26 | 27 | void Reset() { 28 | m_busy = false; 29 | } 30 | 31 | bool IsBusy() const { 32 | return m_busy; 33 | } 34 | 35 | void SetBusy(bool busy) { 36 | m_busy = busy; 37 | } 38 | }; 39 | 40 | struct AcceptOperation final : public SelectOperation { 41 | char* m_buffer{ nullptr }; 42 | SockId_t m_sockId = INVALID_SOCKID; 43 | 44 | AcceptOperation() 45 | : SelectOperation(TYPE_ACCEPT) {} 46 | 47 | void Reset() { 48 | SelectOperation::Reset(); 49 | m_buffer = nullptr; 50 | m_sockId = INVALID_SOCKID; 51 | } 52 | }; 53 | 54 | struct SendOperation final : public SelectOperation { 55 | IOV_TYPE m_iov[NUMBER_SEND_IOV]; 56 | 57 | SendOperation() 58 | : SelectOperation(TYPE_SEND) {} 59 | 60 | void Reset() { 61 | SelectOperation::Reset(); 62 | memset(&m_iov, 0, sizeof(m_iov)); 63 | } 64 | }; 65 | 66 | struct RecvOperation final : public SelectOperation { 67 | IOV_TYPE m_iov[NUMBER_RECV_IOV]; 68 | 69 | RecvOperation() 70 | : SelectOperation(TYPE_RECV) {} 71 | 72 | void Reset() { 73 | SelectOperation::Reset(); 74 | memset(&m_iov, 0, sizeof(m_iov)); 75 | } 76 | }; 77 | 78 | DECL_NAMESPACE_MZ_NET_END 79 | 80 | #endif 81 | 82 | #endif // _MZ_NET_SELECTOPERATION_HPP_ 83 | -------------------------------------------------------------------------------- /Metazion/Net/SelectService.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/SelectService.hpp" 2 | 3 | #include "Metazion/Net/Socket.hpp" 4 | 5 | #if defined(NETWORK_USE_SELECT_MODEL) 6 | 7 | DECL_NAMESPACE_MZ_NET_BEGIN 8 | 9 | SelectService::SelectService() {} 10 | 11 | SelectService::~SelectService() {} 12 | 13 | bool SelectService::Initialize(int socketCapacity, int ioThreadNumber) { 14 | m_socketCapacity = socketCapacity; 15 | m_ioThreadNumber = ioThreadNumber; 16 | return true; 17 | } 18 | 19 | void SelectService::Finalize() {} 20 | 21 | bool SelectService::Associate(Socket* socket) { 22 | return true; 23 | } 24 | 25 | int SelectService::GetThreadIndex(int socketIndex) { 26 | const auto eachCount = (m_socketCapacity + m_ioThreadNumber - 1) / m_ioThreadNumber; 27 | return socketIndex / eachCount; 28 | } 29 | 30 | int SelectService::GetStartIndex(int threadIndex) const { 31 | const auto eachCount = (m_socketCapacity + m_ioThreadNumber - 1) / m_ioThreadNumber; 32 | return eachCount * threadIndex; 33 | } 34 | 35 | int SelectService::GetSocketCount(int threadIndex) const { 36 | const auto eachCount = (m_socketCapacity + m_ioThreadNumber - 1) / m_ioThreadNumber; 37 | const auto startIndex = eachCount * threadIndex; 38 | const auto restCount = m_socketCapacity - startIndex; 39 | return restCount < eachCount ? restCount : eachCount; 40 | } 41 | 42 | DECL_NAMESPACE_MZ_NET_END 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /Metazion/Net/SelectService.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_SELECTSERVICE_HPP_ 2 | #define _MZ_NET_SELECTSERVICE_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include "Metazion/Net/SocketDefine.hpp" 7 | 8 | #if defined(NETWORK_USE_SELECT_MODEL) 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | class Socket; 13 | 14 | class SelectService { 15 | MZ_DISALLOW_COPY_AND_ASSIGN(SelectService) 16 | 17 | private: 18 | int m_socketCapacity{ 0 }; 19 | int m_ioThreadNumber{ 0 }; 20 | 21 | public: 22 | SelectService(); 23 | 24 | ~SelectService(); 25 | 26 | bool Initialize(int socketCapacity, int ioThreadNumber); 27 | 28 | void Finalize(); 29 | 30 | bool Associate(Socket* socket); 31 | 32 | int GetThreadIndex(int socketIndex); 33 | 34 | int GetStartIndex(int threadIndex) const; 35 | 36 | int GetSocketCount(int threadIndex) const; 37 | }; 38 | 39 | DECL_NAMESPACE_MZ_NET_END 40 | 41 | #endif 42 | 43 | #endif // _MZ_NET_SELECTSERVICE_HPP_ 44 | -------------------------------------------------------------------------------- /Metazion/Net/SelectStrategy.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_SELECTSTRATEGY_HPP_ 2 | #define _MZ_NET_SELECTSTRATEGY_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #if defined(NETWORK_USE_SELECT_MODEL) 7 | 8 | #include "Metazion/Net/SelectOperation.hpp" 9 | 10 | DECL_NAMESPACE_MZ_NET_BEGIN 11 | 12 | class SelectStrategy { 13 | MZ_DISALLOW_COPY_AND_ASSIGN(SelectStrategy) 14 | 15 | public: 16 | SelectStrategy() {} 17 | 18 | virtual ~SelectStrategy() {} 19 | 20 | virtual void Reset() = 0; 21 | 22 | virtual void Prepare() = 0; 23 | 24 | virtual void Start() = 0; 25 | 26 | virtual void Launch() = 0; 27 | 28 | virtual bool IsBusy() const = 0; 29 | 30 | virtual void PostInput() = 0; 31 | 32 | virtual void PostOutput() = 0; 33 | 34 | virtual void EnableInput() = 0; 35 | 36 | virtual void EnableOutput() = 0; 37 | 38 | virtual bool ShouldCareAboutOutput() const = 0; 39 | }; 40 | 41 | DECL_NAMESPACE_MZ_NET_END 42 | 43 | #endif 44 | 45 | #endif // _MZ_NET_SELECTSTRATEGY_HPP_ 46 | -------------------------------------------------------------------------------- /Metazion/Net/SelectTransmitStrategy.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/SelectTransmitStrategy.hpp" 2 | 3 | #include 4 | 5 | #include "Metazion/Net/TransmitSocket.hpp" 6 | 7 | #if defined(NETWORK_USE_SELECT_MODEL) 8 | 9 | DECL_NAMESPACE_MZ_NET_BEGIN 10 | 11 | SelectTransmitStrategy::SelectTransmitStrategy(TransmitSocket& transmitSocket) 12 | : m_transmitSocket(transmitSocket) {} 13 | 14 | SelectTransmitStrategy::~SelectTransmitStrategy() {} 15 | 16 | void SelectTransmitStrategy::Reset() { 17 | m_canOutput = false; 18 | } 19 | 20 | void SelectTransmitStrategy::Prepare() { 21 | Reset(); 22 | } 23 | 24 | void SelectTransmitStrategy::Start() { 25 | // Nothing to do. 26 | } 27 | 28 | void SelectTransmitStrategy::Launch() { 29 | // Nothing to do. 30 | } 31 | 32 | bool SelectTransmitStrategy::IsBusy() const { 33 | return false; 34 | } 35 | 36 | void SelectTransmitStrategy::PostInput() { 37 | auto& socketBuffer = m_transmitSocket.TheSocketBuffer(); 38 | 39 | if (!m_canInput) { 40 | return; 41 | } 42 | 43 | const auto& transmitSockId = m_transmitSocket.GetSockId(); 44 | while (true) { 45 | const auto pushLength = socketBuffer.PrepareRecvPlan(); 46 | MZ_UNUSED_VARIABLE(pushLength); 47 | 48 | const auto count = socketBuffer.SetupRecvIov(m_recvOperation.m_iov); 49 | MZ_UNUSED_VARIABLE(count); 50 | 51 | auto buf = static_cast(m_recvOperation.m_iov[0].IOV_PTR_FIELD); 52 | auto len = static_cast(m_recvOperation.m_iov[0].IOV_LEN_FIELD); 53 | const auto recvLength = recv(transmitSockId, buf, len, 0); 54 | if (recvLength == 0) { 55 | NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Info: socket close. [%s:%d]\n", __FILE__, __LINE__); 56 | m_transmitSocket.Close(); 57 | break; 58 | } 59 | else if (recvLength < 0) { 60 | const auto error = SAGetLastError(); 61 | if (IsInterrupted(error)) { 62 | continue; 63 | } 64 | 65 | if (IsWouldBlock(error)) { 66 | m_canInput = false; 67 | break; 68 | } 69 | 70 | NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Error: socket close, error[%d]. [%s:%d]\n", error, __FILE__, __LINE__); 71 | m_transmitSocket.Close(); 72 | m_transmitSocket.OnError(error); 73 | break; 74 | } 75 | 76 | m_transmitSocket.OnRecved(nullptr, recvLength); 77 | 78 | const auto restLength = socketBuffer.PreserveRecvPlan(recvLength); 79 | if (restLength > 0) { 80 | NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Trace: socket close. [%s:%d]\n", __FILE__, __LINE__); 81 | m_transmitSocket.Disconnect(); 82 | } 83 | } 84 | } 85 | 86 | void SelectTransmitStrategy::PostOutput() { 87 | auto& socketBuffer = m_transmitSocket.TheSocketBuffer(); 88 | 89 | if (!m_canOutput) { 90 | return; 91 | } 92 | 93 | if (!m_transmitSocket.IsWorking()) { 94 | return; 95 | } 96 | 97 | if (!socketBuffer.HasDataToSend()) { 98 | return; 99 | } 100 | 101 | const auto& transmitSockId = m_transmitSocket.GetSockId(); 102 | while (true) { 103 | const auto pullLength = socketBuffer.PrepareSendPlan(); 104 | if (pullLength < 1) { 105 | break; 106 | } 107 | 108 | const auto count = socketBuffer.SetupSendIov(m_sendOperation.m_iov); 109 | MZ_UNUSED_VARIABLE(count); 110 | 111 | auto buf = static_cast(m_sendOperation.m_iov[0].IOV_PTR_FIELD); 112 | auto len = static_cast(m_sendOperation.m_iov[0].IOV_LEN_FIELD); 113 | const auto sendLength = send(transmitSockId, buf, len, 0); 114 | if (sendLength < 0) { 115 | const auto error = SAGetLastError(); 116 | if (IsInterrupted(error)) { 117 | continue; 118 | } 119 | 120 | if (IsWouldBlock(error)) { 121 | m_canOutput = false; 122 | break; 123 | } 124 | 125 | NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Error: socket close, error[%d]. [%s:%d]\n", error, __FILE__, __LINE__); 126 | m_transmitSocket.Close(); 127 | m_transmitSocket.OnError(error); 128 | break; 129 | } 130 | 131 | m_transmitSocket.OnSended(nullptr, sendLength); 132 | 133 | const auto restLength = socketBuffer.PreserveSendPlan(sendLength); 134 | MZ_UNUSED_VARIABLE(restLength); 135 | } 136 | } 137 | 138 | void SelectTransmitStrategy::EnableInput() { 139 | m_canInput = true; 140 | } 141 | 142 | void SelectTransmitStrategy::EnableOutput() { 143 | m_canOutput = true; 144 | } 145 | 146 | DECL_NAMESPACE_MZ_NET_END 147 | 148 | #endif 149 | -------------------------------------------------------------------------------- /Metazion/Net/SelectTransmitStrategy.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_SELECTTRANSMITSTRATEGY_HPP_ 2 | #define _MZ_NET_SELECTTRANSMITSTRATEGY_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #if defined(NETWORK_USE_SELECT_MODEL) 7 | 8 | #include 9 | 10 | #include "Metazion/Net/SelectStrategy.hpp" 11 | 12 | DECL_NAMESPACE_MZ_NET_BEGIN 13 | 14 | class TransmitSocket; 15 | 16 | class SelectTransmitStrategy final : public SelectStrategy { 17 | MZ_DISALLOW_COPY_AND_ASSIGN(SelectTransmitStrategy) 18 | 19 | private: 20 | TransmitSocket& m_transmitSocket; 21 | SendOperation m_sendOperation; 22 | RecvOperation m_recvOperation; 23 | std::atomic m_canInput{ false }; 24 | std::atomic m_canOutput{ false }; 25 | 26 | public: 27 | SelectTransmitStrategy(TransmitSocket& transmitSocket); 28 | 29 | ~SelectTransmitStrategy(); 30 | 31 | void Reset() override final; 32 | 33 | void Prepare() override final; 34 | 35 | void Start() override final; 36 | 37 | void Launch() override final; 38 | 39 | bool IsBusy() const override final; 40 | 41 | void PostInput() override final; 42 | 43 | void PostOutput() override final; 44 | 45 | void EnableInput() override final; 46 | 47 | void EnableOutput() override final; 48 | 49 | bool ShouldCareAboutOutput() const override final; 50 | }; 51 | 52 | inline bool SelectTransmitStrategy::ShouldCareAboutOutput() const { 53 | return !m_canOutput; 54 | } 55 | 56 | DECL_NAMESPACE_MZ_NET_END 57 | 58 | #endif 59 | 60 | #endif // _MZ_NET_SELECTTRANSMITSTRATEGY_HPP_ 61 | -------------------------------------------------------------------------------- /Metazion/Net/Socket.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/Socket.hpp" 2 | 3 | #include "Metazion/Share/Time/Time.hpp" 4 | 5 | DECL_NAMESPACE_MZ_NET_BEGIN 6 | 7 | Socket::Socket() {} 8 | 9 | Socket::~Socket() {} 10 | 11 | void Socket::Reset() { 12 | m_reference = 0; 13 | m_sockId = INVALID_SOCKID; 14 | m_index = -1; 15 | m_networkService = nullptr; 16 | m_keepInterval = 0; 17 | m_destroyCallback = [](Socket* socket) { delete socket; }; 18 | m_now = NS_MZ_SHARE::GetNowMillisecond(); 19 | m_working = false; 20 | m_gonnaClose = false; 21 | m_delayTime = 0; 22 | m_wannaClose = false; 23 | } 24 | 25 | void Socket::Prepare() { 26 | m_now = NS_MZ_SHARE::GetNowMillisecond(); 27 | m_working = false; 28 | m_gonnaClose = false; 29 | m_delayTime = 0; 30 | m_wannaClose = false; 31 | } 32 | 33 | void Socket::Tick(int64_t now, int interval) { 34 | m_now = now; 35 | if (m_wannaClose && m_delayTime >= 0) { 36 | m_delayTime -= interval; 37 | if (m_delayTime <= 0) { 38 | Shutdown(); 39 | m_delayTime = -1; 40 | } 41 | } 42 | } 43 | 44 | void Socket::Dispatch() {} 45 | 46 | void Socket::Retain() { 47 | ++m_reference; 48 | } 49 | 50 | void Socket::Release() { 51 | --m_reference; 52 | } 53 | 54 | void Socket::Destory() { 55 | m_destroyCallback(this); 56 | } 57 | 58 | void Socket::AttachSockId(const SockId_t& sockId) { 59 | m_sockId = sockId; 60 | } 61 | 62 | void Socket::DetachSockId() { 63 | if (m_sockId != INVALID_SOCKID) { 64 | DestroySockId(m_sockId); 65 | m_sockId = INVALID_SOCKID; 66 | } 67 | } 68 | 69 | void Socket::Disconnect(int delayTime) { 70 | if (!m_wannaClose) { 71 | m_delayTime = delayTime; 72 | m_wannaClose = true; 73 | } 74 | } 75 | 76 | void Socket::Shutdown() { 77 | if (m_sockId != INVALID_SOCKID) { 78 | ShutdownSockId(m_sockId, SHUT_WR); 79 | } 80 | } 81 | 82 | void Socket::Close() { 83 | m_working = false; 84 | m_gonnaClose = true; 85 | } 86 | 87 | void Socket::Start() { 88 | m_working = true; 89 | 90 | OnStart(); 91 | } 92 | 93 | void Socket::Stop() { 94 | OnStop(); 95 | 96 | DetachSockId(); 97 | m_gonnaClose = false; 98 | } 99 | 100 | DECL_NAMESPACE_MZ_NET_END 101 | -------------------------------------------------------------------------------- /Metazion/Net/Socket.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_SOCKET_HPP_ 2 | #define _MZ_NET_SOCKET_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include 7 | #include 8 | 9 | #include "Metazion/Net/AlternativeStrategy.hpp" 10 | #include "Metazion/Net/Host.hpp" 11 | #include "Metazion/Net/SocketDefine.hpp" 12 | 13 | DECL_NAMESPACE_MZ_NET_BEGIN 14 | 15 | class NetworkService; 16 | 17 | class Socket { 18 | MZ_DISALLOW_COPY_AND_ASSIGN(Socket) 19 | 20 | friend class NetworkService; 21 | friend class IoThread; 22 | friend class MaintenanceThread; 23 | 24 | using DestoryCallback_t = std::function; 25 | 26 | protected: 27 | std::atomic m_reference{ 0 }; 28 | SockId_t m_sockId{ INVALID_SOCKID }; 29 | int m_index{ -1 }; 30 | NetworkService* m_networkService{ nullptr }; 31 | int m_keepInterval{ 0 }; 32 | DestoryCallback_t m_destroyCallback{ nullptr }; 33 | 34 | int64_t m_now{ 0 }; 35 | std::atomic m_working{ false }; 36 | std::atomic m_gonnaClose{ false }; 37 | std::atomic m_delayTime{ 0 }; 38 | std::atomic m_wannaClose{ false }; 39 | 40 | public: 41 | Socket(); 42 | 43 | virtual ~Socket(); 44 | 45 | virtual void Reset(); 46 | 47 | virtual void Prepare(); 48 | 49 | virtual void Tick(int64_t now, int interval); 50 | 51 | virtual void Dispatch(); 52 | 53 | void Retain(); 54 | 55 | void Release(); 56 | 57 | void Destory(); 58 | 59 | const SockId_t& GetSockId() const; 60 | 61 | void AttachSockId(const SockId_t& sockId); 62 | 63 | void DetachSockId(); 64 | 65 | int GetIndex() const; 66 | 67 | NetworkService* GetNetworkService(); 68 | 69 | void SetKeepInterval(int interval); 70 | 71 | void SetDestroyCallback(DestoryCallback_t callback); 72 | 73 | void Disconnect(int delayTime = 0); 74 | 75 | bool IsWorking() const; 76 | 77 | bool IsGonnaClose() const; 78 | 79 | bool IsWannaClose() const; 80 | 81 | bool IsValid() const; 82 | 83 | bool IsActive() const; 84 | 85 | protected: 86 | virtual int GetType() const = 0; 87 | 88 | virtual bool IsAlive() const = 0; 89 | 90 | virtual bool KeepEnough() const = 0; 91 | 92 | virtual IoStrategy& TheIoStrategy() = 0; 93 | 94 | virtual void OnAttached() = 0; 95 | 96 | virtual void OnDetached() = 0; 97 | 98 | virtual void OnStart() = 0; 99 | 100 | virtual void OnStop() = 0; 101 | 102 | virtual void OnError(int error) = 0; 103 | 104 | void Shutdown(); 105 | 106 | void Close(); 107 | 108 | void Start(); 109 | 110 | void Stop(); 111 | 112 | private: 113 | void SetIndex(int index); 114 | 115 | void SetNetworkService(NetworkService* networkService); 116 | }; 117 | 118 | inline const SockId_t& Socket::GetSockId() const { 119 | return m_sockId; 120 | } 121 | 122 | inline int Socket::GetIndex() const { 123 | return m_index; 124 | } 125 | 126 | inline void Socket::SetIndex(int index) { 127 | m_index = index; 128 | } 129 | 130 | inline NetworkService* Socket::GetNetworkService() { 131 | return m_networkService; 132 | } 133 | 134 | inline void Socket::SetNetworkService(NetworkService* networkService) { 135 | m_networkService = networkService; 136 | } 137 | 138 | inline void Socket::SetKeepInterval(int interval) { 139 | m_keepInterval = interval; 140 | } 141 | 142 | inline void Socket::SetDestroyCallback(DestoryCallback_t callback) { 143 | m_destroyCallback = callback; 144 | } 145 | 146 | inline bool Socket::IsWorking() const { 147 | return m_working; 148 | } 149 | 150 | inline bool Socket::IsGonnaClose() const { 151 | return m_gonnaClose; 152 | } 153 | 154 | inline bool Socket::IsWannaClose() const { 155 | return m_wannaClose; 156 | } 157 | 158 | inline bool Socket::IsValid() const { 159 | return m_reference > 0; 160 | } 161 | 162 | inline bool Socket::IsActive() const { 163 | return m_sockId != INVALID_SOCKID; 164 | } 165 | 166 | DECL_NAMESPACE_MZ_NET_END 167 | 168 | #endif // _MZ_NET_SOCKET_HPP_ 169 | -------------------------------------------------------------------------------- /Metazion/Net/SocketBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/SocketBuffer.hpp" 2 | 3 | DECL_NAMESPACE_MZ_NET_BEGIN 4 | 5 | SocketBuffer::SocketBuffer() 6 | : m_sendCachePool(nullptr) 7 | , m_recvCachePool(nullptr) {} 8 | 9 | SocketBuffer::~SocketBuffer() {} 10 | 11 | void SocketBuffer::Reset() { 12 | m_sendCachePool = nullptr; 13 | m_recvCachePool = nullptr; 14 | m_sendCache.Reset(); 15 | m_recvCache.Reset(); 16 | m_sendPlan.Reset(); 17 | m_recvPlan.Reset(); 18 | } 19 | 20 | void SocketBuffer::Prepare() { 21 | m_sendCache.Reset(); 22 | m_sendCache.SetBufferPool(m_sendCachePool); 23 | m_recvCache.Reset(); 24 | m_recvCache.SetBufferPool(m_recvCachePool); 25 | m_sendPlan.Reset(); 26 | m_sendPlan.SetBufferPool(m_sendCachePool); 27 | m_recvPlan.Reset(); 28 | m_recvPlan.SetBufferPool(m_recvCachePool); 29 | } 30 | 31 | void SocketBuffer::SetSendBufferPool(SendCache_t::BufferPool_t& bufferPool) { 32 | m_sendCachePool = &bufferPool; 33 | m_sendCache.SetBufferPool(m_sendCachePool); 34 | m_sendPlan.SetBufferPool(m_sendCachePool); 35 | } 36 | 37 | void SocketBuffer::SetRecvCachePool(RecvCache_t::BufferPool_t& bufferPool) { 38 | m_recvCachePool = &bufferPool; 39 | m_recvCache.SetBufferPool(m_recvCachePool); 40 | m_recvPlan.SetBufferPool(m_recvCachePool); 41 | } 42 | 43 | int SocketBuffer::SetupSendIov(IOV_TYPE iovs[NUMBER_SEND_IOV]) { 44 | auto index = 0; 45 | m_sendPlan.Traverse([&](SendPlan_t::BufferNode_t* buffer) { 46 | const auto ptr = buffer->m_value.GetPullBuffer(); 47 | const auto len = buffer->m_value.GetPullLength(); 48 | if (len < 1) { 49 | return true; 50 | } 51 | 52 | iovs[index].IOV_PTR_FIELD = ptr; 53 | iovs[index].IOV_LEN_FIELD = len; 54 | return ++index >= NUMBER_SEND_IOV; 55 | }); 56 | return index; 57 | } 58 | 59 | int SocketBuffer::SetupRecvIov(IOV_TYPE iovs[NUMBER_RECV_IOV]) { 60 | auto index = 0; 61 | m_recvPlan.Traverse([&](SendPlan_t::BufferNode_t* buffer) { 62 | const auto ptr = buffer->m_value.GetPushBuffer(); 63 | const auto len = buffer->m_value.GetPushLength(); 64 | if (len < 1) { 65 | return true; 66 | } 67 | 68 | iovs[index].IOV_PTR_FIELD = ptr; 69 | iovs[index].IOV_LEN_FIELD = len; 70 | return ++index >= NUMBER_RECV_IOV; 71 | }); 72 | return index; 73 | } 74 | 75 | int SocketBuffer::PrepareSendPlan() { 76 | auto bufferNumber = m_sendPlan.GetStepSize(); 77 | auto bufferLength = m_sendPlan.GetCapLength(); 78 | 79 | m_sendLock.lock(); 80 | 81 | while (bufferNumber < NUMBER_SEND_IOV && bufferLength < LENGTH_SEND_MAX) { 82 | if (m_sendPlan.IsMaximal()) { 83 | break; 84 | } 85 | 86 | auto buffer = m_sendCache.Detach(); 87 | if (IsNull(buffer)) { 88 | break; 89 | } 90 | 91 | if (!m_sendPlan.Attach(buffer)) { 92 | break; 93 | } 94 | 95 | bufferNumber = m_sendPlan.GetStepSize(); 96 | bufferLength = m_sendPlan.GetCapLength(); 97 | } 98 | 99 | m_sendLock.unlock(); 100 | return bufferLength; 101 | } 102 | 103 | int SocketBuffer::PrepareRecvPlan() { 104 | auto bufferNumber = m_recvPlan.GetStepSize(); 105 | auto bufferLength = m_recvPlan.GetCapLength(); 106 | 107 | if (bufferNumber < NUMBER_RECV_IOV && bufferLength < LENGTH_RECV_MAX) { 108 | const auto expandLength = m_recvPlan.Expand(LENGTH_RECV_MAX); 109 | MZ_UNUSED_VARIABLE(expandLength); 110 | 111 | bufferNumber = m_recvPlan.GetStepSize(); 112 | bufferLength = m_recvPlan.GetCapLength(); 113 | } 114 | 115 | return bufferLength; 116 | } 117 | 118 | int SocketBuffer::PreserveSendPlan(int length) { 119 | m_sendPlan.Skip(length); 120 | 121 | auto bufferNumber = m_sendPlan.GetStepSize(); 122 | auto bufferLength = m_sendPlan.GetCurLength(); 123 | 124 | MZ_UNUSED_VARIABLE(bufferNumber); 125 | return bufferLength; 126 | } 127 | 128 | int SocketBuffer::PreserveRecvPlan(int length) { 129 | m_recvPlan.Take(length); 130 | 131 | auto bufferNumber = m_recvPlan.GetStepSize(); 132 | auto bufferLength = m_recvPlan.GetCurLength(); 133 | 134 | m_recvLock.lock(); 135 | 136 | while (bufferNumber > 0 && bufferLength > 0) { 137 | if (m_recvCache.IsMaximal()) { 138 | break; 139 | } 140 | 141 | auto buffer = m_recvPlan.Detach(); 142 | if (IsNull(buffer)) { 143 | break; 144 | } 145 | 146 | if (!m_recvCache.Attach(buffer)) { 147 | break; 148 | } 149 | 150 | bufferNumber = m_recvPlan.GetStepSize(); 151 | bufferLength = m_recvPlan.GetCurLength(); 152 | } 153 | 154 | m_recvLock.unlock(); 155 | return bufferLength; 156 | } 157 | 158 | bool SocketBuffer::HasDataToSend() const { 159 | if (m_sendPlan.GetCurLength() > 0) { 160 | return true; 161 | } 162 | 163 | if (m_sendCache.GetCurLength() > 0) { 164 | return true; 165 | } 166 | 167 | return false; 168 | } 169 | 170 | bool SocketBuffer::HasDataRecvedYet() const { 171 | if (m_recvCache.GetCurLength() > 0) { 172 | return true; 173 | } 174 | 175 | return false; 176 | } 177 | 178 | DECL_NAMESPACE_MZ_NET_END 179 | -------------------------------------------------------------------------------- /Metazion/Net/SocketBuffer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_TCPSOCKETBUFFER_HPP_ 2 | #define _MZ_NET_TCPSOCKETBUFFER_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include "Metazion/Net/SocketDefine.hpp" 12 | 13 | DECL_NAMESPACE_MZ_NET_BEGIN 14 | 15 | class SocketBuffer { 16 | MZ_DISALLOW_COPY_AND_ASSIGN(SocketBuffer) 17 | 18 | using Lock_t = std::mutex; 19 | using LockGuard_t = std::lock_guard; 20 | 21 | public: 22 | using SendCache_t = NS_SHARE::InputBuffer; 23 | using RecvCache_t = NS_SHARE::OutputBuffer; 24 | using SendPlan_t = NS_SHARE::OutputBuffer; 25 | using RecvPlan_t = NS_SHARE::InputBuffer; 26 | 27 | public: 28 | std::mutex m_sendLock; 29 | std::mutex m_recvLock; 30 | 31 | SendCache_t::BufferPool_t* m_sendCachePool; 32 | RecvCache_t::BufferPool_t* m_recvCachePool; 33 | 34 | SendCache_t m_sendCache; 35 | RecvCache_t m_recvCache; 36 | 37 | SendPlan_t m_sendPlan; 38 | RecvPlan_t m_recvPlan; 39 | 40 | public: 41 | SocketBuffer(); 42 | 43 | ~SocketBuffer(); 44 | 45 | void Reset(); 46 | 47 | void Prepare(); 48 | 49 | void SetSendBufferPool(SendCache_t::BufferPool_t& bufferPool); 50 | 51 | void SetRecvCachePool(SendCache_t::BufferPool_t& bufferPool); 52 | 53 | int SetupSendIov(IOV_TYPE iovs[NUMBER_SEND_IOV]); 54 | 55 | int SetupRecvIov(IOV_TYPE iovs[NUMBER_RECV_IOV]); 56 | 57 | int PrepareSendPlan(); 58 | 59 | int PrepareRecvPlan(); 60 | 61 | int PreserveSendPlan(int length); 62 | 63 | int PreserveRecvPlan(int length); 64 | 65 | bool HasDataToSend() const; 66 | 67 | bool HasDataRecvedYet() const; 68 | }; 69 | 70 | DECL_NAMESPACE_MZ_NET_END 71 | 72 | #endif // _MZ_NET_TCPSOCKETBUFFER_HPP_ 73 | -------------------------------------------------------------------------------- /Metazion/Net/SocketCtrl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_SOCKETCTRL_HPP_ 2 | #define _MZ_NET_SOCKETCTRL_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | DECL_NAMESPACE_MZ_NET_BEGIN 7 | 8 | class Socket; 9 | 10 | struct SocketCtrl { 11 | Socket* m_socket{ nullptr }; 12 | bool m_active{ false }; 13 | }; 14 | 15 | DECL_NAMESPACE_MZ_NET_END 16 | 17 | #endif // _MZ_NET_SOCKETCTRL_HPP_ 18 | -------------------------------------------------------------------------------- /Metazion/Net/SocketDefine.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/SocketDefine.hpp" 2 | 3 | DECL_NAMESPACE_MZ_NET_BEGIN 4 | 5 | SockId_t CreateSockId(int transportType) { 6 | const auto sockStream = transportType == TRANSPORT_TCP ? SOCK_STREAM : SOCK_DGRAM; 7 | 8 | #if defined(MZ_PLATFORM_WINDOWS) 9 | auto sockId = WSASocket(AF_INET, sockStream, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED); 10 | #endif 11 | 12 | #if defined(MZ_PLATFORM_LINUX) || defined(MZ_PLATFORM_MACOS) 13 | auto sockId = socket(AF_INET, sockStream, IPPROTO_IP); 14 | #endif 15 | 16 | if (sockId != INVALID_SOCKID) { 17 | SetNonBlock(sockId); 18 | } 19 | 20 | return sockId; 21 | } 22 | 23 | void DestroySockId(SockId_t sockId) { 24 | #if defined(MZ_PLATFORM_WINDOWS) 25 | closesocket(sockId); 26 | #endif 27 | 28 | #if defined(MZ_PLATFORM_LINUX) || defined(MZ_PLATFORM_MACOS) 29 | close(sockId); 30 | #endif 31 | } 32 | 33 | void ShutdownSockId(SockId_t sockId, int how) { 34 | shutdown(sockId, how); 35 | } 36 | 37 | bool SetNonBlock(SockId_t sockId) { 38 | #if defined(MZ_PLATFORM_WINDOWS) 39 | u_long ul = 1; 40 | return 0 == ioctlsocket(sockId, FIONBIO, &ul); 41 | #endif 42 | 43 | #if defined(MZ_PLATFORM_LINUX) || defined(MZ_PLATFORM_MACOS) 44 | auto oldFlags = fcntl(sockId, F_GETFL); 45 | if (oldFlags == -1) { 46 | oldFlags = 0; 47 | } 48 | return 0 == fcntl(sockId, F_SETFL, oldFlags | O_NONBLOCK); 49 | #endif 50 | } 51 | 52 | int GetSockOpt(SockId_t sockId 53 | , int level 54 | , int optname 55 | , void* optval 56 | , SockLen_t* optlen) { 57 | #if defined(MZ_PLATFORM_WINDOWS) 58 | return getsockopt(sockId, level, optname, static_cast(optval), optlen); 59 | #endif 60 | 61 | #if defined(MZ_PLATFORM_LINUX) || defined(MZ_PLATFORM_MACOS) 62 | return getsockopt(sockId, level, optname, optval, optlen); 63 | #endif 64 | } 65 | 66 | int SetSockOpt(SockId_t sockId 67 | , int level 68 | , int optname 69 | , const void* optval 70 | , SockLen_t optlen) { 71 | #if defined(MZ_PLATFORM_WINDOWS) 72 | return setsockopt(sockId, level, optname, static_cast(optval), optlen); 73 | #endif 74 | 75 | #if defined(MZ_PLATFORM_LINUX) || defined(MZ_PLATFORM_MACOS) 76 | return setsockopt(sockId, level, optname, optval, optlen); 77 | #endif 78 | } 79 | 80 | int CheckSockConnected(SockId_t sockId) { 81 | #if defined(MZ_PLATFORM_WINDOWS) 82 | fd_set wfds; 83 | FD_ZERO(&wfds); 84 | FD_SET(sockId, &wfds); 85 | 86 | fd_set efds; 87 | FD_ZERO(&efds); 88 | FD_SET(sockId, &efds); 89 | 90 | struct timeval timeout { 0, 0 }; 91 | const auto nfds = static_cast(sockId + 1); 92 | const auto ret = select(nfds, nullptr, &wfds, &efds, &timeout); 93 | if (ret == 0) { 94 | return 0; 95 | } 96 | else if (ret < 0) { 97 | return -1; 98 | } 99 | 100 | if (FD_ISSET(sockId, &efds)) { 101 | return -1; 102 | } 103 | 104 | if (!FD_ISSET(sockId, &wfds)) { 105 | return -1; 106 | } 107 | #endif 108 | 109 | #if defined(MZ_PLATFORM_LINUX) || defined(MZ_PLATFORM_MACOS) 110 | struct pollfd pfd; 111 | memset(&pfd, 0, sizeof(pfd)); 112 | pfd.fd = sockId; 113 | pfd.events |= POLLOUT; 114 | 115 | const auto ret = poll(&pfd, 1, 0); 116 | if (ret == 0) { 117 | return 0; 118 | } 119 | else if (ret < 0) { 120 | return -1; 121 | } 122 | 123 | if ((pfd.revents & POLLOUT) == 0) { 124 | return -1; 125 | } 126 | #endif 127 | 128 | return 1; 129 | } 130 | 131 | int SAGetLastError() { 132 | #if defined(MZ_PLATFORM_WINDOWS) 133 | return WSAGetLastError(); 134 | #endif 135 | 136 | #if defined(MZ_PLATFORM_LINUX) || defined(MZ_PLATFORM_MACOS) 137 | return errno; 138 | #endif 139 | } 140 | 141 | bool IsInterrupted(int error) { 142 | #if defined(MZ_PLATFORM_WINDOWS) 143 | return false; 144 | #endif 145 | 146 | #if defined(MZ_PLATFORM_LINUX) || defined(MZ_PLATFORM_MACOS) 147 | return error == EINTR; 148 | #endif 149 | } 150 | 151 | bool IsWouldBlock(int error) { 152 | #if defined(MZ_PLATFORM_WINDOWS) 153 | return error == WSAEWOULDBLOCK; 154 | #endif 155 | 156 | #if defined(MZ_PLATFORM_LINUX) || defined(MZ_PLATFORM_MACOS) 157 | return error == EAGAIN || error == EWOULDBLOCK; 158 | #endif 159 | } 160 | 161 | bool IsConnectWouldBlock(int error) { 162 | #if defined(MZ_PLATFORM_WINDOWS) 163 | return error == WSAEWOULDBLOCK; 164 | #endif 165 | 166 | #if defined(MZ_PLATFORM_LINUX) || defined(MZ_PLATFORM_MACOS) 167 | return error == EINPROGRESS; 168 | #endif 169 | } 170 | 171 | DECL_NAMESPACE_MZ_NET_END 172 | -------------------------------------------------------------------------------- /Metazion/Net/SocketDefine.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_SOCKETDEFINE_HPP_ 2 | #define _MZ_NET_SOCKETDEFINE_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #if defined(MZ_PLATFORM_WINDOWS) 7 | #include 8 | #include 9 | #include 10 | #pragma comment(lib, "ws2_32.lib") 11 | #pragma comment(lib, "mswsock.lib") 12 | #endif 13 | 14 | #if defined(MZ_PLATFORM_LINUX) 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #endif 23 | 24 | #if defined(MZ_PLATFORM_MACOS) 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #endif 33 | 34 | DECL_NAMESPACE_MZ_NET_BEGIN 35 | 36 | #if defined(MZ_PLATFORM_WINDOWS) 37 | typedef SOCKET SockId_t; 38 | typedef int SockLen_t; 39 | # define INVALID_SOCKID INVALID_SOCKET 40 | # define SHUT_RD SD_SEND 41 | # define SHUT_WR SD_RECEIVE 42 | # define SHUT_RDWR SD_BOTH 43 | 44 | # define IOV_TYPE WSABUF 45 | # define IOV_PTR_FIELD buf 46 | # define IOV_LEN_FIELD len 47 | # define IOV_LEN_TYPE ULONG 48 | 49 | # define SINGLE_BUFFER_LENGTH 512 50 | # define SINGLE_BUFFER_SIZE 8192 51 | 52 | # define NUMBER_SEND_IOV 16 53 | # define NUMBER_RECV_IOV 16 54 | #endif 55 | 56 | #if defined(MZ_PLATFORM_LINUX) 57 | typedef int SockId_t; 58 | typedef socklen_t SockLen_t; 59 | # define INVALID_SOCKID (-1) 60 | # define SOCKET_ERROR (-1) 61 | 62 | # define IOV_TYPE struct iovec 63 | # define IOV_PTR_FIELD iov_base 64 | # define IOV_LEN_FIELD iov_len 65 | # define IOV_LEN_TYPE size_t 66 | 67 | # define SINGLE_BUFFER_LENGTH 512 68 | # define SINGLE_BUFFER_SIZE 8192 69 | 70 | # define NUMBER_SEND_IOV 16 71 | # define NUMBER_RECV_IOV 16 72 | #endif 73 | 74 | #if defined(MZ_PLATFORM_MACOS) 75 | typedef int SockId_t; 76 | typedef socklen_t SockLen_t; 77 | # define INVALID_SOCKID (-1) 78 | # define SOCKET_ERROR (-1) 79 | 80 | # define IOV_TYPE struct iovec 81 | # define IOV_PTR_FIELD iov_base 82 | # define IOV_LEN_FIELD iov_len 83 | # define IOV_LEN_TYPE size_t 84 | 85 | # define SINGLE_BUFFER_LENGTH 512 86 | # define SINGLE_BUFFER_SIZE 1024 87 | 88 | # define NUMBER_SEND_IOV 1 89 | # define NUMBER_RECV_IOV 1 90 | #endif 91 | 92 | #define LENGTH_SEND_MAX 4096 93 | #define LENGTH_RECV_MAX 4096 94 | 95 | enum TansportType { 96 | TRANSPORT_TCP = 1, 97 | TRANSPORT_UDP, 98 | }; 99 | 100 | enum SocketType { 101 | SOCKET_TCP_LISTEN = 1, 102 | SOCKET_TCP_SERVER, 103 | SOCKET_TCP_CLIENT, 104 | }; 105 | 106 | typedef struct sockaddr SockAddr_t; 107 | typedef struct sockaddr_in SockAddrIn_t; 108 | 109 | SockId_t CreateSockId(int transportType); 110 | 111 | void DestroySockId(SockId_t sockId); 112 | 113 | void ShutdownSockId(SockId_t sockId, int how); 114 | 115 | bool SetNonBlock(SockId_t sockId); 116 | 117 | int GetSockOpt(SockId_t sockId 118 | , int level 119 | , int optname 120 | , void* optval 121 | , SockLen_t* optlen); 122 | 123 | int SetSockOpt(SockId_t sockId 124 | , int level 125 | , int optname 126 | , const void* optval 127 | , SockLen_t optlen); 128 | 129 | int CheckSockConnected(SockId_t sockId); 130 | 131 | int SAGetLastError(); 132 | 133 | bool IsInterrupted(int error); 134 | 135 | bool IsWouldBlock(int error); 136 | 137 | bool IsConnectWouldBlock(int error); 138 | 139 | DECL_NAMESPACE_MZ_NET_END 140 | 141 | #endif // _MZ_NET_SOCKETDEFINE_HPP_ 142 | -------------------------------------------------------------------------------- /Metazion/Net/TransmitSocket.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Net/TransmitSocket.hpp" 2 | 3 | #include 4 | #include 5 | 6 | #include "Metazion/Net/NetworkService.hpp" 7 | 8 | DECL_NAMESPACE_MZ_NET_BEGIN 9 | 10 | TransmitSocket::TransmitSocket() 11 | : m_transmitStrategy(*this) {} 12 | 13 | TransmitSocket::~TransmitSocket() {} 14 | 15 | void TransmitSocket::Reset() { 16 | Socket::Reset(); 17 | 18 | m_transmitStrategy.Reset(); 19 | m_socketBuffer.Reset(); 20 | m_remoteHost.Reset(); 21 | 22 | m_connectedTime = 0; 23 | m_disconnectedTime = 0; 24 | m_firstSendTime = 0; 25 | m_lastSendTime = 0; 26 | m_sendedBytes = 0; 27 | m_firstRecvTime = 0; 28 | m_lastRecvTime = 0; 29 | m_recvedBytes = 0; 30 | } 31 | 32 | void TransmitSocket::Prepare() { 33 | Socket::Prepare(); 34 | 35 | m_socketBuffer.Prepare(); 36 | m_transmitStrategy.Prepare(); 37 | } 38 | 39 | bool TransmitSocket::IsAlive() const { 40 | auto ret = IsValid(); 41 | if (ret) { 42 | return true; 43 | } 44 | 45 | ret = m_transmitStrategy.IsBusy(); 46 | if (ret) { 47 | return true; 48 | } 49 | 50 | return false; 51 | } 52 | 53 | bool TransmitSocket::KeepEnough() const { 54 | if (m_keepInterval <= 0) { 55 | return false; 56 | } 57 | 58 | const auto now = m_now; 59 | const auto lastRecvTime = m_lastRecvTime > 0 ? m_lastRecvTime : now; 60 | const auto interval = now - lastRecvTime; 61 | return interval > m_keepInterval; 62 | } 63 | 64 | void TransmitSocket::OnAttached() { 65 | auto networkService = GetNetworkService(); 66 | MZ_ASSERT_TRUE(!IsNull(networkService)); 67 | 68 | auto& sendBufferPool = networkService->GetSendCachePool(); 69 | m_socketBuffer.SetSendBufferPool(sendBufferPool); 70 | 71 | auto& recvBufferPool = networkService->GetRecvCachePool(); 72 | m_socketBuffer.SetRecvCachePool(recvBufferPool); 73 | } 74 | 75 | void TransmitSocket::OnDetached() {} 76 | 77 | void TransmitSocket::OnStart() { 78 | m_transmitStrategy.Start(); 79 | 80 | OnConnected(); 81 | } 82 | 83 | void TransmitSocket::OnStop() { 84 | OnDisconnected(); 85 | } 86 | 87 | void TransmitSocket::OnError(int error) {} 88 | 89 | int TransmitSocket::Send(const void* data, int length) { 90 | if (!IsWorking()) { 91 | return 0; 92 | } 93 | 94 | m_socketBuffer.m_sendLock.lock(); 95 | const auto pushLength = m_socketBuffer.m_sendCache.Push(data, length); 96 | m_socketBuffer.m_sendLock.unlock(); 97 | 98 | if (pushLength < length) { 99 | NS_SHARE::Log(MZ_LOG_DEBUG, "Socket Trace: socket close. [%s:%d]\n", __FILE__, __LINE__); 100 | Disconnect(); 101 | return 0; 102 | } 103 | 104 | m_transmitStrategy.Launch(); 105 | return pushLength; 106 | } 107 | 108 | void TransmitSocket::OnConnected() { 109 | m_connectedTime = m_now; 110 | } 111 | 112 | void TransmitSocket::OnDisconnected() { 113 | m_disconnectedTime = m_now; 114 | } 115 | 116 | void TransmitSocket::OnSended(const void* data, int length) { 117 | const auto now = m_now; 118 | if (m_firstSendTime == 0) { 119 | m_firstSendTime = now; 120 | } 121 | 122 | m_lastSendTime = now; 123 | m_sendedBytes += length; 124 | } 125 | 126 | void TransmitSocket::OnRecved(const void* data, int length) { 127 | const auto now = m_now; 128 | if (m_firstRecvTime == 0) { 129 | m_firstRecvTime = now; 130 | } 131 | 132 | m_lastRecvTime = now; 133 | m_recvedBytes += length; 134 | } 135 | 136 | DECL_NAMESPACE_MZ_NET_END 137 | -------------------------------------------------------------------------------- /Metazion/Net/TransmitSocket.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_NET_TRANSMITSOCKET_HPP_ 2 | #define _MZ_NET_TRANSMITSOCKET_HPP_ 3 | 4 | #include "Metazion/Net/NetInclude.hpp" 5 | 6 | #include "Metazion/Net/Socket.hpp" 7 | #include "Metazion/Net/SocketBuffer.hpp" 8 | 9 | DECL_NAMESPACE_MZ_NET_BEGIN 10 | 11 | class TransmitSocket : public Socket { 12 | MZ_DISALLOW_COPY_AND_ASSIGN(TransmitSocket) 13 | 14 | friend class TransmitStrategy; 15 | 16 | protected: 17 | TransmitStrategy m_transmitStrategy; 18 | SocketBuffer m_socketBuffer; 19 | Host m_remoteHost; 20 | 21 | int64_t m_connectedTime{ 0 }; 22 | int64_t m_disconnectedTime{ 0 }; 23 | int64_t m_firstSendTime{ 0 }; 24 | int64_t m_lastSendTime{ 0 }; 25 | int64_t m_sendedBytes{ 0 }; 26 | int64_t m_firstRecvTime{ 0 }; 27 | int64_t m_lastRecvTime{ 0 }; 28 | int64_t m_recvedBytes{ 0 }; 29 | 30 | public: 31 | TransmitSocket(); 32 | 33 | virtual ~TransmitSocket(); 34 | 35 | void Reset() override; 36 | 37 | void Prepare() override; 38 | 39 | bool IsAlive() const override final; 40 | 41 | bool KeepEnough() const override final; 42 | 43 | IoStrategy& TheIoStrategy() override final; 44 | 45 | void OnAttached() override final; 46 | 47 | void OnDetached() override final; 48 | 49 | void OnStart() override final; 50 | 51 | void OnStop() override final; 52 | 53 | void OnError(int error) override final; 54 | 55 | int Send(const void* data, int length); 56 | 57 | SocketBuffer& TheSocketBuffer(); 58 | 59 | Host& GetRemoteHost(); 60 | 61 | void SetRemoteHost(const Host& host); 62 | 63 | protected: 64 | virtual void OnConnected(); 65 | 66 | virtual void OnDisconnected(); 67 | 68 | virtual void OnSended(const void* data, int length); 69 | 70 | virtual void OnRecved(const void* data, int length); 71 | }; 72 | 73 | inline IoStrategy& TransmitSocket::TheIoStrategy() { 74 | return m_transmitStrategy; 75 | } 76 | 77 | inline SocketBuffer& TransmitSocket::TheSocketBuffer() { 78 | return m_socketBuffer; 79 | } 80 | 81 | inline Host& TransmitSocket::GetRemoteHost() { 82 | return m_remoteHost; 83 | } 84 | 85 | inline void TransmitSocket::SetRemoteHost(const Host& host) { 86 | m_remoteHost = host; 87 | } 88 | 89 | DECL_NAMESPACE_MZ_NET_END 90 | 91 | #endif // _MZ_NET_TRANSMITSOCKET_HPP_ 92 | -------------------------------------------------------------------------------- /Metazion/Overall.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_OVERALL_HPP_ 2 | #define _MZ_OVERALL_HPP_ 3 | 4 | #include "Metazion/Type.hpp" 5 | #include "Metazion/Define.hpp" 6 | #include "Metazion/Function.hpp" 7 | 8 | #endif // _MZ_OVERALL_HPP_ 9 | -------------------------------------------------------------------------------- /Metazion/Platform.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_PLATFORM_HPP_ 2 | #define _MZ_PLATFORM_HPP_ 3 | 4 | // Current Platform 5 | #if defined(_WIN32) 6 | # define MZ_PLATFORM_WINDOWS 7 | #elif defined(__linux__ ) 8 | # define MZ_PLATFORM_LINUX 9 | #elif defined(__APPLE__) 10 | # define MZ_PLATFORM_MACOS 11 | #else 12 | # define MZ_PLATFORM_OTHER 13 | #endif 14 | 15 | // Current Mode 16 | #if defined(_DEBUG) 17 | # define MZ_MODE_DEBUG 18 | #else 19 | # define MZ_MODE_RELEASE 20 | #endif 21 | 22 | // Platform Dependent 23 | #if defined(MZ_PLATFORM_WINDOWS) 24 | # if defined(MZ_EXPORT_LIB) 25 | # define MZEXPORT _declspec(dllexport) 26 | # else 27 | # define MZEXPORT _declspec(dllimport) 28 | # endif 29 | #else 30 | # if defined(MZ_EXPORT_LIB) 31 | # define MZEXPORT 32 | # else 33 | # define MZEXPORT 34 | # endif 35 | #endif 36 | 37 | // Platform Headers 38 | #if defined(MZ_PLATFORM_WINDOWS) 39 | # define WIN32_LEAN_AND_MEAN 40 | # include 41 | #endif 42 | 43 | #if defined(MZ_PLATFORM_LINUX) 44 | # include 45 | # include 46 | # include 47 | # include 48 | # include 49 | # include 50 | # include 51 | # include 52 | # include 53 | #endif 54 | 55 | #if defined(MZ_PLATFORM_MACOS) 56 | # include 57 | # include 58 | # include 59 | # include 60 | # include 61 | # include 62 | # include 63 | # include 64 | #endif 65 | 66 | #include 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | #include 73 | #include 74 | 75 | #endif // _MZ_PLATFORM_HPP_ 76 | -------------------------------------------------------------------------------- /Metazion/Share/Algorithm/StringHash.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_STRINGHASH_HPP_ 2 | #define _MZ_SHARE_STRINGHASH_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | DECL_NAMESPACE_MZ_SHARE_BEGIN 7 | 8 | int32_t BKDRHash(const char* str) { 9 | uint32_t seed = 131; 10 | uint32_t hash = 0; 11 | 12 | while (*str != '\0') { 13 | hash = hash * seed + (*str++); 14 | } 15 | 16 | return hash & 0x7FFFFFFF; 17 | } 18 | 19 | int32_t APHash(const char* str) { 20 | uint32_t hash = 0; 21 | 22 | for (auto i = 0; *str!= '\0'; ++i) { 23 | if ((i & 1) == 0) { 24 | hash ^= ((hash << 7) ^ (*str++) ^ (hash >> 3)); 25 | } 26 | else { 27 | hash ^= (~((hash << 11) ^ (*str++) ^ (hash >> 5))); 28 | } 29 | } 30 | 31 | return hash & 0x7FFFFFFF; 32 | } 33 | 34 | int32_t DJBHash(const char* str) { 35 | uint32_t hash = 5381; 36 | 37 | while (*str != '\0') { 38 | hash += (hash << 5) + (*str++); 39 | } 40 | 41 | return hash & 0x7FFFFFFF; 42 | } 43 | 44 | int32_t JSHash(const char* str) { 45 | uint32_t hash = 1315423911; 46 | 47 | while (*str != '\0') { 48 | hash ^= ((hash << 5) + (*str++) + (hash >> 2)); 49 | } 50 | 51 | return hash & 0x7FFFFFFF; 52 | } 53 | 54 | int32_t RSHash(const char* str) { 55 | uint32_t b = 378551; 56 | uint32_t a = 63689; 57 | uint32_t hash = 0; 58 | 59 | while (*str != '\0') { 60 | hash = hash * a + (*str++); 61 | a *= b; 62 | } 63 | 64 | return hash & 0x7FFFFFFF; 65 | } 66 | 67 | int32_t SDBMHash(const char* str) { 68 | uint32_t hash = 0; 69 | 70 | while (*str != '\0') { 71 | hash = (*str++) + (hash << 6) + (hash << 16) - hash; 72 | } 73 | 74 | return hash & 0x7FFFFFFF; 75 | } 76 | 77 | DECL_NAMESPACE_MZ_SHARE_END 78 | 79 | #endif // _MZ_SHARE_STRINGHASH_HPP_ 80 | -------------------------------------------------------------------------------- /Metazion/Share/Async/AsyncService.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Share/Async/AsyncService.hpp" 2 | 3 | DECL_NAMESPACE_MZ_SHARE_BEGIN 4 | 5 | AsyncService::AsyncService() {} 6 | 7 | AsyncService::~AsyncService() {} 8 | 9 | bool AsyncService::Initialize(int threadSize) { 10 | m_threadSize = threadSize; 11 | m_asyncThreads = new AsyncThread*[m_threadSize]; 12 | for (auto index = 0; index < m_threadSize; ++index) { 13 | m_asyncThreads[index] = new AsyncThread(*this); 14 | m_asyncThreads[index]->Initialize(); 15 | } 16 | 17 | return true; 18 | } 19 | 20 | void AsyncService::Finalize() { 21 | m_stopDesired = true; 22 | for (auto index = 0; index < m_threadSize; ++index) { 23 | m_asyncThreads[index]->WannaStop(); 24 | } 25 | m_asyncCond.notify_all(); 26 | 27 | for (auto index = 0; index < m_threadSize; ++index) { 28 | m_asyncThreads[index]->Finalize(); 29 | SafeDelete(m_asyncThreads[index]); 30 | } 31 | SafeDeleteArray(m_asyncThreads); 32 | m_threadSize = 0; 33 | } 34 | 35 | void AsyncService::Push(Async_t async) { 36 | std::unique_lock lock(m_asyncMutex); 37 | m_asyncQueue.push(async); 38 | m_asyncCond.notify_one(); 39 | } 40 | 41 | AsyncService::Async_t AsyncService::Pop() { 42 | std::unique_lock lock(m_asyncMutex); 43 | m_asyncCond.wait(lock, [this] { 44 | return !m_asyncQueue.empty() || m_stopDesired; 45 | }); 46 | 47 | Async_t async{ nullptr }; 48 | if (!m_asyncQueue.empty()) { 49 | async = m_asyncQueue.front(); 50 | m_asyncQueue.pop(); 51 | } 52 | return async; 53 | } 54 | 55 | DECL_NAMESPACE_MZ_SHARE_END 56 | -------------------------------------------------------------------------------- /Metazion/Share/Async/AsyncService.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_ASYNCSERVICE_HPP_ 2 | #define _MZ_SHARE_ASYNCSERVICE_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "Metazion/Share/Async/AsyncThread.hpp" 13 | 14 | DECL_NAMESPACE_MZ_SHARE_BEGIN 15 | 16 | class AsyncService { 17 | MZ_DISALLOW_COPY_AND_ASSIGN(AsyncService) 18 | 19 | using Async_t = std::function; 20 | using AsyncQueue_t = std::queue; 21 | 22 | private: 23 | AsyncThread** m_asyncThreads{ nullptr }; 24 | int m_threadSize{ 0 }; 25 | std::atomic m_stopDesired{ false }; 26 | 27 | std::mutex m_asyncMutex; 28 | std::condition_variable m_asyncCond; 29 | AsyncQueue_t m_asyncQueue; 30 | 31 | public: 32 | AsyncService(); 33 | 34 | ~AsyncService(); 35 | 36 | bool Initialize(int threadSize); 37 | 38 | void Finalize(); 39 | 40 | void Push(Async_t async); 41 | 42 | Async_t Pop(); 43 | }; 44 | 45 | DECL_NAMESPACE_MZ_SHARE_END 46 | 47 | #endif // _MZ_SHARE_ASYNCSERVICE_HPP_ 48 | -------------------------------------------------------------------------------- /Metazion/Share/Async/AsyncThread.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Share/Async/AsyncThread.hpp" 2 | 3 | #include "Metazion/Share/Async/AsyncService.hpp" 4 | 5 | DECL_NAMESPACE_MZ_SHARE_BEGIN 6 | 7 | AsyncThread::AsyncThread(AsyncService& asyncService) 8 | : m_asyncService(asyncService) {} 9 | 10 | AsyncThread::~AsyncThread() {} 11 | 12 | bool AsyncThread::Initialize() { 13 | m_thread = std::thread(&AsyncThread::ThreadFunc, this); 14 | m_stopDesired = false; 15 | return true; 16 | } 17 | 18 | void AsyncThread::Finalize() { 19 | m_stopDesired = true; 20 | if (m_thread.joinable()) { 21 | m_thread.join(); 22 | } 23 | } 24 | 25 | void AsyncThread::WannaStop() { 26 | m_stopDesired = true; 27 | } 28 | 29 | void AsyncThread::ThreadFunc() { 30 | while (!m_stopDesired) { 31 | const auto async = m_asyncService.Pop(); 32 | if (async != nullptr) { 33 | async(); 34 | } 35 | } 36 | } 37 | 38 | DECL_NAMESPACE_MZ_SHARE_END 39 | -------------------------------------------------------------------------------- /Metazion/Share/Async/AsyncThread.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_ASYNCTHREAD_HPP_ 2 | #define _MZ_SHARE_ASYNCTHREAD_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | #include 7 | #include 8 | 9 | DECL_NAMESPACE_MZ_SHARE_BEGIN 10 | 11 | class AsyncService; 12 | 13 | class AsyncThread { 14 | MZ_DISALLOW_COPY_AND_ASSIGN(AsyncThread) 15 | 16 | private: 17 | AsyncService& m_asyncService; 18 | std::thread m_thread; 19 | std::atomic m_stopDesired{ false }; 20 | 21 | public: 22 | AsyncThread(AsyncService& asyncService); 23 | 24 | ~AsyncThread(); 25 | 26 | bool Initialize(); 27 | 28 | void Finalize(); 29 | 30 | void WannaStop(); 31 | 32 | private: 33 | void ThreadFunc(); 34 | }; 35 | 36 | DECL_NAMESPACE_MZ_SHARE_END 37 | 38 | #endif // _MZ_SHARE_ASYNCTHREAD_HPP_ 39 | -------------------------------------------------------------------------------- /Metazion/Share/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | FILE(GLOB METAZION_SHARE_HEADERS "./*.hpp") 2 | FILE(GLOB METAZION_SHARE_SOURCES "./*.cpp") 3 | 4 | FILE(GLOB METAZION_SHARE_ALGORITHM_HEADERS "Algorithm/*.hpp") 5 | FILE(GLOB METAZION_SHARE_ALGORITHM_SOURCES "Algorithm/*.cpp") 6 | 7 | FILE(GLOB METAZION_SHARE_ASYNC_HEADERS "Async/*.hpp") 8 | FILE(GLOB METAZION_SHARE_ASYNC_SOURCES "Async/*.cpp") 9 | 10 | FILE(GLOB METAZION_SHARE_COLLECTION_HEADERS "Collection/*.hpp") 11 | FILE(GLOB METAZION_SHARE_COLLECTION_SOURCES "Collection/*.cpp") 12 | 13 | FILE(GLOB METAZION_SHARE_LOG_HEADERS "Log/*.hpp") 14 | FILE(GLOB METAZION_SHARE_LOG_SOURCES "Log/*.cpp") 15 | 16 | FILE(GLOB METAZION_SHARE_MEMORY_HEADERS "Memory/*.hpp") 17 | FILE(GLOB METAZION_SHARE_MEMORY_SOURCES "Memory/*.cpp") 18 | 19 | FILE(GLOB METAZION_SHARE_MISC_HEADERS "Misc/*.hpp") 20 | FILE(GLOB METAZION_SHARE_MISC_SOURCES "Misc/*.cpp") 21 | 22 | FILE(GLOB METAZION_SHARE_PATTERN_HEADERS "Pattern/*.hpp") 23 | FILE(GLOB METAZION_SHARE_PATTERN_SOURCES "Pattern/*.cpp") 24 | 25 | FILE(GLOB METAZION_SHARE_SYNC_HEADERS "Sync/*.hpp") 26 | FILE(GLOB METAZION_SHARE_SYNC_SOURCES "Sync/*.cpp") 27 | 28 | FILE(GLOB METAZION_SHARE_THREAD_HEADERS "Thread/*.hpp") 29 | FILE(GLOB METAZION_SHARE_THREAD_SOURCES "Thread/*.cpp") 30 | 31 | FILE(GLOB METAZION_SHARE_TIME_HEADERS "Time/*.hpp") 32 | FILE(GLOB METAZION_SHARE_TIME_SOURCES "Time/*.cpp") 33 | 34 | FILE(GLOB METAZION_SHARE_UTILITY_HEADERS "Utility/*.hpp") 35 | FILE(GLOB METAZION_SHARE_UTILITY_SOURCES "Utility/*.cpp") 36 | 37 | SET(LIBRARY_OUTPUT_PATH ${BUILD_DIR}/${LIB}/${PLATFORM}) 38 | SET(EXECUTABLE_OUTPUT_PATH ${BUILD_DIR}/${BIN}/${PLATFORM}) 39 | 40 | ADD_LIBRARY(Share STATIC 41 | ${METAZION_HEADERS} 42 | ${METAZION_SOURCES} 43 | ${METAZION_SHARE_HEADERS} 44 | ${METAZION_SHARE_SOURCES} 45 | ${METAZION_SHARE_ALGORITHM_HEADERS} 46 | ${METAZION_SHARE_ALGORITHM_SOURCES} 47 | ${METAZION_SHARE_ASYNC_HEADERS} 48 | ${METAZION_SHARE_ASYNC_SOURCES} 49 | ${METAZION_SHARE_COLLECTION_HEADERS} 50 | ${METAZION_SHARE_COLLECTION_SOURCES} 51 | ${METAZION_SHARE_LOG_HEADERS} 52 | ${METAZION_SHARE_LOG_SOURCES} 53 | ${METAZION_SHARE_MEMORY_HEADERS} 54 | ${METAZION_SHARE_MEMORY_SOURCES} 55 | ${METAZION_SHARE_MISC_HEADERS} 56 | ${METAZION_SHARE_MISC_SOURCES} 57 | ${METAZION_SHARE_PATTERN_HEADERS} 58 | ${METAZION_SHARE_PATTERN_SOURCES} 59 | ${METAZION_SHARE_SYNC_HEADERS} 60 | ${METAZION_SHARE_SYNC_SOURCES} 61 | ${METAZION_SHARE_THREAD_HEADERS} 62 | ${METAZION_SHARE_THREAD_SOURCES} 63 | ${METAZION_SHARE_TIME_HEADERS} 64 | ${METAZION_SHARE_TIME_SOURCES} 65 | ${METAZION_SHARE_UTILITY_HEADERS} 66 | ${METAZION_SHARE_UTILITY_SOURCES} 67 | ) 68 | 69 | SET_TARGET_PROPERTIES(Share PROPERTIES 70 | OUTPUT_NAME "MzShare" 71 | CLEAN_DIRECT_OUTPUT 1 72 | VERSION ${PRODUCT_VERSION} 73 | SOVERSION ${PRODUCT_VERSION} 74 | ) 75 | 76 | IF(PRODUCT_INSTALL) 77 | INSTALL(TARGETS Share 78 | RUNTIME DESTINATION ${BIN_DIR} 79 | LIBRARY DESTINATION ${LIB_DIR} 80 | ARCHIVE DESTINATION ${LIB_DIR} 81 | ) 82 | ENDIF(PRODUCT_INSTALL) 83 | 84 | IF(WIN32) 85 | # create visual studio folders 86 | SOURCE_GROUP(${SELF} FILES ${METAZION_HEADERS} ${METAZION_SOURCES}) 87 | SOURCE_GROUP(Header FILES ${METAZION_SHARE_HEADERS}) 88 | SOURCE_GROUP(Header\\Algorithm FILES ${METAZION_SHARE_ALGORITHM_HEADERS}) 89 | SOURCE_GROUP(Header\\Async FILES ${METAZION_SHARE_ASYNC_HEADERS}) 90 | SOURCE_GROUP(Header\\Collection FILES ${METAZION_SHARE_COLLECTION_HEADERS}) 91 | SOURCE_GROUP(Header\\Log FILES ${METAZION_SHARE_LOG_HEADERS}) 92 | SOURCE_GROUP(Header\\Memory FILES ${METAZION_SHARE_MEMORY_HEADERS}) 93 | SOURCE_GROUP(Header\\Misc FILES ${METAZION_SHARE_MISC_HEADERS}) 94 | SOURCE_GROUP(Header\\Pattern FILES ${METAZION_SHARE_PATTERN_HEADERS}) 95 | SOURCE_GROUP(Header\\Sync FILES ${METAZION_SHARE_SYNC_HEADERS}) 96 | SOURCE_GROUP(Header\\Thread FILES ${METAZION_SHARE_THREAD_HEADERS}) 97 | SOURCE_GROUP(Header\\Time FILES ${METAZION_SHARE_TIME_HEADERS}) 98 | SOURCE_GROUP(Header\\Utility FILES ${METAZION_SHARE_UTILITY_HEADERS}) 99 | SOURCE_GROUP(Source FILES ${METAZION_SHARE_SOURCES}) 100 | SOURCE_GROUP(Source\\Algorithm FILES ${METAZION_SHARE_ALGORITHM_SOURCES}) 101 | SOURCE_GROUP(Source\\Async FILES ${METAZION_SHARE_ASYNC_SOURCES}) 102 | SOURCE_GROUP(Source\\Collection FILES ${METAZION_SHARE_COLLECTION_SOURCES}) 103 | SOURCE_GROUP(Source\\Log FILES ${METAZION_SHARE_LOG_SOURCES}) 104 | SOURCE_GROUP(Source\\Memory FILES ${METAZION_SHARE_MEMORY_SOURCES}) 105 | SOURCE_GROUP(Source\\Misc FILES ${METAZION_SHARE_MISC_SOURCES}) 106 | SOURCE_GROUP(Source\\Pattern FILES ${METAZION_SHARE_PATTERN_SOURCES}) 107 | SOURCE_GROUP(Source\\Sync FILES ${METAZION_SHARE_SYNC_SOURCES}) 108 | SOURCE_GROUP(Source\\Thread FILES ${METAZION_SHARE_THREAD_SOURCES}) 109 | SOURCE_GROUP(Source\\Time FILES ${METAZION_SHARE_TIME_SOURCES}) 110 | SOURCE_GROUP(Source\\Utility FILES ${METAZION_SHARE_UTILITY_SOURCES}) 111 | ENDIF(WIN32) -------------------------------------------------------------------------------- /Metazion/Share/Collection/DynamicArray.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_DYNAMICARRAY_HPP_ 2 | #define _MZ_SHARE_DYNAMICARRAY_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | DECL_NAMESPACE_MZ_SHARE_BEGIN 7 | 8 | template 12 | class DynamicArray { 13 | 14 | using Value_t = ValueType; 15 | 16 | private: 17 | Value_t* m_values{ nullptr }; 18 | int m_capacity{ 0 }; 19 | int m_size{ 0 }; 20 | 21 | public: 22 | DynamicArray() {} 23 | 24 | ~DynamicArray() { 25 | Clear(); 26 | } 27 | 28 | DynamicArray(const DynamicArray& other) { 29 | *this = other; 30 | } 31 | 32 | DynamicArray& operator =(const DynamicArray& other) { 33 | if (&other != this) { 34 | Clear(); 35 | m_values = new Value_t[other.m_capacity]; 36 | memcpy(m_values, other.m_values, sizeof(Value_t) * other.m_size); 37 | m_capacity = other.m_capacity; 38 | m_size = other.m_size; 39 | } 40 | return *this; 41 | } 42 | 43 | DynamicArray(DynamicArray&& other) { 44 | *this = std::move(other); 45 | } 46 | 47 | DynamicArray& operator =(DynamicArray&& other) { 48 | if (&other != this) { 49 | Clear(); 50 | m_values = other.m_values; 51 | m_capacity = other.m_capacity; 52 | m_size = other.m_size; 53 | 54 | other.m_values = nullptr; 55 | other.m_capacity = 0; 56 | other.m_size = 0; 57 | } 58 | return *this; 59 | } 60 | 61 | public: 62 | void Clear() { 63 | SafeDeleteArray(m_values); 64 | m_capacity = 0; 65 | m_size = 0; 66 | } 67 | 68 | Value_t& At(int index) { 69 | MZ_ASSERT_TRUE(index >= 0 && index < m_size); 70 | 71 | return m_values[index]; 72 | } 73 | 74 | const Value_t& At(int index) const { 75 | MZ_ASSERT_TRUE(index >= 0 && index < m_size); 76 | 77 | return m_values[index]; 78 | } 79 | 80 | Value_t& operator [](int index) { 81 | return At(index); 82 | } 83 | 84 | const Value_t& operator [](int index) const { 85 | return At(index); 86 | } 87 | 88 | int Insert(int index, const Value_t& value) { 89 | if (index >= m_size) { 90 | return Set(index, value); 91 | } 92 | 93 | if (m_size >= m_capacity) { 94 | Inflate(m_size + 1); 95 | } 96 | 97 | memmove(m_values + index + 1, m_values + index 98 | , sizeof(Value_t)* (m_size - index)); 99 | 100 | m_values[index] = value; 101 | ++m_size; 102 | return index; 103 | } 104 | 105 | int Append(const Value_t& value) { 106 | const auto index = m_size; 107 | return Set(index, value); 108 | } 109 | 110 | int Remove(int index) { 111 | if (index < 0 || index >= m_size) { 112 | return -1; 113 | } 114 | 115 | memmove(m_values + index, m_values + index + 1 116 | , sizeof(Value_t) * (m_size - index - 1)); 117 | --m_size; 118 | return index; 119 | } 120 | 121 | int GetCapacity() const { 122 | return m_capacity; 123 | } 124 | 125 | int GetSize() const { 126 | return m_size; 127 | } 128 | 129 | private: 130 | int Set(int index, const Value_t& value) { 131 | MZ_ASSERT_TRUE(index >= 0); 132 | 133 | const int size = index + 1; 134 | if (size > m_capacity) { 135 | Inflate(size); 136 | } 137 | 138 | if (size > m_size) { 139 | m_size = size; 140 | } 141 | 142 | m_values[index] = value; 143 | return index; 144 | } 145 | 146 | void Inflate(int capacity) { 147 | MZ_ASSERT_TRUE(capacity > m_capacity); 148 | 149 | if (m_capacity <= 0) { 150 | m_capacity = INITSIZE; 151 | } 152 | 153 | while (m_capacity < capacity) { 154 | m_capacity += STEPSIZE; 155 | } 156 | 157 | if (IsNull(m_values)) { 158 | m_values = new Value_t[m_capacity]; 159 | return; 160 | } 161 | 162 | auto tValues = new Value_t[m_capacity]; 163 | memmove(tValues, m_values, sizeof(Value_t) * m_size); 164 | SafeDeleteArray(m_values); 165 | m_values = tValues; 166 | } 167 | }; 168 | 169 | DECL_NAMESPACE_MZ_SHARE_END 170 | 171 | #endif // _MZ_SHARE_DYNAMICARRAY_HPP_ 172 | -------------------------------------------------------------------------------- /Metazion/Share/Collection/DynamicSortedArray.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_DYNAMICSORTEDARRAY_HPP_ 2 | #define _MZ_SHARE_DYNAMICSORTEDARRAY_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | #include "Metazion/Share/Collection/DynamicArray.hpp" 7 | 8 | DECL_NAMESPACE_MZ_SHARE_BEGIN 9 | 10 | template 12 | , int INITSIZE = 16 13 | , int STEPSIZE = 16 14 | > 15 | class DynamicSortedArray { 16 | 17 | using Value_t = ValueType; 18 | using Compare_t = CompareType; 19 | using Array_t = DynamicArray; 20 | 21 | private: 22 | Compare_t m_compare; 23 | Array_t m_array; 24 | 25 | public: 26 | DynamicSortedArray() {} 27 | 28 | ~DynamicSortedArray() {} 29 | 30 | DynamicSortedArray(const DynamicSortedArray& other) { 31 | *this = other; 32 | } 33 | 34 | DynamicSortedArray& operator =(const DynamicSortedArray& other) { 35 | if (&other != this) { 36 | Clear(); 37 | m_array = other.m_array; 38 | } 39 | return *this; 40 | } 41 | 42 | DynamicSortedArray(DynamicSortedArray&& other) { 43 | *this = std::move(other); 44 | } 45 | 46 | DynamicSortedArray& operator =(DynamicSortedArray&& other) { 47 | if (&other != this) { 48 | Clear(); 49 | m_array = std::move(other.m_array); 50 | } 51 | return *this; 52 | } 53 | 54 | public: 55 | void Clear() { 56 | m_array.Clear(); 57 | } 58 | 59 | Value_t& At(int index) { 60 | return m_array.At(index); 61 | } 62 | 63 | const Value_t& At(int index) const { 64 | return m_array.At(index); 65 | } 66 | 67 | Value_t& operator [](int index) { 68 | return m_array[index]; 69 | } 70 | 71 | const Value_t& operator [](int index) const { 72 | return m_array[index]; 73 | } 74 | 75 | int Find(const Value_t& value) const { 76 | int index = 0; 77 | auto found = BinarySearch(value, index); 78 | return found ? index : -1; 79 | } 80 | 81 | int Append(const Value_t& value) { 82 | int index = 0; 83 | auto found = BinarySearch(value, index); 84 | return m_array.Insert(index, value); 85 | } 86 | 87 | int Remove(int index) { 88 | return m_array.Remove(index); 89 | } 90 | 91 | int GetCapacity() const { 92 | return m_array.GetCapacity(); 93 | } 94 | 95 | int GetSize() const { 96 | return m_array.GetSize(); 97 | } 98 | 99 | private: 100 | bool BinarySearch(const Value_t& value, int& index) const { 101 | auto low = 0; 102 | auto high = m_array.GetSize() - 1; 103 | auto middle = 0; 104 | auto found = false; 105 | while (low <= high) { 106 | middle = low + ((high - low) >> 1); 107 | const auto ret = m_compare(value, m_array[middle]); 108 | if (ret > 0) { 109 | low = middle + 1; 110 | } 111 | else if (ret < 0) { 112 | high = middle - 1; 113 | } 114 | else { 115 | low = middle; 116 | found = true; 117 | break; 118 | } 119 | } 120 | 121 | index = low; 122 | return found; 123 | } 124 | }; 125 | 126 | DECL_NAMESPACE_MZ_SHARE_END 127 | 128 | #endif // _MZ_SHARE_DYNAMICSORTEDARRAY_HPP_ 129 | -------------------------------------------------------------------------------- /Metazion/Share/Collection/Hasher.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_HASHER_HPP_ 2 | #define _MZ_SHARE_HASHER_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | #include "Metazion/Share/Algorithm/StringHash.hpp" 7 | 8 | DECL_NAMESPACE_MZ_SHARE_BEGIN 9 | 10 | template 11 | struct IntegerHasher { 12 | int32_t operator ()(const T& value) const { 13 | const auto magicNumber = 13; 14 | auto hash = static_cast(value); 15 | hash *= magicNumber; 16 | return hash & 0x7fffffff; 17 | } 18 | }; 19 | 20 | template 21 | struct PointerHasher { 22 | int32_t operator ()(const T& value) const { 23 | const auto magicNumber = 13; 24 | auto ptr = reinterpret_cast(value); 25 | auto hash = static_cast(ptr); 26 | hash >>= 2; 27 | hash *= magicNumber; 28 | return hash & 0x7fffffff; 29 | } 30 | }; 31 | 32 | template 33 | struct StringHasher { 34 | int32_t operator ()(const T& value) const { 35 | const auto str = static_cast(value); 36 | const auto hash = BKDRHash(str); 37 | return hash & 0x7fffffff; 38 | } 39 | }; 40 | 41 | DECL_NAMESPACE_MZ_SHARE_END 42 | 43 | #endif // _MZ_SHARE_HASHER_HPP_ 44 | -------------------------------------------------------------------------------- /Metazion/Share/Collection/PriorityQueue.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_PRIORITY_HPP_ 2 | #define _MZ_SHARE_PRIORITY_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | #include "Metazion/Share/Collection/DynamicArray.hpp" 7 | 8 | DECL_NAMESPACE_MZ_SHARE_BEGIN 9 | 10 | template 12 | , int INITSIZE = 16 13 | , int STEPSIZE = 16 14 | > 15 | class PriorityQueue { 16 | using Value_t = ValueType; 17 | using Compare_t = CompareType; 18 | using Array_t = DynamicArray; 19 | 20 | private: 21 | Compare_t m_compare; 22 | Array_t m_array; 23 | 24 | public: 25 | PriorityQueue() {} 26 | 27 | ~PriorityQueue() {} 28 | 29 | PriorityQueue(const PriorityQueue& other) { 30 | *this = other; 31 | } 32 | 33 | PriorityQueue& operator =(const PriorityQueue& other) { 34 | if (&other != this) { 35 | Clear(); 36 | m_array = other.m_array; 37 | } 38 | return *this; 39 | } 40 | 41 | PriorityQueue(PriorityQueue&& other) { 42 | *this = std::move(other); 43 | } 44 | 45 | PriorityQueue& operator =(PriorityQueue&& other) { 46 | if (&other != this) { 47 | Clear(); 48 | m_array = std::move(other.m_array); 49 | } 50 | return *this; 51 | } 52 | 53 | public: 54 | void Clear() { 55 | m_array.Clear(); 56 | } 57 | 58 | Value_t& Top() { 59 | MZ_ASSERT_TRUE(GetSize() > 0); 60 | 61 | return m_array[0]; 62 | } 63 | 64 | const Value_t& Top() const { 65 | MZ_ASSERT_TRUE(GetSize() > 0); 66 | 67 | return m_array[0]; 68 | } 69 | 70 | void Push(const Value_t& value) { 71 | m_array.Append(value); 72 | 73 | const auto size = GetSize(); 74 | SiftUp(size - 1); 75 | } 76 | 77 | void Pop() { 78 | const auto size = GetSize(); 79 | MZ_ASSERT_TRUE(size > 0); 80 | m_array[0] = m_array[size - 1]; 81 | m_array.Remove(size - 1); 82 | 83 | SiftDown(0); 84 | } 85 | 86 | int GetSize() const { 87 | return m_array.GetSize(); 88 | } 89 | 90 | bool IsEmpty() const { 91 | return GetSize() == 0; 92 | } 93 | 94 | private: 95 | void SiftUp(int localIndex) { 96 | auto index = ToLogicIndex(localIndex); 97 | while (index > 1) { 98 | const auto parent = index >> 1; 99 | if (m_compare(Data(parent), Data(index)) < 0) { 100 | break; 101 | } 102 | 103 | std::swap(Data(index), Data(parent)); 104 | 105 | index = parent; 106 | } 107 | } 108 | 109 | void SiftDown(int localIndex){ 110 | auto index = ToLogicIndex(localIndex); 111 | const auto size = GetSize(); 112 | auto next = index << 1; 113 | while (next <= size) { 114 | const auto right = next + 1; 115 | if (right <= size && m_compare(Data(right), Data(next)) < 0) { 116 | next = right; 117 | } 118 | 119 | if (m_compare(Data(index), Data(next)) < 0) { 120 | break; 121 | } 122 | 123 | std::swap(Data(next), Data(index)); 124 | 125 | index = next; 126 | next = index << 1; 127 | } 128 | } 129 | 130 | Value_t& Data(int logicIndex) { 131 | return m_array[ToLocalIndex(logicIndex)]; 132 | } 133 | 134 | int ToLogicIndex(int localIndex) const { 135 | return localIndex + 1; 136 | } 137 | 138 | int ToLocalIndex(int logicIndex) const { 139 | return logicIndex - 1; 140 | } 141 | }; 142 | 143 | DECL_NAMESPACE_MZ_SHARE_END 144 | 145 | #endif // _MZ_SHARE_PRIORITY_HPP_ 146 | -------------------------------------------------------------------------------- /Metazion/Share/Collection/StaticArray.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_STATICARRAY_HPP_ 2 | #define _MZ_SHARE_STATICARRAY_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | DECL_NAMESPACE_MZ_SHARE_BEGIN 7 | 8 | template 9 | class StaticArray { 10 | MZ_DISALLOW_COPY_AND_ASSIGN(StaticArray); 11 | 12 | using Value_t = ValueType; 13 | 14 | private: 15 | Value_t* m_values{ nullptr }; 16 | int m_capacity{ 0 }; 17 | int m_size{ 0 }; 18 | 19 | public: 20 | StaticArray() {} 21 | 22 | ~StaticArray() {} 23 | 24 | public: 25 | void Attach(Value_t* buffer, int capacity, int size) { 26 | m_values = buffer; 27 | m_capacity = capacity; 28 | m_size = size; 29 | } 30 | 31 | void Detach() { 32 | m_values = nullptr; 33 | m_capacity = 0; 34 | m_size = 0; 35 | } 36 | 37 | void Clear() { 38 | m_size = 0; 39 | } 40 | 41 | Value_t& At(int index) { 42 | MZ_ASSERT_TRUE(index >= 0 && index < m_size); 43 | 44 | return m_values[index]; 45 | } 46 | 47 | const Value_t& At(int index) const { 48 | MZ_ASSERT_TRUE(index >= 0 && index < m_size); 49 | 50 | return m_values[index]; 51 | } 52 | 53 | Value_t& operator [](int index) { 54 | return At(index); 55 | } 56 | 57 | const Value_t& operator [](int index) const { 58 | return At(index); 59 | } 60 | 61 | int Insert(int index, const Value_t& value) { 62 | if (m_size >= m_capacity || index >= m_capacity) { 63 | return -1; 64 | } 65 | 66 | if (index >= m_size) { 67 | return Set(index, value); 68 | } 69 | 70 | memmove(m_values + index + 1, m_values + index 71 | , sizeof(Value_t)* (m_size - index)); 72 | 73 | m_values[index] = value; 74 | ++m_size; 75 | return index; 76 | } 77 | 78 | int Append(const Value_t& value) { 79 | if (m_size >= m_capacity) { 80 | return -1; 81 | } 82 | 83 | const int index = m_size; 84 | return Set(index, value); 85 | } 86 | 87 | int Remove(int index) { 88 | if (index < 0 || index >= m_size) { 89 | return -1; 90 | } 91 | 92 | memmove(m_values + index, m_values + index + 1 93 | , sizeof(Value_t)* (m_size - index - 1)); 94 | --m_size; 95 | return index; 96 | } 97 | 98 | int GetCapacity() const { 99 | return m_capacity; 100 | } 101 | 102 | int GetSize() const { 103 | return m_size; 104 | } 105 | 106 | private: 107 | int Set(int index, const Value_t& value) { 108 | MZ_ASSERT_TRUE(index >= 0 && index < m_capacity); 109 | 110 | const auto size = index + 1; 111 | if (size > m_size) { 112 | m_size = size; 113 | } 114 | 115 | m_values[index] = value; 116 | return index; 117 | } 118 | }; 119 | 120 | DECL_NAMESPACE_MZ_SHARE_END 121 | 122 | #endif // _MZ_SHARE_STATICARRAY_HPP_ 123 | -------------------------------------------------------------------------------- /Metazion/Share/Collection/StaticSortedArray.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_STATICSORTEDARRAY_HPP_ 2 | #define _MZ_SHARE_STATICSORTEDARRAY_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | #include "Metazion/Share/Collection/StaticArray.hpp" 7 | 8 | DECL_NAMESPACE_MZ_SHARE_BEGIN 9 | 10 | template 12 | > 13 | class StaticSortedArray { 14 | MZ_DISALLOW_COPY_AND_ASSIGN(StaticSortedArray); 15 | 16 | using Value_t = ValueType; 17 | using Compare_t = CompareType; 18 | using Array_t = StaticArray; 19 | 20 | private: 21 | Compare_t m_compare; 22 | Array_t m_array; 23 | 24 | public: 25 | StaticSortedArray() {} 26 | 27 | ~StaticSortedArray() {} 28 | 29 | public: 30 | void Attach(Value_t* buffer, int capacity, int size) { 31 | m_array.Attach(buffer, capacity, size); 32 | } 33 | 34 | void Detach() { 35 | m_array.Detach(); 36 | } 37 | 38 | void Clear() { 39 | m_array.Clear(); 40 | } 41 | 42 | Value_t& At(int index) { 43 | return m_array.At(index); 44 | } 45 | 46 | const Value_t& At(int index) const { 47 | return m_array.At(index); 48 | } 49 | 50 | Value_t& operator [](int index) { 51 | return m_array[index]; 52 | } 53 | 54 | const Value_t& operator [](int index) const { 55 | return m_array[index]; 56 | } 57 | 58 | int Find(const Value_t& value) { 59 | int index = 0; 60 | auto found = BinarySearch(value, index); 61 | return found ? index : -1; 62 | } 63 | 64 | int Append(const Value_t& value) { 65 | int index = 0; 66 | auto found = BinarySearch(value, index); 67 | return m_array.Insert(index, value); 68 | } 69 | 70 | int Remove(int index) { 71 | return m_array.Remove(index); 72 | } 73 | 74 | int GetCapacity() const { 75 | return m_array.GetCapacity(); 76 | } 77 | 78 | int GetSize() const { 79 | return m_array.GetSize(); 80 | } 81 | 82 | private: 83 | bool BinarySearch(const Value_t& value, int& index) { 84 | int low = 0; 85 | int high = m_array.GetSize() - 1; 86 | int middle = 0; 87 | bool found = false; 88 | while (low <= high) { 89 | middle = low + ((high - low) >> 1); 90 | const auto ret = m_compare(value, m_array[middle]); 91 | if (ret > 0) { 92 | low = middle + 1; 93 | } 94 | else if (ret < 0) { 95 | high = middle - 1; 96 | } 97 | else { 98 | low = middle; 99 | found = true; 100 | break; 101 | } 102 | } 103 | 104 | index = low; 105 | return found; 106 | } 107 | }; 108 | 109 | DECL_NAMESPACE_MZ_SHARE_END 110 | 111 | #endif // _MZ_SHARE_STATICSORTEDARRAY_HPP_ 112 | -------------------------------------------------------------------------------- /Metazion/Share/Log/LogDefine.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_LOGDEFINE_HPP_ 2 | #define _MZ_SHARE_LOGDEFINE_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | DECL_NAMESPACE_MZ_SHARE_BEGIN 7 | 8 | #define MZ_LOG_NONE 0x00 9 | #define MZ_LOG_DEBUG 0x01 10 | #define MZ_LOG_WARNNING 0x02 11 | #define MZ_LOG_ERROR 0x04 12 | 13 | DECL_NAMESPACE_MZ_SHARE_END 14 | 15 | #endif // _MZ_SHARE_LOGDEFINE_HPP_ 16 | -------------------------------------------------------------------------------- /Metazion/Share/Log/Logger.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_LOGGER_HPP_ 2 | #define _MZ_SHARE_LOGGER_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | #include "Metazion/Share/Log/LogDefine.hpp" 7 | 8 | DECL_NAMESPACE_MZ_SHARE_BEGIN 9 | 10 | template 11 | void Log(T type, const char* format, Args... args) { 12 | printf(format, args...); 13 | } 14 | 15 | DECL_NAMESPACE_MZ_SHARE_END 16 | 17 | #endif // _MZ_SHARE_LOGGER_HPP_ 18 | -------------------------------------------------------------------------------- /Metazion/Share/Memory/BlockAllocator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_BLOCKALLOCATOR_HPP_ 2 | #define _MZ_SHARE_BLOCKALLOCATOR_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | #include "Metazion/Share/Memory/MemoryPiece.hpp" 7 | 8 | DECL_NAMESPACE_MZ_SHARE_BEGIN 9 | 10 | template 13 | class BlockAllocator { 14 | MZ_DISALLOW_COPY_AND_ASSIGN(BlockAllocator) 15 | 16 | enum { ALIGNLENGTH = MZ_ALIGN_LENGTH(UNITLENGTH, MZ_DEFAULT_ALIGNMENT) }; 17 | 18 | using Piece_t = MemoryPiece; 19 | 20 | public: 21 | template 22 | using Rebind = BlockAllocator; 23 | 24 | private: 25 | Piece_t* m_piece{ nullptr }; 26 | 27 | public: 28 | BlockAllocator() { 29 | m_piece = new Piece_t(); 30 | } 31 | 32 | ~BlockAllocator() { 33 | SafeDelete(m_piece); 34 | } 35 | 36 | public: 37 | void* Alloc() { 38 | return m_piece->Obtain(); 39 | } 40 | 41 | void Free(void* memory) { 42 | return m_piece->Return(memory); 43 | } 44 | }; 45 | 46 | DECL_NAMESPACE_MZ_SHARE_END 47 | 48 | #endif // _MZ_SHARE_BLOCKALLOCATOR_HPP_ 49 | -------------------------------------------------------------------------------- /Metazion/Share/Memory/HeapAllocator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_HEAPALLOCATOR_HPP_ 2 | #define _MZ_SHARE_HEAPALLOCATOR_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | DECL_NAMESPACE_MZ_SHARE_BEGIN 7 | 8 | template 9 | class HeapAllocator { 10 | MZ_DISALLOW_COPY_AND_ASSIGN(HeapAllocator) 11 | 12 | enum { ALIGNLENGTH = MZ_ALIGN_LENGTH(UNITLENGTH, MZ_DEFAULT_ALIGNMENT) }; 13 | 14 | public: 15 | template 16 | using Rebind = HeapAllocator; 17 | 18 | public: 19 | HeapAllocator() {} 20 | 21 | ~HeapAllocator() {} 22 | 23 | public: 24 | void* Alloc() { 25 | return malloc(ALIGNLENGTH); 26 | } 27 | 28 | void Free(void* memory) { 29 | free(memory); 30 | } 31 | }; 32 | 33 | DECL_NAMESPACE_MZ_SHARE_END 34 | 35 | #endif // _MZ_SHARE_HEAPALLOCATOR_HPP_ 36 | -------------------------------------------------------------------------------- /Metazion/Share/Memory/MemoryPiece.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_MEMORYPIECE_HPP_ 2 | #define _MZ_SHARE_MEMORYPIECE_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | DECL_NAMESPACE_MZ_SHARE_BEGIN 7 | 8 | template 11 | class MemoryPiece { 12 | MZ_DISALLOW_COPY_AND_ASSIGN(MemoryPiece) 13 | 14 | typedef struct Node { 15 | Node* m_nextNode{ nullptr }; 16 | } Node_t; 17 | 18 | enum { 19 | MINLENGTH = MZ_MAX(UNITLENGTH, sizeof(Node_t)), 20 | ALIGNLENGTH = MZ_ALIGN_LENGTH(MINLENGTH, MZ_DEFAULT_ALIGNMENT), 21 | }; 22 | 23 | typedef struct Unit { 24 | char m_buffer[ALIGNLENGTH]{ 0 }; 25 | } Unit_t; 26 | 27 | private: 28 | Unit_t m_units[MAXSIZE]; 29 | Node_t* m_freeList{ nullptr }; 30 | int m_count{ 0 }; 31 | int m_freeCount{ 0 }; 32 | 33 | public: 34 | MemoryPiece() {} 35 | 36 | ~MemoryPiece() {} 37 | 38 | public: 39 | void Reset() { 40 | m_freeList = nullptr; 41 | m_count = 0; 42 | m_freeCount = 0; 43 | } 44 | 45 | void* Obtain() { 46 | if (!IsNull(m_freeList)) { 47 | auto node = m_freeList; 48 | m_freeList = m_freeList->m_nextNode; 49 | --m_freeCount; 50 | return node; 51 | } 52 | 53 | if (m_count < MAXSIZE) { 54 | auto unit = &m_units[m_count]; 55 | ++m_count; 56 | return unit; 57 | } 58 | 59 | return nullptr; 60 | } 61 | 62 | void Return(void* memory) { 63 | MZ_ASSERT_TRUE(IsResponsible(memory)); 64 | 65 | auto node = static_cast(memory); 66 | node->m_nextNode = m_freeList; 67 | m_freeList = node; 68 | ++m_freeCount; 69 | } 70 | 71 | bool IsResponsible(void* memory) const { 72 | return memory >= &m_units[0] && memory <= &m_units[m_count - 1]; 73 | } 74 | 75 | bool IsAvaliable() const { 76 | return m_count < MAXSIZE || m_freeCount > 0; 77 | } 78 | 79 | bool IsEmpty() const { 80 | return m_freeCount == m_count; 81 | } 82 | 83 | int GetUnitLength() const { 84 | return ALIGNLENGTH; 85 | } 86 | }; 87 | 88 | DECL_NAMESPACE_MZ_SHARE_END 89 | 90 | #endif // _MZ_SHARE_MEMORYPIECE_HPP_ 91 | -------------------------------------------------------------------------------- /Metazion/Share/Memory/MemoryRecordset.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Share/Memory/MemoryRecordset.hpp" 2 | 3 | DECL_NAMESPACE_MZ_SHARE_BEGIN 4 | 5 | MemoryRecordset::MemoryRecordset() 6 | : m_activeHeader(nullptr) 7 | , m_buffer(nullptr) 8 | , m_length(0) 9 | , m_ownMemory(false) {} 10 | 11 | MemoryRecordset::~MemoryRecordset() {} 12 | 13 | void MemoryRecordset::Initialize(int recordSize, int capacity) { 14 | MZ_ASSERT_TRUE(recordSize > 0); 15 | MZ_ASSERT_TRUE(capacity > 0); 16 | 17 | m_personalHeader.m_recordSize = AlignLength(recordSize, RECORDALIGNLENGTH); 18 | m_personalHeader.m_capacity = capacity; 19 | m_personalHeader.m_firstFree = INVALIDRECORDINDEX; 20 | m_personalHeader.m_usedCount = 0; 21 | 22 | m_length = m_personalHeader.m_recordSize * m_personalHeader.m_capacity; 23 | m_buffer = new char[m_length]; 24 | 25 | m_activeHeader = &m_personalHeader; 26 | m_ownMemory = true; 27 | } 28 | 29 | void MemoryRecordset::Finalize() { 30 | MZ_ASSERT_TRUE(m_ownMemory); 31 | 32 | SafeDeleteArray(m_buffer); 33 | m_length = 0; 34 | m_activeHeader = nullptr; 35 | m_ownMemory = false; 36 | } 37 | 38 | void MemoryRecordset::Attach(Header& header, void* buffer) { 39 | MZ_ASSERT_TRUE(IsLengthAlign(header.m_recordSize, RECORDALIGNLENGTH)); 40 | 41 | m_length = header.m_recordSize * header.m_capacity; 42 | m_buffer = reinterpret_cast(buffer); 43 | 44 | m_activeHeader = &header; 45 | m_ownMemory = false; 46 | } 47 | 48 | void MemoryRecordset::Detach() { 49 | MZ_ASSERT_TRUE(!m_ownMemory); 50 | 51 | m_length = 0; 52 | m_buffer = nullptr; 53 | m_activeHeader = nullptr; 54 | m_ownMemory = true; 55 | } 56 | 57 | void MemoryRecordset::Reset() { 58 | m_activeHeader->m_firstFree = INVALIDRECORDINDEX; 59 | m_activeHeader->m_usedCount = 0; 60 | } 61 | 62 | MemoryRecordset::Handle MemoryRecordset::ObtainRecord() { 63 | if (m_activeHeader->m_firstFree == INVALIDRECORDINDEX) { 64 | auto recordIndex = m_activeHeader->m_usedCount; 65 | if (!IsValidRecordIndex(recordIndex)) { 66 | return Handle(0); 67 | } 68 | 69 | Handle handle = RecordIndexToHandle(recordIndex); 70 | ++m_activeHeader->m_usedCount; 71 | return handle; 72 | } 73 | 74 | const auto recordIndex = m_activeHeader->m_firstFree; 75 | Handle handle = RecordIndexToHandle(recordIndex); 76 | auto memory = GetMemory(handle); 77 | auto record = static_cast(memory); 78 | m_activeHeader->m_firstFree = record->m_flag; 79 | return handle; 80 | } 81 | 82 | bool MemoryRecordset::ReturnRecord(MemoryRecordset::Handle handle) { 83 | if (!IsValidHandle(handle)) { 84 | return false; 85 | } 86 | 87 | auto memory = GetMemory(handle); 88 | auto record = static_cast(memory); 89 | record->m_flag = m_activeHeader->m_firstFree; 90 | m_activeHeader->m_firstFree = HandleToRecordIndex(handle); 91 | return true; 92 | } 93 | 94 | void* MemoryRecordset::GetMemory(MemoryRecordset::Handle handle) { 95 | if (!IsValidHandle(handle)) { 96 | return nullptr; 97 | } 98 | 99 | auto memory = reinterpret_cast(handle); 100 | return memory; 101 | } 102 | 103 | MemoryRecordset::Handle MemoryRecordset::GetHandle(void* memory) { 104 | return Handle(memory); 105 | } 106 | 107 | bool MemoryRecordset::IsValidHandle(MemoryRecordset::Handle handle) { 108 | auto memory = reinterpret_cast(handle); 109 | return memory >= m_buffer && memory < m_buffer + m_length; 110 | } 111 | 112 | bool MemoryRecordset::IsValidMomory(void* memory) { 113 | return memory >= m_buffer && memory < m_buffer + m_length; 114 | } 115 | 116 | int MemoryRecordset::HandleToRecordIndex(MemoryRecordset::Handle handle) { 117 | const auto memory = reinterpret_cast(handle); 118 | const auto memoryLength = static_cast(memory - m_buffer); 119 | return static_cast(memoryLength / m_activeHeader->m_recordSize); 120 | } 121 | 122 | MemoryRecordset::Handle MemoryRecordset::RecordIndexToHandle(int index) { 123 | const auto memoryLength = m_activeHeader->m_recordSize * index; 124 | return Handle(m_buffer + memoryLength); 125 | } 126 | 127 | bool MemoryRecordset::IsValidRecordIndex(int index) { 128 | return index >= 0 && index < m_activeHeader->m_capacity; 129 | } 130 | 131 | DECL_NAMESPACE_MZ_SHARE_END 132 | -------------------------------------------------------------------------------- /Metazion/Share/Memory/MemoryRecordset.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_MEMORYRECORDSET_HPP_ 2 | #define _MZ_SHARE_MEMORYRECORDSET_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | DECL_NAMESPACE_MZ_SHARE_BEGIN 7 | 8 | class MemoryRecordset { 9 | MZ_DISALLOW_COPY_AND_ASSIGN(MemoryRecordset) 10 | 11 | public: 12 | using Handle = void*; 13 | 14 | struct Header { 15 | volatile int m_usedCount{ 0 }; 16 | int m_firstFree{ 0 }; 17 | int m_recordSize{ 0 }; 18 | int m_capacity{ 0 }; 19 | }; 20 | 21 | private: 22 | enum { 23 | INVALIDRECORDINDEX = 0x7FFFFFFF, 24 | RECORDALIGNLENGTH = MZ_DEFAULT_ALIGNMENT, 25 | }; 26 | 27 | struct Record { 28 | Record() { memset(this, 0, sizeof(*this)); } 29 | 30 | union { 31 | int m_flag; 32 | char m_record[1]; 33 | }; 34 | }; 35 | 36 | private: 37 | Header m_personalHeader; 38 | Header* m_activeHeader{ nullptr }; 39 | char* m_buffer{ nullptr }; 40 | int m_length{ 0 }; 41 | bool m_ownMemory{ false }; 42 | 43 | public: 44 | MemoryRecordset(); 45 | 46 | ~MemoryRecordset(); 47 | 48 | public: 49 | void Initialize(int recordSize, int capacity); 50 | 51 | void Finalize(); 52 | 53 | void Attach(Header& header, void* buffer); 54 | 55 | void Detach(); 56 | 57 | void Reset(); 58 | 59 | Handle ObtainRecord(); 60 | 61 | bool ReturnRecord(Handle handle); 62 | 63 | void* GetMemory(Handle handle); 64 | 65 | Handle GetHandle(void* memory); 66 | 67 | bool IsValidHandle(Handle handle); 68 | 69 | bool IsValidMomory(void* memory); 70 | 71 | private: 72 | int HandleToRecordIndex(Handle handle); 73 | 74 | Handle RecordIndexToHandle(int index); 75 | 76 | bool IsValidRecordIndex(int index); 77 | }; 78 | 79 | DECL_NAMESPACE_MZ_SHARE_END 80 | 81 | #endif // _MZ_SHARE_MEMORYRECORDSET_HPP_ 82 | -------------------------------------------------------------------------------- /Metazion/Share/Memory/ObjectPool.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_OBJECTPOOL_HPP_ 2 | #define _MZ_SHARE_OBJECTPOOL_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | #include "Metazion/Share/Collection/UDList.hpp" 7 | #include "Metazion/Share/Collection/UDSelfList.hpp" 8 | #include "Metazion/Share/Memory/StepAllocator.hpp" 9 | #include "Metazion/Share/Sync/NoneLock.hpp" 10 | 11 | DECL_NAMESPACE_MZ_SHARE_BEGIN 12 | 13 | template 15 | , typename LockType = NoneLock 16 | > 17 | class ObjectPool { 18 | MZ_DISALLOW_COPY_AND_ASSIGN(ObjectPool) 19 | 20 | using Object_t = ObjectType; 21 | using Lock_t = LockType; 22 | using Allocator_t = typename AllocatorFamily::template Rebind; 23 | 24 | private: 25 | Allocator_t m_allocator; 26 | Lock_t m_lock; 27 | 28 | public: 29 | ObjectPool() {} 30 | 31 | ~ObjectPool() {} 32 | 33 | public: 34 | Object_t* Obtain() { 35 | std::lock_guard lockGuard(m_lock); 36 | 37 | return CreateObject(); 38 | } 39 | 40 | void Return(Object_t* object) { 41 | std::lock_guard lockGuard(m_lock); 42 | 43 | DestoryObject(object); 44 | } 45 | 46 | private: 47 | Object_t* CreateObject() { 48 | auto memory = m_allocator.Alloc(); 49 | auto object = new(memory) Object_t(); 50 | return object; 51 | } 52 | 53 | void DestoryObject(Object_t* object) { 54 | object->~Object_t(); 55 | m_allocator.Free(object); 56 | } 57 | }; 58 | 59 | template 61 | , typename LockType = NoneLock 62 | > 63 | class PortableObjectPool { 64 | using Object_t = ObjectType; 65 | using ObjectPool_t = ObjectPool; 66 | 67 | public: 68 | static Object_t* Obtain() { 69 | return GetObjectPool().Obtain(); 70 | } 71 | 72 | static void Return(Object_t* object) { 73 | GetObjectPool().Return(object); 74 | } 75 | 76 | private: 77 | static ObjectPool_t& GetObjectPool() { 78 | static ObjectPool_t s_objectPool; 79 | return s_objectPool; 80 | } 81 | }; 82 | 83 | DECL_NAMESPACE_MZ_SHARE_END 84 | 85 | #endif // _MZ_SHARE_OBJECTPOOL_HPP_ 86 | -------------------------------------------------------------------------------- /Metazion/Share/Memory/PieceBuffer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_PIECEBUFFER_HPP_ 2 | #define _MZ_SHARE_PIECEBUFFER_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | DECL_NAMESPACE_MZ_SHARE_BEGIN 7 | 8 | template 9 | class PieceBuffer { 10 | MZ_DISALLOW_COPY_AND_ASSIGN(PieceBuffer) 11 | 12 | private: 13 | char m_buffer[MAXLENGTH]{ 0 }; 14 | int m_pushIndex{ 0 }; 15 | int m_pullIndex{ 0 }; 16 | 17 | public: 18 | PieceBuffer() {} 19 | 20 | ~PieceBuffer() {} 21 | 22 | public: 23 | void Reset() { 24 | memset(m_buffer, 0, sizeof(m_buffer)); 25 | m_pushIndex = 0; 26 | m_pullIndex = 0; 27 | } 28 | 29 | int Push(const void* data, int length) { 30 | auto pushLength = this->GetPushLength(); 31 | if (pushLength <= 0) { 32 | return 0; 33 | } 34 | 35 | if (pushLength < length) { 36 | length = pushLength; 37 | } 38 | memcpy(&m_buffer[m_pushIndex], data, length); 39 | m_pushIndex += length; 40 | return length; 41 | } 42 | 43 | int Take(int length) { 44 | auto pushLength = this->GetPushLength(); 45 | if (pushLength <= 0) { 46 | return 0; 47 | } 48 | 49 | if (pushLength < length) { 50 | length = pushLength; 51 | } 52 | m_pushIndex += length; 53 | return length; 54 | } 55 | 56 | int Pull(void* data, int length) { 57 | const auto pullLength = GetPullLength(); 58 | if (pullLength <= 0) { 59 | return 0; 60 | } 61 | 62 | if (pullLength < length) { 63 | length = pullLength; 64 | } 65 | memcpy(data, &m_buffer[m_pullIndex], length); 66 | m_pullIndex += length; 67 | return length; 68 | } 69 | 70 | int Peek(void* data, int length) { 71 | const auto pullLength = GetPullLength(); 72 | if (pullLength <= 0) { 73 | return 0; 74 | } 75 | 76 | if (pullLength < length) { 77 | length = pullLength; 78 | } 79 | memcpy(data, &m_buffer[m_pullIndex], length); 80 | return length; 81 | } 82 | 83 | int Skip(int length) { 84 | const auto pullLength = GetPullLength(); 85 | if (pullLength <= 0) { 86 | return 0; 87 | } 88 | 89 | if (pullLength < length) { 90 | length = pullLength; 91 | } 92 | m_pullIndex += length; 93 | return length; 94 | } 95 | 96 | void Compact() { 97 | if (m_pullIndex == 0) { 98 | return; 99 | } 100 | 101 | if(m_pushIndex > m_pullIndex) { 102 | memmove(&m_buffer[0], &m_buffer[m_pullIndex], m_pushIndex - m_pullIndex); 103 | m_pushIndex = m_pushIndex - m_pullIndex; 104 | m_pullIndex = 0; 105 | } else { 106 | m_pushIndex = 0; 107 | m_pullIndex = 0; 108 | } 109 | } 110 | 111 | char* GetBuffer() { 112 | return m_buffer; 113 | } 114 | 115 | const char* GetBuffer() const { 116 | return m_buffer; 117 | } 118 | 119 | int GetMaxLength() const { 120 | return MAXLENGTH; 121 | } 122 | 123 | int GetPullLength() const { 124 | return m_pushIndex - m_pullIndex; 125 | } 126 | 127 | void SetPullIndex(int pullIndex) { 128 | m_pullIndex = pullIndex; 129 | } 130 | 131 | void JumpPullIndex(int pullOffset) { 132 | m_pullIndex += pullOffset; 133 | } 134 | 135 | char* GetPullBuffer() { 136 | return &m_buffer[m_pullIndex]; 137 | } 138 | 139 | const char* GetPullBuffer() const { 140 | return &m_buffer[m_pullIndex]; 141 | } 142 | 143 | int GetPushLength() const { 144 | return MAXLENGTH - m_pushIndex; 145 | } 146 | 147 | void SetPushIndex(int pushIndex) { 148 | m_pushIndex = pushIndex; 149 | } 150 | 151 | void JumpPushIndex(int pushOffset) { 152 | m_pushIndex += pushOffset; 153 | } 154 | 155 | char* GetPushBuffer() { 156 | return &m_buffer[m_pushIndex]; 157 | } 158 | 159 | const char* GetPushBuffer() const { 160 | return &m_buffer[m_pushIndex]; 161 | } 162 | }; 163 | 164 | DECL_NAMESPACE_MZ_SHARE_END 165 | 166 | #endif // _MZ_SHARE_PIECEBUFFER_HPP_ 167 | -------------------------------------------------------------------------------- /Metazion/Share/Memory/RingBuffer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_RINGBUFFER_HPP_ 2 | #define _MZ_SHARE_RINGBUFFER_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | DECL_NAMESPACE_MZ_SHARE_BEGIN 7 | 8 | template 9 | class RingBuffer { 10 | MZ_DISALLOW_COPY_AND_ASSIGN(RingBuffer) 11 | 12 | private: 13 | char m_buffer[MAXLENGTH]{ 0 }; 14 | int m_length{ 0 }; 15 | int m_pushIndex{ 0 }; 16 | int m_pullIndex{ 0 }; 17 | 18 | public: 19 | RingBuffer() {} 20 | 21 | ~RingBuffer() {} 22 | 23 | public: 24 | void Reset() { 25 | memset(m_buffer, 0, sizeof(m_buffer)); 26 | m_length = 0; 27 | m_pushIndex = 0; 28 | m_pullIndex = 0; 29 | } 30 | 31 | int Push(const void* data, int length) { 32 | const auto buffer = static_cast(data); 33 | const auto vacant = GetPushLength(); 34 | const auto properLength = vacant < length ? vacant : length; 35 | if (properLength <= 0) { 36 | return 0; 37 | } 38 | 39 | const auto rightLength = MAXLENGTH - m_pushIndex; 40 | if (properLength <= rightLength) { 41 | memcpy(&m_buffer[m_pushIndex], buffer, properLength); 42 | m_pushIndex += properLength; 43 | } 44 | else { 45 | memcpy(&m_buffer[m_pushIndex], buffer, rightLength); 46 | memcpy(m_buffer, &buffer[rightLength], properLength - rightLength); 47 | m_pushIndex = properLength - rightLength; 48 | } 49 | 50 | m_pushIndex %= MAXLENGTH; 51 | m_length += properLength; 52 | return properLength; 53 | } 54 | 55 | int Pull(void* data, int length) { 56 | auto buffer = static_cast(data); 57 | 58 | const auto engaged = GetPullLength(); 59 | const auto properLength = engaged < length ? engaged : length; 60 | if (properLength <= 0) { 61 | return 0; 62 | } 63 | 64 | const auto rightLength = MAXLENGTH - m_pullIndex; 65 | if (properLength <= rightLength) { 66 | memcpy(buffer, &m_buffer[m_pullIndex], properLength); 67 | m_pullIndex += properLength; 68 | } 69 | else { 70 | memcpy(buffer, &m_buffer[m_pullIndex], rightLength); 71 | memcpy(&buffer[rightLength], m_buffer, properLength - rightLength); 72 | m_pullIndex = properLength - rightLength; 73 | } 74 | 75 | m_pullIndex %= MAXLENGTH; 76 | m_length -= properLength; 77 | return properLength; 78 | } 79 | 80 | int Peek(void* data, int length) { 81 | auto buffer = static_cast(data); 82 | 83 | const auto engaged = GetPullLength(); 84 | const auto properLength = engaged < length ? engaged : length; 85 | if (properLength <= 0) { 86 | return 0; 87 | } 88 | 89 | const auto rightLength = MAXLENGTH - m_pullIndex; 90 | if (properLength <= rightLength) { 91 | memcpy(buffer, &m_buffer[m_pullIndex], properLength); 92 | } 93 | else { 94 | memcpy(buffer, &m_buffer[m_pullIndex], rightLength); 95 | memcpy(&buffer[rightLength], m_buffer, properLength - rightLength); 96 | } 97 | 98 | return properLength; 99 | } 100 | 101 | int Skip(int length) { 102 | const auto engaged = GetPullLength(); 103 | const auto properLength = engaged < length ? engaged : length; 104 | if (properLength <= 0) { 105 | return 0; 106 | } 107 | 108 | m_pullIndex = (m_pullIndex + properLength) % MAXLENGTH; 109 | m_length -= properLength; 110 | return properLength; 111 | } 112 | 113 | bool IsEmpty() const { return m_length == 0; } 114 | 115 | bool IsFull() const { return m_length == MAXLENGTH; } 116 | 117 | int GetCapacity() const { return MAXLENGTH; } 118 | 119 | int GetPushLength() const { return MAXLENGTH - m_length; } 120 | 121 | int GetPullLength() const { return m_length; } 122 | }; 123 | 124 | DECL_NAMESPACE_MZ_SHARE_END 125 | 126 | #endif // _MZ_SHARE_RINGBUFFER_HPP_ 127 | -------------------------------------------------------------------------------- /Metazion/Share/Memory/StepAllocator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_STEPALLOCATOR_HPP_ 2 | #define _MZ_SHARE_STEPALLOCATOR_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | #include "Metazion/Share/Collection/UDSelfList.hpp" 7 | #include "Metazion/Share/Memory/MemoryPiece.hpp" 8 | 9 | DECL_NAMESPACE_MZ_SHARE_BEGIN 10 | 11 | template 14 | class StepAllocator { 15 | MZ_DISALLOW_COPY_AND_ASSIGN(StepAllocator) 16 | 17 | using UnitNode_t = UDSelfListNode; 18 | using UnitList_t = UDSelfList; 19 | 20 | enum { 21 | MINLENGTH = MZ_MAX(UNITLENGTH, sizeof(UnitNode_t)), 22 | ALIGNLENGTH = MZ_ALIGN_LENGTH(MINLENGTH, MZ_DEFAULT_ALIGNMENT), 23 | }; 24 | 25 | using Piece_t = MemoryPiece; 26 | using PieceNode_t = UDSelfListNode; 27 | using PieceList_t = UDSelfList; 28 | 29 | public: 30 | template 31 | using Rebind = StepAllocator; 32 | 33 | private: 34 | PieceList_t m_fullPieceList; 35 | PieceList_t m_availPieceList; 36 | UnitList_t m_freeUnitList; 37 | 38 | public: 39 | StepAllocator() {} 40 | 41 | ~StepAllocator() { 42 | m_freeUnitList.Clear(); 43 | m_fullPieceList.Clear(); 44 | m_availPieceList.Clear(); 45 | } 46 | 47 | public: 48 | void* Alloc() { 49 | auto unitNode = m_freeUnitList.Front(); 50 | if (!IsNull(unitNode)) { 51 | m_freeUnitList.PopFront(); 52 | return unitNode; 53 | } 54 | 55 | auto pieceNode = m_availPieceList.Front(); 56 | if (IsNull(pieceNode)) { 57 | pieceNode = CreatePieceNode(); 58 | m_availPieceList.PushBack(pieceNode); 59 | } 60 | 61 | auto& piece = pieceNode->m_value; 62 | auto memory = piece.Obtain(); 63 | if (!piece.IsAvaliable()) { 64 | m_availPieceList.PopFront(); 65 | m_fullPieceList.PushBack(pieceNode); 66 | } 67 | 68 | return memory; 69 | } 70 | 71 | void Free(void* memory) { 72 | UnitNode_t* unitNode = static_cast(memory); 73 | m_freeUnitList.PushBack(unitNode); 74 | } 75 | 76 | private: 77 | PieceNode_t* CreatePieceNode() { 78 | return new PieceNode_t(); 79 | } 80 | 81 | void DestoryPieceNode(PieceNode_t* object) { 82 | SafeDelete(object); 83 | } 84 | }; 85 | 86 | DECL_NAMESPACE_MZ_SHARE_END 87 | 88 | #endif // _MZ_SHARE_STEPALLOCATOR_HPP_ 89 | -------------------------------------------------------------------------------- /Metazion/Share/Misc/MemoryInputStream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_MEMORYINPUTSTREAM_HPP_ 2 | #define _MZ_SHARE_MEMORYINPUTSTREAM_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | DECL_NAMESPACE_MZ_SHARE_BEGIN 7 | 8 | class MemoryInputStream { 9 | MZ_DISALLOW_COPY_AND_ASSIGN(MemoryInputStream); 10 | 11 | private: 12 | const char* m_buffer{ nullptr }; 13 | int m_length{ 0 }; 14 | int m_position{ 0 }; 15 | 16 | public: 17 | MemoryInputStream() {} 18 | 19 | ~MemoryInputStream() {} 20 | 21 | public: 22 | void Attach(const void* buffer, int length) { 23 | MZ_ASSERT_TRUE(!IsNull(buffer)); 24 | MZ_ASSERT_TRUE(length > 0); 25 | 26 | m_buffer = static_cast(buffer); 27 | m_length = length; 28 | m_position = 0; 29 | } 30 | 31 | void Detach() { 32 | m_buffer = nullptr; 33 | m_length = 0; 34 | m_position = 0; 35 | } 36 | 37 | void Seek(int position) { 38 | MZ_ASSERT_TRUE(position >= 0 && position < m_length); 39 | 40 | m_position = position; 41 | } 42 | 43 | bool ReadInt8(int8_t& arg) { 44 | return Read(&arg, sizeof(arg)); 45 | } 46 | 47 | bool ReadUint8(uint8_t& arg) { 48 | return Read(&arg, sizeof(arg)); 49 | } 50 | 51 | bool ReadInt16(int16_t& arg) { 52 | return Read(&arg, sizeof(arg)); 53 | } 54 | 55 | bool ReadUint16(uint16_t& arg) { 56 | return Read(&arg, sizeof(arg)); 57 | } 58 | 59 | bool ReadInt32(int32_t& arg) { 60 | return Read(&arg, sizeof(arg)); 61 | } 62 | 63 | bool ReadUint32(uint32_t& arg) { 64 | return Read(&arg, sizeof(arg)); 65 | } 66 | 67 | bool ReadInt64(int64_t& arg) { 68 | return Read(&arg, sizeof(arg)); 69 | } 70 | 71 | bool ReadUint64(uint64_t& arg) { 72 | return Read(&arg, sizeof(arg)); 73 | } 74 | 75 | bool ReadFloat(float& arg) { 76 | return Read(&arg, sizeof(arg)); 77 | } 78 | 79 | bool ReadDouble(double& arg) { 80 | return Read(&arg, sizeof(arg)); 81 | } 82 | 83 | bool ReadString(char* buffer, int length) { 84 | MZ_ASSERT_TRUE(!IsNull(buffer)); 85 | MZ_ASSERT_TRUE(length > 0); 86 | 87 | int16_t strLength = 0; 88 | if (!ReadInt16(strLength)) { 89 | return false; 90 | } 91 | 92 | if (length < strLength + 1) { 93 | return false; 94 | } 95 | 96 | if (strLength == 0) { 97 | buffer[0] = '\0'; 98 | return true; 99 | } 100 | 101 | if (!Read(buffer, strLength)) { 102 | return false; 103 | } 104 | 105 | buffer[strLength] = '\0'; 106 | return true; 107 | } 108 | 109 | bool ReadString32(char* buffer, int length) { 110 | MZ_ASSERT_TRUE(!IsNull(buffer)); 111 | MZ_ASSERT_TRUE(length > 0); 112 | 113 | int strLength = 0; 114 | if (!ReadInt32(strLength)) { 115 | return false; 116 | } 117 | 118 | if (length < strLength + 1) { 119 | return false; 120 | } 121 | 122 | if (strLength == 0) { 123 | buffer[0] = '\0'; 124 | return true; 125 | } 126 | 127 | if (!Read(buffer, strLength)) { 128 | return false; 129 | } 130 | 131 | buffer[strLength] = '\0'; 132 | return true; 133 | } 134 | 135 | bool Read(void* buffer, int length) { 136 | if (!Check(length)) { 137 | return false; 138 | } 139 | 140 | memcpy(buffer, m_buffer + m_position, length); 141 | m_position += length; 142 | return true; 143 | } 144 | 145 | 146 | private: 147 | bool Check(int length) const { 148 | return m_position + length <= m_length; 149 | } 150 | }; 151 | 152 | DECL_NAMESPACE_MZ_SHARE_END 153 | 154 | #endif // _MZ_SHARE_MEMORYINPUTSTREAM_HPP_ 155 | -------------------------------------------------------------------------------- /Metazion/Share/Misc/MemoryOutputStream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_MEMORYOUTPUTSTREAM_HPP_ 2 | #define _MZ_SHARE_MEMORYOUTPUTSTREAM_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | DECL_NAMESPACE_MZ_SHARE_BEGIN 7 | 8 | template 9 | class MemoryOutputStream { 10 | MZ_DISALLOW_COPY_AND_ASSIGN(MemoryOutputStream); 11 | 12 | private: 13 | char m_buffer[MAXLENGTH]{ 0 }; 14 | int m_position{ 0 }; 15 | 16 | public: 17 | MemoryOutputStream() {} 18 | 19 | ~MemoryOutputStream() {} 20 | 21 | public: 22 | const char* GetBuffer() const { 23 | return m_buffer; 24 | } 25 | 26 | int GetLength() const { 27 | return m_position; 28 | } 29 | 30 | void Seek(int position) { 31 | MZ_ASSERT_TRUE(position >= 0 && position < MAXLENGTH); 32 | 33 | m_position = position; 34 | } 35 | 36 | bool WriteInt8(int8_t value) { 37 | return Write(&value, sizeof(value)); 38 | } 39 | 40 | bool WriteUint8(uint8_t value) { 41 | return Write(&value, sizeof(value)); 42 | } 43 | 44 | bool WriteInt16(int16_t value) { 45 | return Write(&value, sizeof(value)); 46 | } 47 | 48 | bool WriteUint16(uint16_t value) { 49 | return Write(&value, sizeof(value)); 50 | } 51 | 52 | bool WriteInt32(int32_t value) { 53 | return Write(&value, sizeof(value)); 54 | } 55 | 56 | bool WriteUint32(uint32_t value) { 57 | return Write(&value, sizeof(value)); 58 | } 59 | 60 | bool WriteInt64(int64_t value) { 61 | return Write(&value, sizeof(value)); 62 | } 63 | 64 | bool WriteUint64(uint64_t value) { 65 | return Write(&value, sizeof(value)); 66 | } 67 | 68 | bool WriteFloat(float value) { 69 | return Write(&value, sizeof(value)); 70 | } 71 | 72 | bool WriteDouble(double value) { 73 | return Write(&value, sizeof(value)); 74 | } 75 | 76 | bool WriteString(const char* buffer, int length) { 77 | MZ_ASSERT_TRUE(!IsNull(buffer)); 78 | MZ_ASSERT_TRUE(length >= 0); 79 | 80 | if (!WriteInt16(length)) { 81 | return true; 82 | } 83 | 84 | if (length == 0) { 85 | return true; 86 | } 87 | 88 | if (!Write(buffer, length)) { 89 | return false; 90 | } 91 | 92 | return true; 93 | } 94 | 95 | bool WriteString32(const char* buffer, int length) { 96 | MZ_ASSERT_TRUE(!IsNull(buffer)); 97 | MZ_ASSERT_TRUE(length >= 0); 98 | 99 | if (!WriteInt32(length)) { 100 | return true; 101 | } 102 | 103 | if (length == 0) { 104 | return true; 105 | } 106 | 107 | if (!Write(buffer, length)) { 108 | return false; 109 | } 110 | 111 | return true; 112 | } 113 | 114 | bool Write(const void* buffer, int length) { 115 | if (!Check(length)) { 116 | return false; 117 | } 118 | 119 | memcpy(m_buffer + m_position, buffer, length); 120 | m_position += length; 121 | return true; 122 | } 123 | 124 | private: 125 | bool Check(int length) const { 126 | return m_position + length <= MAXLENGTH; 127 | } 128 | }; 129 | 130 | DECL_NAMESPACE_MZ_SHARE_END 131 | 132 | #endif // _MZ_SHARE_MEMORYOUTPUTSTREAM_HPP_ 133 | -------------------------------------------------------------------------------- /Metazion/Share/Pattern/Singleton.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_SINGLETON_HPP_ 2 | #define _MZ_SHARE_SINGLETON_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | DECL_NAMESPACE_MZ_SHARE_BEGIN 7 | 8 | template 9 | class Singleton { 10 | MZ_DISALLOW_COPY_AND_ASSIGN(Singleton); 11 | 12 | protected: 13 | Singleton() {} 14 | 15 | virtual ~Singleton() {} 16 | 17 | public: 18 | static T& Instance() { static T t; return t; } 19 | 20 | static T* Pointer() { return &Instance(); } 21 | }; 22 | 23 | DECL_NAMESPACE_MZ_SHARE_END 24 | 25 | #endif // _MZ_SHARE_SINGLETON_HPP_ 26 | -------------------------------------------------------------------------------- /Metazion/Share/ShareInclude.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_INCLUDE_HPP_ 2 | #define _MZ_SHARE_INCLUDE_HPP_ 3 | 4 | #include "Metazion/Overall.hpp" 5 | 6 | #define DECL_NAMESPACE_MZ_SHARE_BEGIN namespace mz { namespace share { 7 | #define DECL_NAMESPACE_MZ_SHARE_END } } 8 | #define USING_NAMESPACE_MZ_SHARE using namespace mz::share; 9 | #define USING_NAMESPACE_SHARE using namespace share; 10 | #define NS_MZ_SHARE mz::share 11 | #define NS_SHARE share 12 | 13 | #endif // _MZ_SHARE_INCLUDE_HPP_ 14 | -------------------------------------------------------------------------------- /Metazion/Share/Sync/NoneLock.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_NONELOCK_HPP_ 2 | #define _MZ_SHARE_NONELOCK_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | #include 7 | 8 | DECL_NAMESPACE_MZ_SHARE_BEGIN 9 | 10 | class NoneLock { 11 | MZ_DISALLOW_COPY_AND_ASSIGN(NoneLock) 12 | 13 | public: 14 | NoneLock() {} 15 | 16 | ~NoneLock() {} 17 | 18 | public: 19 | void lock() {} 20 | 21 | bool try_lock() { return true; } 22 | 23 | void unlock() {} 24 | }; 25 | 26 | DECL_NAMESPACE_MZ_SHARE_END 27 | 28 | #endif // _MZ_SHARE_NONELOCK_HPP_ 29 | -------------------------------------------------------------------------------- /Metazion/Share/Thread/Thread.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Share/Thread/Thread.hpp" 2 | 3 | DECL_NAMESPACE_MZ_SHARE_BEGIN 4 | 5 | Thread::Thread() {} 6 | 7 | Thread::~Thread() {} 8 | 9 | void Thread::Run() { 10 | m_thread = std::thread(&Thread::ThreadFunc, this); 11 | } 12 | 13 | void Thread::Join() { 14 | if (m_thread.joinable()) { 15 | m_thread.join(); 16 | } 17 | } 18 | 19 | void Thread::Detach() { 20 | m_thread.detach(); 21 | } 22 | 23 | void Thread::ThreadFunc() { 24 | Execute(); 25 | } 26 | 27 | DECL_NAMESPACE_MZ_SHARE_END 28 | -------------------------------------------------------------------------------- /Metazion/Share/Thread/Thread.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_THREAD_HPP_ 2 | #define _MZ_SHARE_THREAD_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | #include 7 | 8 | DECL_NAMESPACE_MZ_SHARE_BEGIN 9 | 10 | class Thread { 11 | MZ_DISALLOW_COPY_AND_ASSIGN(Thread) 12 | 13 | private: 14 | std::thread m_thread; 15 | 16 | public: 17 | Thread(); 18 | 19 | virtual ~Thread(); 20 | 21 | public: 22 | void Run(); 23 | 24 | void Join(); 25 | 26 | void Detach(); 27 | 28 | std::thread::id GetThreadId() const; 29 | 30 | protected: 31 | virtual void Execute() = 0; 32 | 33 | private: 34 | void ThreadFunc(); 35 | }; 36 | 37 | inline std::thread::id Thread::GetThreadId() const { 38 | return m_thread.get_id(); 39 | } 40 | 41 | DECL_NAMESPACE_MZ_SHARE_END 42 | 43 | #endif // _MZ_SHARE_THREAD_HPP_ 44 | -------------------------------------------------------------------------------- /Metazion/Share/Time/Time.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Share/Time/Time.hpp" 2 | 3 | #include 4 | #include 5 | 6 | using namespace std::chrono; 7 | 8 | DECL_NAMESPACE_MZ_SHARE_BEGIN 9 | 10 | int64_t GetNowMillisecond() { 11 | const auto timePoint = system_clock::now(); 12 | const auto timeDuration = timePoint.time_since_epoch(); 13 | return duration_cast(timeDuration).count(); 14 | } 15 | 16 | int64_t GetNowMicrosecond() { 17 | const auto timePoint = system_clock::now(); 18 | const auto timeDuration = timePoint.time_since_epoch(); 19 | return duration_cast(timeDuration).count(); 20 | } 21 | 22 | Calendar TimeToLocalCalendar(int64_t ms) { 23 | const auto td = std::chrono::milliseconds(ms); 24 | const auto tp = std::chrono::time_point(td); 25 | const auto tt = std::chrono::system_clock::to_time_t(tp); 26 | const auto lt = std::localtime(&tt); 27 | Calendar calendar; 28 | calendar.m_year = lt->tm_year + 1900; 29 | calendar.m_month = lt->tm_mon + 1; 30 | calendar.m_day = lt->tm_mday; 31 | calendar.m_hour = lt->tm_hour; 32 | calendar.m_minute = lt->tm_min; 33 | calendar.m_second = lt->tm_sec; 34 | calendar.m_dayOfWeek = lt->tm_wday; 35 | calendar.m_dayOfYear = lt->tm_yday; 36 | return calendar; 37 | } 38 | 39 | int64_t CalendarToLocalTime(const Calendar& calendar) { 40 | tm lt; 41 | lt.tm_year = calendar.m_year - 1900; 42 | lt.tm_mon = calendar.m_month - 1; 43 | lt.tm_mday = calendar.m_day; 44 | lt.tm_hour = calendar.m_hour; 45 | lt.tm_min = calendar.m_minute; 46 | lt.tm_sec = calendar.m_second; 47 | const auto tt = std::mktime(<); 48 | const auto tp = system_clock::from_time_t(tt); 49 | const auto td = tp.time_since_epoch(); 50 | const auto ms = duration_cast(td).count(); 51 | return ms; 52 | } 53 | 54 | DECL_NAMESPACE_MZ_SHARE_END 55 | -------------------------------------------------------------------------------- /Metazion/Share/Time/Time.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_TIME_HPP_ 2 | #define _MZ_SHARE_TIME_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | DECL_NAMESPACE_MZ_SHARE_BEGIN 7 | 8 | struct Calendar { 9 | 10 | Calendar() {} 11 | 12 | Calendar(int year, int month, int day, int hour, int minute, int second) 13 | : m_year(year) 14 | , m_month(month) 15 | , m_day(day) 16 | , m_hour(hour) 17 | , m_minute(minute) 18 | , m_second(second) {} 19 | 20 | int m_year{ 0 }; 21 | int m_month{ 0 }; 22 | int m_day{ 0 }; 23 | int m_hour{ 0 }; 24 | int m_minute{ 0 }; 25 | int m_second{ 0 }; 26 | int m_dayOfWeek{ 0 }; 27 | int m_dayOfYear{ 0 }; 28 | }; 29 | 30 | int64_t GetNowMillisecond(); 31 | 32 | int64_t GetNowMicrosecond(); 33 | 34 | Calendar TimeToLocalCalendar(int64_t ms); 35 | 36 | int64_t CalendarToLocalTime(const Calendar& calendar); 37 | 38 | DECL_NAMESPACE_MZ_SHARE_END 39 | 40 | #endif // _MZ_SHARE_TIME_HPP_ 41 | -------------------------------------------------------------------------------- /Metazion/Share/Utility/Random.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Share/Utility/Random.hpp" 2 | 3 | DECL_NAMESPACE_MZ_SHARE_BEGIN 4 | 5 | Random::Random() { 6 | m_randomEngine = std::mt19937(m_randomDevice()); 7 | } 8 | 9 | Random::~Random() {} 10 | 11 | int Random::GetRangeInt(int begin, int end) { 12 | MZ_ASSERT_TRUE(begin <= end); 13 | 14 | if (begin >= end) { 15 | return begin; 16 | } 17 | 18 | std::uniform_int_distribution distribution(begin, end); 19 | return distribution(m_randomEngine); 20 | } 21 | 22 | double Random::GetRangeDouble(double begin, double end) { 23 | MZ_ASSERT_TRUE(begin <= end); 24 | 25 | if (begin >= end) { 26 | return begin; 27 | } 28 | 29 | std::uniform_real_distribution distribution(begin, end); 30 | return distribution(m_randomEngine); 31 | } 32 | 33 | DECL_NAMESPACE_MZ_SHARE_END 34 | -------------------------------------------------------------------------------- /Metazion/Share/Utility/Random.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_RANDOM_HPP_ 2 | #define _MZ_SHARE_RANDOM_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | #include 7 | 8 | DECL_NAMESPACE_MZ_SHARE_BEGIN 9 | 10 | class Random { 11 | MZ_DISALLOW_COPY_AND_ASSIGN(Random) 12 | 13 | using RandomDevice_t = std::random_device; 14 | using RandomEngine_t = std::mt19937; 15 | 16 | private: 17 | RandomDevice_t m_randomDevice; 18 | RandomEngine_t m_randomEngine; 19 | 20 | public: 21 | Random(); 22 | 23 | ~Random(); 24 | 25 | public: 26 | // value range: [begin, end] 27 | int GetRangeInt(int begin, int end); 28 | 29 | // value range: [begin, end) 30 | double GetRangeDouble(double begin, double end); 31 | }; 32 | 33 | DECL_NAMESPACE_MZ_SHARE_END 34 | 35 | #endif // _MZ_SHARE_RANDOM_HPP_ 36 | -------------------------------------------------------------------------------- /Metazion/Share/Utility/StringFunction.cpp: -------------------------------------------------------------------------------- 1 | #include "Metazion/Share/Utility/StringFunction.hpp" 2 | 3 | DECL_NAMESPACE_MZ_SHARE_BEGIN 4 | 5 | int mzstrlen(const char* str) { 6 | MZ_ASSERT_TRUE(!IsNull(str)); 7 | 8 | auto count = 0; 9 | while (*str++ != '\0') { 10 | ++count; 11 | } 12 | 13 | return count; 14 | } 15 | 16 | char* mzstrcpy(char* dst, int size, const char* src) { 17 | MZ_ASSERT_TRUE(!IsNull(dst)); 18 | MZ_ASSERT_TRUE(!IsNull(src)); 19 | MZ_ASSERT_TRUE(size > 0); 20 | 21 | auto ptr = dst; 22 | auto count = size; 23 | while (count > 1 && (*ptr++ = *src++) != '\0') { 24 | --count; 25 | } 26 | 27 | dst[size - 1] = '\0'; 28 | return dst; 29 | } 30 | 31 | char* mzstrcat(char* dst, int size, const char* src) { 32 | MZ_ASSERT_TRUE(!IsNull(dst)); 33 | MZ_ASSERT_TRUE(!IsNull(src)); 34 | MZ_ASSERT_TRUE(size > 0); 35 | 36 | auto ptr = dst; 37 | auto count = size; 38 | while (count > 1 && *ptr != '\0') { 39 | --count; 40 | ++ptr; 41 | } 42 | 43 | while (count > 1 && (*ptr++ = *src++) != '\0') { 44 | --count; 45 | } 46 | 47 | dst[size - 1] = '\0'; 48 | return dst; 49 | } 50 | 51 | DECL_NAMESPACE_MZ_SHARE_END 52 | -------------------------------------------------------------------------------- /Metazion/Share/Utility/StringFunction.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_SHARE_STRINGFUNCTION_HPP_ 2 | #define _MZ_SHARE_STRINGFUNCTION_HPP_ 3 | 4 | #include "Metazion/Share/ShareInclude.hpp" 5 | 6 | DECL_NAMESPACE_MZ_SHARE_BEGIN 7 | 8 | int mzstrlen(const char* str); 9 | 10 | char* mzstrcpy(char* dst, int size, const char* src); 11 | 12 | char* mzstrcat(char* dst, int size, const char* src); 13 | 14 | DECL_NAMESPACE_MZ_SHARE_END 15 | 16 | #endif // _MZ_SHARE_STRINGFUNCTION_HPP_ 17 | -------------------------------------------------------------------------------- /Metazion/Type.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _MZ_TYPE_HPP_ 2 | #define _MZ_TYPE_HPP_ 3 | 4 | #include "Metazion/CoreInclude.hpp" 5 | 6 | DECL_NAMESPACE_MZ_BEGIN 7 | 8 | template 9 | struct LessCompare { 10 | int operator ()(const T& left, const T& right) const { 11 | if (left < right) { 12 | return -1; 13 | } 14 | else if (left > right) { 15 | return 1; 16 | } 17 | else { 18 | return 0; 19 | } 20 | } 21 | }; 22 | 23 | template 24 | struct GreaterCompare { 25 | int operator ()(const T& left, const T& right) const { 26 | if (left > right) { 27 | return -1; 28 | } 29 | else if (left < right) { 30 | return 1; 31 | } 32 | else { 33 | return 0; 34 | } 35 | } 36 | }; 37 | 38 | template 41 | struct Pair { 42 | using First_t = FirstType; 43 | using Second_t = SecondType; 44 | 45 | First_t first; 46 | Second_t second; 47 | 48 | Pair() {} 49 | 50 | Pair(const First_t& first, const Second_t& second) 51 | : first(first) 52 | , second(second) {} 53 | 54 | Pair(const Pair& other) 55 | : first(other.first) 56 | , second(other.second) {} 57 | 58 | Pair& operator =(const Pair& other) { 59 | if (&other != this) { 60 | first = other.first; 61 | second = other.second; 62 | } 63 | return *this; 64 | } 65 | }; 66 | 67 | template 69 | > 70 | struct PairCompare { 71 | using Pair_t = PairType; 72 | using Compare_t = CompareType; 73 | 74 | Compare_t m_compare; 75 | 76 | int operator ()(const Pair_t& left, const Pair_t& right) const { 77 | return m_compare(left.first, right.first); 78 | } 79 | }; 80 | 81 | DECL_NAMESPACE_MZ_END 82 | 83 | #endif // _MZ_TYPE_HPP_ 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Metazion 2 | 3 | Metazion Library 4 | -------------------------------------------------------------------------------- /lcmake.sh: -------------------------------------------------------------------------------- 1 | rm -rf Build/Linux 2 | mkdir -p Build/Linux 3 | cd Build/Linux 4 | cmake -G "Unix Makefiles" ../.. 5 | cd ../.. 6 | -------------------------------------------------------------------------------- /mcmake.sh: -------------------------------------------------------------------------------- 1 | rm -rf Build/Macos 2 | mkdir -p Build/Macos 3 | cd Build/Macos 4 | cmake -G "Xcode" ../.. 5 | cd ../.. -------------------------------------------------------------------------------- /wcmake.sh: -------------------------------------------------------------------------------- 1 | rm -rf Build/Windows 2 | mkdir -p Build/Windows 3 | cd Build/Windows 4 | cmake -G "Visual Studio 16 2019" ../.. 5 | cd ../.. --------------------------------------------------------------------------------