{"id":29899199,"url":"https://github.com/wenzhang-dev/evcpp","last_synced_at":"2025-08-01T12:17:32.497Z","repository":{"id":305858879,"uuid":"997695672","full_name":"wenzhang-dev/evcpp","owner":"wenzhang-dev","description":"easy-used, lightweight, coroutine-based asynchronous framework","archived":false,"fork":false,"pushed_at":"2025-07-22T09:47:54.000Z","size":15,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-22T11:40:47.647Z","etag":null,"topics":["asynchronous-programming","coroutine","cxx20","event-loop","libev","lightweight-framework","message-loop","modern-cpp","promise"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wenzhang-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-07T01:39:32.000Z","updated_at":"2025-07-22T09:55:36.000Z","dependencies_parsed_at":"2025-07-22T11:40:49.365Z","dependency_job_id":"08f2756a-3c65-4960-9568-7dda1b38b9c8","html_url":"https://github.com/wenzhang-dev/evcpp","commit_stats":null,"previous_names":["wenzhang-dev/evcpp"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/wenzhang-dev/evcpp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenzhang-dev%2Fevcpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenzhang-dev%2Fevcpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenzhang-dev%2Fevcpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenzhang-dev%2Fevcpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wenzhang-dev","download_url":"https://codeload.github.com/wenzhang-dev/evcpp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenzhang-dev%2Fevcpp/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268221647,"owners_count":24215696,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-01T02:00:08.611Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asynchronous-programming","coroutine","cxx20","event-loop","libev","lightweight-framework","message-loop","modern-cpp","promise"],"created_at":"2025-08-01T12:17:28.621Z","updated_at":"2025-08-01T12:17:32.488Z","avatar_url":"https://github.com/wenzhang-dev.png","language":"C++","readme":"# evcpp\nThe evcpp is an easy-to-use, lightweight, coroutine-based asynchronous framework.\n\nIt has an internal event loop based on the libev implementation. All asynchronous operations are done in this event loop, such as timer event, io event and so on. The evcpp also encapsulates Promises specifically for asynchronous operations. Asynchronous tasks can be easily orchestrated using Promises, such as all, any, race. In addition, to simplify asynchronous programming, the evcpp also supports cxx20 coroutine and is highly integrated with promise for more flexible control of synchronous and asynchronous programming.\n\nThe Promise can encapsulate any asynchronous operation and make it coroutine.\n\n## Examples\n\nHere is a cxx20 coroutine-based echo tcp server service.\n\n```c++\n#include \u003cevcpp.h\u003e\n#include \u003cnetinet/in.h\u003e\n#include \u003cstring.h\u003e\n#include \u003csys/socket.h\u003e\n#include \u003cunistd.h\u003e\n\nevcpp::Promise\u003cevcpp::Fd\u003e AsyncAccept(evcpp::EventLoop* loop,\n                                      evcpp::Fd listen_fd) {\n    evcpp::Promise\u003cevcpp::Fd\u003e promise;\n\n    auto io_event = loop-\u003eAddIOEvent(\n        listen_fd, evcpp::IOEventType::kRead,\n        evcpp::MakeCallback(\n            [listen_fd, resolver = promise.GetResolver()]() mutable -\u003e void {\n                evcpp::Fd client_fd = ::accept(listen_fd, nullptr, nullptr);\n                if (client_fd \u003e= 0) {\n                    resolver.Resolve(std::move(client_fd));\n                } else {\n                    auto ec = std::error_code(errno, std::generic_category());\n                    resolver.Reject(std::move(ec));\n                }\n            }));\n\n    co_return co_await promise;\n}\n\nevcpp::Promise\u003cssize_t\u003e AsyncRead(evcpp::EventLoop* loop, evcpp::Fd fd,\n                                  char* buf, size_t size) {\n    evcpp::Promise\u003cssize_t\u003e promise;\n\n    auto io_event = loop-\u003eAddIOEvent(\n        fd, evcpp::IOEventType::kRead,\n        evcpp::MakeCallback(\n            [fd, buf, size,\n             resolver = promise.GetResolver()]() mutable -\u003e void {\n                auto n = ::read(fd, buf, size);\n                if (n \u003e= 0) {\n                    resolver.Resolve(ssize_t(n));\n                } else {\n                    auto ec = std::error_code(errno, std::generic_category());\n                    resolver.Reject(std::move(ec));\n                }\n            }));\n\n    co_return co_await promise;\n}\n\nevcpp::Promise\u003cssize_t\u003e AsyncWrite(evcpp::EventLoop* loop, evcpp::Fd fd,\n                                   const char* buf, size_t size) {\n    evcpp::Promise\u003cssize_t\u003e promise;\n\n    auto io_event = loop-\u003eAddIOEvent(\n        fd, evcpp::IOEventType::kWrite,\n        evcpp::MakeCallback(\n            [fd, buf, size,\n             resolver = promise.GetResolver()]() mutable -\u003e void {\n                auto n = ::write(fd, buf, size);\n                if (n \u003e= 0) {\n                    resolver.Resolve(std::move(n));\n                } else {\n                    auto ec = std::error_code(errno, std::generic_category());\n                    resolver.Reject(std::move(ec));\n                }\n            }));\n\n    co_return co_await promise;\n}\n\nevcpp::Promise\u003cvoid\u003e HandleClient(evcpp::EventLoop* loop, evcpp::Fd client_fd) {\n    char buffer[1024];\n\n    while (true) {\n        auto r1 = co_await AsyncRead(loop, client_fd, buffer, sizeof(buffer));\n        if (r1.IsError() || r1.Value() == 0) {\n            std::cerr \u003c\u003c \"fd #\" \u003c\u003c client_fd \u003c\u003c \" disconnect\" \u003c\u003c std::endl;\n            break;\n        }\n\n        auto size = r1.Value();\n        auto r2 = co_await AsyncWrite(loop, client_fd, buffer, size);\n        if (r2.IsError()) {\n            std::cerr \u003c\u003c \"fd #\" \u003c\u003c client_fd \u003c\u003c \" disconnect\" \u003c\u003c std::endl;\n            break;\n        }\n    }\n\n    ::close(client_fd);\n\n    co_return evcpp::Result\u003cvoid\u003e();\n}\n\nevcpp::Promise\u003cvoid\u003e StartEchoServer(evcpp::EventLoop* loop, uint16_t port) {\n    int listen_fd = ::socket(AF_INET, SOCK_STREAM, 0);\n    int yes = 1;\n    ::setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, \u0026yes, sizeof(yes));\n\n    ::sockaddr_in addr{};\n    addr.sin_family = AF_INET;\n    addr.sin_addr.s_addr = INADDR_ANY;\n    addr.sin_port = ::htons(port);\n\n    ::bind(listen_fd, (sockaddr*)\u0026addr, sizeof(addr));\n    ::listen(listen_fd, SOMAXCONN);\n\n    while (true) {\n        auto result = co_await AsyncAccept(loop, listen_fd);\n        if (result) {\n            int client_fd = result.Value();\n            HandleClient(loop, client_fd);\n        } else {\n            std::cerr \u003c\u003c \"Accept failed: \" \u003c\u003c ::strerror(result.Error().value())\n                      \u003c\u003c std::endl;\n        }\n    }\n\n    ::close(listen_fd);\n\n    co_return evcpp::Result\u003cvoid\u003e();\n}\n\nint main() {\n    auto loop = std::make_unique\u003cevcpp::EventLoopLibevImpl\u003e();\n    StartEchoServer(loop.get(), 18080);\n    loop-\u003eRunForever();\n\n    return 0;\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwenzhang-dev%2Fevcpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwenzhang-dev%2Fevcpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwenzhang-dev%2Fevcpp/lists"}