├── .gitignore ├── CMakeLists.txt ├── async ├── CMakeLists.txt ├── async │ ├── async.cpp │ ├── async.h │ ├── comm.hpp │ ├── cpu │ │ ├── async_cpu.cpp │ │ ├── async_cpu.h │ │ ├── async_cpu2.cpp │ │ └── module.cpp │ ├── curl │ │ ├── async_curl.cpp │ │ ├── async_curl.h │ │ ├── callback.cpp │ │ ├── callback.h │ │ ├── curl_parser.cpp │ │ ├── curl_parser.h │ │ ├── data.cpp │ │ ├── data.h │ │ ├── module.cpp │ │ ├── op.cpp │ │ └── op.h │ ├── mongo │ │ ├── async_mongo.cpp │ │ ├── async_mongo.h │ │ ├── data.cpp │ │ ├── data.h │ │ ├── module.cpp │ │ ├── mongo_cmd.cpp │ │ ├── mongo_cmd.h │ │ ├── mongo_reply_parser.cpp │ │ ├── mongo_reply_parser.h │ │ ├── mongo_struct.cpp │ │ ├── mongo_struct.h │ │ ├── op.cpp │ │ └── op.h │ ├── mysql │ │ ├── async_mysql.cpp │ │ ├── async_mysql.h │ │ ├── callback.cpp │ │ ├── callback.h │ │ ├── data.cpp │ │ ├── data.h │ │ ├── module.cpp │ │ ├── mysql_reply_parser.cpp │ │ └── mysql_reply_parser.h │ ├── rabbitmq │ │ ├── async_rabbitmq.cpp │ │ ├── async_rabbitmq.h │ │ ├── data.cpp │ │ ├── data.h │ │ ├── module.cpp │ │ ├── op.cpp │ │ ├── op.h │ │ ├── rabbitmq_cmd..cpp │ │ ├── rabbitmq_cmd.h │ │ ├── rabbitmq_parser.cpp │ │ └── rabbitmq_parser.h │ ├── redis │ │ ├── async_redis.cpp │ │ ├── async_redis.h │ │ ├── callback.cpp │ │ ├── callback.h │ │ ├── cluster.cpp │ │ ├── data.cpp │ │ ├── data.h │ │ ├── module.cpp │ │ ├── noncluster.cpp │ │ ├── redis_cmd.cpp │ │ ├── redis_cmd.h │ │ ├── redis_exception.cpp │ │ ├── redis_exception.h │ │ ├── redis_parser.cpp │ │ └── redis_parser.h │ └── zookeeper │ │ ├── async_zookeeper.cpp │ │ ├── async_zookeeper.h │ │ ├── callback.cpp │ │ ├── callback.h │ │ ├── data.cpp │ │ ├── data.h │ │ ├── module.cpp │ │ ├── op.cpp │ │ ├── op.h │ │ ├── zook_cmd.cpp │ │ ├── zook_cmd.h │ │ ├── zook_parser.cpp │ │ └── zook_parser.h ├── co_async │ ├── async.cpp │ ├── async.h │ ├── comm.hpp │ ├── cpu │ │ ├── co_cpu.cpp │ │ └── co_cpu.h │ ├── curl │ │ ├── co_curl.cpp │ │ └── co_curl.h │ ├── ipc │ │ ├── co_ipc.cpp │ │ └── co_ipc.h │ ├── mongo │ │ ├── co_mongo.cpp │ │ └── co_mongo.h │ ├── mysql │ │ ├── co_mysql.cpp │ │ └── co_mysql.h │ ├── promise.cpp │ ├── promise.h │ ├── rabbitmq │ │ ├── co_rabbitmq.cpp │ │ └── co_rabbitmq.h │ ├── redis │ │ ├── co_redis.cpp │ │ └── co_redis.h │ ├── time_pool.cpp │ ├── time_pool.h │ └── zookeeper │ │ ├── co_zookeeper.cpp │ │ └── co_zookeeper.h ├── coroutine │ ├── config.hpp │ ├── coroutine.cpp │ ├── coroutine.h │ ├── coroutine.hpp │ ├── coroutine_linux.cpp │ ├── coroutine_task.cpp │ ├── coroutine_task.h │ ├── coroutine_win.cpp │ ├── svector.hpp │ └── tls.hpp ├── ipc │ ├── ipc.cpp │ ├── ipc.h │ ├── zero_mq_handler.cpp │ ├── zero_mq_handler.h │ ├── zero_mq_unit.cpp │ └── zero_mq_unit.h ├── log.cpp ├── log.h ├── net │ ├── event_base.cpp │ ├── event_base.h │ ├── http_listener.cpp │ ├── http_listener.h │ ├── tcp_client.cpp │ ├── tcp_client.h │ ├── tcp_listener.cpp │ ├── tcp_listener.h │ ├── udp_client.cpp │ ├── udp_client.h │ ├── udp_listener.cpp │ └── udp_listener.h ├── signal │ ├── sig.cpp │ └── sig.h ├── threads │ └── thread_pool.h ├── tls.hpp └── transaction │ ├── base_tick_transaction.cpp │ ├── base_tick_transaction.h │ ├── base_transaction.cpp │ ├── base_transaction.h │ ├── transaction_bucket.h │ ├── transaction_mgr.cpp │ └── transaction_mgr.h ├── example ├── CMakeLists.txt ├── co_parallel_test.cpp ├── common.h ├── cpu_test.cpp ├── curl_test.cpp ├── example.cpp ├── ipc_test.cpp ├── mongo_test.cpp ├── mysql_test.cpp ├── net_test.cpp ├── parallel_test.cpp ├── rabbit_test.cpp ├── redis_test.cpp └── zook_test.cpp ├── readme ├── serve ├── CMakeLists.txt ├── gate │ ├── CMakeLists.txt │ ├── gate.json │ └── main.cpp ├── router │ ├── CMakeLists.txt │ ├── main.cpp │ └── router.json ├── serve │ ├── CMakeLists.txt │ ├── backend.cpp │ ├── backend.h │ ├── backend_transaction.h │ ├── base.cpp │ ├── base.h │ ├── gate.cpp │ ├── gate.h │ ├── getopt.c │ ├── getopt.h │ ├── http.cpp │ ├── http.h │ ├── http_transaction.h │ ├── json.hpp │ ├── router.cpp │ ├── router.h │ ├── serve.cpp │ ├── serve.h │ └── serve.json ├── test │ ├── CMakeLists.txt │ └── main.cpp └── testhttp │ ├── CMakeLists.txt │ └── main.cpp └── tools └── excel2proto ├── gen_xls_mgr.py ├── loghelper.py ├── protoc.exe ├── run_me.py ├── sheet_reader.h └── xls_translator.py /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /.vscode 3 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | set(TARGET_NAME "test") 3 | project(${TARGET_NAME}) 4 | 5 | # 添加开启功能的宏 6 | #set(USE_ASYNC_CURL 1) 7 | #set(USE_ASYNC_REDIS 1) 8 | #set(USE_ASYNC_MONGO 1) 9 | #set(USE_ASYNC_MYSQL 1) 10 | #set(USE_IPC 1) 11 | #set(USE_NET 1) 12 | #set(USE_TRANS 1) 13 | 14 | 15 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 16 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 17 | 18 | set(PROJECT_LIB_TARGETS "async") 19 | 20 | add_subdirectory(async) 21 | add_subdirectory(example) 22 | add_subdirectory(serve) 23 | -------------------------------------------------------------------------------- /async/async/comm.hpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace async { 14 | 15 | // 模块结构 16 | struct AsyncModule { 17 | std::string name; 18 | // 主循环钩子 19 | std::function loopFunc; 20 | // 日志钩子 21 | std::function)> logFunc; 22 | // 线程钩子 23 | std::function)>)> thrFunc; 24 | }; 25 | 26 | // 注册模块 27 | bool regModule(const AsyncModule&); 28 | 29 | } 30 | 31 | // 注册异步模块 32 | #define REG_ASYNC_MODULE(mod) \ 33 | static bool ret_##__LINE__ = async::regModule(mod); 34 | 35 | -------------------------------------------------------------------------------- /async/async/cpu/async_cpu.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | #define CUR_CPU_VERSION (2) 14 | 15 | namespace async { 16 | namespace cpu { 17 | 18 | typedef std::function async_cpu_op; 19 | typedef std::function async_cpu_cb; 20 | 21 | void execute(async_cpu_op op, void* user_data, async_cpu_cb cb); 22 | 23 | bool loop(uint32_t curTime); 24 | 25 | void setThreadFunc(std::function)>); 26 | 27 | } 28 | } -------------------------------------------------------------------------------- /async/async/cpu/module.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #include "async/async/comm.hpp" 10 | #include "async/async/cpu/async_cpu.h" 11 | 12 | // 注册模块 13 | static async::AsyncModule mod = { 14 | // 名字 15 | "async_cpu", 16 | // 主循环钩子 17 | std::bind(async::cpu::loop, std::placeholders::_1), 18 | // 日志钩子 19 | nullptr, 20 | // 线程钩子 21 | std::bind(async::cpu::setThreadFunc, std::placeholders::_1) 22 | }; 23 | 24 | REG_ASYNC_MODULE(mod); -------------------------------------------------------------------------------- /async/async/curl/async_curl.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include "async/async/curl/curl_parser.h" 14 | 15 | #define CUR_CURL_VERSION (2) 16 | 17 | namespace async { 18 | namespace curl { 19 | 20 | // CURLcode, response_code, body 21 | typedef std::function async_curl_cb; 22 | 23 | typedef std::function async_curl_cb2; 24 | 25 | void get(const std::string &url, async_curl_cb cb, const std::unordered_map& headers = {}); 26 | void get(const std::string &url, async_curl_cb2 cb, const std::unordered_map& headers = {}); 27 | 28 | void post(const std::string& url, const std::string& content, async_curl_cb cb, const std::unordered_map& headers = {}); 29 | void post(const std::string& url, const std::string& content, async_curl_cb2 cb, const std::unordered_map& headers = {}); 30 | 31 | bool loop(uint32_t curTime); 32 | 33 | void setThreadFunc(std::function)>); 34 | 35 | void setMaxConnection(uint32_t c); 36 | 37 | }// curl 38 | }// async 39 | 40 | 41 | -------------------------------------------------------------------------------- /async/async/curl/callback.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_CURL 10 | 11 | #include "async/async/curl/data.h" 12 | 13 | namespace async { 14 | namespace curl { 15 | 16 | void onPushRsp(CurlRspDataPtr rsp, void* t) { 17 | CurlThreadData* tData = (CurlThreadData*)t; 18 | tData->rspLock.lock(); 19 | tData->rspQueue.push_back(rsp); 20 | tData->rspLock.unlock(); 21 | } 22 | 23 | size_t onWriteCb(void *buffer, size_t size, size_t count, void* param) { 24 | std::string* s = static_cast(param); 25 | if (nullptr == s) { 26 | return 0; 27 | } 28 | 29 | s->append(reinterpret_cast(buffer), size * count); 30 | return size * count; 31 | } 32 | 33 | } 34 | } 35 | 36 | #endif -------------------------------------------------------------------------------- /async/async/curl/callback.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | namespace async { 12 | namespace curl { 13 | 14 | void onPushRsp(CurlRspDataPtr rsp, void* t); 15 | 16 | size_t onWriteCb(void *buffer, size_t size, size_t count, void* param); 17 | 18 | } 19 | } -------------------------------------------------------------------------------- /async/async/curl/curl_parser.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_CURL 10 | 11 | #include "async/async/curl/curl_parser.h" 12 | #include 13 | 14 | namespace async { 15 | namespace curl { 16 | 17 | CurlParser::CurlParser(const std::string& value, int32_t curlCode, int32_t rspCode) { 18 | this->value = value; 19 | this->curlCode = curlCode; 20 | this->rspCode = rspCode; 21 | } 22 | 23 | void CurlParser::swapValue(std::string& value) { 24 | this->value.swap(value); 25 | } 26 | 27 | std::string& CurlParser::getValue() { 28 | return this->value; 29 | } 30 | 31 | int32_t CurlParser::getCurlCode() { 32 | return this->curlCode; 33 | } 34 | 35 | int32_t CurlParser::getRspCode() { 36 | return this->rspCode; 37 | } 38 | 39 | bool CurlParser::curlOk() { 40 | return this->curlCode == CURLE_OK; 41 | } 42 | 43 | } 44 | } 45 | 46 | #endif -------------------------------------------------------------------------------- /async/async/curl/curl_parser.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | namespace async { 15 | namespace curl { 16 | 17 | struct CurlParser { 18 | CurlParser(const std::string& value, int32_t curlCode, int32_t rspCode); 19 | 20 | void swapValue(std::string& value); 21 | 22 | std::string& getValue(); 23 | 24 | int32_t getCurlCode(); 25 | 26 | int32_t getRspCode(); 27 | 28 | // 库操作成功 29 | bool curlOk(); 30 | private: 31 | std::string value; 32 | // curl操作的错误码 33 | int32_t curlCode = 0; 34 | // http协议的错误码, 为0则表示服务器没有返回,一般是200是成功码 35 | int32_t rspCode = 0; 36 | }; 37 | 38 | typedef std::shared_ptr CurlParserPtr; 39 | 40 | } 41 | } -------------------------------------------------------------------------------- /async/async/curl/data.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_CURL 10 | 11 | #include "async/async/curl/data.h" 12 | #include 13 | 14 | namespace async { 15 | namespace curl { 16 | 17 | CurlReqData::~CurlReqData() { 18 | if (header) { 19 | curl_slist_free_all(header); 20 | } 21 | } 22 | 23 | CurlCore::~CurlCore() { 24 | if (curlm) { 25 | curl_multi_cleanup(curlm); 26 | } 27 | } 28 | 29 | } 30 | } 31 | 32 | #endif -------------------------------------------------------------------------------- /async/async/curl/data.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "async/async/curl/async_curl.h" 20 | #include "async/log.h" 21 | 22 | namespace async { 23 | namespace curl { 24 | 25 | enum HTTP_METHOD { 26 | METHOD_GET = 0, 27 | METHOD_POST, 28 | METHOD_PUT, 29 | }; 30 | 31 | // 请求 32 | struct CurlReqData { 33 | async_curl_cb cb; 34 | async_curl_cb2 cb2; 35 | int32_t method = 0; 36 | std::string url; 37 | std::unordered_map headers; 38 | struct curl_slist* header = 0; 39 | std::string postBody; 40 | std::string rspBody; 41 | void* tData = 0; 42 | ~CurlReqData(); 43 | }; 44 | 45 | typedef std::shared_ptr CurlReqDataPtr; 46 | 47 | // 回复 48 | struct CurlRspData { 49 | CurlParserPtr parser; 50 | CurlReqDataPtr req; 51 | }; 52 | 53 | typedef std::shared_ptr CurlRspDataPtr; 54 | 55 | struct CurlCore { 56 | CURLM* curlm = 0; 57 | std::atomic task; 58 | bool running = false; 59 | clock_t lastRunTime = 0; 60 | std::unordered_map curlMap; 61 | std::list waitQueue; 62 | std::mutex waitLock; 63 | ~CurlCore(); 64 | }; 65 | 66 | typedef std::shared_ptr CurlCorePtr; 67 | 68 | struct CorePool { 69 | uint32_t polling = 0; // 轮询索引 70 | std::vector valid; 71 | }; 72 | 73 | struct GlobalData { 74 | // 连接池 75 | CorePool corePool; 76 | std::mutex pLock; 77 | 78 | // 分发标识 79 | std::atomic_flag dispatchTask; 80 | 81 | // 初始化标识 82 | bool init = false; 83 | 84 | // 最大连接数量 85 | uint32_t maxConnection = 0; 86 | 87 | GlobalData() :dispatchTask(ATOMIC_FLAG_INIT) {} 88 | }; 89 | 90 | struct CurlThreadData { 91 | // 请求任务的数量 92 | uint64_t reqTaskCnt = 0; 93 | // 回复任务的数量 94 | uint64_t rspTaskCnt = 0; 95 | // 请求队列 96 | std::list reqQueue; 97 | // 回复队列 98 | std::mutex rspLock; 99 | std::list rspQueue; 100 | uint32_t lastRunTime = 0; 101 | // 上一次统计输出时间 102 | time_t lastPrintTime = 0; 103 | // 初始化 104 | bool init = false; 105 | }; 106 | 107 | ///////////////////////////////////////////////////////////////////////// 108 | 109 | #define curlLog(format, ...) log("[async_curl] " format, __VA_ARGS__) 110 | 111 | } 112 | } -------------------------------------------------------------------------------- /async/async/curl/module.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_CURL 10 | 11 | #include "async/async/comm.hpp" 12 | #include "async/async/curl/async_curl.h" 13 | 14 | // 注册模块 15 | static async::AsyncModule mod = { 16 | // 名字 17 | "async_curl", 18 | // 主循环钩子 19 | std::bind(async::curl::loop, std::placeholders::_1), 20 | // 日志钩子 21 | nullptr, 22 | // 线程钩子 23 | std::bind(async::curl::setThreadFunc, std::placeholders::_1) 24 | }; 25 | 26 | REG_ASYNC_MODULE(mod); 27 | 28 | #endif -------------------------------------------------------------------------------- /async/async/curl/op.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_CURL 10 | 11 | #include "async/async/curl/data.h" 12 | #include "async/async/curl/curl_parser.h" 13 | #include "async/async/curl/callback.h" 14 | 15 | namespace async { 16 | namespace curl { 17 | 18 | void opRequest(CurlCorePtr c, CurlReqDataPtr req) { 19 | do { 20 | auto curl = curl_easy_init(); 21 | if (!curl) { 22 | curlLog("[error] failed to call curl_easy_init%s", ""); 23 | break; 24 | } 25 | 26 | curl_easy_setopt(curl, CURLOPT_VERBOSE, 0); 27 | curl_easy_setopt(curl, CURLOPT_URL, req->url.c_str()); 28 | curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); 29 | curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15); 30 | curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15); 31 | curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true); 32 | curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); 33 | curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); 34 | curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L); 35 | curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L); 36 | curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 120L); 37 | 38 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, &req->rspBody); 39 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, onWriteCb); 40 | 41 | if (req->method == METHOD_POST) { 42 | curl_easy_setopt(curl, CURLOPT_POST, 1); 43 | curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, req->postBody.size()); 44 | curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req->postBody.c_str()); 45 | } 46 | else if (req->method == METHOD_PUT) { 47 | curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); 48 | curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req->postBody.c_str()); 49 | } 50 | 51 | // set header 52 | struct curl_slist* curl_headers = 0; 53 | curl_headers = curl_slist_append(curl_headers, "connection: keep-alive"); 54 | for (const auto& header : req->headers) { 55 | curl_headers = curl_slist_append(curl_headers, (header.first + ": " + header.second).c_str()); 56 | } 57 | if (curl_headers) { 58 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers); 59 | } 60 | 61 | req->header = curl_headers; 62 | 63 | auto code = curl_multi_add_handle(c->curlm, curl); 64 | if (code != CURLM_OK) { 65 | curlLog("[error] failed to call curl_multi_add_handle: %d", code); 66 | break; 67 | } 68 | 69 | c->curlMap[curl] = req; 70 | return; 71 | } while (false); 72 | 73 | auto rsp = std::make_shared(); 74 | rsp->req = req; 75 | rsp->parser = std::make_shared("", CURLE_FAILED_INIT, 0); 76 | onPushRsp(rsp, req->tData); 77 | } 78 | 79 | } 80 | } 81 | 82 | #endif -------------------------------------------------------------------------------- /async/async/curl/op.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | namespace async { 12 | namespace curl { 13 | 14 | void opRequest(CurlCorePtr c, CurlReqDataPtr req); 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /async/async/mongo/async_mongo.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | /* 10 | * 每个io线程都维护了自己的连接池 11 | */ 12 | 13 | #pragma once 14 | 15 | #include 16 | #include "async/async/mongo/mongo_cmd.h" 17 | #include "async/async/mongo/mongo_reply_parser.h" 18 | 19 | namespace async { 20 | namespace mongo { 21 | 22 | typedef std::function async_mongo_cb; 23 | 24 | // @uri: addr|db|collection 25 | void execute(std::string uri, const BaseMongoCmd& cmd, async_mongo_cb cb); 26 | 27 | bool loop(uint32_t curTime); 28 | 29 | void setThreadFunc(std::function)>); 30 | 31 | } 32 | } -------------------------------------------------------------------------------- /async/async/mongo/data.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_MONGO 10 | 11 | #include "async/async/mongo/data.h" 12 | 13 | namespace async { 14 | 15 | // 声明 16 | void split(const std::string source, const std::string &separator, std::vector &array); 17 | 18 | namespace mongo { 19 | 20 | MongoAddr::MongoAddr(const std::string& uri) { 21 | Parse(uri); 22 | } 23 | 24 | void MongoAddr::Parse(const std::string &uri) { 25 | // 解析uri 26 | std::vector values; 27 | async::split(uri, "|", values); 28 | if (values.size() == 3) { 29 | this->host = values[0]; 30 | this->db = values[1]; 31 | this->collection = values[2]; 32 | this->id = this->host + "|" + this->db; 33 | } 34 | else { 35 | mongoLog("[async_mongo] [error] uri error:%s", uri.c_str()); 36 | assert(false); 37 | } 38 | } 39 | 40 | MongoConn::~MongoConn() { 41 | if (mongoc_uri) { 42 | mongoc_uri_destroy(mongoc_uri); 43 | } 44 | if (mongoc_client) { 45 | mongoc_client_destroy(mongoc_client); 46 | } 47 | } 48 | 49 | MongoCore::~MongoCore() { 50 | } 51 | 52 | CorePoolPtr GlobalData::getPool(const std::string& id) { 53 | CorePoolPtr pool; 54 | auto iter = this->corePool.find(id); 55 | if (iter == this->corePool.end()) { 56 | pool = std::make_shared(); 57 | this->corePool[id] = pool; 58 | } else { 59 | pool = iter->second; 60 | } 61 | return pool; 62 | } 63 | 64 | } 65 | } 66 | #endif -------------------------------------------------------------------------------- /async/async/mongo/data.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/async/mongo/async_mongo.h" 12 | #include "async/log.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | namespace async { 22 | 23 | uint32_t supposeIothread(); 24 | 25 | namespace mongo { 26 | 27 | // mongo地址结构 28 | struct MongoAddr { 29 | // @uri: [mongourl-db-collection] 30 | MongoAddr(const std::string& uri); 31 | 32 | void Parse(const std::string &uri); 33 | 34 | std::string id; 35 | std::string host; 36 | std::string db; 37 | std::string collection; 38 | std::string expire_filed; 39 | uint32_t expire_time = 0; 40 | }; 41 | 42 | typedef std::shared_ptr MongoAddrPtr; 43 | 44 | // 请求 45 | struct MongoReqData { 46 | MongoAddrPtr addr; 47 | BaseMongoCmd cmd; 48 | async_mongo_cb cb; 49 | time_t reqTime = 0; 50 | void* tData = 0; 51 | }; 52 | 53 | typedef std::shared_ptr MongoReqDataPtr; 54 | 55 | struct MongoRspData { 56 | MongoReqDataPtr req; 57 | MongoReplyParserPtr parser; 58 | }; 59 | 60 | typedef std::shared_ptr MongoRspDataPtr; 61 | 62 | struct MongoConn { 63 | mongoc_uri_t* mongoc_uri = 0; 64 | mongoc_client_t* mongoc_client = 0; 65 | ~MongoConn(); 66 | }; 67 | 68 | typedef std::shared_ptr MongoConnPtr; 69 | 70 | // mongo连接核心 71 | struct MongoCore { 72 | MongoConnPtr conn; 73 | MongoAddrPtr addr; 74 | std::atomic task; 75 | bool running = false; 76 | clock_t lastRunTime = 0; 77 | std::list waitQueue; 78 | std::mutex waitLock; 79 | ~MongoCore(); 80 | }; 81 | 82 | typedef std::shared_ptr MongoCorePtr; 83 | 84 | struct CorePool { 85 | uint32_t polling = 0; 86 | std::vector valid; 87 | }; 88 | 89 | typedef std::shared_ptr CorePoolPtr; 90 | 91 | struct GlobalData { 92 | // 连接池 93 | std::unordered_map corePool; 94 | std::mutex pLock; 95 | 96 | bool init = false; 97 | 98 | // 分发标识 99 | std::atomic_flag dispatchTask; 100 | 101 | GlobalData() :dispatchTask(ATOMIC_FLAG_INIT) {} 102 | 103 | CorePoolPtr getPool(const std::string& id); 104 | }; 105 | 106 | struct MongoThreadData { 107 | // 请求任务的数量 108 | uint64_t reqTaskCnt = 0; 109 | // 回复任务的数量 110 | uint64_t rspTaskCnt = 0; 111 | // 请求队列 112 | std::unordered_map> reqQueue; 113 | // 回复队列 114 | std::mutex rspLock; 115 | std::list rspQueue; 116 | uint32_t lastRunTime = 0; 117 | // 上一次统计输出时间 118 | time_t lastPrintTime = 0; 119 | // 初始化 120 | bool init = false; 121 | }; 122 | 123 | /////////////////////////////////////////////////////////////////////////////// 124 | 125 | #define mongoLog(format, ...) log("[async_mongo] " format, __VA_ARGS__) 126 | 127 | 128 | } 129 | } -------------------------------------------------------------------------------- /async/async/mongo/module.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_MONGO 10 | 11 | #include "async/async/comm.hpp" 12 | #include "async/async/mongo/async_mongo.h" 13 | 14 | // 注册模块 15 | static async::AsyncModule mod = { 16 | // 名字 17 | "async_mongo", 18 | // 主循环钩子 19 | std::bind(async::mongo::loop, std::placeholders::_1), 20 | // 日志钩子 21 | nullptr, 22 | // 线程钩子 23 | std::bind(async::mongo::setThreadFunc, std::placeholders::_1) 24 | }; 25 | 26 | REG_ASYNC_MODULE(mod); 27 | 28 | #endif -------------------------------------------------------------------------------- /async/async/mongo/mongo_reply_parser.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_MONGO 10 | 11 | #include "async/async/mongo/mongo_reply_parser.h" 12 | #include 13 | 14 | namespace async { 15 | namespace mongo { 16 | 17 | MongoReplyParser::MongoReplyParser() { 18 | this->error = malloc(sizeof(bson_error_t)); 19 | this->bson_idx = 0; 20 | } 21 | 22 | MongoReplyParser::~MongoReplyParser() { 23 | free(this->error); 24 | this->error = 0; 25 | for (auto p : this->bsons) { 26 | bson_destroy((bson_t*)p); 27 | } 28 | } 29 | 30 | bool MongoReplyParser::IsOk() { 31 | return this->op_result == 0; 32 | } 33 | 34 | uint32_t MongoReplyParser::Code() { 35 | return ((bson_error_t*)this->error)->code; 36 | } 37 | 38 | const char* MongoReplyParser::What() { 39 | return ((bson_error_t*)this->error)->message; 40 | } 41 | 42 | const void* MongoReplyParser::NextBson() { 43 | if (this->bson_idx >= this->bsons.size()) { 44 | return 0; 45 | } 46 | 47 | return this->bsons[this->bson_idx++]; 48 | } 49 | 50 | void MongoReplyParser::ResetNextBson() { 51 | this->bson_idx = 0; 52 | } 53 | 54 | bool MongoReplyParser::GetDeletedCount(int& cnt) { 55 | return GetKeyValue("deletedCount", cnt); 56 | } 57 | 58 | bool MongoReplyParser::GetModifiedCount(int& cnt) { 59 | return GetKeyValue("modifiedCount", cnt); 60 | } 61 | 62 | bool MongoReplyParser::GetMatchedCount(int& cnt) { 63 | return GetKeyValue("matchedCount", cnt); 64 | } 65 | 66 | bool MongoReplyParser::GetUpsertedCount(int& cnt) { 67 | return GetKeyValue("upsertedCount", cnt); 68 | } 69 | 70 | bool MongoReplyParser::GetKeyValue(const char* key, int& v) { 71 | if (this->bsons.empty()) { 72 | return false; 73 | } 74 | 75 | bson_t* b = (bson_t*)this->bsons[0]; 76 | bson_iter_t iter; 77 | if (!bson_iter_init(&iter, (const bson_t*)b)) { 78 | return false; 79 | } 80 | 81 | bson_iter_t desc; 82 | if (!bson_iter_find_descendant(&iter, key, &desc)) { 83 | return false; 84 | } 85 | 86 | v = (int)bson_iter_as_int64(&desc); 87 | return true; 88 | } 89 | 90 | char* MongoReplyParser::NextJson() { 91 | const bson_t* doc = (const bson_t*)this->NextBson(); 92 | if (doc) { 93 | char* json = bson_as_relaxed_extended_json(doc, nullptr); 94 | return json; 95 | } 96 | return 0; 97 | } 98 | 99 | void MongoReplyParser::FreeJson(void* json) { 100 | bson_free(json); 101 | } 102 | 103 | } // mongo 104 | } // async 105 | 106 | #endif -------------------------------------------------------------------------------- /async/async/mongo/mongo_reply_parser.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace async { 16 | 17 | namespace mongo { 18 | 19 | // 如果是返回的结果集,必须先调用完NextJson才知道IsOk()函数的正确性 20 | struct MongoReplyParser { 21 | MongoReplyParser(); 22 | 23 | ~MongoReplyParser(); 24 | 25 | bool IsOk(); 26 | 27 | uint32_t Code(); 28 | 29 | const char* What(); 30 | 31 | // 返回一个bson_t指针 32 | const void* NextBson(); 33 | 34 | char* NextJson(); 35 | 36 | void FreeJson(void* json); 37 | 38 | void ResetNextBson(); 39 | 40 | bool GetDeletedCount(int& cnt); 41 | 42 | bool GetModifiedCount(int& cnt); 43 | 44 | bool GetKeyValue(const char* key, int& v); 45 | 46 | bool GetMatchedCount(int& cnt); 47 | 48 | bool GetUpsertedCount(int& cnt); 49 | 50 | int op_result = -1; // 0表示成功 51 | void* error; 52 | void* cursor; 53 | std::vector bsons; 54 | size_t bson_idx; 55 | }; 56 | 57 | typedef std::shared_ptr MongoReplyParserPtr; 58 | 59 | } // mongo 60 | } // async 61 | -------------------------------------------------------------------------------- /async/async/mongo/op.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | namespace async { 10 | namespace mongo { 11 | 12 | void onPushRsp(MongoRspDataPtr rsp, void* t); 13 | 14 | void opCmd(MongoCorePtr core, MongoReqDataPtr req); 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /async/async/mysql/async_mysql.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include "async/async/mysql/mysql_reply_parser.h" 13 | 14 | namespace async { 15 | namespace mysql { 16 | 17 | // @int errno, MYSQL_ROW row, int row_idx, int fields, int affected_rows 18 | typedef std::function async_mysql_query_cb; 19 | 20 | typedef std::function async_mysql_cb; 21 | 22 | // 不支持查询多结果集,如果执行了返回多结果集的sql语句,行为是未可知的 23 | void query(const std::string& id, const std::string& sql, async_mysql_cb cb); 24 | 25 | // id: host|port|db|user|pwd 26 | void execute(const std::string& id, const std::string& sql, async_mysql_cb cb); 27 | 28 | /////////////// 29 | 30 | void setMaxConnection(uint32_t cnt); 31 | 32 | bool loop(uint32_t curTime); 33 | 34 | void setThreadFunc(std::function)>); 35 | 36 | } 37 | } -------------------------------------------------------------------------------- /async/async/mysql/callback.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_MYSQL 10 | 11 | #include "async/async/mysql/data.h" 12 | 13 | namespace async { 14 | namespace mysql { 15 | 16 | void onPushRsp(MysqlRspDataPtr rsp, void* t) { 17 | MysqlThreadData* tData = (MysqlThreadData*)t; 18 | tData->rspLock.lock(); 19 | tData->rspQueue.push_back(rsp); 20 | tData->rspLock.unlock(); 21 | } 22 | 23 | void onTimeout(MysqlReqDataPtr req, MysqlCorePtr c, void* t) { 24 | if (c) { 25 | c->task--; 26 | } 27 | 28 | MysqlRspDataPtr rsp = std::make_shared(); 29 | rsp->req = req; 30 | rsp->parser = std::make_shared(nullptr, 0, true, 0); 31 | onPushRsp(rsp, req->tData); 32 | } 33 | 34 | void onResult(MysqlReqDataPtr req, MysqlCorePtr c, void* res) { 35 | c->task--; 36 | int err = mysql_errno(c->conn->c); 37 | int affect = 0; 38 | 39 | if (err == 0) { 40 | affect = mysql_affected_rows(c->conn->c); 41 | } 42 | 43 | MysqlRspDataPtr rsp = std::make_shared(); 44 | rsp->req = req; 45 | rsp->parser = std::make_shared(res, err, false, affect); 46 | onPushRsp(rsp, req->tData); 47 | } 48 | 49 | } 50 | } 51 | 52 | #endif -------------------------------------------------------------------------------- /async/async/mysql/callback.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | namespace async { 12 | namespace mysql { 13 | 14 | void onPushRsp(MysqlRspDataPtr rsp, void* t); 15 | 16 | void onTimeout(MysqlReqDataPtr req, MysqlCorePtr c, void* t); 17 | 18 | void onResult(MysqlReqDataPtr req, MysqlCorePtr c, void* res); 19 | 20 | } 21 | } -------------------------------------------------------------------------------- /async/async/mysql/data.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_MYSQL 10 | 11 | #include "async/async/mysql/data.h" 12 | #include 13 | #include 14 | 15 | namespace async { 16 | 17 | // 声明 18 | void split(const std::string source, const std::string &separator, std::vector &array); 19 | 20 | namespace mysql { 21 | 22 | MysqlAddr::MysqlAddr (const std::string& id) { 23 | Parse(id); 24 | } 25 | 26 | void MysqlAddr::Parse(const std::string& id) { 27 | this->id = id; 28 | std::vector values; 29 | async::split(id, "|", values); 30 | if (values.size() == 5) { 31 | this->host = values[0]; 32 | this->port = atoi(values[1].c_str()); 33 | this->db = values[2]; 34 | this->user = values[3]; 35 | this->pwd = values[4]; 36 | } 37 | else { 38 | mysqlLog("[error] uri error:%s", id.c_str()); 39 | assert(false); 40 | } 41 | } 42 | 43 | MysqlConn::~MysqlConn() { 44 | if (c) { 45 | mysql_close(c); 46 | } 47 | } 48 | 49 | MysqlCore::~MysqlCore() { 50 | } 51 | 52 | CorePoolPtr GlobalData::getPool(const std::string& id) { 53 | CorePoolPtr pool; 54 | auto iter = this->corePool.find(id); 55 | if (iter == this->corePool.end()) { 56 | pool = std::make_shared(); 57 | this->corePool[id] = pool; 58 | } else { 59 | pool = iter->second; 60 | } 61 | return pool; 62 | } 63 | 64 | } 65 | } 66 | 67 | #endif -------------------------------------------------------------------------------- /async/async/mysql/data.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/async/mysql/async_mysql.h" 12 | #include "async/async/mysql/mysql_reply_parser.h" 13 | #include "async/log.h" 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace async { 23 | namespace mysql { 24 | 25 | // mysql连接状态 26 | enum { 27 | enum_connecting_state, 28 | enum_connected_state, 29 | enum_querying_state, 30 | enum_storing_state, 31 | // enum_stored_state, 32 | // enum_error_state, 33 | // enum_disconnected_state, 34 | }; 35 | 36 | // mysql地址结构 37 | struct MysqlAddr { 38 | MysqlAddr (const std::string& id); 39 | 40 | void Parse(const std::string& id); 41 | 42 | std::string id; 43 | std::string host; 44 | uint32_t port = 0; 45 | std::string db; 46 | std::string user; 47 | std::string pwd; 48 | }; 49 | 50 | typedef std::shared_ptr MysqlAddrPtr; 51 | 52 | // 请求 53 | struct MysqlReqData { 54 | async_mysql_cb cb; 55 | MysqlAddrPtr addr; 56 | std::string cmd; 57 | time_t reqTime = 0; 58 | bool isQuery = false; 59 | void* tData = 0; 60 | }; 61 | 62 | typedef std::shared_ptr MysqlReqDataPtr; 63 | 64 | // 回复 65 | struct MysqlRspData { 66 | MysqlReqDataPtr req; 67 | MysqlReplyParserPtr parser; 68 | }; 69 | 70 | typedef std::shared_ptr MysqlRspDataPtr; 71 | 72 | struct MysqlConn { 73 | MYSQL *c = 0; 74 | uint32_t state = enum_connecting_state; 75 | ~MysqlConn(); 76 | }; 77 | 78 | typedef std::shared_ptr MysqlConnPtr; 79 | 80 | // 核心 81 | struct MysqlCore { 82 | MysqlConnPtr conn; 83 | MysqlAddrPtr addr; 84 | std::atomic task; 85 | bool running = false; 86 | clock_t lastRunTime = 0; 87 | time_t lastConnTime = 0; 88 | MysqlReqDataPtr curReq; 89 | std::list waitQueue; 90 | std::mutex waitLock; 91 | ~MysqlCore(); 92 | }; 93 | 94 | typedef std::shared_ptr MysqlCorePtr; 95 | 96 | // 连接池 97 | struct CorePool { 98 | uint32_t polling = 0; 99 | std::vector valid; 100 | }; 101 | 102 | typedef std::shared_ptr CorePoolPtr; 103 | 104 | struct GlobalData { 105 | // 连接池 106 | std::unordered_map corePool; 107 | std::mutex pLock; 108 | 109 | // 分发标识 110 | std::atomic_flag dispatchTask; 111 | 112 | GlobalData() :dispatchTask(ATOMIC_FLAG_INIT) {} 113 | 114 | CorePoolPtr getPool(const std::string& id); 115 | }; 116 | 117 | struct MysqlThreadData { 118 | // 请求任务的数量 119 | uint64_t reqTaskCnt = 0; 120 | // 回复任务的数量 121 | uint64_t rspTaskCnt = 0; 122 | // 请求队列 123 | std::unordered_map> reqQueue; 124 | // 回复队列 125 | std::mutex rspLock; 126 | std::list rspQueue; 127 | uint32_t lastRunTime = 0; 128 | // 上一次统计输出时间 129 | time_t lastPrintTime = 0; 130 | // 初始化 131 | bool init = false; 132 | }; 133 | 134 | /////////////////////////////////////////////////////////////////////////////// 135 | 136 | #define mysqlLog(format, ...) log("[async_mysql] " format, __VA_ARGS__) 137 | 138 | 139 | } 140 | } -------------------------------------------------------------------------------- /async/async/mysql/module.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_MYSQL 10 | 11 | #include "async/async/comm.hpp" 12 | #include "async/async/mysql/async_mysql.h" 13 | 14 | // 注册模块 15 | static async::AsyncModule mod = { 16 | // 名字 17 | "async_mysql", 18 | // 主循环钩子 19 | std::bind(async::mysql::loop, std::placeholders::_1), 20 | // 日志钩子 21 | nullptr, 22 | // 线程钩子 23 | std::bind(async::mysql::setThreadFunc, std::placeholders::_1) 24 | }; 25 | 26 | REG_ASYNC_MODULE(mod); 27 | 28 | #endif -------------------------------------------------------------------------------- /async/async/mysql/mysql_reply_parser.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_MYSQL 10 | 11 | #include "async/async/mysql/mysql_reply_parser.h" 12 | #include 13 | 14 | namespace async { 15 | namespace mysql { 16 | 17 | MysqlReplyParser::MysqlReplyParser(const void* res, int err, bool timeout, int affect) { 18 | this->_res = res; 19 | this->_errno = err; 20 | this->_timeout = timeout; 21 | this->_affect = affect; 22 | } 23 | 24 | MysqlReplyParser::~MysqlReplyParser() { 25 | if (this->_res) { 26 | mysql_free_result((MYSQL_RES*)this->_res); 27 | } 28 | } 29 | 30 | int MysqlReplyParser::GetAffectedRow() { 31 | return this->_affect; 32 | } 33 | 34 | int MysqlReplyParser::GetNumRow() { 35 | if (this->_res && this->_errno == 0) { 36 | auto rows = (int)mysql_num_rows((MYSQL_RES*)this->_res); 37 | return rows; 38 | } 39 | else { 40 | return 0; 41 | } 42 | } 43 | 44 | int MysqlReplyParser::GetField() { 45 | if (this->_res && this->_errno == 0) { 46 | auto field = (int)mysql_num_fields((MYSQL_RES*)this->_res); 47 | return field; 48 | } 49 | else { 50 | return 0; 51 | } 52 | } 53 | 54 | const void* MysqlReplyParser::Next() { 55 | if (this->_res && this->_errno == 0) { 56 | // 同步取值 57 | MYSQL_ROW row = mysql_fetch_row((MYSQL_RES*)this->_res); 58 | return (const void*)row; 59 | } 60 | else { 61 | return 0; 62 | } 63 | } 64 | 65 | int MysqlReplyParser::GetError() { 66 | return this->_errno; 67 | } 68 | 69 | bool MysqlReplyParser::IsTimeout() { 70 | return this->_timeout; 71 | } 72 | 73 | const char* MysqlReplyParser::GetRowValue(const void* row, int idx) { 74 | MYSQL_ROW r = (MYSQL_ROW)row; 75 | return r[idx]; 76 | } 77 | 78 | } 79 | } 80 | 81 | #endif -------------------------------------------------------------------------------- /async/async/mysql/mysql_reply_parser.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace async { 14 | namespace mysql { 15 | 16 | struct MysqlReplyParser { 17 | MysqlReplyParser(const void* res, int err, bool timeout, int affect); 18 | 19 | ~MysqlReplyParser(); 20 | 21 | // 获取受影响的行数 22 | int GetAffectedRow(); 23 | 24 | // 获取结果集行数 25 | int GetNumRow(); 26 | 27 | // 获取列数 28 | int GetField(); 29 | 30 | const void* Next(); 31 | 32 | int GetError(); 33 | 34 | bool IsTimeout(); 35 | 36 | const char* GetRowValue(const void* row, int idx); 37 | 38 | private: 39 | const void* _res; 40 | int _errno; 41 | bool _timeout; 42 | int _affect; 43 | }; 44 | 45 | typedef std::shared_ptr MysqlReplyParserPtr; 46 | 47 | } 48 | } -------------------------------------------------------------------------------- /async/async/rabbitmq/async_rabbitmq.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | #include "async/async/rabbitmq/rabbitmq_cmd.h" 15 | #include "async/async/rabbitmq/rabbitmq_parser.h" 16 | 17 | namespace async { 18 | namespace rabbitmq { 19 | 20 | // reply: amqp_rpc_reply_t 21 | typedef std::function async_rabbit_cb; 22 | 23 | // @uri: [host|port|vhost|user|pwd] 24 | void execute(const std::string& uri, std::shared_ptr cmd, async_rabbit_cb cb); 25 | 26 | // 监听 27 | bool watch(const std::string& uri, std::shared_ptr cmd, async_rabbit_cb cb); 28 | 29 | // 取消监听 30 | void unwatch(const std::string& uri, std::shared_ptr cmd); 31 | 32 | // 监听ack 33 | bool watchAck(const std::string& uri, std::shared_ptr cmd, async_rabbit_cb cb); 34 | 35 | bool loop(uint32_t curTime); 36 | 37 | void setThreadFunc(std::function)> f); 38 | 39 | // 控制watch的接收速率 40 | void setConsumeRate(uint32_t rate); 41 | 42 | } // rabbitmq 43 | } // async -------------------------------------------------------------------------------- /async/async/rabbitmq/module.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_RABBITMQ 10 | 11 | #include "async/async/comm.hpp" 12 | #include "async/async/rabbitmq/async_rabbitmq.h" 13 | 14 | // 注册模块 15 | static async::AsyncModule mod = { 16 | // 名字 17 | "async_rabbitmq", 18 | // 主循环钩子 19 | std::bind(async::rabbitmq::loop, std::placeholders::_1), 20 | // 日志钩子 21 | nullptr, 22 | // 线程钩子 23 | std::bind(async::rabbitmq::setThreadFunc, std::placeholders::_1) 24 | }; 25 | 26 | REG_ASYNC_MODULE(mod); 27 | 28 | #endif -------------------------------------------------------------------------------- /async/async/rabbitmq/op.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | namespace async { 12 | namespace rabbitmq { 13 | 14 | void onPushRsp(RabbitRspDataPtr rsp, void* t); 15 | 16 | void onTimeout(RabbitReqDataPtr req); 17 | 18 | void opAckError(RabbitReqDataPtr req); 19 | 20 | bool opCmd(RabbitCorePtr c, uint32_t chId, RabbitReqDataPtr req); 21 | 22 | bool opWatch(RabbitCorePtr c); 23 | 24 | } 25 | } -------------------------------------------------------------------------------- /async/async/rabbitmq/rabbitmq_parser.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_RABBITMQ 10 | 11 | #include "async/async/rabbitmq/rabbitmq_parser.h" 12 | #include 13 | 14 | namespace async { 15 | namespace rabbitmq { 16 | 17 | #define ENVELOPE ((amqp_envelope_t*)this->envelope) 18 | #define MESSAGE ((amqp_message_t*)this->message) 19 | #define REPLY ((amqp_rpc_reply_t*)this->reply) 20 | 21 | RabbitParser::RabbitParser() { 22 | this->reply = malloc(sizeof(amqp_rpc_reply_t)); 23 | REPLY->reply_type = AMQP_RESPONSE_NORMAL; 24 | this->envelope = 0;//malloc(sizeof(amqp_envelope_t)); 25 | this->message = 0;//malloc(sizeof(amqp_message_t)); 26 | } 27 | 28 | RabbitParser::~RabbitParser() { 29 | if (this->envelope) { 30 | amqp_destroy_envelope(ENVELOPE); 31 | free(this->envelope); 32 | } 33 | if (this->message) { 34 | amqp_destroy_message(MESSAGE); 35 | free(this->message); 36 | } 37 | 38 | free(this->reply); 39 | } 40 | 41 | bool RabbitParser::isOk() { 42 | if (this->timeout) { 43 | return false; 44 | } 45 | 46 | return REPLY->reply_type == AMQP_RESPONSE_NORMAL && this->x == AMQP_STATUS_OK; 47 | } 48 | 49 | bool RabbitParser::isTimeout() { 50 | return this->timeout; 51 | } 52 | 53 | uint64_t RabbitParser::getDeliveryTag() { 54 | if (ENVELOPE) { 55 | return ENVELOPE->delivery_tag; 56 | } 57 | return 0; 58 | } 59 | 60 | char* RabbitParser::getBody() { 61 | if (ENVELOPE) { 62 | return (char*)ENVELOPE->message.body.bytes; 63 | } 64 | if (MESSAGE) { 65 | return (char*)MESSAGE->body.bytes; 66 | } 67 | return nullptr; 68 | } 69 | 70 | size_t RabbitParser::getBodyLen() { 71 | if (ENVELOPE) { 72 | return ENVELOPE->message.body.len; 73 | } 74 | if (MESSAGE) { 75 | return MESSAGE->body.len; 76 | } 77 | return 0; 78 | } 79 | 80 | } 81 | } 82 | 83 | #endif -------------------------------------------------------------------------------- /async/async/rabbitmq/rabbitmq_parser.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace async { 14 | namespace rabbitmq { 15 | 16 | struct RabbitParser { 17 | RabbitParser(); 18 | 19 | ~RabbitParser(); 20 | 21 | bool isOk(); 22 | 23 | bool isTimeout(); 24 | 25 | uint64_t getDeliveryTag(); 26 | 27 | char* getBody(); 28 | 29 | size_t getBodyLen(); 30 | 31 | int x = 0; 32 | void* reply; 33 | void* envelope; 34 | void* message; 35 | bool timeout = false; 36 | }; 37 | 38 | typedef std::shared_ptr RabbitParserPtr; 39 | 40 | } 41 | } -------------------------------------------------------------------------------- /async/async/redis/async_redis.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include "async/async/redis/redis_parser.h" 13 | #include "async/async/redis/redis_cmd.h" 14 | 15 | namespace async { 16 | namespace redis { 17 | 18 | struct BaseRedisCmd; 19 | 20 | typedef std::function async_redis_cb; 21 | 22 | // @uri: [host|port|pwd|idx|cluster] 23 | void execute(std::string uri, const BaseRedisCmd& redis_cmd, async_redis_cb cb); 24 | 25 | void execute(std::string uri, std::shared_ptr redis_cmd, async_redis_cb cb); 26 | 27 | bool loop(uint32_t curTime); 28 | 29 | void setThreadFunc(std::function)>); 30 | 31 | } // redis 32 | } // async -------------------------------------------------------------------------------- /async/async/redis/callback.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_REDIS 10 | 11 | #include "async/async/redis/data.h" 12 | #include 13 | #include 14 | 15 | namespace async { 16 | namespace redis { 17 | 18 | void onPushRsp(RedisRspDataPtr rsp, void* t) { 19 | RedisThreadData* tData = (RedisThreadData*)t; 20 | tData->rspLock.lock(); 21 | tData->rspQueue.push_back(rsp); 22 | tData->rspLock.unlock(); 23 | } 24 | 25 | void onTimeout(RedisReqDataPtr req, RedisCorePtr c, void* t) { 26 | c->task--; 27 | 28 | redisReply* r = (redisReply*)hi_calloc(1, sizeof(*r)); 29 | memset(r, 0, sizeof(*r)); 30 | r->type = REDIS_REPLY_SELF_TIMEOUT; 31 | 32 | // 将结果写入队列 33 | RedisRspDataPtr rsp = std::make_shared(); 34 | rsp->req = req; 35 | rsp->parser = std::make_shared(r); 36 | onPushRsp(rsp, t); 37 | } 38 | 39 | } 40 | } 41 | 42 | #endif -------------------------------------------------------------------------------- /async/async/redis/callback.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | namespace async { 10 | namespace redis { 11 | 12 | void onPushRsp(RedisRspDataPtr rsp, void* t); 13 | 14 | void onTimeout(RedisReqDataPtr req, RedisCorePtr c, void* t); 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /async/async/redis/cluster.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // desc: 使用的是同步api,因为异步api无法区分不同连接的redisAsyncContext 5 | // 6 | // author: 404558965@qq.com (xiaoquanjie) 7 | // github: https://github.com/xiaoquanjie/async 8 | //----------------------------------------------------------------*/ 9 | 10 | #ifdef USE_ASYNC_REDIS 11 | 12 | #include "async/async/redis/data.h" 13 | #include "async/async/redis/callback.h" 14 | #include 15 | 16 | #ifdef USE_ASYNC_CLUSTER_REDIS 17 | #include 18 | #endif 19 | 20 | namespace async { 21 | namespace redis { 22 | 23 | // 释放 24 | void freeClusterCore(void* c) { 25 | #ifdef USE_ASYNC_CLUSTER_REDIS 26 | if (c) { 27 | redisClusterFree((redisClusterContext*)c); 28 | } 29 | #endif 30 | } 31 | 32 | // 创建conn 33 | RedisConnPtr clusterCreateConn(RedisCorePtr core) { 34 | auto conn = std::make_shared(); 35 | conn->cluster = true; 36 | 37 | #ifdef USE_ASYNC_CLUSTER_REDIS 38 | redisClusterContext *cc = redisClusterContextInit(); 39 | if (!cc) { 40 | redisLog("[error] failed to call redisClusterContextInit: %s", core->addr->id.c_str()); 41 | return nullptr; 42 | } 43 | 44 | conn->ctxt = cc; 45 | conn->id = core->addr->id; 46 | redisClusterSetOptionAddNodes(cc, core->addr->host.c_str()); 47 | 48 | // 1.5s 49 | struct timeval timeout = {1, 500000}; 50 | redisClusterSetOptionConnectTimeout(cc, timeout); 51 | redisClusterSetOptionRouteUseSlots(cc); 52 | 53 | if (!core->addr->pwd.empty()) { 54 | redisClusterSetOptionPassword(cc, core->addr->pwd.c_str()); 55 | } 56 | 57 | redisClusterConnect2(cc); 58 | if (cc->err) { 59 | redisLog("[error] failed to call redisClusterConnect2: %s", cc->errstr); 60 | return nullptr; 61 | } 62 | 63 | redisLog("redisClusterContext:%p|%s connection is successful", cc, conn->id.c_str()); 64 | 65 | if (!core->addr->pwd.empty()) { 66 | redisLog("redisClusterContext:%p|%s auth successfully", cc, conn->id.c_str()); 67 | } 68 | 69 | // 一切就绪 70 | conn->state = enum_selected_state; 71 | #endif 72 | 73 | return conn; 74 | } 75 | 76 | // 执行命令 77 | void clusterOp(RedisCorePtr core, RedisReqDataPtr req) { 78 | #ifdef USE_ASYNC_CLUSTER_REDIS 79 | redisClusterContext *cc = (redisClusterContext *)core->conn->ctxt; 80 | 81 | size_t cmdSize = req->cmd->cmd.size(); 82 | std::vector argv(cmdSize); 83 | std::vector argc(cmdSize); 84 | convertCmd(*(req->cmd), argv, argc); 85 | 86 | int status = redisClusterAppendCommandArgv(cc, cmdSize, &(argv[0]), &(argc[0])); 87 | 88 | // 获取结果 89 | redisReply *reply = 0; 90 | redisClusterGetReply(cc, (void **)&reply); 91 | 92 | core->task--; 93 | auto r = copyRedisReply(reply); 94 | 95 | // 将结果写入队列 96 | RedisRspDataPtr rsp = std::make_shared(); 97 | rsp->req = req; 98 | rsp->parser = std::make_shared(r); 99 | onPushRsp(rsp, req->tData); 100 | 101 | if (status != REDIS_OK) { 102 | redisLog("[error] failed to call redisClusterAppendCommandArgv: %s", cc->errstr); 103 | core->conn->state = enum_disconnected_state; 104 | } 105 | 106 | #endif 107 | } 108 | 109 | 110 | } // for redis 111 | } // for async 112 | #endif -------------------------------------------------------------------------------- /async/async/redis/module.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_REDIS 10 | 11 | #include "async/async/comm.hpp" 12 | #include "async/async/redis/async_redis.h" 13 | 14 | // 注册模块 15 | static async::AsyncModule mod = { 16 | // 名字 17 | "async_redis", 18 | // 主循环钩子 19 | std::bind(async::redis::loop, std::placeholders::_1), 20 | // 日志钩子 21 | nullptr, 22 | // 线程钩子 23 | std::bind(async::redis::setThreadFunc, std::placeholders::_1) 24 | }; 25 | 26 | REG_ASYNC_MODULE(mod); 27 | 28 | #endif -------------------------------------------------------------------------------- /async/async/redis/redis_exception.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_REDIS 10 | 11 | #include "async/async/redis/redis_exception.h" 12 | 13 | namespace async { 14 | namespace redis { 15 | 16 | RedisException::RedisException() { 17 | } 18 | 19 | RedisException::RedisException(const char* what) { 20 | m_what = std::make_shared(what); 21 | } 22 | 23 | RedisException::RedisException(const std::string& what) { 24 | m_what = std::make_shared(what); 25 | } 26 | 27 | const std::string& RedisException::What()const { 28 | if (!m_what) { 29 | static std::string empty; 30 | return empty; 31 | } else { 32 | return *m_what; 33 | } 34 | } 35 | 36 | bool RedisException::Empty()const { 37 | return (!m_what); 38 | } 39 | 40 | } // redis 41 | } // async 42 | 43 | #endif -------------------------------------------------------------------------------- /async/async/redis/redis_exception.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | #ifndef REDIS_ERR 15 | #define REDIS_ERR -1 16 | #endif 17 | 18 | #ifndef REDIS_OK 19 | #define REDIS_OK 0 20 | #endif 21 | 22 | #ifndef REDIS_REPLY_STRING 23 | #define REDIS_REPLY_STRING 1 24 | #endif 25 | 26 | #ifndef REDIS_REPLY_ARRAY 27 | #define REDIS_REPLY_ARRAY 2 28 | #endif 29 | 30 | #ifndef REDIS_REPLY_INTEGER 31 | #define REDIS_REPLY_INTEGER 3 32 | #endif 33 | 34 | #ifndef REDIS_REPLY_NIL 35 | #define REDIS_REPLY_NIL 4 36 | #endif 37 | 38 | #ifndef REDIS_REPLY_STATUS 39 | #define REDIS_REPLY_STATUS 5 40 | #endif 41 | 42 | #ifndef REDIS_REPLY_ERROR 43 | #define REDIS_REPLY_ERROR 6 44 | #endif 45 | 46 | #ifndef REDIS_REPLY_SELF_TIMEOUT 47 | #define REDIS_REPLY_SELF_TIMEOUT 10000 48 | #endif 49 | 50 | #define M_ERR_NOT_DEFINED ("wrong type") 51 | #define M_ERR_REDIS_CONNECT_FAIL ("redisConnect fail") 52 | #define M_ERR_REDIS_NOT_CONNECTED ("redis is not connected") 53 | #define M_ERR_REDIS_REPLY_NULL ("redis reply is null") 54 | #define M_ERR_REDIS_TYPE_NOT_MATCH ("type doesn't match") 55 | #define M_ERR_REDIS_KEY_NOT_EXIST ("key not exist") 56 | #define M_ERR_REDIS_ARRAY_SIZE_NOT_MATCH ("array size doesn't match") 57 | #define M_ERR_REDIS_SELECT_DB_ERROR ("select db error") 58 | #define M_ERR_REDIS_AUTH_ERROR ("auth error") 59 | #define M_ERR_REDIS_SCAN ("scan error") 60 | #define M_ERR_REDIS_TIMEOUT ("request timeout") 61 | 62 | 63 | namespace async { 64 | namespace redis { 65 | 66 | // redis异常 67 | struct RedisException 68 | { 69 | RedisException(); 70 | 71 | RedisException(const char* what); 72 | 73 | RedisException(const std::string& what); 74 | 75 | const std::string& What() const; 76 | 77 | bool Empty() const; 78 | 79 | private: 80 | std::shared_ptr m_what; 81 | }; 82 | 83 | } 84 | } -------------------------------------------------------------------------------- /async/async/zookeeper/async_zookeeper.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | /* 10 | * 每个uri都会单独创建一条或多条zhandle_t连接作为连接池,数量取决于setThreadFunc函数并发的线程数。zhandle_t有自动重连接的机制,会一直重连下去 11 | * 每条zhandle_t可以同时处理多个请求,同一时刻只会有一个io线程拥有zhandle_t 12 | */ 13 | 14 | #pragma once 15 | 16 | #include 17 | #include 18 | #include 19 | #include "async/async/zookeeper/zook_parser.h" 20 | #include "async/async/zookeeper/zook_cmd.h" 21 | 22 | namespace async { 23 | namespace zookeeper { 24 | 25 | typedef std::function async_zookeeper_cb; 26 | 27 | // uri: host[ip1:port1,ip2:port2]|scheme[user:pwd] 28 | void execute(const std::string& uri, std::shared_ptr cmd, async_zookeeper_cb cb); 29 | 30 | // 监听, 返回false意味着重复监听了 31 | bool watch(const std::string& uri, const std::string& path, async_zookeeper_cb cb); 32 | 33 | // 监听一次 34 | bool watchOnce(const std::string& uri, const std::string& path, async_zookeeper_cb cb); 35 | 36 | // 监听子节点 37 | bool watchChild(const std::string& uri, const std::string& path, async_zookeeper_cb cb); 38 | 39 | bool watchChildOnce(const std::string& uri, const std::string& path, async_zookeeper_cb cb); 40 | 41 | bool loop(uint32_t curTime); 42 | 43 | void setThreadFunc(std::function)>); 44 | 45 | // 设置zook内部的日志等级 46 | void zooSetDebugLevel(uint32_t level); 47 | 48 | } 49 | } -------------------------------------------------------------------------------- /async/async/zookeeper/callback.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | namespace async { 12 | namespace zookeeper { 13 | 14 | void onPushRsp(ZookRspDataPtr rsp, void* t); 15 | 16 | void onTimeout(ZookReqDataPtr req, ZookCorePtr c, void* t); 17 | 18 | // 连接 19 | void onConnCb(zhandle_t* zh, int type, int state, const char *path, void* v); 20 | 21 | // 22 | void onAuthCb(int rc, const void *data); 23 | 24 | // 数据回调 25 | void onDataCb(int rc, const char *value, int value_len, const struct Stat *stat, const void *data); 26 | 27 | void onStringCb(int rc, const char *value, const void *data); 28 | 29 | void onVoidCb(int rc, const void *data); 30 | 31 | void onStatCb(int rc, const struct Stat *stat, const void *data); 32 | 33 | void onAclCb(int rc, struct ACL_vector *acl, struct Stat *stat, const void *data); 34 | 35 | void onStringsCb(int rc, const struct String_vector *strings, const void *data); 36 | 37 | void onWatchDataCb(int rc, const char *value, int value_len, const struct Stat *stat, const void *data); 38 | 39 | // 数据监听 40 | void onWatchCb(zhandle_t *zh, int type, int state, const char *path,void *watcherCtx); 41 | 42 | void onWatchStringsCb(int rc, const struct String_vector *strings, const void *data); 43 | 44 | // 子节点监听 45 | void onWatchChildCb(zhandle_t *zh, int type, int state, const char *path,void *watcherCtx); 46 | 47 | } 48 | } -------------------------------------------------------------------------------- /async/async/zookeeper/data.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_ZOOKEEPER 10 | 11 | #include "async/async/zookeeper/data.h" 12 | #include 13 | #include 14 | #include 15 | 16 | namespace async { 17 | 18 | // 声明 19 | void split(const std::string source, const std::string &separator, std::vector &array); 20 | 21 | namespace zookeeper { 22 | 23 | ZookAddr::ZookAddr(const std::string& id) { 24 | parse(id); 25 | } 26 | 27 | void ZookAddr::parse(const std::string& id) { 28 | this->id = id; 29 | std::vector values; 30 | async::split(id, "|", values); 31 | 32 | if (values.size() < 1) { 33 | zookLog("[error] failed to parse id: %s", id.c_str()); 34 | assert(false); 35 | return; 36 | } 37 | 38 | this->host = values[0]; 39 | if (values.size() == 2) { 40 | this->scheme = values[1]; 41 | } 42 | } 43 | 44 | ZookConn::~ZookConn() { 45 | if (zh) { 46 | zookeeper_close(zh); 47 | } 48 | } 49 | 50 | ZookCore::~ZookCore() { 51 | } 52 | 53 | CorePoolPtr GlobalData::getPool(const std::string& id) { 54 | CorePoolPtr pool; 55 | auto iter = this->corePool.find(id); 56 | if (iter == this->corePool.end()) { 57 | pool = std::make_shared(); 58 | this->corePool[id] = pool; 59 | } else { 60 | pool = iter->second; 61 | } 62 | return pool; 63 | } 64 | 65 | //////////////////////////////////////////////////////////////////////////////// 66 | 67 | const char* state2String(int state) { 68 | if (state == 0) return "CLOSED_STATE"; 69 | if (state == ZOO_CONNECTING_STATE)return "CONNECTING_STATE"; 70 | if (state == ZOO_ASSOCIATING_STATE)return "ASSOCIATING_STATE"; 71 | if (state == ZOO_CONNECTED_STATE)return "CONNECTED_STATE"; 72 | if (state == ZOO_EXPIRED_SESSION_STATE)return "EXPIRED_SESSION_STATE"; 73 | if (state == ZOO_AUTH_FAILED_STATE)return "AUTH_FAILED_STATE"; 74 | return "INVALID_STATE"; 75 | } 76 | 77 | const char* type2String(int type) { 78 | if (type == ZOO_CREATED_EVENT)return "CREATED_EVENT"; 79 | if (type == ZOO_DELETED_EVENT)return "DELETED_EVENT"; 80 | if (type == ZOO_CHANGED_EVENT)return "CHANGED_EVENT"; 81 | if (type == ZOO_CHILD_EVENT)return "CHILD_EVENT"; 82 | if (type == ZOO_SESSION_EVENT)return "SESSION_EVENT"; 83 | if (type == ZOO_NOTWATCHING_EVENT)return "NOTWATCHING_EVENT"; 84 | return "UNKNOWN_EVENT_TYPE"; 85 | } 86 | 87 | const char* lastError() { 88 | return strerror(errno); 89 | } 90 | 91 | bool checkOk(int rc, const char* ctxt) { 92 | if (rc == ZOK) { 93 | return true; 94 | } 95 | 96 | zookLog("[error] failed to call %s: %d: %s", ctxt, rc, zerror(rc)); 97 | return false; 98 | } 99 | 100 | } 101 | } 102 | 103 | #endif -------------------------------------------------------------------------------- /async/async/zookeeper/module.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_ZOOKEEPER 10 | 11 | #include "async/async/comm.hpp" 12 | #include "async/async/zookeeper/async_zookeeper.h" 13 | 14 | // 注册模块 15 | static async::AsyncModule mod = { 16 | // 名字 17 | "async_zookeeper", 18 | // 主循环钩子 19 | std::bind(async::zookeeper::loop, std::placeholders::_1), 20 | // 日志钩子 21 | nullptr, 22 | // 线程钩子 23 | std::bind(async::zookeeper::setThreadFunc, std::placeholders::_1) 24 | }; 25 | 26 | REG_ASYNC_MODULE(mod); 27 | 28 | #endif -------------------------------------------------------------------------------- /async/async/zookeeper/op.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | namespace async { 12 | namespace zookeeper { 13 | 14 | void opCmd(ZookCorePtr core, ZookReqDataPtr req); 15 | 16 | void opWatch(ZookCorePtr core, WatcherPtr w); 17 | 18 | } 19 | } -------------------------------------------------------------------------------- /async/async/zookeeper/zook_cmd.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_ZOOKEEPER 10 | 11 | #include "async/async/zookeeper/zook_cmd.h" 12 | 13 | namespace async { 14 | namespace zookeeper { 15 | 16 | GetCmd::GetCmd() { 17 | this->cmdType = get_cmd; 18 | } 19 | 20 | GetCmd::GetCmd(const std::string& path) { 21 | this->cmdType = get_cmd; 22 | this->path = path; 23 | } 24 | 25 | CreateCmd::CreateCmd() { 26 | this->cmdType = create_cmd; 27 | } 28 | 29 | CreateCmd::CreateCmd(const std::string& path, const std::string& value, const std::initializer_list& acls) { 30 | this->cmdType = create_cmd; 31 | this->path = path; 32 | this->value = value; 33 | for (auto s : acls) { 34 | this->acls.push_back(s); 35 | } 36 | } 37 | 38 | CreateCmd::CreateCmd(const std::string& path, 39 | const std::string& value, 40 | bool ephemeral, 41 | bool withSeq, 42 | int64_t ttl, 43 | const std::initializer_list& acls) 44 | { 45 | this->cmdType = create_cmd; 46 | this->path = path; 47 | this->value = value; 48 | this->ephemeral = ephemeral; 49 | this->withSeq = withSeq; 50 | this->ttl = ttl; 51 | for (auto s : acls) { 52 | this->acls.push_back(s); 53 | } 54 | } 55 | 56 | DeleteCmd::DeleteCmd() { 57 | this->cmdType = delete_cmd; 58 | } 59 | 60 | DeleteCmd::DeleteCmd(const std::string& path, int32_t version) { 61 | this->cmdType = delete_cmd; 62 | this->path = path; 63 | this->version = version; 64 | } 65 | 66 | ExistsCmd::ExistsCmd() { 67 | this->cmdType = exists_cmd; 68 | } 69 | 70 | ExistsCmd::ExistsCmd(const std::string& path) { 71 | this->cmdType = exists_cmd; 72 | this->path = path; 73 | } 74 | 75 | SetCmd::SetCmd() { 76 | this->cmdType = set_cmd; 77 | } 78 | 79 | SetCmd::SetCmd(const std::string& path, const std::string& value, int32_t version) { 80 | this->cmdType = set_cmd; 81 | this->path = path; 82 | this->value = value; 83 | this->version = version; 84 | } 85 | 86 | GetAclCmd::GetAclCmd() { 87 | this->cmdType = get_acl_cmd; 88 | } 89 | 90 | GetAclCmd::GetAclCmd(const std::string& path) { 91 | this->cmdType = get_acl_cmd; 92 | this->path = path; 93 | } 94 | 95 | SetAclCmd::SetAclCmd() { 96 | this->cmdType = set_acl_cmd; 97 | } 98 | 99 | SetAclCmd::SetAclCmd(const std::string& path, 100 | const std::initializer_list& acls, 101 | int32_t version) { 102 | this->cmdType = set_acl_cmd; 103 | this->path = path; 104 | for (auto s : acls) { 105 | this->acls.push_back(s); 106 | } 107 | this->version = version; 108 | } 109 | 110 | ListCmd::ListCmd() { 111 | this->cmdType = list_cmd; 112 | } 113 | 114 | 115 | ListCmd::ListCmd(const std::string& path) { 116 | this->cmdType = list_cmd; 117 | this->path = path; 118 | } 119 | 120 | } 121 | } 122 | 123 | #endif -------------------------------------------------------------------------------- /async/async/zookeeper/zook_cmd.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | namespace async { 15 | namespace zookeeper { 16 | 17 | enum cmd_type { 18 | get_cmd = 1, // 获取节点 19 | create_cmd = 2, // 创建节点 20 | delete_cmd = 3, // 删除节点 21 | exists_cmd = 4, // 存在节点 22 | set_cmd = 5, // 设置节点 23 | get_acl_cmd = 6, // 获取权限 24 | set_acl_cmd = 7, 25 | list_cmd = 8, // 列出子节点 26 | }; 27 | 28 | struct BaseZookCmd { 29 | uint32_t cmdType = 0; 30 | virtual ~BaseZookCmd() {} 31 | }; 32 | 33 | struct GetCmd : public BaseZookCmd { 34 | GetCmd(); 35 | 36 | GetCmd(const std::string& path); 37 | 38 | std::string path; // 节点路径 39 | }; 40 | 41 | // warn: std::make_shared不支持std::initializer_list 42 | struct CreateCmd : public BaseZookCmd { 43 | CreateCmd(); 44 | 45 | CreateCmd(const std::string& path, 46 | const std::string& value, 47 | const std::initializer_list& acls = {}); 48 | 49 | CreateCmd(const std::string& path, 50 | const std::string& value, 51 | bool ephemeral, 52 | bool withSeq, 53 | int64_t ttl, 54 | const std::initializer_list& acls = {}); 55 | 56 | std::string path; // 节点路径 57 | std::string value; // 节点值 58 | bool ephemeral = false; // 临时的, 临时节点不能带ttl 59 | bool withSeq = false; // 带有序号 60 | int64_t ttl = 0; // ttl,毫秒 61 | std::vector acls; // 格式是: scheme:id:perm,例如:world:anyone:cdrwa, ip:xx.xx.xx.xx:cdrwa, auth::cdrwa, digest:user:pwd:cdrwa 62 | }; 63 | 64 | struct DeleteCmd : public BaseZookCmd { 65 | DeleteCmd(); 66 | 67 | DeleteCmd(const std::string& path, int32_t version = -1); 68 | 69 | std::string path; // 节点路径 70 | int32_t version = -1; // 版本号, -1不检查版本号 71 | }; 72 | 73 | struct ExistsCmd : public BaseZookCmd { 74 | ExistsCmd(); 75 | 76 | ExistsCmd(const std::string& path); 77 | 78 | std::string path; // 节点路径 79 | }; 80 | 81 | struct SetCmd : public BaseZookCmd { 82 | SetCmd(); 83 | 84 | SetCmd(const std::string& path, const std::string& value, int32_t version = -1); 85 | 86 | std::string path; // 节点路径 87 | std::string value; // 节点值 88 | int32_t version = -1; // 版本号, -1不检查版本号 89 | }; 90 | 91 | struct GetAclCmd : public BaseZookCmd { 92 | GetAclCmd(); 93 | 94 | GetAclCmd(const std::string& path); 95 | 96 | std::string path; // 节点路径 97 | }; 98 | 99 | struct SetAclCmd : public BaseZookCmd { 100 | SetAclCmd(); 101 | 102 | SetAclCmd(const std::string& path, 103 | const std::initializer_list& acls, 104 | int32_t version = -1); 105 | 106 | std::string path; // 节点路径 107 | int32_t version = -1; // 版本号, -1不检查版本号 108 | std::vector acls; // 格式是: scheme:id:perm,例如:world:anyone:cdrwa, ip:xx.xx.xx.xx:cdrwa, auth::cdrwa, digest:user:pwd:cdrwa 109 | }; 110 | 111 | struct ListCmd : public BaseZookCmd { 112 | ListCmd(); 113 | 114 | ListCmd(const std::string& path); 115 | 116 | std::string path; // 节点路径 117 | }; 118 | 119 | 120 | } 121 | } -------------------------------------------------------------------------------- /async/async/zookeeper/zook_parser.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace async { 17 | namespace zookeeper { 18 | 19 | // zookeeper结果解析 20 | struct ZookParser { 21 | struct ZookAcl { 22 | std::string scheme; 23 | std::string id; 24 | int32_t perms = 0; 25 | }; 26 | 27 | ZookParser(int rc, const void* s, const char* v, int len); 28 | 29 | ~ZookParser(); 30 | 31 | const std::string& getValue(); 32 | 33 | int getRc(); 34 | 35 | const char* error(); 36 | 37 | void setChilds(const void* c); 38 | 39 | const std::vector& getChilds(); 40 | 41 | // 设置权限 42 | void setAcls(const void* acl); 43 | 44 | const std::vector& getAcls(); 45 | 46 | // 全部权限 47 | bool allPerm(uint32_t perms); 48 | 49 | bool readPerm(uint32_t perms); 50 | 51 | bool writePerm(uint32_t perms); 52 | 53 | bool DeletePerm(uint32_t perms); 54 | 55 | bool CreatePerm(uint32_t perms); 56 | 57 | bool AdminPerm(uint32_t perms); 58 | 59 | void* getStat(); 60 | 61 | // 这是导致创建znode更改的事务ID 62 | int64_t getStatCzxid(); 63 | 64 | // 这是最后修改znode更改的事务ID。 65 | int64_t getStatMzxid(); 66 | 67 | // 表示从1970-01-01T00:00:00Z开始以毫秒为单位的znode创建时间 68 | int64_t getStatCtime(); 69 | 70 | // 表示从1970-01-01T00:00:00Z开始以毫秒为单位的znode最近修改时间 71 | int64_t getStatMtime(); 72 | 73 | // 表示对该znode的数据所做的更改次数 74 | int32_t getStatVersion(); 75 | 76 | // 这表示对此znode的子节点进行的更改次数 77 | int32_t getStatCversion(); 78 | 79 | // 表示对此znode的ACL进行更改的次数 80 | int32_t getStatAversion(); 81 | 82 | // 如果znode是ephemeral类型节点,则这是znode所有者的 session ID。 如果znode不是ephemeral节点,则该字段设置为零。 83 | int64_t getStatEphemeralOwner(); 84 | 85 | // 这是znode数据字段的长度 86 | int32_t getStatDataLength(); 87 | 88 | // 这表示znode的子节点的数量 89 | int32_t getStatNumChildren(); 90 | 91 | // 这是用于添加或删除子节点的znode更改的事务ID 92 | int64_t getStatPzxid(); 93 | 94 | bool zTimeout(); 95 | 96 | bool zOk(); 97 | 98 | bool zNoNode(); 99 | 100 | bool zNoAuth(); 101 | 102 | // invalid ACL specified 103 | bool zInvalIdAcl(); 104 | 105 | // expected version does not match actual version. 106 | bool zBadVersion(); 107 | 108 | // authentication failed 109 | bool zAuthFailed(); 110 | 111 | bool zNotEmpty(); 112 | private: 113 | int rc = 0; 114 | void* stat = 0; 115 | std::string* value; 116 | std::vector acls; 117 | std::vector childs; 118 | }; 119 | 120 | typedef std::shared_ptr ZookParserPtr; 121 | 122 | } 123 | } -------------------------------------------------------------------------------- /async/co_async/async.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #include "async/co_async/async.h" 10 | #include "async/co_async/promise.h" 11 | #include "async/async/async.h" 12 | #include 13 | #include 14 | 15 | namespace co_async { 16 | 17 | ////////////////////////////////////////////////////////////////////////// 18 | 19 | std::pair parallel(const std::initializer_list& fns, int timeOut) { 20 | auto res = promise([fns](Resolve resolve, Reject reject) { 21 | async::parallel([resolve](int64_t result) { 22 | resolve(std::make_shared(result)); 23 | }, fns); 24 | }, timeOut); 25 | 26 | std::pair ret = std::make_pair(res.first, 0); 27 | if (checkOk(res)) { 28 | auto p = getOk(res); 29 | ret.second = *p; 30 | } 31 | 32 | return ret; 33 | } 34 | 35 | ///////////////////////////////////////////////////////////////////////// 36 | 37 | bool loop(uint32_t curTime) { 38 | if (curTime == 0) { 39 | time((time_t*)&curTime); 40 | } 41 | bool ret1 = loopPromise(curTime); 42 | bool ret2 = async::loop(curTime); 43 | return ret1 || ret2; 44 | } 45 | 46 | // 带有sleep功能,在没有任务时降低cpu使用率 47 | void loopSleep(uint32_t curTime, uint32_t sleepMil) { 48 | if (curTime == 0) { 49 | time((time_t*)&curTime); 50 | } 51 | 52 | loopPromise(curTime); 53 | async::loopSleep(curTime, sleepMil); 54 | } 55 | 56 | } -------------------------------------------------------------------------------- /async/co_async/async.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include "async/co_async/comm.hpp" 14 | 15 | namespace co_async { 16 | 17 | typedef std::function next_cb; 18 | typedef std::function fn_cb; 19 | 20 | // 并行执行里面的所有异步操作 21 | std::pair parallel(const std::initializer_list& fns, int timeOut = 10 * 1000); 22 | 23 | bool loop(uint32_t curTime = 0); 24 | 25 | // 带有sleep功能,在没有任务时降低cpu使用率 26 | void loopSleep(uint32_t curTime, uint32_t sleepMil = 0); 27 | 28 | } 29 | 30 | -------------------------------------------------------------------------------- /async/co_async/comm.hpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | /* 10 | * 11 | */ 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | namespace co_async { 18 | 19 | #ifndef PROMISE_RET 20 | #define PROMISE_RET 21 | // promise的返回值 22 | enum { 23 | // 访问成功 24 | E_OK = 0, 25 | // 访问超时 26 | E_TIMEOUT = 1, 27 | // 访问失败, 28 | E_ERROR = 2 29 | }; 30 | #endif 31 | 32 | struct PromiseReject { 33 | int err = 0; 34 | std::string msg; 35 | }; 36 | 37 | struct PromiseResult { 38 | bool timeOutFlag = false; 39 | int64_t timerId = 0; 40 | uint64_t uniqueId = 0; 41 | uint32_t coId = 0; 42 | uint32_t fns = 0; 43 | std::shared_ptr resolveRes; 44 | std::shared_ptr rejectRes; 45 | }; 46 | 47 | struct Resolve { 48 | std::shared_ptr result; 49 | void operator()(std::shared_ptr res) const; 50 | uint32_t coId() { return result->coId; } 51 | }; 52 | 53 | struct Reject { 54 | std::shared_ptr result; 55 | void operator()(int err, const std::string& msg) const; 56 | }; 57 | 58 | struct UniqueInfo { 59 | Resolve resolve; 60 | Reject reject; 61 | }; 62 | 63 | struct TimeOut { 64 | int v; 65 | explicit TimeOut(int t = 30 * 1000) : v(t) {} 66 | int operator()() const { return v; } 67 | }; 68 | 69 | //////////////////////// // 辅助获取promise的值 70 | 71 | inline bool checkOk(std::pair> p) { 72 | return (p.first == E_OK); 73 | } 74 | 75 | inline bool checkTimeout(std::pair> p) { 76 | return (p.first == E_TIMEOUT); 77 | } 78 | 79 | inline bool checkError(std::pair> p) { 80 | return (p.first == E_ERROR); 81 | } 82 | 83 | template 84 | inline std::shared_ptr getOk(std::pair> p) { 85 | if (checkOk(p)) { 86 | auto res = std::static_pointer_cast(p.second); 87 | return res; 88 | } 89 | else { 90 | return nullptr; 91 | } 92 | } 93 | 94 | inline std::shared_ptr getError(std::pair> p) { 95 | if (checkError(p)) { 96 | auto res = std::static_pointer_cast(p.second); 97 | return res; 98 | } 99 | else { 100 | return nullptr; 101 | } 102 | } 103 | 104 | //////////////////////// // 辅助获取promise的值 105 | 106 | } -------------------------------------------------------------------------------- /async/co_async/cpu/co_cpu.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #include "async/co_async/cpu/co_cpu.h" 10 | #include "async/co_async/promise.h" 11 | namespace co_async { 12 | namespace cpu { 13 | 14 | ///////////////////////////////////////////////// 15 | 16 | std::pair execute(async::cpu::async_cpu_op op, void* userData, const TimeOut& t) { 17 | auto res = co_async::promise([op, userData](co_async::Resolve resolve, co_async::Reject) { 18 | async::cpu::execute(op, userData, [resolve](int64_t res, void*) { 19 | resolve(std::make_shared(res)); 20 | }); 21 | }, t()); 22 | 23 | auto ret = std::make_pair(res.first, 0); 24 | if (co_async::checkOk(res)) { 25 | auto p = co_async::getOk(res); 26 | ret.second = *p; 27 | } 28 | 29 | return ret; 30 | } 31 | 32 | } 33 | } -------------------------------------------------------------------------------- /async/co_async/cpu/co_cpu.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/async/cpu/async_cpu.h" 12 | #include "async/co_async/comm.hpp" 13 | 14 | namespace co_async { 15 | namespace cpu { 16 | 17 | std::pair execute(async::cpu::async_cpu_op op, void* userData, const TimeOut& t = TimeOut()); 18 | 19 | } 20 | } -------------------------------------------------------------------------------- /async/co_async/curl/co_curl.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_CURL 10 | 11 | #include "async/co_async/curl/co_curl.h" 12 | #include "async/co_async/promise.h" 13 | 14 | namespace co_async { 15 | namespace curl { 16 | 17 | std::pair> get(const std::string& url, const std::unordered_map& headers, const TimeOut& t) { 18 | auto res = co_async::promise([&url, &headers](co_async::Resolve resolve, co_async::Reject reject) { 19 | async::curl::get(url, [resolve](async::curl::CurlParserPtr parser) { 20 | resolve(parser); 21 | }, headers); 22 | }, t()); 23 | 24 | std::pair> ret = std::make_pair(res.first, nullptr); 25 | if (co_async::checkOk(res)) { 26 | ret.second = co_async::getOk(res); 27 | } 28 | 29 | return ret; 30 | } 31 | 32 | int get(const std::string& url, std::string& body, const std::unordered_map& headers, const TimeOut& t) { 33 | auto ret = get(url, headers, t); 34 | if (co_async::checkOk(ret)) { 35 | ret.second->swapValue(body); 36 | } 37 | 38 | return ret.first; 39 | } 40 | 41 | std::pair> post(const std::string& url, const std::string& content, const std::unordered_map& headers, const TimeOut& t) { 42 | auto res = co_async::promise([&url, &content, &headers](co_async::Resolve resolve, co_async::Reject reject) { 43 | async::curl::post(url, content, [resolve](async::curl::CurlParserPtr parser) { 44 | resolve(parser); 45 | }, headers); 46 | }, t()); 47 | 48 | std::pair> ret = std::make_pair(res.first, nullptr); 49 | if (co_async::checkOk(res)) { 50 | ret.second = co_async::getOk(res); 51 | } 52 | 53 | return ret; 54 | } 55 | 56 | int post(const std::string& url, const std::string& content, std::string& rspBody, const std::unordered_map& headers, const TimeOut& t) { 57 | auto ret = post(url, content, headers, t); 58 | if (co_async::checkOk(ret)) { 59 | ret.second->swapValue(rspBody); 60 | } 61 | 62 | return ret.first; 63 | } 64 | 65 | } 66 | } 67 | 68 | #endif -------------------------------------------------------------------------------- /async/co_async/curl/co_curl.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/async/curl/async_curl.h" 12 | #include "async/co_async/comm.hpp" 13 | #include 14 | 15 | namespace co_async { 16 | namespace curl { 17 | 18 | std::pair> get(const std::string& url, const std::unordered_map& headers = {}, const TimeOut& t = TimeOut()); 19 | 20 | // @body是返回内容的body 21 | int get(const std::string& url, std::string& body, const std::unordered_map& headers = {}, const TimeOut& t = TimeOut()); 22 | 23 | std::pair> post(const std::string& url, const std::string& content, const std::unordered_map& headers = {}, const TimeOut& t = TimeOut()); 24 | 25 | // @rspBody是返回内容的body 26 | int post(const std::string& url, const std::string& content, std::string& rspBody, const std::unordered_map& headers = {}, const TimeOut& t = TimeOut()); 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /async/co_async/ipc/co_ipc.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #include "async/co_async//ipc/co_ipc.h" 10 | #include "async/co_async/promise.h" 11 | #include 12 | 13 | namespace co_async { 14 | 15 | std::shared_ptr getByUniqueId(uint64_t id); 16 | 17 | namespace ipc { 18 | 19 | std::pair send(std::function fn, const TimeOut& t) { 20 | auto res = co_async::promise([fn, t](co_async::Resolve resolve, co_async::Reject) { 21 | // 取出序列号id 22 | uint64_t seqId = resolve.result->uniqueId; 23 | 24 | // 执行真正的发送 25 | fn(seqId); 26 | 27 | }, t()); 28 | 29 | std::pair ret = std::make_pair(res.first, nullptr); 30 | if (co_async::checkOk(res)) { 31 | ret.second = co_async::getOk(res); 32 | } 33 | 34 | return ret; 35 | } 36 | 37 | void recv(uint64_t seqId, const char* data, uint32_t dataLen) { 38 | auto info = getByUniqueId(seqId); 39 | if (info == nullptr) { 40 | return; 41 | } 42 | 43 | // 校验信息 44 | uint32_t coId = seqId & 0xffffffff; 45 | if (info->resolve.coId() != coId) { 46 | return; 47 | } 48 | 49 | auto ptr = std::make_shared(); 50 | ptr->data = data; 51 | ptr->dataLen = dataLen; 52 | 53 | // 唤醒 54 | info->resolve(ptr); 55 | } 56 | 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /async/co_async/ipc/co_ipc.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include "async/co_async/comm.hpp" 13 | 14 | namespace co_async { 15 | namespace ipc { 16 | 17 | struct IpcData { 18 | const char* data = 0; 19 | uint32_t dataLen = 0; 20 | }; 21 | 22 | typedef std::shared_ptr IpcDataPtr; 23 | 24 | // fn是真正的发送函数,它的参数:第一个是序列码(作为唤醒协程的凭证) 25 | std::pair send(std::function fn, const TimeOut& t = TimeOut(5 * 1000)); 26 | 27 | // 唤醒 28 | void recv(uint64_t seqId, const char* data, uint32_t dataLen); 29 | 30 | } 31 | } -------------------------------------------------------------------------------- /async/co_async/mongo/co_mongo.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/async/mongo/async_mongo.h" 12 | #include "async/co_async/comm.hpp" 13 | 14 | namespace co_async { 15 | namespace mongo { 16 | 17 | // pair.first表示是[E_OK/E_TIMEOUT] 18 | // 详细信息放在返回值里 19 | std::pair execute(const std::string &uri, const async::mongo::BaseMongoCmd &cmd, const TimeOut& t = TimeOut()); 20 | 21 | // @返回值pair.second表示mongo语句操作是否成功 22 | // @jsonResult表示返回的结果集 23 | std::pair execute(const std::string &uri, const async::mongo::BaseMongoCmd &cmd, std::string* jsonResult, const TimeOut& t = TimeOut()); 24 | 25 | // @deletedCount是删除命令下的删除条数 26 | std::pair execute(const std::string &uri, const async::mongo::BaseMongoCmd &cmd, int* deletedCount, const TimeOut& t = TimeOut()); 27 | 28 | // @modifiedCount, @matchedCount, @upsertedCount是更新命令下的返回 29 | std::pair execute(const std::string &uri, const async::mongo::BaseMongoCmd &cmd, int* modifiedCount, int* matchedCount, int* upsertedCount, const TimeOut& t = TimeOut()); 30 | 31 | } 32 | } -------------------------------------------------------------------------------- /async/co_async/mysql/co_mysql.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | //#define USE_ASYNC_MYSQL 10 | #ifdef USE_ASYNC_MYSQL 11 | 12 | #include "async/co_async/mysql/co_mysql.h" 13 | #include "async/co_async/promise.h" 14 | #include 15 | 16 | 17 | namespace co_async { 18 | namespace mysql { 19 | 20 | std::pair query(const std::string& uri, const std::string& sql, const TimeOut& t) { 21 | auto res = co_async::promise([&uri, &sql](co_async::Resolve resolve, co_async::Reject reject) { 22 | async::mysql::query(uri, sql, [resolve](async::mysql::MysqlReplyParserPtr ptr) { 23 | resolve(ptr); 24 | }); 25 | }, t()); 26 | 27 | std::pair ret = std::make_pair(res.first, nullptr); 28 | if (co_async::checkOk(res)) { 29 | ret.second = co_async::getOk(res); 30 | } 31 | 32 | return ret; 33 | } 34 | 35 | std::pair execute(const std::string& uri, const std::string& sql, const TimeOut& t) { 36 | auto res = co_async::promise([&uri, &sql](co_async::Resolve resolve, co_async::Reject reject) { 37 | async::mysql::execute(uri, sql, [resolve](async::mysql::MysqlReplyParserPtr ptr) { 38 | resolve(ptr); 39 | }); 40 | }, t()); 41 | 42 | std::pair ret = std::make_pair(res.first, nullptr); 43 | if (co_async::checkOk(res)) { 44 | ret.second = co_async::getOk(res); 45 | } 46 | 47 | return ret; 48 | } 49 | 50 | std::pair execute(const std::string& uri, const std::string& sql, int& effectRow, const TimeOut& t) { 51 | auto res = execute(uri, sql, t); 52 | std::pair ret = std::make_pair(res.first, 0); 53 | 54 | if (co_async::checkOk(res)) { 55 | auto parser = res.second; 56 | ret.second = parser->GetError(); 57 | effectRow = parser->GetAffectedRow(); 58 | } 59 | 60 | return ret; 61 | } 62 | 63 | std::pair query(const std::string& uri, const std::string& sql, async::mysql::async_mysql_query_cb cb, const TimeOut& t) { 64 | auto res = query(uri, sql, t); 65 | std::pair ret = std::make_pair(res.first, 0); 66 | 67 | if (co_async::checkOk(res)) { 68 | auto parser = res.second; 69 | ret.second = parser->GetError(); 70 | 71 | int idx = 1; 72 | int affectedRow = parser->GetNumRow(); 73 | int fields = parser->GetField(); 74 | 75 | while (true) { 76 | auto row = parser->Next(); 77 | if (row) { 78 | cb(ret.second, row, idx, fields, affectedRow); 79 | } 80 | else { 81 | break; 82 | } 83 | } 84 | } 85 | 86 | return ret; 87 | } 88 | 89 | 90 | 91 | } 92 | } 93 | 94 | #endif -------------------------------------------------------------------------------- /async/co_async/mysql/co_mysql.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/async/mysql/async_mysql.h" 12 | #include "async/co_async/comm.hpp" 13 | 14 | namespace co_async { 15 | namespace mysql { 16 | 17 | // 不支持查询多结果集,如果执行了返回多结果集的sql语句,行为是未可知的 18 | std::pair query(const std::string& uri, const std::string& sql, const TimeOut& t = TimeOut()); 19 | 20 | std::pair execute(const std::string& uri, const std::string& sql, const TimeOut& t = TimeOut()); 21 | 22 | // 不支持查询多结果集,如果执行了返回多结果集的sql语句,行为是未可知的 23 | std::pair query(const std::string& uri, const std::string& sql, async::mysql::async_mysql_query_cb cb, const TimeOut& t = TimeOut()); 24 | 25 | // pair.second表示错误码 26 | std::pair execute(const std::string& uri, const std::string& sql, int& effectRow, const TimeOut& t = TimeOut()); 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /async/co_async/promise.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | /* 10 | * 11 | */ 12 | 13 | #pragma once 14 | 15 | #include 16 | #include "async/co_async/comm.hpp" 17 | 18 | namespace co_async { 19 | 20 | // 循环,内部调用异步循环 21 | bool loopPromise(uint32_t curTime = 0); 22 | 23 | // 返回值是pair: first=[E_OK/E_TIMEOUT/E_ERROR], second=[std::shared_ptr/nullptr/other] 24 | // 1、first=E_OK时, second=目标 25 | // 2、first=E_TIMEOUT时,second=nullptr 26 | // 3、first=E_ERROR时,second=[std::shared_ptr/nullptr] 27 | std::pair> promise(std::function fn, int timeOut); 28 | 29 | void setTimeout(std::function fn, int timeOut); 30 | 31 | // 协程等待n毫秒 32 | void wait(int timeOut); 33 | 34 | } 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /async/co_async/rabbitmq/co_rabbitmq.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_RABBITMQ 10 | 11 | #include "async/co_async/rabbitmq/co_rabbitmq.h" 12 | #include "async/coroutine/coroutine.hpp" 13 | #include "async/co_async/promise.h" 14 | #include 15 | 16 | namespace co_async { 17 | namespace rabbitmq { 18 | 19 | struct rabbit_get_result { 20 | bool ok; 21 | std::string msg; 22 | }; 23 | 24 | std::pair execute(const std::string& uri, std::shared_ptr cmd, const TimeOut& t) { 25 | auto res = co_async::promise([&uri, cmd](co_async::Resolve resolve, co_async::Reject reject) { 26 | async::rabbitmq::execute(uri, cmd, [resolve](async::rabbitmq::RabbitParserPtr parser) { 27 | resolve(parser); 28 | }); 29 | }, t()); 30 | 31 | std::pair ret = std::make_pair(res.first, nullptr); 32 | if (co_async::checkOk(res)) { 33 | ret.second = co_async::getOk(res); 34 | } 35 | return ret; 36 | } 37 | 38 | std::pair execute2(const std::string& uri, std::shared_ptr cmd, const TimeOut& t) { 39 | auto res = execute(uri, cmd, t); 40 | std::pair ret = std::make_pair(res.first, false); 41 | if (co_async::checkOk(res)) { 42 | auto parser = res.second; 43 | } 44 | 45 | return ret; 46 | } 47 | 48 | std::pair watchAck(const std::string& uri, std::shared_ptr cmd, const TimeOut& t) { 49 | auto res = co_async::promise([&uri, cmd](co_async::Resolve resolve, co_async::Reject reject) { 50 | async::rabbitmq::watchAck(uri, cmd, [resolve](async::rabbitmq::RabbitParserPtr parser) { 51 | resolve(parser); 52 | }); 53 | }, t()); 54 | 55 | std::pair ret = std::make_pair(res.first, false); 56 | if (co_async::checkOk(res)) { 57 | auto parser = co_async::getOk(res); 58 | ret.second = parser->isOk(); 59 | } 60 | return ret; 61 | } 62 | 63 | // bool watch(const std::string& uri, std::shared_ptr cmd, co_async_rabbit_watch_cb cb) { 64 | // bool ret = async::rabbitmq::watch(uri, cmd, [cb](void* reply, void* envelope, uint64_t delivery_tag, char* body, size_t len) { 65 | // CoroutineTask::doTask([cb, reply, envelope, delivery_tag, body, len](void*) { 66 | // cb(reply, envelope, delivery_tag, body, len); 67 | // }, 0); 68 | // }); 69 | // return ret; 70 | // } 71 | 72 | } 73 | } 74 | 75 | #endif -------------------------------------------------------------------------------- /async/co_async/rabbitmq/co_rabbitmq.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/async/rabbitmq/async_rabbitmq.h" 12 | #include "async/co_async/comm.hpp" 13 | 14 | namespace co_async { 15 | namespace rabbitmq { 16 | 17 | std::pair execute(const std::string& uri, std::shared_ptr cmd, const TimeOut& t = TimeOut()); 18 | 19 | // pair.second表示执行结果 20 | std::pair execute2(const std::string& uri, std::shared_ptr cmd, const TimeOut& t = TimeOut()); 21 | 22 | std::pair watchAck(const std::string& uri, std::shared_ptr cmd, const TimeOut& t = TimeOut()); 23 | 24 | // 当有队列消息被监听到,cb会在协程里被调用 25 | // warn: 此函数不能在子协程里被调用,要在主协程里被调用 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 26 | //bool watch(const std::string& uri, std::shared_ptr cmd, co_async_rabbit_watch_cb cb); 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /async/co_async/redis/co_redis.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_REDIS 10 | 11 | #include "async/co_async/redis/co_redis.h" 12 | #include "async/async/redis/redis_exception.h" 13 | 14 | namespace co_async { 15 | namespace redis { 16 | 17 | ///////////////////////////////////////////////////////////////////////// 18 | 19 | std::pair execute(const std::string& uri, const async::redis::BaseRedisCmd& cmd, const TimeOut& t) { 20 | auto res = co_async::promise([&uri, &cmd](co_async::Resolve resolve, co_async::Reject reject) { 21 | async::redis::execute(uri, cmd, [resolve](async::redis::RedisReplyParserPtr parser) { 22 | resolve(parser); 23 | }); 24 | }, t()); 25 | 26 | std::pair ret = std::make_pair(res.first, nullptr); 27 | if (co_async::checkOk(res)) { 28 | ret.second = co_async::getOk(res); 29 | } 30 | else { 31 | log("[co_async_redis] failed to execute redis, timeout or error|%s|%d", cmd.GetCmd().c_str(), ret.first); 32 | } 33 | 34 | return ret; 35 | } 36 | 37 | std::pair execute(const std::string& uri, const async::redis::BaseRedisCmd& cmd, long long& result, const TimeOut& t) { 38 | auto res = execute(uri, cmd, t); 39 | std::pair ret = std::make_pair(res.first, false); 40 | 41 | if (co_async::checkOk(res)) { 42 | try { 43 | auto parser = res.second; 44 | parser->GetInteger(result); 45 | ret.second = true; 46 | } 47 | catch(async::redis::RedisException& exce) { 48 | log("[co_async_redis] failed to execute redis|%s|%s", cmd.GetCmd().c_str(), exce.What().c_str()); 49 | } 50 | } 51 | 52 | return ret; 53 | } 54 | 55 | std::pair execute(const std::string& uri, const async::redis::BaseRedisCmd& cmd, std::string& result, const TimeOut& t) { 56 | auto res = execute(uri, cmd, t); 57 | std::pair ret = std::make_pair(res.first, false); 58 | 59 | if (co_async::checkOk(res)) { 60 | try { 61 | auto parser = res.second; 62 | parser->GetString(result); 63 | ret.second = true; 64 | } 65 | catch(async::redis::RedisException& exce) { 66 | log("[co_async_redis] failed to execute redis|%s|%s", cmd.GetCmd().c_str(), exce.What().c_str()); 67 | } 68 | } 69 | 70 | return ret; 71 | } 72 | 73 | std::pair execute(const std::string& uri, const async::redis::BaseRedisCmd& cmd, bool& result, const TimeOut& t) { 74 | auto res = execute(uri, cmd, t); 75 | std::pair ret = std::make_pair(res.first, false); 76 | 77 | if (co_async::checkOk(res)) { 78 | try { 79 | auto parser = res.second; 80 | parser->GetOk(result); 81 | ret.second = true; 82 | } 83 | catch(async::redis::RedisException& exce) { 84 | log("[co_async_redis] failed to execute redis|%s|%s", cmd.GetCmd().c_str(), exce.What().c_str()); 85 | } 86 | } 87 | 88 | return ret; 89 | } 90 | 91 | } 92 | } 93 | 94 | #endif -------------------------------------------------------------------------------- /async/co_async/redis/co_redis.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/async/redis/async_redis.h" 12 | #include "async/co_async/promise.h" 13 | #include "async/log.h" 14 | #include 15 | 16 | /** 17 | * notice:因为async::redis::execute内部有链接失败重试机制(10秒),所以co_async::redis::execute的超时时间最好不要短于10秒 18 | */ 19 | 20 | namespace co_async { 21 | namespace redis { 22 | 23 | std::pair execute(const std::string& uri, const async::redis::BaseRedisCmd& cmd, const TimeOut& t = TimeOut()); 24 | 25 | // @返回值pair.second表示redis语句操作是否成功 26 | std::pair execute(const std::string& uri, const async::redis::BaseRedisCmd& cmd, long long& result, const TimeOut& t = TimeOut()); 27 | 28 | std::pair execute(const std::string& uri, const async::redis::BaseRedisCmd& cmd, std::string& result, const TimeOut& t = TimeOut()); 29 | 30 | std::pair execute(const std::string& uri, const async::redis::BaseRedisCmd& cmd, bool& result, const TimeOut& t = TimeOut()); 31 | 32 | // get array 33 | template 34 | std::pair execute(const std::string& uri, const async::redis::BaseRedisCmd& cmd, T& result, const TimeOut& t = TimeOut()) { 35 | auto res = execute(uri, cmd, t); 36 | std::pair ret = std::make_pair(res.first, false); 37 | 38 | if (co_async::checkOk(res)) { 39 | try { 40 | auto parser = res.second; 41 | parser->GetArray(result); 42 | ret.second = true; 43 | } 44 | catch (const async::redis::RedisException &exce) { 45 | log("[co_async_redis] failed to execute redis|%s|%s", cmd.GetCmd().c_str(), exce.What().c_str()); 46 | } 47 | } 48 | 49 | return ret; 50 | } 51 | 52 | // get map 53 | template 54 | std::pair execute(const std::string& uri, const async::redis::BaseRedisCmd& cmd, std::map& result, const TimeOut& t = TimeOut()) { 55 | auto res = execute(uri, cmd, t); 56 | std::pair ret = std::make_pair(res.first, false); 57 | 58 | if (co_async::checkOk(res)) { 59 | try { 60 | auto parser = res.second; 61 | parser->GetMap(result); 62 | ret.second = true; 63 | } 64 | catch (const async::redis::RedisException &exce) { 65 | log("[co_async_redis] failed to execute redis|%s|%s", cmd.GetCmd().c_str(), exce.What().c_str()); 66 | } 67 | } 68 | 69 | return ret; 70 | } 71 | 72 | // get scan result 73 | template 74 | std::pair execute(const std::string& uri, const async::redis::BaseRedisCmd& cmd, long long& cursor, T& result, const TimeOut& t = TimeOut()) { 75 | auto res = execute(uri, cmd, t); 76 | std::pair ret = std::make_pair(res.first, false); 77 | 78 | if (co_async::checkOk(res)) { 79 | try { 80 | auto parser = res.second; 81 | parser->GetScan(cursor, result); 82 | ret.second = true; 83 | } 84 | catch (const async::redis::RedisException &exce) { 85 | log("[co_async_redis] failed to execute redis|%s|%s", cmd.GetCmd().c_str(), exce.What().c_str()); 86 | } 87 | } 88 | 89 | return ret; 90 | } 91 | 92 | } // redis 93 | } // co_async -------------------------------------------------------------------------------- /async/co_async/time_pool.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | namespace co_async { 15 | namespace t_pool { 16 | 17 | // 设置最大的间隔小时, 最大不能超过24,默认是1小时 18 | // 这个需要在addTimer之前就调用 19 | void setMaxInterval(uint32_t hours); 20 | 21 | // 不允许interval的值超过setMaxInterval的限制 22 | uint64_t addTimer(uint32_t interval, std::functionfunc); 23 | 24 | bool cancelTimer(uint64_t id); 25 | 26 | // 调用此函数,超时的节点会被调用回调,时间是毫秒 27 | bool update(); 28 | 29 | } 30 | } -------------------------------------------------------------------------------- /async/co_async/zookeeper/co_zookeeper.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_ASYNC_ZOOKEEPER 10 | 11 | #include "async/co_async/zookeeper/co_zookeeper.h" 12 | #include "async/co_async/promise.h" 13 | 14 | namespace co_async { 15 | namespace zookeeper { 16 | 17 | std::pair execute(const std::string& uri, std::shared_ptr cmd, const TimeOut& t) { 18 | auto res = co_async::promise([&uri, cmd](co_async::Resolve resolve, co_async::Reject reject) { 19 | async::zookeeper::execute(uri, cmd, [resolve](async::zookeeper::ZookParserPtr parser) { 20 | resolve(parser); 21 | }); 22 | }, t()); 23 | 24 | std::pair ret = std::make_pair(res.first, nullptr); 25 | if (co_async::checkOk(res)) { 26 | ret.second = co_async::getOk(res); 27 | } 28 | return ret; 29 | } 30 | 31 | int execute(const std::string& uri, std::shared_ptr cmd, bool& ok, const TimeOut& t) { 32 | ok = false; 33 | auto res = co_async::promise([&uri, cmd](co_async::Resolve resolve, co_async::Reject reject) { 34 | async::zookeeper::execute(uri, cmd, [resolve](async::zookeeper::ZookParserPtr parser) { 35 | resolve(parser); 36 | }); 37 | }, t()); 38 | 39 | if (co_async::checkOk(res)) { 40 | auto parser = co_async::getOk(res); 41 | ok = parser->zOk(); 42 | } 43 | 44 | return res.first; 45 | } 46 | 47 | std::pair execute2(const std::string& uri, std::shared_ptr cmd, const TimeOut& t) { 48 | auto res = execute(uri, cmd, t); 49 | std::pair ret = std::make_pair(res.first, false); 50 | 51 | if (co_async::checkOk(res)) { 52 | auto parser = res.second; 53 | ret.second = parser->zOk(); 54 | } 55 | 56 | return ret; 57 | } 58 | 59 | } 60 | } 61 | #endif -------------------------------------------------------------------------------- /async/co_async/zookeeper/co_zookeeper.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2023 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/async/zookeeper/async_zookeeper.h" 12 | #include "async/co_async/comm.hpp" 13 | 14 | namespace co_async { 15 | namespace zookeeper { 16 | 17 | // pair.first表示协程是否成功 18 | std::pair execute(const std::string& uri, std::shared_ptr cmd, const TimeOut& t = TimeOut()); 19 | 20 | int execute(const std::string& uri, std::shared_ptr cmd, bool& ok, const TimeOut& t = TimeOut()); 21 | 22 | // pair.second表示命令执行是否成功 23 | std::pair execute2(const std::string& uri, std::shared_ptr cmd, const TimeOut& t = TimeOut()); 24 | 25 | } 26 | } -------------------------------------------------------------------------------- /async/coroutine/config.hpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #ifndef M_PLATFORM_WIN32 12 | #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 13 | #define M_PLATFORM_WIN32 1 14 | #endif 15 | #endif 16 | 17 | #ifndef M_PLATFORM_WIN 18 | #if defined(M_PLATFORM_WIN32) || defined(WIN64) 19 | #define M_PLATFORM_WIN 1 20 | #endif 21 | #endif 22 | 23 | #ifdef M_PLATFORM_WIN 24 | #ifndef M_WIN32_LEAN_AND_MEAN 25 | #define WIN32_LEAN_AND_MEAN 26 | #endif // end M_WIN32_LEAN_AND_MEAN 27 | #include 28 | #else 29 | #include 30 | #include 31 | #endif // end M_PLATFORM_WIN 32 | 33 | // common header 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #ifndef COROUTINE_READY 40 | #define COROUTINE_READY (1) 41 | #endif 42 | 43 | #ifndef COROUTINE_RUNNING 44 | #define COROUTINE_RUNNING (2) 45 | #endif 46 | 47 | #ifndef COROUTINE_SUSPEND 48 | #define COROUTINE_SUSPEND (3) 49 | #endif 50 | 51 | #ifndef COROUTINE_DEAD 52 | #define COROUTINE_DEAD (4) 53 | #endif 54 | 55 | #ifndef DEFAULT_COROUTINE 56 | #define DEFAULT_COROUTINE (1024) 57 | #endif 58 | 59 | // invalid coroutine id 60 | #ifndef M_INVALID_COROUTINE_ID 61 | #define M_INVALID_COROUTINE_ID (-1) 62 | #endif 63 | 64 | // main coroutine id 65 | #ifndef M_MAIN_COROUTINE_ID 66 | #define M_MAIN_COROUTINE_ID (0) 67 | #endif 68 | 69 | // for private stack 70 | #ifndef M_COROUTINE_STACK_SIZE 71 | #define M_COROUTINE_STACK_SIZE 4*1024*1024 72 | #endif 73 | 74 | // coroutine func type 75 | typedef void(*_coroutine_func_)(void*ud); 76 | 77 | -------------------------------------------------------------------------------- /async/coroutine/coroutine.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #include "async/coroutine/coroutine.hpp" 10 | #include "async/coroutine/tls.hpp" 11 | #include 12 | 13 | #define gschedule tlsdata<_schedule_>::data() 14 | 15 | unsigned int Coroutine::curid() { 16 | _schedule_& schedule = gschedule; 17 | if (schedule._curco) { 18 | return schedule._curco->_id; 19 | } 20 | return M_MAIN_COROUTINE_ID; 21 | } 22 | 23 | void Coroutine::_alloc_schedule_(_schedule_& schedule) { 24 | if (!schedule._co) { 25 | schedule._nco = 0; 26 | schedule._cap = DEFAULT_COROUTINE; 27 | schedule._curco = NULL; 28 | schedule._co = (_coroutine_**)malloc(sizeof(_coroutine_*) * schedule._cap); 29 | assert(schedule._co); 30 | memset(schedule._co, 0, sizeof(_coroutine_*) * schedule._cap); 31 | schedule._freeid.clear(); 32 | } 33 | else { 34 | if (schedule._nco < schedule._cap) { 35 | return; 36 | } 37 | int cap = schedule._cap * 2; 38 | schedule._co = (_coroutine_**)realloc(schedule._co, cap * sizeof(_coroutine_*)); 39 | assert(schedule._co); 40 | memset(schedule._co + schedule._cap, 0, schedule._cap * sizeof(_coroutine_*)); 41 | schedule._cap = cap; 42 | } 43 | } 44 | 45 | _coroutine_* Coroutine::_alloc_co_(_schedule_& schedule, _coroutine_func_ routine, void* data) { 46 | _coroutine_* co = (_coroutine_*)malloc(sizeof(_coroutine_)); 47 | co->_function = routine; 48 | co->_data = data; 49 | co->_status = COROUTINE_READY; 50 | if (!schedule._freeid.empty()) { 51 | int id = schedule._freeid.back(); 52 | schedule._freeid.pop_back(); 53 | schedule._co[id - 1] = co; 54 | co->_id = id; 55 | } 56 | else { 57 | if (schedule._nco == schedule._cap) { 58 | _alloc_schedule_(schedule); 59 | } 60 | schedule._co[schedule._nco] = co; 61 | ++schedule._nco; 62 | co->_id = schedule._nco; 63 | } 64 | return co; 65 | } 66 | 67 | bool Coroutine::_check_co_id(_schedule_& schedule, int co_id) { 68 | if (co_id <= M_MAIN_COROUTINE_ID) { 69 | return false; 70 | } 71 | if (co_id > schedule._cap) { 72 | return false; 73 | } 74 | return true; 75 | } 76 | 77 | bool Coroutine::_check_resume_(_schedule_& schedule, int co_id) { 78 | if (schedule._curco) { 79 | return false; 80 | } 81 | return _check_co_id(schedule, co_id); 82 | } 83 | -------------------------------------------------------------------------------- /async/coroutine/coroutine.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/coroutine/config.hpp" 12 | #include "async/coroutine/svector.hpp" 13 | 14 | struct _base_coroutine_{ 15 | int _id; 16 | int _status; 17 | void* _data; 18 | _coroutine_func_ _function; 19 | }; 20 | 21 | struct _coroutine_; 22 | 23 | struct _base_schedule_ { 24 | bool init; 25 | int _cap; 26 | int _nco; 27 | unsigned int _stack_size; 28 | _coroutine_** _co; 29 | _coroutine_* _curco; 30 | svector _freeid; 31 | }; 32 | 33 | ///////////////////////////////////////////////////////// 34 | 35 | #ifdef M_PLATFORM_WIN 36 | 37 | struct _coroutine_ : public _base_coroutine_ { 38 | LPVOID _ctx; 39 | }; 40 | 41 | struct _schedule_ : public _base_schedule_ { 42 | _schedule_() { 43 | clear(); 44 | } 45 | void clear() { 46 | _cap = 0; 47 | _nco = 0; 48 | _curco = 0; 49 | _ctx = 0; 50 | _co = 0; 51 | _stack_size = 0; 52 | _freeid.clear(); 53 | } 54 | LPVOID _ctx; 55 | }; 56 | 57 | #else 58 | 59 | struct _coroutine_ : public _base_coroutine_ { 60 | char*_stack; 61 | int _size; 62 | int _cap; 63 | ucontext_t _ctx; 64 | }; 65 | 66 | struct _schedule_ : public _base_schedule_ { 67 | _schedule_() { 68 | clear(); 69 | } 70 | void clear() { 71 | _cap = 0; 72 | _nco = 0; 73 | _curco = 0; 74 | // _ctx = 0; 75 | _co = 0; 76 | _freeid.clear(); 77 | _pri_stack = false; 78 | _stack_size = 0; 79 | } 80 | 81 | bool _pri_stack; 82 | ucontext_t _ctx; 83 | char _stack[M_COROUTINE_STACK_SIZE]; 84 | }; 85 | 86 | #endif 87 | 88 | class Coroutine { 89 | public: 90 | // init private stack environment 91 | static bool init(unsigned int stack_size); 92 | 93 | // init public stack environment 94 | static bool init(); 95 | 96 | // create one new coroutine 97 | static int create(_coroutine_func_ routine, void* data); 98 | 99 | // close 100 | static bool close(); 101 | 102 | // resume 103 | static void resume(int co_id); 104 | 105 | // yield 106 | static void yield(); 107 | 108 | // current coroutine id 109 | static unsigned int curid(); 110 | 111 | static bool destroy(int co_id); 112 | 113 | private: 114 | static bool _init(unsigned int stack_size, bool pri_stack = false); 115 | 116 | static void _alloc_schedule_(_schedule_& schedule); 117 | 118 | static _coroutine_* _alloc_co_(_schedule_& schedule, _coroutine_func_ routine, void* data); 119 | 120 | static bool _check_co_id(_schedule_& schedule, int co_id); 121 | 122 | static bool _check_resume_(_schedule_& schedule, int co_id); 123 | }; 124 | 125 | -------------------------------------------------------------------------------- /async/coroutine/coroutine.hpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/coroutine/coroutine.h" 12 | #include "async/coroutine/coroutine_task.h" -------------------------------------------------------------------------------- /async/coroutine/coroutine_task.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #include "async/coroutine/coroutine_task.h" 10 | #include "async/coroutine/coroutine.h" 11 | #include "async/coroutine/tls.hpp" 12 | #include 13 | 14 | // 定义该宏会打开调试日志 15 | //#define M_COROUTINE_TASK_LOG (1) 16 | 17 | #ifdef M_COROUTINE_TASK_LOG 18 | #include 19 | #define COROUTINE_TASK_LOG printf 20 | #else 21 | #define COROUTINE_TASK_LOG(...) 22 | #endif 23 | 24 | // max reserve coroutine count in CoroutineTask 25 | #ifndef M_MAX_RESERVE_COROUTINE 26 | #define M_MAX_RESERVE_COROUTINE (100) 27 | #endif 28 | 29 | struct new_co_task { 30 | int co_id; 31 | coroutine_task_func func; 32 | void* p; 33 | }; 34 | 35 | typedef std::list new_co_task_vector; 36 | 37 | new_co_task* create_new_co_task(coroutine_task_func func, void*p); 38 | bool recycle_new_co_task(new_co_task*); 39 | void co_task_func(void*); 40 | 41 | bool CoroutineTask::doTask(coroutine_task_func func, void*p) { 42 | if (Coroutine::curid() != M_MAIN_COROUTINE_ID) { 43 | COROUTINE_TASK_LOG("need to call doTask in main_coroutine\n"); 44 | return false; 45 | } 46 | 47 | new_co_task* task = create_new_co_task(func, p); 48 | if (!task) { 49 | COROUTINE_TASK_LOG("failed to create new_co_task\n"); 50 | return false; 51 | } 52 | 53 | Coroutine::resume(task->co_id); 54 | return true; 55 | } 56 | 57 | bool CoroutineTask::resumeTask(int co_id) { 58 | if (Coroutine::curid() != M_MAIN_COROUTINE_ID) { 59 | COROUTINE_TASK_LOG("need to call resumeTask in main_coroutine\n"); 60 | return false; 61 | } 62 | 63 | Coroutine::resume(co_id); 64 | return true; 65 | } 66 | 67 | ///////////////////////////////////////////////////////////////////////////////////////////// 68 | 69 | new_co_task* create_new_co_task(coroutine_task_func func, void*p) { 70 | new_co_task_vector& task_vec = tlsdata::data(); 71 | new_co_task* task = 0; 72 | if (task_vec.empty()) { 73 | // 创建一个 74 | task = new new_co_task; 75 | task->co_id = Coroutine::create(co_task_func, task); 76 | } 77 | else { 78 | task = task_vec.front(); 79 | task_vec.pop_front(); 80 | } 81 | task->func = func; 82 | task->p = p; 83 | return task; 84 | } 85 | 86 | void co_task_func(void* p) { 87 | new_co_task* task = (new_co_task*)p; 88 | int co_id = task->co_id; 89 | COROUTINE_TASK_LOG("start new corouitine: %d\n", co_id); 90 | 91 | while (true) { 92 | if (!task->func) { 93 | break; 94 | } 95 | 96 | task->func(task->p); 97 | if (recycle_new_co_task(task)) { 98 | COROUTINE_TASK_LOG("yield corouitine: %d\n", co_id); 99 | Coroutine::yield(); 100 | continue; 101 | } 102 | break; 103 | } 104 | 105 | COROUTINE_TASK_LOG("exit corouitine: %d\n", co_id); 106 | 107 | #ifndef M_COROUTINE_TASK_LOG 108 | co_id++; 109 | #endif 110 | } 111 | 112 | bool recycle_new_co_task(new_co_task* task) { 113 | task->func = nullptr; 114 | task->p = 0; 115 | new_co_task_vector& task_vec = tlsdata::data(); 116 | if (task_vec.size() > M_MAX_RESERVE_COROUTINE) { 117 | delete task; 118 | return false; 119 | } 120 | else { 121 | task_vec.push_back(task); 122 | return true; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /async/coroutine/coroutine_task.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | typedef std::function coroutine_task_func; 14 | 15 | class CoroutineTask { 16 | public: 17 | static bool doTask(coroutine_task_func func, void*p); 18 | 19 | static bool resumeTask(int co_id); 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /async/coroutine/svector.hpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | template 14 | class svector{ 15 | protected: 16 | size_t _cap; 17 | size_t _size; 18 | T* _head; 19 | public: 20 | svector() { 21 | _cap = 100; 22 | _size = 0; 23 | _head = (T*)malloc(sizeof(T)*_cap); 24 | } 25 | 26 | svector(size_t cap) { 27 | _cap = cap; 28 | _size = 0; 29 | _head = (T*)malloc(sizeof(T)*_cap); 30 | } 31 | 32 | ~svector() { 33 | clear(); 34 | free(_head); 35 | } 36 | 37 | bool empty()const { 38 | return (_size == 0); 39 | } 40 | 41 | size_t size()const { 42 | return _size; 43 | } 44 | 45 | void swap(svector& other) { 46 | size_t tmp = this->_cap; 47 | this->_cap = other._cap; 48 | other._cap = tmp; 49 | tmp = this->_size; 50 | this->_size = other._size; 51 | other._size = tmp; 52 | T* tmp2 = this->_head; 53 | this->_head = other._head; 54 | other._head = tmp2; 55 | } 56 | 57 | T& back() { 58 | return _head[_size-1]; 59 | } 60 | 61 | void pop_back() { 62 | if (_size > 0) { 63 | _size--; 64 | T* p = &(this->_head[_size]); 65 | p->~T(); 66 | } 67 | } 68 | 69 | void push_back(const T& t) { 70 | if (_size >= _cap) { 71 | this->_cap = this->_cap * 2; 72 | this->_head = (T*)realloc(this->_head, sizeof(T)*this->_cap); 73 | } 74 | T* p = &(_head[_size++]); 75 | new(p)T(t); 76 | } 77 | 78 | void clear() { 79 | for (size_t i = 0; i < _size; ++i) { 80 | T* p = &(this->_head[i]); 81 | p->~T(); 82 | } 83 | _size = 0; 84 | } 85 | 86 | T& operator[](int i) { 87 | return _head[i]; 88 | } 89 | }; 90 | 91 | -------------------------------------------------------------------------------- /async/coroutine/tls.hpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/coroutine/config.hpp" 12 | 13 | #ifdef M_PLATFORM_WIN 14 | 15 | template 16 | class tlsdata 17 | { 18 | public: 19 | struct _init_{ 20 | DWORD _tkey; 21 | _init_(){ 22 | _tkey = TlsAlloc(); 23 | assert(_tkey != TLS_OUT_OF_INDEXES); 24 | } 25 | ~_init_(){ 26 | T* pv = (T*)TlsGetValue(_tkey); 27 | TlsFree(_tkey); 28 | delete pv; 29 | } 30 | }; 31 | 32 | inline static T& data(){ 33 | T* pv = 0; 34 | if (0 == (pv = (T*)TlsGetValue(_data._tkey))){ 35 | pv = new T; 36 | TlsSetValue(_data._tkey, (void*)pv); 37 | } 38 | return *pv; 39 | } 40 | 41 | protected: 42 | tlsdata(const tlsdata&); 43 | tlsdata& operator=(const tlsdata&); 44 | 45 | private: 46 | static _init_ _data; 47 | }; 48 | 49 | #else 50 | 51 | #include 52 | 53 | template 54 | class tlsdata 55 | { 56 | public: 57 | struct _init_{ 58 | pthread_key_t _tkey; 59 | _init_(){ 60 | pthread_key_create(&_tkey, destructor); 61 | } 62 | ~_init_(){ 63 | } 64 | }; 65 | 66 | union _point_ { 67 | T* p1; 68 | T* p2; 69 | }; 70 | 71 | static T& data(){ 72 | // ���������ɼƣ����gcc�����Ż�ѡ�������clobbered����Χɱ 73 | _point_ p; 74 | if (0 == (p.p1 = (T*)pthread_getspecific(_data._tkey))) { 75 | p.p1 = new T; 76 | pthread_setspecific(_data._tkey, p.p1); 77 | } 78 | return *p.p2; 79 | } 80 | 81 | protected: 82 | tlsdata(const tlsdata&); 83 | tlsdata& operator=(const tlsdata&); 84 | 85 | static void destructor(void* v) { 86 | T* pv = (T*)v; 87 | delete pv; 88 | } 89 | 90 | private: 91 | static _init_ _data; 92 | }; 93 | 94 | #endif 95 | 96 | template 97 | typename tlsdata::_init_ tlsdata::_data; 98 | 99 | -------------------------------------------------------------------------------- /async/ipc/ipc.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #include "async/ipc/ipc.h" 10 | 11 | namespace ipc { 12 | 13 | } -------------------------------------------------------------------------------- /async/ipc/ipc.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/ipc/zero_mq_unit.h" 12 | #include "async/ipc/zero_mq_handler.h" 13 | #include "async/log.h" 14 | #include 15 | 16 | namespace ipc { 17 | 18 | } -------------------------------------------------------------------------------- /async/ipc/zero_mq_handler.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_IPC 10 | 11 | #include "async/ipc/ipc.h" 12 | #include 13 | #include 14 | #include 15 | 16 | namespace ipc { 17 | 18 | bool ZeromqHandler::update(unsigned int) { 19 | if (m_unit_vec.empty()) { 20 | return false; 21 | } 22 | 23 | // 最大路由数量限制为512 24 | size_t size = m_unit_vec.size(); 25 | if (size > 512) { 26 | throw std::string("error"); 27 | return false; 28 | } 29 | 30 | zmq_pollitem_t items[512]; 31 | for (size_t idx = 0; idx < size; ++idx) { 32 | items[idx].socket = m_unit_vec[idx]->getSock(); 33 | items[idx].events = ZMQ_POLLIN; 34 | items[idx].fd = 0; 35 | } 36 | 37 | /** 38 | * 后面可优化的点:rc的返回值是zmq_pollitem_t的数量,所以没有必要遍历全部 39 | */ 40 | size_t rc = zmq_poll(items, size, 0); 41 | if (rc > 0) { 42 | for (size_t idx = 0; idx < rc; ++idx) { 43 | if (items[idx].revents & ZMQ_POLLIN) { 44 | do { 45 | uint32_t identify; 46 | std::string data; 47 | if (m_unit_vec[idx]->recvData(identify, data) <= 0) { 48 | break; 49 | } 50 | onData(m_unit_vec[idx]->uniqueId(), identify, data); 51 | } while (true); 52 | } 53 | } 54 | } 55 | 56 | return (rc > 0); 57 | } 58 | 59 | bool ZeromqHandler::addUnit(ZeromqUnitPtr ptr) { 60 | // 按id进行排序 61 | m_unit_vec.push_back(ptr); 62 | return true; 63 | } 64 | 65 | ///////////////////////////////////////////////////// 66 | 67 | uint64_t ZeromqRouterHandler::listen(const std::string& addr) { 68 | auto ptr = std::make_shared(addr); 69 | if (!ptr->listen()) { 70 | assert(false); 71 | return 0; 72 | } 73 | 74 | addUnit(ptr); 75 | return ptr->uniqueId(); 76 | } 77 | 78 | int ZeromqRouterHandler::sendData(uint64_t uniqueId, uint32_t otherIdentify, const std::string& data) { 79 | for (auto& item : m_unit_vec) { 80 | if (item->uniqueId() == uniqueId) { 81 | typedef std::shared_ptr ZeromqRouterPtr; 82 | ZeromqRouterPtr ptr = std::dynamic_pointer_cast(item); 83 | return ptr->sendData(otherIdentify, data); 84 | } 85 | } 86 | 87 | assert(false); 88 | return 0; 89 | } 90 | 91 | ///////////////////////////////////////////////////// 92 | 93 | uint64_t ZeromqDealerHandler::connect(uint32_t id, const std::string& addr) { 94 | auto ptr = std::make_shared(id, addr); 95 | if (!ptr->connect()) { 96 | assert(false); 97 | return 0; 98 | } 99 | 100 | addUnit(ptr); 101 | return ptr->uniqueId(); 102 | } 103 | 104 | int ZeromqDealerHandler::sendData(uint64_t unique_id, const std::string& data) { 105 | for (auto& item : m_unit_vec) { 106 | if (item->uniqueId() == unique_id) { 107 | typedef std::shared_ptr ZeromqDealerPtr; 108 | ZeromqDealerPtr ptr = std::dynamic_pointer_cast(item); 109 | return ptr->sendData(data); 110 | } 111 | } 112 | 113 | assert(false); 114 | return 0; 115 | } 116 | 117 | } 118 | #endif -------------------------------------------------------------------------------- /async/ipc/zero_mq_handler.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/ipc/zero_mq_unit.h" 12 | #include 13 | #include 14 | 15 | namespace ipc { 16 | 17 | // ZeromqUnit管理器 18 | class ZeromqHandler { 19 | public: 20 | virtual ~ZeromqHandler() {} 21 | 22 | typedef std::shared_ptr ZeromqUnitPtr; 23 | 24 | bool update(unsigned int); 25 | 26 | protected: 27 | bool addUnit(ZeromqUnitPtr ptr); 28 | 29 | // 数据回调 30 | // @uniqueId代表一个ZeromqUnit的唯一id 31 | // @identify表示的是对方连接的标识符 32 | // @data是数据包 33 | virtual void onData(uint64_t /*uniqueId*/, uint32_t /*otherIdentify*/, const std::string& /*data*/) {} 34 | 35 | protected: 36 | std::vector m_unit_vec; 37 | }; 38 | 39 | ///////////////////////////////////////////////////// 40 | 41 | // router, 可以监听多个相同功能的端口(但一般不会这么做) 42 | class ZeromqRouterHandler : public ZeromqHandler { 43 | public: 44 | // 返回唯一id, 失败返回0 45 | uint64_t listen(const std::string& addr); 46 | 47 | // @uniqueId代表一个ZeromqUnit的唯一id 48 | // @otherIdentify对方的id 49 | // @data数据 50 | int sendData(uint64_t uniqueId, uint32_t otherIdentify, const std::string& data); 51 | }; 52 | 53 | ///////////////////////////////////////////////////// 54 | 55 | // dealer, 可以连接多个相同功能的router 56 | class ZeromqDealerHandler : public ZeromqHandler { 57 | public: 58 | // 返回唯一id, 失败返回0 59 | uint64_t connect(uint32_t id, const std::string& addr); 60 | 61 | // @unique_id代表一个ZeromqUnit的唯一id 62 | // @data数据 63 | int sendData(uint64_t unique_id, const std::string& data); 64 | }; 65 | 66 | } -------------------------------------------------------------------------------- /async/ipc/zero_mq_unit.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | /* 10 | * zeromq消息队列通信单元, 用户后端进程之间的通信 11 | */ 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | namespace ipc { 19 | 20 | // 使用的是router--dealer模式 21 | class ZeromqUnit { 22 | public: 23 | struct Context { 24 | Context(); 25 | ~Context(); 26 | uint64_t m_gen_id; 27 | void* m_ctx; 28 | }; 29 | 30 | // addr格式:tcp://192.168.0.81:7000 31 | ZeromqUnit(uint32_t identify, const std::string& addr); 32 | 33 | virtual ~ZeromqUnit(); 34 | 35 | int recvFd(); 36 | 37 | void* getSock(); 38 | 39 | bool isPollIn(); 40 | 41 | virtual int recvData(uint32_t& /*identify*/, std::string& /*data*/) = 0; 42 | 43 | uint64_t uniqueId(); 44 | protected: 45 | // 编码身份 46 | std::string encodeIdentify(bool isRouter); 47 | 48 | std::string encodeIdentify(bool isRouter, uint32_t id); 49 | 50 | // 解码身份 51 | uint32_t decodeIdentify(const std::string& id); 52 | 53 | bool reInit(bool is_router); 54 | 55 | int send(bool is_router, const std::string& identify, const std::string& data); 56 | 57 | void printError(); 58 | 59 | protected: 60 | static Context m_ctx; 61 | void* m_sock; 62 | std::string m_addr; 63 | uint64_t m_unique_id; // 内部分配的唯一id 64 | uint32_t m_identify; // zeromq用的标识符id 65 | }; 66 | 67 | ///////////////////////////////////////////////////// 68 | 69 | // router 70 | class ZeromqRouter : public ZeromqUnit { 71 | public: 72 | ZeromqRouter(const std::string& addr); 73 | 74 | bool listen(); 75 | 76 | virtual int recvData(uint32_t& identify, std::string& data) override; 77 | 78 | // @identify表示发送到哪个标识符 79 | int sendData(uint32_t identify, const std::string& data); 80 | }; 81 | 82 | //////////////////////////////////////////////////// 83 | 84 | // dealer 85 | class ZeromqDealer : public ZeromqUnit { 86 | public: 87 | /* 88 | @identify 是客户端的唯一id, 每个连接一个id(不管连接是否同进程), 89 | 因为zeromq是消息队列,tcp连接断开后,数据并不会丢,所以它要求有个能证明之前链接的凭证, 90 | */ 91 | ZeromqDealer(uint32_t identify, const std::string& addr); 92 | 93 | bool connect(); 94 | 95 | virtual int recvData(uint32_t&, std::string& data) override; 96 | 97 | int sendData(const std::string& data); 98 | }; 99 | 100 | } -------------------------------------------------------------------------------- /async/log.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #include "async/log.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #ifndef WIN32 18 | #include 19 | #endif 20 | 21 | std::string curThreadId() { 22 | std::stringstream ss; 23 | ss << std::this_thread::get_id(); 24 | return ss.str(); 25 | } 26 | 27 | // 日志输出接口,是线程安全的 28 | std::function gLogCb = [](const char* data) { 29 | #ifdef WIN32 30 | auto tp = std::chrono::system_clock::now(); 31 | time_t t = std::chrono::system_clock::to_time_t(tp); 32 | std::stringstream ss; 33 | ss << std::put_time(localtime(&t), "%Y-%m-%d %H-%M-%S"); 34 | #else 35 | struct timeval tv; 36 | gettimeofday(&tv,0); 37 | 38 | time_t now = tv.tv_sec; 39 | struct tm lt; 40 | localtime_r(&now, <); 41 | 42 | char buf[50]; 43 | int len = strftime(buf, 50, "%Y-%m-%d %H:%M:%S", <); 44 | len += snprintf(buf + len, 50 - len, ":%03d", (int)(tv.tv_usec/1000)); 45 | #endif 46 | 47 | static std::mutex sMutex; 48 | sMutex.lock(); 49 | #ifdef WIN32 50 | printf("[%s] [%s] %s\n", curThreadId().c_str(), ss.str().c_str(), data); 51 | #else 52 | printf("[%s] [%s] %s\n", curThreadId().c_str(), buf, data); 53 | #endif 54 | sMutex.unlock(); 55 | }; 56 | 57 | void log(const char* format, ...) { 58 | if (!gLogCb) { 59 | return; 60 | } 61 | 62 | char buf[1024] = { 0 }; 63 | va_list ap; 64 | va_start(ap, format); 65 | vsprintf(buf, format, ap); 66 | gLogCb(buf); 67 | } 68 | 69 | void setSafeLogFunc(std::function cb) { 70 | gLogCb = cb; 71 | } -------------------------------------------------------------------------------- /async/log.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | void log(const char* format, ...); 14 | 15 | #ifdef DEBUG 16 | #define logDebug log 17 | #else 18 | #define logDebug(...) 19 | #endif 20 | 21 | #ifdef TRACE 22 | #define logTrace log 23 | #else 24 | #define logTrace(...) 25 | #endif 26 | 27 | // 设置日志接口, 要求是线程安全的 28 | void setSafeLogFunc(std::function cb); -------------------------------------------------------------------------------- /async/net/event_base.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_NET 10 | 11 | #include "async/net/event_base.h" 12 | #include 13 | 14 | namespace net { 15 | 16 | void* createEventBase() { 17 | void* base = event_base_new(); 18 | return base; 19 | } 20 | 21 | void freeEventBase(void* base) { 22 | event_base_free((event_base*)base); 23 | } 24 | 25 | } 26 | 27 | #endif -------------------------------------------------------------------------------- /async/net/event_base.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | namespace net { 12 | 13 | void* createEventBase(); 14 | 15 | void freeEventBase(void* base); 16 | 17 | } -------------------------------------------------------------------------------- /async/net/http_listener.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | namespace net { 15 | 16 | class HttpListener { 17 | public: 18 | friend void on_request_cb_helper(void*, void*); 19 | 20 | // 如果event_base传递空,则内部将自创建一个base 21 | HttpListener(void* event_base); 22 | 23 | virtual ~HttpListener(); 24 | 25 | void* getEventBase(); 26 | 27 | // @time_t保留 28 | void update(time_t); 29 | 30 | bool listen(const std::string& ip, uint32_t port); 31 | 32 | static void send(void* request, const char* buf, uint32_t len); 33 | 34 | static void send(void* request, 35 | const std::unordered_map& header, 36 | const char* buf, 37 | uint32_t len); 38 | 39 | // 设置接受数据的回调 40 | void setDataCb(std::function cb); 41 | 42 | // 获取对方host 43 | static const char* getRemoteHost(const void* request); 44 | 45 | // 获取路径 46 | static const char* getUrlPath(const void* request); 47 | 48 | // 获取参数 49 | static const char* getUrlParam(const void* request); 50 | 51 | static const char* decodeUri(const char* s); 52 | private: 53 | bool m_created_base; 54 | void* m_event_base; 55 | void* m_evhttp; 56 | std::function m_data_cb; 57 | }; 58 | 59 | } 60 | 61 | -------------------------------------------------------------------------------- /async/net/tcp_client.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | namespace net { 15 | 16 | class TcpClient { 17 | public: 18 | friend void on_cb_recv_t(void* bev, void* ctx); 19 | friend void on_cb_event_t(void* bev, short what, void* ctx); 20 | 21 | // 如果event_base传递空,则内部将自创建一个base 22 | TcpClient(void* event_base); 23 | 24 | virtual ~TcpClient(); 25 | 26 | void update(time_t); 27 | 28 | // @addr: ip:port 29 | bool connect(const std::string& addr); 30 | 31 | void send(const char* buf, uint32_t len); 32 | 33 | // 主动关闭连接 34 | void close(); 35 | 36 | void setClosedCb(std::function cb); 37 | 38 | // 设置接受数据的回调: 一个完整包的数据(如果没有设置解析器,则返回捕捉到的每一段数据) 39 | void setDataCb(std::function cb); 40 | 41 | // 设置包解析器: 42 | // @header_size: 头包长度 43 | // @parser: 返回值包体长度 44 | void setParser(uint32_t header_size, std::function parser); 45 | 46 | protected: 47 | bool m_created_base; 48 | void* m_event_base; 49 | void* m_buff_ev; 50 | uint32_t m_header_size; 51 | char* m_header_buf; 52 | std::function m_disconnected_cb; 53 | std::function m_data_cb; 54 | std::function m_parser; 55 | }; 56 | 57 | } -------------------------------------------------------------------------------- /async/net/tcp_listener.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace net { 17 | 18 | // tcp监听者 19 | class TcpListener { 20 | public: 21 | friend void on_accept_cb_helper(TcpListener*, void* sock, void* bev); 22 | friend void on_cb_send(void* bev, void* ctx); 23 | friend void on_cb_recv(void* bev, void* ctx); 24 | 25 | struct ConnInfo { 26 | void* buff_ev = 0; 27 | bool is_closing = false; // 是否在关闭中 28 | int s_data_cnt = 0; // 发送字节数 29 | std::string ip; // 对方ip 30 | }; 31 | 32 | // 如果event_base传递空,则内部将自创建一个base 33 | TcpListener(void* event_base); 34 | 35 | virtual ~TcpListener(); 36 | 37 | void* getEventBase(); 38 | 39 | // @time_t保留 40 | void update(time_t); 41 | 42 | // @addr: ip:port 43 | bool listen(const std::string& addr); 44 | 45 | // 发送数据 46 | int send(uint32_t fd, const char* buf, uint32_t len); 47 | 48 | // 主动关闭连接 49 | void close(uint32_t fd); 50 | 51 | std::string getIp(uint32_t fd); 52 | 53 | // 设置connected回调 54 | void setAcceptCb(std::function cb); 55 | 56 | // 设置连接断开时的回调,无论什么原因,只要断开必然会触发 57 | void setClosedCb(std::function cb); 58 | 59 | // 设置接受数据的回调: 一个完整包的数据(如果没有设置解析器,则返回捕捉到的每一段数据) 60 | void setDataCb(std::function cb); 61 | 62 | // 设置包解析器: 63 | // @header_size: 头包长度 64 | // @parser: 返回值包体长度 65 | void setParser(uint32_t header_size, std::function parser); 66 | protected: 67 | void closed(uint32_t fd); 68 | 69 | protected: 70 | bool m_created_base; 71 | void* m_event_base; 72 | void* m_listener; 73 | uint32_t m_header_size; 74 | std::unordered_map m_conn_map; 75 | std::list m_closing_list; 76 | std::function m_connected_cb; 77 | std::function m_disconnected_cb; 78 | std::function m_data_cb; 79 | std::function m_parser; 80 | char* m_header_buf; 81 | }; 82 | 83 | } 84 | -------------------------------------------------------------------------------- /async/net/udp_client.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_NET 10 | 11 | #include "async/net/udp_client.h" 12 | #include 13 | #include 14 | 15 | namespace net { 16 | 17 | void on_cb_recv_c(int fd, short what, void *arg) { 18 | UdpClient* u = (UdpClient*)arg; 19 | if (what | EV_READ) { 20 | if (!u->m_data_buf) { 21 | return; 22 | } 23 | 24 | socklen_t len = sizeof(*((sockaddr*)u->m_addr)); 25 | auto ret = recvfrom(fd, u->m_data_buf, 1024, 0, (sockaddr*)u->m_addr, &len); 26 | if (ret > 0 && u->m_data_cb) { 27 | u->m_data_cb(u, u->m_data_buf, ret); 28 | } 29 | } 30 | } 31 | 32 | UdpClient::UdpClient(void* event_base) { 33 | m_created_base = 0; 34 | m_event_base = event_base; 35 | m_fd = 0; 36 | m_evt = 0; 37 | m_data_buf = 0; 38 | if (!event_base) { 39 | m_event_base = event_base_new(); 40 | assert(m_event_base); 41 | m_created_base = true; 42 | } 43 | m_addr = malloc(sizeof(sockaddr)); 44 | } 45 | 46 | UdpClient::~UdpClient() { 47 | if (m_fd != 0) { 48 | evutil_closesocket(m_fd); 49 | } 50 | if (m_evt) { 51 | event_free((event*)m_evt); 52 | } 53 | if (m_created_base) { 54 | event_base_free((event_base*)m_event_base); 55 | } 56 | free(m_addr); 57 | 58 | if (m_data_buf) { 59 | free(m_data_buf); 60 | } 61 | } 62 | 63 | void UdpClient::update(time_t) { 64 | if (m_created_base) { 65 | event_base_loop((event_base*)m_event_base, EVLOOP_NONBLOCK); 66 | } 67 | } 68 | 69 | bool UdpClient::connect(const std::string& addr) { 70 | m_fd = socket(AF_INET, SOCK_DGRAM, 0); 71 | if (m_fd < 0) { 72 | return false; 73 | } 74 | 75 | sockaddr* sock_addr = (sockaddr*)m_addr; 76 | int len = sizeof(*sock_addr); 77 | if (evutil_parse_sockaddr_port(addr.c_str(), sock_addr, &len) != 0) { 78 | evutil_closesocket(m_fd); 79 | return false; 80 | } 81 | 82 | if (::connect(m_fd, sock_addr, len) != 0) { 83 | return false; 84 | } 85 | 86 | m_evt = event_new((event_base*)m_event_base, m_fd, EV_READ|EV_PERSIST, on_cb_recv_c, this); 87 | event_add((event*)m_evt, nullptr); 88 | return true; 89 | } 90 | 91 | int UdpClient::send(const char* buf, uint32_t len) { 92 | sockaddr* sock_addr = (sockaddr*)m_addr; 93 | int addr_len = sizeof(*sock_addr); 94 | return sendto(m_fd, buf, len, 0, sock_addr, addr_len); 95 | } 96 | 97 | void UdpClient::setDataCb(std::function cb) { 98 | m_data_cb = cb; 99 | if (!m_data_buf) { 100 | m_data_buf = (char*)malloc(1024); 101 | } 102 | } 103 | 104 | } 105 | 106 | #endif -------------------------------------------------------------------------------- /async/net/udp_client.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace net { 14 | 15 | class UdpClient { 16 | public: 17 | friend void on_cb_recv_c(int fd, short, void *arg); 18 | 19 | UdpClient(void* event_base); 20 | 21 | virtual ~UdpClient(); 22 | 23 | void update(time_t cur_time); 24 | 25 | bool connect(const std::string& addr); 26 | 27 | int send(const char* buf, uint32_t len); 28 | 29 | void setDataCb(std::function cb); 30 | 31 | protected: 32 | bool m_created_base; 33 | void* m_event_base; 34 | void* m_evt; 35 | void* m_addr; 36 | char* m_data_buf; 37 | int32_t m_fd; 38 | std::function m_data_cb; 39 | }; 40 | 41 | } -------------------------------------------------------------------------------- /async/net/udp_listener.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | namespace net { 15 | 16 | // 会话信息保留10分钟 17 | class UdpListener { 18 | public: 19 | struct SessionInfo { 20 | void* addr; 21 | time_t active = 0; 22 | SessionInfo(); 23 | ~SessionInfo(); 24 | }; 25 | 26 | friend void on_cb_recv(int fd, short, void *arg); 27 | 28 | // 如果event_base传递空,则内部将自创建一个base 29 | UdpListener(void* event_base); 30 | 31 | virtual ~UdpListener(); 32 | 33 | virtual void update(time_t cur_time); 34 | 35 | // @addr: ip:port 36 | bool listen(const std::string& addr); 37 | 38 | int send(uint32_t fd, const char* buf, uint32_t len); 39 | 40 | void setDataCb(std::function cb); 41 | 42 | protected: 43 | void expire(time_t cur_time); 44 | 45 | protected: 46 | bool m_created_base; 47 | void* m_event_base; 48 | void* m_evt; 49 | std::function m_data_cb; 50 | char* m_data_buf; 51 | std::unordered_map m_fd_addr_map; 52 | uint32_t m_cur_poll_key; 53 | }; 54 | 55 | } -------------------------------------------------------------------------------- /async/signal/sig.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_NET 10 | 11 | #include "async/signal/sig.h" 12 | #include "async/log.h" 13 | #include 14 | #include 15 | #include 16 | 17 | namespace sig { 18 | 19 | struct SignalItem { 20 | std::function f; 21 | void* evt = 0; 22 | }; 23 | 24 | struct SignalInfo { 25 | void* eventBase = 0; 26 | bool createdBase = false; 27 | std::unordered_map handlerMap; 28 | 29 | ~SignalInfo() { 30 | for (auto& item : handlerMap) { 31 | evsignal_del((event*)item.second.evt); 32 | } 33 | if (createdBase) { 34 | event_base_free((event_base*)eventBase); 35 | } 36 | 37 | logTrace("[signal] free"); 38 | } 39 | }; 40 | 41 | SignalInfo gInfo; 42 | 43 | void onSignal(int signal, short s, void* ctx) { 44 | auto iter = gInfo.handlerMap.find(signal); 45 | if (iter == gInfo.handlerMap.end()) { 46 | return; 47 | } 48 | 49 | iter->second.f(signal); 50 | } 51 | 52 | void initSignal(void* eventBase) { 53 | gInfo.eventBase = eventBase; 54 | if (!eventBase) { 55 | gInfo.eventBase = event_base_new(); 56 | gInfo.createdBase = true; 57 | } 58 | } 59 | 60 | bool regSinal(uint32_t signal, std::function handler) { 61 | auto iter = gInfo.handlerMap.find(signal); 62 | if (iter != gInfo.handlerMap.end()) { 63 | iter->second.f = handler; 64 | return true; 65 | } 66 | 67 | SignalItem item; 68 | item.evt = evsignal_new((event_base*)gInfo.eventBase, signal, onSignal, 0); 69 | if (!item.evt) { 70 | return false; 71 | } 72 | 73 | auto r = evsignal_add((event*)item.evt, nullptr); 74 | if (r != 0) { 75 | return false; 76 | } 77 | 78 | item.f = handler; 79 | gInfo.handlerMap[signal] = item; 80 | return true; 81 | } 82 | 83 | void regKill(std::function handler) { 84 | // ctrl+c 85 | regSinal(SIGINT, handler); 86 | // kill -9 87 | //registe(SIGKILL, handler); 88 | // kill 89 | regSinal(SIGTERM, handler); 90 | } 91 | 92 | void update() { 93 | if (gInfo.createdBase) { 94 | event_base_loop((event_base*)gInfo.eventBase, EVLOOP_NONBLOCK); 95 | } 96 | } 97 | 98 | } 99 | 100 | #endif -------------------------------------------------------------------------------- /async/signal/sig.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace sig { 14 | 15 | void initSignal(void* eventBase); 16 | 17 | bool regSinal(uint32_t signal, std::function handler); 18 | 19 | void regKill(std::function handler); 20 | 21 | void update(); 22 | 23 | } -------------------------------------------------------------------------------- /async/threads/thread_pool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * author : https://github.com/progschj/ThreadPool 3 | */ 4 | #ifndef THREAD_POOL_H 5 | #define THREAD_POOL_H 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | class ThreadPool { 18 | public: 19 | ThreadPool(size_t); 20 | ThreadPool(); 21 | template 22 | auto enqueue(F&& f, Args&&... args) 23 | -> std::future::type>; 24 | ~ThreadPool(); 25 | 26 | uint32_t taskCount() { 27 | return tasks.size(); 28 | } 29 | private: 30 | // init thread count 31 | void init(size_t threads); 32 | // need to keep track of threads so we can join them 33 | std::vector< std::thread > workers; 34 | // the task queue 35 | std::queue< std::function > tasks; 36 | 37 | // synchronization 38 | std::mutex queue_mutex; 39 | std::condition_variable condition; 40 | bool stop; 41 | }; 42 | 43 | // the constructor just launches some amount of workers 44 | inline ThreadPool::ThreadPool(size_t threads) 45 | : stop(false) { 46 | init(threads); 47 | } 48 | 49 | inline ThreadPool::ThreadPool() 50 | : stop(false) { 51 | init(std::thread::hardware_concurrency()); 52 | } 53 | 54 | inline void ThreadPool::init(size_t threads) { 55 | for(size_t i = 0;i task; 62 | 63 | { 64 | std::unique_lock lock(this->queue_mutex); 65 | this->condition.wait(lock, 66 | [this]{ return this->stop || !this->tasks.empty(); }); 67 | if(this->stop && this->tasks.empty()) 68 | return; 69 | task = std::move(this->tasks.front()); 70 | this->tasks.pop(); 71 | } 72 | 73 | task(); 74 | } 75 | } 76 | ); 77 | } 78 | } 79 | 80 | // add new work item to the pool 81 | template 82 | auto ThreadPool::enqueue(F&& f, Args&&... args) 83 | -> std::future::type> 84 | { 85 | using return_type = typename std::result_of::type; 86 | 87 | auto task = std::make_shared< std::packaged_task >( 88 | std::bind(std::forward(f), std::forward(args)...) 89 | ); 90 | 91 | std::future res = task->get_future(); 92 | { 93 | std::unique_lock lock(queue_mutex); 94 | 95 | // don't allow enqueueing after stopping the pool 96 | if(stop) 97 | throw std::runtime_error("enqueue on stopped ThreadPool"); 98 | 99 | tasks.emplace([task](){ (*task)(); }); 100 | } 101 | condition.notify_one(); 102 | return res; 103 | } 104 | 105 | // the destructor joins all threads 106 | inline ThreadPool::~ThreadPool() 107 | { 108 | { 109 | std::unique_lock lock(queue_mutex); 110 | stop = true; 111 | } 112 | condition.notify_all(); 113 | for(std::thread &worker: workers) 114 | worker.join(); 115 | } 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /async/tls.hpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #ifndef M_PLATFORM_WIN32 12 | #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 13 | #define M_PLATFORM_WIN32 1 14 | #endif 15 | #endif 16 | 17 | #ifndef M_PLATFORM_WIN 18 | #if defined(M_PLATFORM_WIN32) || defined(WIN64) 19 | #define M_PLATFORM_WIN 1 20 | #endif 21 | #endif 22 | 23 | #ifdef M_PLATFORM_WIN 24 | #ifndef M_WIN32_LEAN_AND_MEAN 25 | #define WIN32_LEAN_AND_MEAN 26 | #endif // end M_WIN32_LEAN_AND_MEAN 27 | #include 28 | #else 29 | #include 30 | #include 31 | #endif // end M_PLATFORM_WIN 32 | 33 | namespace async { 34 | 35 | #ifdef M_PLATFORM_WIN 36 | 37 | template 38 | class tlsdata 39 | { 40 | public: 41 | struct _init_{ 42 | DWORD _tkey; 43 | _init_(){ 44 | _tkey = TlsAlloc(); 45 | assert(_tkey != TLS_OUT_OF_INDEXES); 46 | } 47 | ~_init_(){ 48 | T* pv = (T*)TlsGetValue(_tkey); 49 | TlsFree(_tkey); 50 | delete pv; 51 | } 52 | }; 53 | 54 | inline static T& data(){ 55 | T* pv = 0; 56 | if (0 == (pv = (T*)TlsGetValue(_data._tkey))){ 57 | pv = new T; 58 | TlsSetValue(_data._tkey, (void*)pv); 59 | } 60 | return *pv; 61 | } 62 | 63 | protected: 64 | tlsdata(const tlsdata&); 65 | tlsdata& operator=(const tlsdata&); 66 | 67 | private: 68 | static _init_ _data; 69 | }; 70 | 71 | #else 72 | 73 | #include 74 | 75 | template 76 | class tlsdata 77 | { 78 | public: 79 | struct _init_{ 80 | pthread_key_t _tkey; 81 | _init_(){ 82 | pthread_key_create(&_tkey, destructor); 83 | } 84 | ~_init_(){ 85 | } 86 | }; 87 | 88 | union _point_ { 89 | T* p1; 90 | T* p2; 91 | }; 92 | 93 | static T& data(){ 94 | // 借用奇淫巧计,躲避gcc开启优化选项后编译的clobbered错误围杀 95 | _point_ p; 96 | if (0 == (p.p1 = (T*)pthread_getspecific(_data._tkey))) { 97 | p.p1 = new T; 98 | pthread_setspecific(_data._tkey, p.p1); 99 | } 100 | return *p.p2; 101 | } 102 | 103 | protected: 104 | tlsdata(const tlsdata&); 105 | tlsdata& operator=(const tlsdata&); 106 | 107 | static void destructor(void* v) { 108 | T* pv = (T*)v; 109 | delete pv; 110 | } 111 | 112 | private: 113 | static _init_ _data; 114 | }; 115 | 116 | #endif 117 | 118 | template 119 | typename tlsdata::_init_ tlsdata::_data; 120 | 121 | 122 | } -------------------------------------------------------------------------------- /async/transaction/base_tick_transaction.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_TRANS 10 | 11 | #include "async/transaction/base_tick_transaction.h" 12 | 13 | BaseTickTransaction::BaseTickTransaction() { 14 | m_work_state = en_idle_wstate; 15 | m_cur_time = 0; 16 | } 17 | 18 | void BaseTickTransaction::Tick(uint32_t cur_time) { 19 | if (m_work_state == en_working_state) { 20 | return; 21 | } 22 | 23 | m_cur_time = cur_time; 24 | m_work_state = en_working_state; 25 | 26 | this->Handle(0, 0, 0); 27 | } 28 | 29 | void BaseTickTransaction::InCoroutine() { 30 | OnTick(m_cur_time); 31 | m_work_state = en_idle_wstate; 32 | } 33 | 34 | #endif -------------------------------------------------------------------------------- /async/transaction/base_tick_transaction.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/transaction/base_transaction.h" 12 | 13 | class BaseTickTransaction : public BaseTransaction { 14 | public: 15 | enum { 16 | en_idle_wstate = 0, 17 | en_working_state, 18 | }; 19 | 20 | BaseTickTransaction(); 21 | 22 | void Tick(uint32_t cur_time); 23 | 24 | virtual bool ParsePacket(const char*, uint32_t) override { return false; } 25 | protected: 26 | virtual void InCoroutine() override; 27 | 28 | virtual void OnTick(uint32_t) = 0; 29 | private: 30 | uint32_t m_work_state; 31 | uint32_t m_cur_time; 32 | }; -------------------------------------------------------------------------------- /async/transaction/base_transaction.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_TRANS 10 | 11 | #include "async/transaction/base_transaction.h" 12 | #include "async/coroutine/coroutine.hpp" 13 | #include "async/transaction/transaction_mgr.h" 14 | 15 | void BaseTransaction::Construct() { 16 | m_req_cmd_id = 0; 17 | m_rsp_cmd_id = 0; 18 | m_trans_id = 0; 19 | m_packet = 0; 20 | m_packet_size = 0; 21 | m_ext = 0; 22 | } 23 | 24 | BaseTransaction::BaseTransaction() { 25 | Construct(); 26 | } 27 | 28 | void BaseTransaction::SetReqCmdId(uint32_t cmd) { 29 | m_req_cmd_id = cmd; 30 | } 31 | 32 | uint32_t BaseTransaction::ReqCmdId() { 33 | return m_req_cmd_id; 34 | } 35 | 36 | void BaseTransaction::SetRspCmdId(uint32_t cmd) { 37 | m_rsp_cmd_id = cmd; 38 | } 39 | 40 | uint32_t BaseTransaction::RspCmdId() { 41 | return m_rsp_cmd_id; 42 | } 43 | 44 | void BaseTransaction::SetTransId(uint32_t trans_id) { 45 | m_trans_id = trans_id; 46 | } 47 | 48 | uint32_t BaseTransaction::TransId() { 49 | return m_trans_id; 50 | } 51 | 52 | int BaseTransaction::Handle(const char* packet, uint32_t packet_size, void* ext) { 53 | // 启动协程 54 | m_packet = packet; 55 | m_packet_size = packet_size; 56 | m_ext = ext; 57 | CoroutineTask::doTask(_transaction_coroutine_enter_, (void*)this); 58 | return 0; 59 | } 60 | 61 | void _transaction_coroutine_enter_(void* p) { 62 | BaseTransaction* trans = (BaseTransaction*)p; 63 | // 运行 64 | trans->InCoroutine(); 65 | // 协程退出 66 | trans_mgr::clearTransCxt(); 67 | trans_mgr::recycleTrans(trans); 68 | } 69 | 70 | #endif -------------------------------------------------------------------------------- /async/transaction/base_transaction.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | void _transaction_coroutine_enter_(void*); 15 | 16 | class BaseTransaction { 17 | public: 18 | friend void _transaction_coroutine_enter_(void*); 19 | 20 | void Construct(); 21 | 22 | BaseTransaction(); 23 | 24 | virtual ~BaseTransaction() {} 25 | 26 | void SetReqCmdId(uint32_t cmd); 27 | 28 | uint32_t ReqCmdId(); 29 | 30 | void SetRspCmdId(uint32_t cmd); 31 | 32 | uint32_t RspCmdId(); 33 | 34 | void SetTransId(uint32_t trans_id); 35 | 36 | uint32_t TransId(); 37 | 38 | int Handle(const char* packet, uint32_t packet_size, void* ext); 39 | 40 | protected: 41 | virtual void InCoroutine() = 0; 42 | 43 | virtual bool ParsePacket(const char* /*packet*/, uint32_t /*packet_size*/) = 0; 44 | protected: 45 | uint32_t m_req_cmd_id; 46 | uint32_t m_rsp_cmd_id; 47 | uint32_t m_trans_id; 48 | const char* m_packet; 49 | uint32_t m_packet_size; 50 | void* m_ext; 51 | }; 52 | 53 | ///////////////////////////////////////////////////////////////////// 54 | 55 | // http的事务 56 | class BaseHttpTransaction : public BaseTransaction { 57 | public: 58 | const std::string& Url() { 59 | return m_url; 60 | } 61 | 62 | void SetUrl(const std::string& url) { 63 | m_url = url; 64 | } 65 | 66 | void InCoroutine() override { 67 | if (!m_packet) { 68 | return; 69 | } 70 | 71 | // 解包 72 | if (!ParsePacket(m_packet, m_packet_size)) { 73 | return; 74 | } 75 | 76 | if (OnBefore()) { 77 | OnRequest(); 78 | } 79 | 80 | OnAfter(); 81 | } 82 | 83 | virtual bool OnBefore() { return true; } 84 | 85 | virtual int OnRequest() = 0; 86 | 87 | virtual bool OnAfter() { return true; } 88 | 89 | protected: 90 | std::string m_url; 91 | }; 92 | 93 | ///////////////////////////////////////////////////////////////////// 94 | 95 | // 空回复 96 | struct NullRespond { 97 | bool SerializeToString(std::string*) const {return false;} 98 | }; 99 | 100 | template 101 | class Transaction : public BaseTransaction { 102 | public: 103 | int ReturnValue() { 104 | return m_return_value; 105 | } 106 | 107 | RequestType& Request() { 108 | return m_request; 109 | } 110 | 111 | RespondType& Respond() { 112 | return m_respond; 113 | } 114 | 115 | void InCoroutine() override { 116 | if (!m_packet) { 117 | return; 118 | } 119 | 120 | // 解包 121 | if (!ParsePacket(m_packet, m_packet_size)) { 122 | return; 123 | } 124 | 125 | m_return_value = -1; 126 | if (OnBefore()) { 127 | m_return_value = OnRequest(); 128 | } 129 | 130 | OnAfter(); 131 | } 132 | 133 | virtual bool OnBefore() { return true; } 134 | 135 | virtual int OnRequest() = 0; 136 | 137 | virtual bool OnAfter() { return true; } 138 | 139 | protected: 140 | int m_return_value; // 返回值 141 | RequestType m_request; // 请求的数据结构 142 | RespondType m_respond; // 回复的数据结构 143 | }; 144 | -------------------------------------------------------------------------------- /async/transaction/transaction_bucket.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/transaction/base_transaction.h" 12 | #include 13 | #include 14 | #include 15 | 16 | namespace trans_mgr { 17 | 18 | uint32_t genTransId(); 19 | 20 | // 事务桶 21 | class TransactionBucket { 22 | public: 23 | TransactionBucket(uint32_t req_cmd_id, uint32_t rsp_cmd_id) { 24 | m_req_cmd_id = req_cmd_id; 25 | m_rsp_cmd_id = rsp_cmd_id; 26 | } 27 | 28 | virtual ~TransactionBucket() {} 29 | 30 | virtual BaseTransaction* Create() = 0; 31 | 32 | virtual void Recycle(BaseTransaction*) = 0; 33 | 34 | virtual uint32_t Size() const = 0; 35 | 36 | virtual const char* TransName() = 0; 37 | 38 | uint32_t ReqCmdId() { 39 | return m_req_cmd_id; 40 | } 41 | 42 | uint32_t RspCmdId() { 43 | return m_rsp_cmd_id; 44 | } 45 | protected: 46 | uint32_t m_req_cmd_id; 47 | uint32_t m_rsp_cmd_id; 48 | }; 49 | 50 | template 51 | class TransactionBucketImpl : public TransactionBucket { 52 | public: 53 | TransactionBucketImpl(uint32_t req_cmd_id, uint32_t rsp_cmd_id) 54 | : TransactionBucket(req_cmd_id, rsp_cmd_id) { 55 | } 56 | 57 | ~TransactionBucketImpl() { 58 | for (auto iter = m_trans_vec.begin(); iter != m_trans_vec.end(); ++iter) { 59 | delete (*iter); 60 | } 61 | m_trans_vec.clear(); 62 | } 63 | 64 | BaseTransaction* Create() { 65 | TransactionType* trans = 0; 66 | if (m_trans_vec.empty()) { 67 | trans = new TransactionType(); 68 | } 69 | else { 70 | trans = m_trans_vec.back(); 71 | m_trans_vec.pop_back(); 72 | new(trans)TransactionType(); 73 | } 74 | 75 | trans->SetReqCmdId(m_req_cmd_id); 76 | trans->SetRspCmdId(m_rsp_cmd_id); 77 | trans->SetTransId(genTransId()); 78 | return trans; 79 | } 80 | 81 | void Recycle(BaseTransaction* trans) { 82 | TransactionType* t = dynamic_cast(trans); 83 | if (m_trans_vec.size() > 20) { 84 | delete t; 85 | } 86 | else { 87 | t->~TransactionType(); 88 | m_trans_vec.push_back(t); 89 | } 90 | } 91 | 92 | uint32_t Size() const { 93 | return m_trans_vec.size(); 94 | } 95 | 96 | virtual const char* TransName() { 97 | return typeid(TransactionType).name(); 98 | } 99 | 100 | protected: 101 | std::list m_trans_vec; 102 | }; 103 | 104 | } -------------------------------------------------------------------------------- /async/transaction/transaction_mgr.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2021 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/transaction/base_transaction.h" 12 | #include "async/transaction/base_tick_transaction.h" 13 | #include "async/transaction/transaction_bucket.h" 14 | #include 15 | #include 16 | #include 17 | 18 | namespace trans_mgr { 19 | 20 | // 设置最大并行运行trans 21 | void setMaxTrans(uint32_t max_trans); 22 | 23 | // 返回0说明启动trans成功, 返回-1说明目前已达到最大trans限制,可保留消息下次再调用 24 | // @ext 额外参数 25 | int handle(uint32_t req_cmd_id, const char* packet, uint32_t packet_size, void* ext = 0); 26 | 27 | int handle(uint32_t id, std::string url, const char* packet, uint32_t packet_size, void* ext); 28 | 29 | void tick(uint32_t cur_time); 30 | 31 | // 注册事务桶 32 | int regBucket(TransactionBucket* bucket); 33 | 34 | // 回收事务 35 | void recycleTrans(BaseTransaction* t); 36 | 37 | // 注册tick事务 38 | int regTickTrans(TransactionBucket* bucket); 39 | 40 | // 注册http事务 41 | int regHttpTrans(uint32_t id, std::string url, TransactionBucket* bucket); 42 | 43 | // 设置事务的上下文环境 44 | void setTransCxt(std::shared_ptr ctx); 45 | 46 | std::shared_ptr getTransCxt(); 47 | 48 | void clearTransCxt(); 49 | }; 50 | 51 | #define SetTransCtx(ctx) trans_mgr::setTransCxt(ctx) 52 | #define GetTransCtx(type) std::static_pointer_cast(trans_mgr::getTransCxt()) 53 | 54 | // 注册相关的宏 55 | #define REAL_REGIST_TRANSACTION(t, req_cmd, rsp_cmd) \ 56 | static int ret_##t##__LINE__ = trans_mgr::regBucket(new trans_mgr::TransactionBucketImpl(req_cmd, rsp_cmd)); 57 | 58 | // 简化版注册事务宏 59 | #define REGIST_TRANSACTION(t) REAL_REGIST_TRANSACTION(t##Transaction, Cmd##t##Req, 0) 60 | 61 | // 简化版注册事务宏 62 | #define REGIST_TRANSACTION_2(t) REAL_REGIST_TRANSACTION(t##Transaction, Cmd##t##Req, Cmd##t##Rsp) 63 | 64 | // 注册tick事务宏 65 | #define REGIST_TICK_TRANSACTION(t) \ 66 | static int ret_##t = trans_mgr::regTickTrans(new trans_mgr::TransactionBucketImpl(0, 0)); 67 | 68 | // 注册http事务宏 69 | #define REGIST_HTTP_TRANSACTION(id, url, t) \ 70 | static int ret_##t_##__LINE__ = trans_mgr::regHttpTrans(id, url, new trans_mgr::TransactionBucketImpl(0, 0)); 71 | -------------------------------------------------------------------------------- /example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | set(TARGET_NAME "example") 3 | project(${TARGET_NAME}) 4 | 5 | if(USE_ASYNC_CURL) 6 | add_definitions(-DUSE_ASYNC_CURL) 7 | endif(USE_ASYNC_CURL) 8 | 9 | if(USE_ASYNC_REDIS) 10 | add_definitions(-DUSE_ASYNC_REDIS) 11 | endif(USE_ASYNC_REDIS) 12 | 13 | if(USE_ASYNC_MONGO) 14 | add_definitions(-DUSE_ASYNC_MONGO) 15 | endif(USE_ASYNC_MONGO) 16 | 17 | if(USE_ASYNC_MYSQL) 18 | add_definitions(-DUSE_ASYNC_MYSQL) 19 | endif(USE_ASYNC_MYSQL) 20 | 21 | if(USE_IPC) 22 | add_definitions(-DUSE_IPC) 23 | endif(USE_IPC) 24 | 25 | if(USE_TRANS) 26 | add_definitions(-DUSE_TRANS) 27 | endif(USE_TRANS) 28 | 29 | if(USE_NET) 30 | add_definitions(-DUSE_NET) 31 | endif(USE_NET) 32 | 33 | if(USE_ASYNC_RABBITMQ) 34 | add_definitions(-DUSE_ASYNC_RABBITMQ) 35 | endif(USE_ASYNC_RABBITMQ) 36 | 37 | if(USE_ASYNC_ZOOKEEPER) 38 | add_definitions(-DUSE_ASYNC_ZOOKEEPER) 39 | endif(USE_ASYNC_ZOOKEEPER) 40 | 41 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11") 42 | file(GLOB_RECURSE ALL_CPP *.cpp *.cc) 43 | 44 | include_directories(./) 45 | include_directories(../) 46 | 47 | link_directories(/usr/local/lib64 /usr/local/lib) 48 | 49 | add_executable(${TARGET_NAME} ${ALL_CPP}) 50 | 51 | add_dependencies(${TARGET_NAME} async) 52 | 53 | target_link_libraries(${TARGET_NAME} PRIVATE async pthread) 54 | -------------------------------------------------------------------------------- /example/co_parallel_test.cpp: -------------------------------------------------------------------------------- 1 | #ifdef USE_ASYNC_CURL 2 | 3 | #include "./common.h" 4 | 5 | void co_parallel_test() { 6 | // 启动一个协程任务 7 | CoroutineTask::doTask([](void*) { 8 | // 异步io并行访问,等待访问结束时协程被唤醒 9 | auto ret = co_async::parallel( 10 | { 11 | [](co_async::next_cb next) { 12 | std::cout << "begin1" << std::endl; 13 | async::curl::get("http://baidu.com", [next](int, int, std::string& body) { 14 | std::cout << "parallel body3:" << body.length() < 4 | #include 5 | #include 6 | #include "async/coroutine/coroutine.hpp" 7 | #include "async/co_async/async.h" 8 | #include "async/co_async/cpu/co_cpu.h" 9 | #include "async/co_async/curl/co_curl.h" 10 | #include "async/co_async/mongo/co_mongo.h" 11 | #include "async/co_async/redis/co_redis.h" 12 | #include "async/co_async/mysql/co_mysql.h" 13 | #include "async/ipc/zero_mq_handler.h" 14 | #include "async/async/async.h" 15 | #include "async/net/tcp_client.h" 16 | #include "async/net/tcp_listener.h" 17 | #include "async/net/udp_listener.h" 18 | #include "async/net/udp_client.h" 19 | #include "async/threads/thread_pool.h" 20 | #include "async/co_async//ipc/co_ipc.h" 21 | #include "async/co_async/rabbitmq/co_rabbitmq.h" 22 | #include "async/async/zookeeper/async_zookeeper.h" 23 | #include "async/co_async/zookeeper/co_zookeeper.h" 24 | 25 | // 计时器 26 | struct TimeElapsed { 27 | void begin() { 28 | gettimeofday(&tv, NULL); 29 | } 30 | 31 | uint64_t end() { 32 | struct timeval tv2; 33 | gettimeofday(&tv2, NULL); 34 | return (tv2.tv_sec * 1000 + tv2.tv_usec / 1000) - (tv.tv_sec * 1000 + tv.tv_usec / 1000); 35 | } 36 | 37 | struct timeval tv; 38 | }; -------------------------------------------------------------------------------- /example/cpu_test.cpp: -------------------------------------------------------------------------------- 1 | #include "./common.h" 2 | 3 | extern bool print_log; 4 | 5 | void cpu_test(bool use_co) { 6 | // 使用协程 7 | if (use_co) { 8 | // 启动一个协程任务 9 | CoroutineTask::doTask([](void*) { 10 | auto ret = co_async::cpu::execute([](void*) { 11 | int count = 100000000; 12 | int64_t t = 0; 13 | while (count--) { 14 | t += count; 15 | } 16 | return t; 17 | }, 0); 18 | 19 | std::cout << "co_cpu test, result=" << ret.second << std::endl; 20 | }, 0); 21 | } 22 | // 不使用协程 23 | else { 24 | // 发起一个cpu异步运算并期待回调被调用 25 | async::cpu::execute([](void*) { 26 | int count = 100000000; 27 | int64_t t = 0; 28 | while (count--) { 29 | t += count; 30 | } 31 | return t; 32 | }, 33 | 0, 34 | [](int64_t res, void*) { 35 | std::cout << "cpu test, result=" << res << std::endl; 36 | }); 37 | } 38 | } -------------------------------------------------------------------------------- /example/curl_test.cpp: -------------------------------------------------------------------------------- 1 | #ifdef USE_ASYNC_CURL 2 | 3 | #include "./common.h" 4 | 5 | extern bool print_log; 6 | 7 | // http测试 8 | void curl_test(bool use_co) { 9 | // 使用协程 10 | if (use_co) { 11 | // 启动一个协程任务 12 | CoroutineTask::doTask([](void*) { 13 | int* count = new int(0); 14 | int* fail = new int(0); 15 | for (int i = 0; i < 1000; i++) { 16 | async::curl::get("http://baidu.com", [i, count, fail](async::curl::CurlParserPtr parser) { 17 | //log("%d curlCode:%d, resCode:%d, bodySize:%ld\n", i, parser->getCurlCode(), parser->getRspCode(), parser->getValue().size()); 18 | if (parser->getRspCode() != 200) { 19 | (*fail)++; 20 | } 21 | (*count)++; 22 | 23 | if (*count == 1000) { 24 | log("finish: count: %d, fail: %d", *count, *fail); 25 | } 26 | }); 27 | } 28 | return; 29 | 30 | // 执行http访问并等待协程返回 31 | { 32 | auto res = co_async::curl::get("http://baidu.com"); 33 | if (co_async::checkOk(res)) { 34 | auto parser = res.second; 35 | log("1、curlCode:%d, resCode:%d, bodySize:%ld\n", parser->getCurlCode(), parser->getRspCode(), parser->getValue().size()); 36 | } 37 | if (co_async::checkTimeout(res)) { 38 | log("1、timeout\n"); 39 | } 40 | } 41 | 42 | { 43 | std::string body; 44 | auto ret = co_async::curl::post("http://192.168.0.160/user/showEmail", "", body); 45 | if (ret == co_async::E_OK) { 46 | log("2、bodySize:%ld\n", body.size()); 47 | } 48 | if (ret == co_async::E_TIMEOUT) { 49 | log("2、timeout\n"); 50 | } 51 | } 52 | 53 | { 54 | auto res = co_async::curl::post("http://192.168.0.160/user/showEmail", ""); 55 | if (co_async::checkOk(res)) { 56 | auto parser = res.second; 57 | log("3、curlCode:%d, resCode:%d, bodySize:%ld\n", parser->getCurlCode(), parser->getRspCode(), parser->getValue().size()); 58 | } 59 | if (co_async::checkTimeout(res)) { 60 | log("3、timeout\n"); 61 | } 62 | } 63 | 64 | }, 0); 65 | } 66 | // 不使用协程 67 | else { 68 | // 发起一个http异步访问并期待回调被调用 69 | async::curl::get("http://baidu.com", [](int, int, const std::string& body) { 70 | std::cout << "curl body.len: " << body.length() << std::endl; 71 | }); 72 | } 73 | } 74 | 75 | #endif -------------------------------------------------------------------------------- /example/example.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "async/async/async.h" 4 | #include "async/co_async/async.h" 5 | #include "async/co_async/promise.h" 6 | #include "async/coroutine/coroutine.hpp" 7 | #include "async/threads/thread_pool.h" 8 | #include "async/log.h" 9 | #include 10 | 11 | //////////////////// 12 | bool print_log = false; 13 | 14 | void co_parallel_test(); 15 | void net_test(); 16 | void cpu_test(bool use_co); 17 | void curl_test(bool use_co); 18 | void mongo_test(bool use_co); 19 | void redis_test(bool use_co); 20 | void co_mysql_test(); 21 | void ipc_test(); 22 | void rabbit_test(bool use_co, int seq); 23 | void zookeeper_test(bool use_co, int seq); 24 | 25 | void promise_test() { 26 | CoroutineTask::doTask([](void*){ 27 | printf("promise begin\n"); 28 | auto ret = co_async::promise([](co_async::Resolve resolve, co_async::Reject reject) { 29 | co_async::setTimeout([resolve]() { 30 | printf("异步执行结束\n"); 31 | resolve(nullptr); 32 | }, 4*1000); 33 | }, 3 * 1000); 34 | 35 | printf("promise over:%d\n", ret.first); 36 | }, 0); 37 | } 38 | 39 | int main() { 40 | // io线程 41 | ThreadPool tp(std::thread::hardware_concurrency()); 42 | async::setThreadFunc([&tp](std::function f) { 43 | tp.enqueue(f); 44 | }); 45 | 46 | async::setIoThread(std::thread::hardware_concurrency()); 47 | 48 | // 模拟有多个工作线程 49 | for (int i = 0; i < 1; i++) { 50 | new std::thread([&tp, i]() { 51 | //promise_test(); 52 | //cpu_test(true); 53 | //co_parallel_test(); 54 | //curl_test(true); 55 | //mongo_test(true); 56 | //redis_test(true); 57 | //co_mysql_test(); 58 | //ipc_test(); 59 | //rabbit_test(true, i); 60 | //zookeeper_test(true, i); 61 | 62 | uint32_t lastPrintTime = 0; 63 | while (true) { 64 | time_t curTime = time(0); 65 | co_async::loopSleep(curTime); 66 | 67 | if (curTime - lastPrintTime >= 2) { 68 | lastPrintTime = curTime; 69 | //log("task: %d", tp.taskCount()); 70 | } 71 | } 72 | }); 73 | } 74 | 75 | // 主线程废弃 76 | while (true) { 77 | sleep(10); 78 | } 79 | 80 | return 0; 81 | } 82 | 83 | -------------------------------------------------------------------------------- /example/mongo_test.cpp: -------------------------------------------------------------------------------- 1 | #ifdef USE_ASYNC_MONGO 2 | 3 | #include "./common.h" 4 | 5 | extern bool print_log; 6 | 7 | // mongo测试 8 | void mongo_test(bool use_co) { 9 | std::string uri = "mongodb://127.0.0.1:27017|test|student2"; 10 | // 使用协程 11 | if (use_co) { 12 | // 启动一个协程任务 13 | CoroutineTask::doTask([uri](void*) { 14 | { 15 | auto res = co_async::mongo::execute(uri, async::mongo::CreateExpireIndexMongoCmd("name", 120)); 16 | if (res.second) { 17 | log("ok"); 18 | } else { 19 | log("fail"); 20 | } 21 | return; 22 | } 23 | 24 | // 执行mongo访问并等待协程返回 25 | { 26 | // ok 27 | std::string value; 28 | co_async::mongo::execute(uri, async::mongo::FindMongoCmd({}), &value); 29 | std::cout << "ret1:" << value << std::endl; 30 | } 31 | 32 | { 33 | int modifiedCount = 0; 34 | co_async::mongo::execute(uri, async::mongo::UpdateManyMongoCmd({ 35 | {"userName", "test3"} 36 | }, { 37 | {"password", "1234510"} 38 | }), &modifiedCount, 0, 0); 39 | 40 | std::cout << "ret4:" << modifiedCount << std::endl; 41 | } 42 | 43 | }, 0); 44 | } 45 | // 不使用协程 46 | else { 47 | // 发起一个mongo异步访问并期待回调被调用 48 | async::mongo::execute(uri, async::mongo::FindMongoCmd({}), [](async::mongo::MongoReplyParserPtr ptr) { 49 | while (true) { 50 | char* json = ptr->NextJson(); 51 | if (!json) { 52 | break; 53 | } 54 | std::cout << "mongo value:" << json << std::endl; 55 | ptr->FreeJson(json); 56 | } 57 | }); 58 | } 59 | } 60 | 61 | 62 | #endif -------------------------------------------------------------------------------- /example/mysql_test.cpp: -------------------------------------------------------------------------------- 1 | #ifdef USE_ASYNC_MYSQL 2 | 3 | #include "./common.h" 4 | 5 | void co_mysql_test() 6 | { 7 | // 启动一个协程任务 8 | CoroutineTask::doTask([](void*) { 9 | { 10 | auto ret = co_async::mysql::query("192.168.0.89|3306|test||", 11 | "select * from student", 12 | [](int err, const void* row, int row_idx, int field, int affected_row) { 13 | for (int f = 0; f < field; ++f) { 14 | std::cout << ((const char**)row)[f] << ", "; 15 | } 16 | std::cout << std::endl; 17 | }); 18 | 19 | std::cout << "ret:" << ret.first << "|" << ret.second; 20 | } 21 | 22 | { 23 | auto ret = co_async::mysql::query("192.168.0.89|3306|test||", "select * from student"); 24 | } 25 | }, 0); 26 | 27 | } 28 | 29 | #endif -------------------------------------------------------------------------------- /example/net_test.cpp: -------------------------------------------------------------------------------- 1 | #ifdef USE_NET 2 | 3 | #include "./common.h" 4 | 5 | void net_test() { 6 | std::cout << "action\n"; 7 | net::UdpListener l(0); 8 | if (!l.listen("0.0.0.0:3001")) { 9 | std::cout << "failed to listen\n"; 10 | return; 11 | } 12 | l.setDataCb([](net::UdpListener* l, uint32_t fd, const char* data, uint32_t len) { 13 | std::cout << "[server]:" << std::string(data, len) << std::endl; 14 | std::string d = "i am server"; 15 | l->send(fd, d.c_str(), d.length()); 16 | sleep(1); 17 | }); 18 | 19 | net::UdpClient c(0); 20 | if (!c.connect("127.0.0.1:3001")) { 21 | std::cout << "failed to connect\n"; 22 | return; 23 | } 24 | c.setDataCb([](net::UdpClient* c, const char* data, uint32_t len) { 25 | std::cout << "[client]:" << std::string(data, len) << std::endl; 26 | std::string d = "i am client"; 27 | c->send(d.c_str(), d.length()); 28 | sleep(1); 29 | }); 30 | c.send("action", 6); 31 | 32 | try 33 | { 34 | while (true) 35 | { 36 | l.update(0); 37 | c.update(0); 38 | usleep(1000 * 100); 39 | } 40 | } 41 | catch (...) 42 | { 43 | std::cout << "exce\n"; 44 | } 45 | 46 | std::cout << "over\n"; 47 | } 48 | 49 | #endif -------------------------------------------------------------------------------- /example/parallel_test.cpp: -------------------------------------------------------------------------------- 1 | #ifdef USE_ASYNC_CURL 2 | 3 | #include "./common.h" 4 | 5 | void parallel_test() { 6 | // 异步io并行访问,并期待结束时回调被调用 7 | async::parallel([](int err) { 8 | std::cout << "parallel done:" << err << std::endl; 9 | }, 10 | { 11 | [](async::next_cb next) { 12 | async::curl::get("http://baidu.com", [next](int, int, std::string& body) { 13 | std::cout << "parallel body1:" << body.length() <GetString(value); 35 | std::cout << "redis value:" << value << std::endl; 36 | }); 37 | } 38 | } 39 | 40 | #endif -------------------------------------------------------------------------------- /serve/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | 3 | add_subdirectory(serve) 4 | add_subdirectory(router) 5 | add_subdirectory(gate) 6 | add_subdirectory(testhttp) 7 | add_subdirectory(test) 8 | -------------------------------------------------------------------------------- /serve/gate/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | 3 | set(TARGET_NAME "gate") 4 | 5 | project(${TARGET_NAME} CXX) 6 | 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11") 8 | 9 | #file(GLOB_RECURSE ALL_CPP *.cpp *.c) 10 | # 不使用file(GLOB_RECURSE ALL_CPP *.cpp *.c),因为它会自动创建CMakeCxxCompilerId.cpp,尚未找到答案 11 | aux_source_directory(. ALL_CPP) 12 | 13 | include_directories(../../) 14 | 15 | set(LINK_LIBRARYS ${LINK_LIBRARYS} serve async) 16 | 17 | add_executable(${TARGET_NAME} ${ALL_CPP}) 18 | 19 | # 指定链接库 20 | target_link_libraries(${TARGET_NAME} PRIVATE ${LINK_LIBRARYS}) -------------------------------------------------------------------------------- /serve/gate/gate.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "本配置文件描述的是进程监听及连接端口的信息", 3 | 4 | "@self": "标识进程身份的信息", 5 | "self": { 6 | "world": 1, 7 | "type": 1, 8 | "id": 1 9 | }, 10 | 11 | "@zm_connect": "zeromq的连接信息列表", 12 | "zm_connect": [ 13 | { 14 | "protocol": "tcp", 15 | "ip": "0.0.0.0", 16 | "port": 5001 17 | } 18 | ], 19 | 20 | "@net_listen": "tcp/udp的监听信息列表, 一般是给gate使用", 21 | "net_listen": [ 22 | { 23 | "protocol": "tcp", 24 | "ip": "0.0.0.0", 25 | "port": 4001 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /serve/router/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | 3 | set(TARGET_NAME "router") 4 | 5 | project(${TARGET_NAME} CXX) 6 | 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11") 8 | 9 | #file(GLOB_RECURSE ALL_CPP *.cpp *.c) 10 | # 不使用file(GLOB_RECURSE ALL_CPP *.cpp *.c),因为它会自动创建CMakeCxxCompilerId.cpp,尚未找到答案 11 | aux_source_directory(. ALL_CPP) 12 | 13 | include_directories(../../) 14 | 15 | set(LINK_LIBRARYS ${LINK_LIBRARYS} serve) 16 | 17 | add_executable(${TARGET_NAME} ${ALL_CPP}) 18 | 19 | # 指定链接库 20 | target_link_libraries(${TARGET_NAME} PRIVATE ${LINK_LIBRARYS}) -------------------------------------------------------------------------------- /serve/router/main.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #include "serve/serve/serve.h" 10 | 11 | int main(int argc, char** argv) { 12 | Serve srv; 13 | srv.useRouter(true); 14 | srv.useAsync(false); 15 | if (!srv.init(argc, argv)) { 16 | return -1; 17 | } 18 | 19 | srv.start(); 20 | return 0; 21 | } -------------------------------------------------------------------------------- /serve/router/router.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "本配置文件描述的是进程监听及连接端口的信息", 3 | 4 | "@zm_listen": "zeromq的监听信息列表, 一般是给路由使用", 5 | "zm_listen": [ 6 | { 7 | "world": 1, 8 | "protocol": "tcp", 9 | "ip": "0.0.0.0", 10 | "port": 5001 11 | }, 12 | { 13 | "world": 2, 14 | "protocol": "tcp", 15 | "ip": "0.0.0.0", 16 | "port": 5002 17 | } 18 | ], 19 | 20 | "@routes": "描述的是将会连接到本进程的连接信息,以便做路由选择使用", 21 | "routes": [ 22 | { 23 | "world": 1, 24 | "type": 1, 25 | "id": 1 26 | }, 27 | { 28 | "world": 1, 29 | "type": 2, 30 | "id": 1 31 | }, 32 | { 33 | "world": 2, 34 | "type": 1, 35 | "id": 1 36 | }, 37 | { 38 | "world": 2, 39 | "type": 2, 40 | "id": 1 41 | } 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /serve/serve/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | 3 | set(TARGET_NAME "serve") 4 | 5 | project(${TARGET_NAME} CXX) 6 | 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11") 8 | 9 | #file(GLOB_RECURSE ALL_CPP *.cpp *.c) 10 | # 不使用file(GLOB_RECURSE ALL_CPP *.cpp *.c),因为它会自动创建CMakeCxxCompilerId.cpp,尚未找到答案 11 | aux_source_directory(. ALL_CPP) 12 | 13 | include_directories(../../) 14 | link_directories(/usr/local/lib64 /usr/local/lib) 15 | 16 | if(USE_IPC) 17 | add_definitions(-DUSE_IPC) 18 | endif(USE_IPC) 19 | 20 | if(USE_NET) 21 | add_definitions(-DUSE_NET) 22 | endif(USE_NET) 23 | 24 | set(LINK_LIBRARYS ${LINK_LIBRARYS} async) 25 | 26 | add_library(${TARGET_NAME} SHARED ${ALL_CPP}) 27 | 28 | add_dependencies(${TARGET_NAME} async) 29 | 30 | # 指定链接库 31 | target_link_libraries(${TARGET_NAME} PRIVATE ${LINK_LIBRARYS}) 32 | -------------------------------------------------------------------------------- /serve/serve/backend.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #ifdef USE_IPC 10 | 11 | #include "serve/serve/backend.h" 12 | #include "async/ipc/ipc.h" 13 | #include "async/transaction/transaction_mgr.h" 14 | #include 15 | 16 | namespace backend { 17 | 18 | std::function gMiddle = nullptr; 19 | 20 | struct ZqDealer : public ipc::ZeromqDealerHandler { 21 | void onData(uint64_t uniqueId, uint32_t identify, const std::string& data) override { 22 | if (!(gMiddle && gMiddle(uniqueId, identify, data))) { 23 | BackendMsg message; 24 | message.decode(data); 25 | 26 | if (message.header.rspSeqId == 0) { 27 | #ifdef USE_TRANS 28 | trans_mgr::handle(message.header.cmd, (char*)&message, 0, (void*)0); 29 | #endif 30 | } 31 | else { 32 | co_async::ipc::recv(message.header.rspSeqId, (char*)&message, 0); 33 | } 34 | } 35 | } 36 | }; 37 | 38 | ZqDealer gDealer; 39 | LinkInfo gLinkInfo; 40 | World gSelf; 41 | 42 | bool init(const World& self, const LinkInfo& link) { 43 | gLinkInfo = link; 44 | gSelf = self; 45 | 46 | for (auto& item : gLinkInfo.itemVec) { 47 | uint64_t id = gDealer.connect(gSelf.identify(), item.addr()); 48 | if (id == 0) { 49 | return false; 50 | } 51 | item.uniqueId = id; 52 | } 53 | return true; 54 | } 55 | 56 | bool update(time_t now) { 57 | return gDealer.update(now); 58 | } 59 | 60 | void use(std::function fn) { 61 | gMiddle = fn; 62 | } 63 | 64 | uint32_t selfWorld() { 65 | return gSelf.world; 66 | } 67 | 68 | uint32_t selfWorldId() { 69 | return gSelf.identify(); 70 | } 71 | 72 | void send(uint64_t uniqueId, const std::string& data) { 73 | gDealer.sendData(uniqueId, data); 74 | } 75 | 76 | void send(BackendMsg& frame) { 77 | // 挑选出一个路由 78 | if (gLinkInfo.itemVec.empty()) { 79 | assert(false); 80 | return; 81 | } 82 | 83 | std::string output; 84 | frame.header.cmdLength = frame.data.size(); 85 | frame.encode(output); 86 | 87 | size_t idx = frame.header.targetId % gLinkInfo.itemVec.size(); 88 | uint64_t uniqueId = gLinkInfo.itemVec[idx].uniqueId; 89 | 90 | send(uniqueId, output); 91 | } 92 | 93 | } 94 | 95 | #endif -------------------------------------------------------------------------------- /serve/serve/backend_transaction.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/transaction/transaction_mgr.h" 12 | #include "serve/serve/base.h" 13 | #include "serve/serve/backend.h" 14 | #include 15 | 16 | template 17 | class BackendTransaction : public Transaction { 18 | public: 19 | using BaseTrans = Transaction; 20 | 21 | bool ParsePacket(const char* packet, uint32_t /*packet_size*/) override { 22 | const BackendMsg* msg = (const BackendMsg*)packet; 23 | if (!BaseTrans::m_request.ParseFromString(msg->data)) { 24 | assert(false); 25 | return false; 26 | } 27 | 28 | this->mHeader = msg->header; 29 | return true; 30 | } 31 | 32 | bool OnAfter() override { 33 | if (BaseTrans::RspCmdId() != 0) { 34 | sendBack(BaseTrans::m_respond); 35 | } 36 | return true; 37 | } 38 | 39 | void sendBack(RespondType &data) { 40 | backend::notifyBack(mHeader.srcWorldId, 41 | mHeader.targetId, 42 | data, 43 | BaseTrans::RspCmdId(), 44 | mHeader.frontSeqNo, 45 | mHeader.reqSeqId, 46 | BaseTrans::m_return_value, 47 | 0); 48 | } 49 | 50 | protected: 51 | BackendHeader mHeader; 52 | }; 53 | 54 | -------------------------------------------------------------------------------- /serve/serve/base.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // 这三个值,每个都不能大于255 16 | struct World { 17 | uint32_t world = 0; 18 | uint32_t type = 0; // 可用来对应服务类型 19 | uint32_t id = 0; // 可用来对应服务id 20 | 21 | World() {} 22 | World(uint32_t identify); 23 | bool operator <(const World&) const; 24 | uint32_t identify() const; 25 | }; 26 | 27 | struct LinkInfo { 28 | struct Item { 29 | uint64_t uniqueId = 0; 30 | World w; 31 | std::string protocol; 32 | std::string ip; 33 | uint32_t port = 0; 34 | bool isTcp() const; 35 | bool isUdp() const; 36 | std::string addr() const; 37 | std::string rawAddr() const; 38 | }; 39 | 40 | std::vector itemVec; 41 | }; 42 | 43 | struct BackendHeader { 44 | static uint32_t size(); 45 | uint32_t srcWorldId = 0; // 消息从哪来 46 | uint32_t dstWorldId = 0; // 消息到哪去 47 | uint64_t targetId = 0; // 发给哪个目标 48 | uint32_t cmd = 0; // 消息id 49 | uint64_t remoteFd = 0; // 如果是zeromq,则fd表示为uniqueId。如果是net,则fd表示为fd 50 | uint64_t reqSeqId = 0; // 请求的消息编号 51 | uint64_t rspSeqId = 0; // 回复的消息编号 52 | uint32_t broadcast = 0; // 是否广播,在没有路由的情况下,此字段不生效 53 | uint32_t result = 0; // 消息返回时的结果 54 | uint32_t frontSeqNo = 0; // 前端请求编号 55 | uint32_t cmdLength = 0; // 消息长度,不包括包头 56 | }; 57 | 58 | struct BackendMsg { 59 | BackendHeader header; 60 | std::string data; 61 | void encode(std::string& output) const; 62 | void decode(const std::string& input); 63 | }; 64 | 65 | // 默认的前端协议, 里面的字段全使用网络字节序 66 | struct FrontendHeader { 67 | static uint32_t size(); 68 | void encode(FrontendHeader& h) const; 69 | void decode(const FrontendHeader& h); 70 | uint32_t cmdLength = 0; // 消息长度,不包括包头 71 | uint32_t frontSeqNo = 0; // 前端请求编号 72 | uint32_t cmd = 0; // 消息id 73 | uint32_t result = 0; // 消息返回时的结果 74 | }; 75 | 76 | struct FrontendMsg { 77 | FrontendHeader header; 78 | std::string data; 79 | void encode(std::string& output) const; 80 | void decode(const std::string& input); 81 | void decode(const char* d, uint32_t len); 82 | }; 83 | 84 | struct HttpRequest { 85 | void* r; 86 | std::string url; 87 | std::string host; 88 | std::string squery; 89 | std::string body; 90 | std::unordered_map query; 91 | 92 | void swap(HttpRequest& req); 93 | }; 94 | 95 | struct HttpRespond { 96 | HttpRespond() { 97 | header["Content-Type"] = "text/plain"; 98 | } 99 | std::string body; 100 | std::unordered_map header; 101 | 102 | void swap(HttpRespond& rsp); 103 | }; 104 | 105 | struct HttpMsg { 106 | HttpRequest req; 107 | HttpRespond rsp; 108 | }; 109 | 110 | struct CmdInfo { 111 | World w; // 表明消息服务身份 112 | uint64_t targetId = 0; // 113 | uint32_t fd = 0; 114 | bool isLogin = false; // 是否为登录消息 115 | }; 116 | 117 | void split(const std::string source, const std::string &separator, std::vector &array); -------------------------------------------------------------------------------- /serve/serve/gate.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | /* 10 | * 提供以下网关功能 11 | 1、允许指定前端协议 12 | 2、将前端协议转换为后端协议,并转发到后端 13 | 3、验证fd的合法性 14 | 4、限制fd的消息速率 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "serve/serve/base.h" 20 | #include 21 | 22 | namespace gate { 23 | 24 | bool init(void* event_base, const World& self, const LinkInfo& link); 25 | 26 | bool update(time_t now); 27 | 28 | // 指定前端协议解析方法 29 | // 设置包解析器: 30 | // @headerSize: 头包长度 31 | // @parser: 返回值包体长度 32 | void setHeader(uint32_t headerSize, std::function parser); 33 | 34 | // 设置包处理接口 35 | void setPacket(std::function packet); 36 | 37 | // 设置cmd身份识别接口 38 | void setCmdParser(std::function parser); 39 | 40 | std::function getCmdParser(); 41 | 42 | // 设置消息速率 43 | void setMsgFreq(uint32_t f); 44 | 45 | // 设置是否授权 46 | void setAuth(uint32_t fd, bool flag); 47 | 48 | bool getAuth(uint32_t fd); 49 | 50 | // 设置目标id, 这个会导致原来的连接失效 51 | void setTargetId(uint32_t fd, uint64_t targetId); 52 | 53 | uint64_t getTargetId(uint32_t fd); 54 | 55 | uint32_t getFd(uint64_t targetId); 56 | 57 | // 心跳超时,即多过长时间没有数据包就断开连接 58 | void setExpire(uint32_t t); 59 | 60 | void close(uint32_t fd); 61 | 62 | int send(uint32_t fd, const char* buf, uint32_t len); 63 | 64 | uint32_t selfWorldId(); 65 | 66 | } -------------------------------------------------------------------------------- /serve/serve/http.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "serve/serve/base.h" 12 | #include 13 | #include 14 | 15 | namespace http { 16 | 17 | bool init(void* event_base, const LinkInfo& link); 18 | 19 | void update(uint32_t curTime); 20 | 21 | // 添加消息中间件 22 | void use(uint32_t, std::function fn); 23 | 24 | void send(void* request, const char* buf, uint32_t len); 25 | 26 | void send(void* request, const std::unordered_map& header, const char* buf, uint32_t len); 27 | 28 | const char* decodeUri(const char* s); 29 | } -------------------------------------------------------------------------------- /serve/serve/http_transaction.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "async/transaction/transaction_mgr.h" 12 | #include "serve/serve/base.h" 13 | #include "serve/serve/http.h" 14 | #include 15 | 16 | class HttpTransaction : public BaseHttpTransaction { 17 | public: 18 | using BaseTrans = BaseHttpTransaction; 19 | 20 | struct Request { 21 | void* r; 22 | std::string url; 23 | std::string host; 24 | std::string squery; 25 | std::string body; 26 | std::unordered_map query; 27 | }; 28 | 29 | struct Respond { 30 | Respond() { 31 | header["Content-Type"] = "text/plain"; 32 | } 33 | std::string body; 34 | std::unordered_map header; 35 | }; 36 | 37 | bool ParsePacket(const char* packet, uint32_t /*packet_size*/) override { 38 | HttpMsg* msg = const_cast((const HttpMsg*)packet); 39 | m_request.swap(msg->req); 40 | m_respond.swap(msg->rsp); 41 | return true; 42 | } 43 | 44 | bool OnAfter() override { 45 | http::send(m_request.r, m_respond.header, m_respond.body.c_str(), m_respond.body.size()); 46 | return true; 47 | } 48 | 49 | protected: 50 | HttpRequest m_request; 51 | HttpRespond m_respond; 52 | }; -------------------------------------------------------------------------------- /serve/serve/router.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | #pragma once 10 | 11 | #include "serve/serve/base.h" 12 | #include 13 | 14 | namespace router { 15 | 16 | bool init(const LinkInfo& link, const LinkInfo& routes); 17 | 18 | bool update(time_t now); 19 | 20 | // 添加消息中间件 21 | void use(std::function fn); 22 | 23 | } -------------------------------------------------------------------------------- /serve/serve/serve.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | // github: https://github.com/xiaoquanjie/async 7 | //----------------------------------------------------------------*/ 8 | 9 | /* 10 | * 提供类似的服务器进程脚手架 11 | 设计原则: 12 | 1、根据配置自动监听相应的类型端口 13 | 2、根据配置自动的连接到相应类型地址,如果是zm_connect还会进行注册 14 | 3、根据收到的消息启动已注册的transaction 15 | 4、为了便于测试,serve允许同时能扮演router, serve A, serve B三者的角色,router为A,B之间的通信做转发 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "serve/serve/base.h" 21 | #include 22 | 23 | // 服务基类 24 | class Serve { 25 | public: 26 | virtual ~Serve(); 27 | 28 | bool init(int argc, char** argv); 29 | 30 | void start(); 31 | 32 | void useRouter(bool u); 33 | 34 | void stop(); 35 | 36 | void onInit(std::function init); 37 | 38 | void onLoop(std::function loop); 39 | 40 | void idleCount(uint32_t cnt); 41 | 42 | void sleep(uint32_t s); 43 | 44 | void useAsync(bool u); 45 | 46 | void useGate(bool u); 47 | 48 | const World& self(); 49 | 50 | void setLogFunc(std::function cb); 51 | protected: 52 | bool parseArgv(int argc, char** argv); 53 | 54 | protected: 55 | bool mStopped = false; 56 | uint32_t mIdleCnt = 200; 57 | uint32_t mSleep = 15; 58 | 59 | bool mUseRouter = false; 60 | bool mUseDealer = false; 61 | bool mUseAsyn = true; 62 | bool mUseHttp = false; 63 | bool mUseGate = false; 64 | 65 | std::function mOnInit; 66 | std::function mOnLoop; 67 | 68 | std::string mConfFile; 69 | World mSelf; 70 | LinkInfo mZmListen; 71 | LinkInfo mZmConnect; 72 | LinkInfo mNetListen; 73 | LinkInfo mNetConnect; 74 | LinkInfo mHttpListen; 75 | LinkInfo mRoutes; 76 | }; 77 | -------------------------------------------------------------------------------- /serve/serve/serve.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "本配置文件描述的是进程监听及连接端口的信息", 3 | 4 | "@self": "标识进程身份的信息", 5 | "self": { 6 | "world": 1, 7 | "type": 1, 8 | "id": 1 9 | }, 10 | 11 | "@zm_listen": "zeromq的监听信息列表, 一般是给路由使用", 12 | "zm_listen": [ 13 | { 14 | "world": 1, 15 | "protocol": "tcp", 16 | "ip": "0.0.0.0", 17 | "port": 5001 18 | } 19 | ], 20 | 21 | "@zm_connect": "zeromq的连接信息列表", 22 | "zm_connect": [ 23 | { 24 | "protocol": "tcp", 25 | "ip": "0.0.0.0", 26 | "port": 5001 27 | } 28 | ], 29 | 30 | "@net_listen": "tcp/udp的监听信息列表, 一般是给gate使用", 31 | "net_listen": [ 32 | { 33 | "protocol": "tcp/udp", 34 | "ip": "0.0.0.0", 35 | "port": 5002 36 | } 37 | ], 38 | 39 | "@net_connect": "tcp/udp的连接信息列表", 40 | "net_connect": [ 41 | { 42 | "protocol": "tcp/udp", 43 | "ip": "0.0.0.0", 44 | "port": 5002 45 | } 46 | ], 47 | 48 | "@http_listen": "http协议的监听信息列表", 49 | "http_listen": [ 50 | { 51 | "id": 1, 52 | "ip": "0.0.0.0", 53 | "port": 5003 54 | } 55 | ], 56 | 57 | "@routes": "描述的是将会连接到本进程的连接信息,以便做路由选择使用", 58 | "routes": [ 59 | { 60 | "world": 1, 61 | "type": 1, 62 | "id": 1 63 | } 64 | ] 65 | } -------------------------------------------------------------------------------- /serve/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | 3 | set(TARGET_NAME "testServe") 4 | 5 | project(${TARGET_NAME} CXX) 6 | 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11") 8 | 9 | #file(GLOB_RECURSE ALL_CPP *.cpp *.c) 10 | # 不使用file(GLOB_RECURSE ALL_CPP *.cpp *.c),因为它会自动创建CMakeCxxCompilerId.cpp,尚未找到答案 11 | aux_source_directory(. ALL_CPP) 12 | 13 | include_directories(../../) 14 | 15 | set(LINK_LIBRARYS ${LINK_LIBRARYS} serve async) 16 | 17 | add_executable(${TARGET_NAME} ${ALL_CPP}) 18 | 19 | # 指定链接库 20 | target_link_libraries(${TARGET_NAME} PRIVATE ${LINK_LIBRARYS}) -------------------------------------------------------------------------------- /serve/testhttp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | 3 | set(TARGET_NAME "testHttp") 4 | 5 | project(${TARGET_NAME} CXX) 6 | 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11") 8 | 9 | #file(GLOB_RECURSE ALL_CPP *.cpp *.c) 10 | # 不使用file(GLOB_RECURSE ALL_CPP *.cpp *.c),因为它会自动创建CMakeCxxCompilerId.cpp,尚未找到答案 11 | aux_source_directory(. ALL_CPP) 12 | 13 | include_directories(../../) 14 | 15 | set(LINK_LIBRARYS ${LINK_LIBRARYS} serve async) 16 | 17 | add_executable(${TARGET_NAME} ${ALL_CPP}) 18 | 19 | # 指定链接库 20 | target_link_libraries(${TARGET_NAME} PRIVATE ${LINK_LIBRARYS}) -------------------------------------------------------------------------------- /serve/testhttp/main.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------- 2 | // Copyright 2022 3 | // All rights reserved. 4 | // 5 | // author: 404558965@qq.com (xiaoquanjie) 6 | //----------------------------------------------------------------*/ 7 | 8 | #include "serve/serve/serve.h" 9 | #include "serve/serve/http_transaction.h" 10 | #include "async/log.h" 11 | 12 | class GetNameTransaction : public HttpTransaction { 13 | public: 14 | int OnRequest() { 15 | log("url:%s", m_request.url.c_str()); 16 | log("host:%s", m_request.host.c_str()); 17 | log("query:%s", m_request.squery.c_str()); 18 | log("body:%s", m_request.body.c_str()); 19 | 20 | // 回复 21 | m_respond.body = "hello"; 22 | return 0; 23 | } 24 | }; 25 | 26 | REGIST_HTTP_TRANSACTION(1, "/getname", GetNameTransaction); 27 | 28 | int main(int argc, char** argv) { 29 | Serve srv; 30 | 31 | if (!srv.init(argc, argv)) { 32 | return -1; 33 | } 34 | 35 | // 添加中间件 36 | http::use(1, [](uint32_t, HttpRequest& req, HttpRespond&) { 37 | log("middle %s", req.url.c_str()); 38 | req.squery += "&name=jack"; 39 | // 消息往下传 40 | return false; 41 | }); 42 | 43 | srv.start(); 44 | return 0; 45 | } -------------------------------------------------------------------------------- /tools/excel2proto/loghelper.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # coding=utf-8 3 | 4 | import sys 5 | import os 6 | import logging 7 | 8 | 9 | class Color(object): 10 | BLACK = "\033[30m" 11 | RED = "\033[31m" 12 | GREEN = "\033[32m" 13 | YELLOW = "\033[33m" 14 | BLUE = "\033[34m" 15 | PURPLE = "\033[35m" 16 | CYAN = "\033[36m" 17 | WHITE = "\033[37m" 18 | NONE = "\033[0m" 19 | 20 | 21 | class LogHelper: 22 | """日志辅助类""" 23 | _logger = None 24 | _close_imme = True 25 | 26 | @staticmethod 27 | def set_close_flag(flag): 28 | LogHelper._close_imme = flag 29 | 30 | @staticmethod 31 | def _init(): 32 | # file log 33 | formatter = logging.Formatter('%(asctime)s|%(levelname)s|%(lineno)d|%(funcName)s|%(message)s') 34 | handler = logging.FileHandler('xls_translator.log', mode='w') 35 | handler.setFormatter(formatter) 36 | LogHelper._logger = logging.getLogger() 37 | #LogHelper._logger.addHandler(handler) 38 | LogHelper._logger.setLevel(logging.DEBUG) 39 | 40 | # console log 41 | console_handler = logging.StreamHandler() 42 | console_handler.setFormatter(formatter) 43 | LogHelper._logger.addHandler(console_handler) 44 | 45 | @staticmethod 46 | def get_logger(): 47 | if LogHelper._logger is None: 48 | LogHelper._init() 49 | 50 | return LogHelper._logger 51 | 52 | @staticmethod 53 | def close(): 54 | if LogHelper._close_imme: 55 | if LogHelper._logger is None: 56 | return 57 | logging.shutdown() 58 | 59 | 60 | # log wrapper 61 | LOG_DEBUG=LogHelper.get_logger().debug 62 | LOG_INFO=LogHelper.get_logger().info 63 | LOG_WARN=LogHelper.get_logger().warn 64 | LOG_ERROR=LogHelper.get_logger().error 65 | 66 | -------------------------------------------------------------------------------- /tools/excel2proto/protoc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoquanjie/async/fb2a352bf4af186a706397650381e62c61fe0f6b/tools/excel2proto/protoc.exe --------------------------------------------------------------------------------