{"id":13531627,"url":"https://github.com/acl-dev/libfiber","last_synced_at":"2025-04-01T19:32:31.475Z","repository":{"id":149129290,"uuid":"212288085","full_name":"acl-dev/libfiber","owner":"acl-dev","description":"The high performance coroutine library for Linux/FreeBSD/MacOS/Windows, supporting select/poll/epoll/kqueue/iocp/windows GUI","archived":false,"fork":true,"pushed_at":"2025-03-25T07:10:43.000Z","size":1394,"stargazers_count":16,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-25T08:22:08.773Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"iqiyi/libfiber","license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/acl-dev.png","metadata":{"files":{"readme":"README.md","changelog":"changes.txt","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2019-10-02T08:18:00.000Z","updated_at":"2025-03-25T07:10:47.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/acl-dev/libfiber","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acl-dev%2Flibfiber","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acl-dev%2Flibfiber/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acl-dev%2Flibfiber/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acl-dev%2Flibfiber/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/acl-dev","download_url":"https://codeload.github.com/acl-dev/libfiber/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246700715,"owners_count":20819923,"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","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":[],"created_at":"2024-08-01T07:01:04.431Z","updated_at":"2025-04-01T19:32:31.460Z","avatar_url":"https://github.com/acl-dev.png","language":"C","readme":"# The high performance coroutine library, supporting Linux/BSD/Mac/Windows\n\n[中文说明](README_cn.md)  \n\n\u003c!-- vim-markdown-toc GFM --\u003e\n\n* [1 About](#1-about)\n* [2 Which IO events are supported?](#2-which-io-events-are-supported-)\n* [3 SAMPLES](#3-samples)\n    * [3.1 One server sample with C API](#31-one-server-sample-with-c-api)\n    * [3.2 One client sample with C API](#32-one-client-sample-with-c-api)\n    * [3.3 Resolve domain address in coroutine](#33-resolve-domain-address-in-coroutine)\n    * [3.4 Create fiber with standard C++ API](#34-create-fiber-with-standard-c-api)\n    * [3.5 Create fiber with C++1x API](#35-create-fiber-with-c1x-api)\n    * [3.6 Create shared stack fiber](#36-create-shared-stack-fiber)\n    * [3.7 Sync between fibers and threads](#37-sync-between-fibers-and-threads)\n    * [3.8 Transfer objects through box](#38-transfer-objects-through-box)\n    * [3.9 Using wait_group to wait for the others done](#39-using-wait_group-to-wait-for-the-others-done)\n    * [3.10 Using fiber_pool to execute different tasks](#310-using-fiber_pool-to-execute-different-tasks)\n    * [3.11 Wait for the result from a thread](#311-wait-for-the-result-from-a-thread)\n    * [3.12 Http server supporting http url route](#312-http-server-supporting-http-url-route)\n    * [3.13 Windows GUI sample](#313-windows-gui-sample)\n    * [3.14 More SAMPLES](#314-more-samples)\n* [4 BUILDING](#4-building)\n    * [4.1 On Unix](#41-on-unix)\n    * [4.2 On Windows](#42-on-windows)\n* [5 Benchmark](#5-benchmark)\n* [6 API support](#6-api-support)\n    * [6.1 Base API](#61-base-api)\n    * [6.2 IO API](#62-io-api)\n    * [6.3 Net API](#63-net-api)\n    * [6.4 Channel API](#64-channel-api)\n    * [6.5 Sync API](#65-sync-api)\n* [7 About API Hook](#7-about-api-hook)\n* [8 FAQ](#8-faq)\n\n\u003c!-- vim-markdown-toc --\u003e\n\n## 1 About\n\nThe libfiber project comes from the coroutine module of the [acl project](#https://github.com/acl-dev/acl) in lib_fiber directory of which. It can be used on OS platforms including Linux, FreeBSD, macOS, and Windows, which supports select, poll, epoll, kqueue, iocp, and even Windows GUI messages for different platform. With libfiber, you can write network application services having the high performance and large concurrent more easily than the traditional asynchronous  framework with event-driven model. \u003cb\u003eWhat's more\u003c/b\u003e, with the help of libfiber, you can even write network module of the Windows GUI application written by MFC, wtl or other GUI framework on Windows in coroutine way. That's really amazing.\n\n## 2 Which IO events are supported ?\n\nThe libfiber supports many events including select/poll/epoll/kqueue/iocp, and Windows GUI messages.\n\n| Platform       | Event type                      |\n|----------------|---------------------------------|\n| \u003cb\u003eLinux\u003c/b\u003e   | select, poll, epoll, io-uring   |\n| \u003cb\u003eBSD\u003c/b\u003e     | select, poll, kqueue            |\n| \u003cb\u003eMac\u003c/b\u003e     | select, poll, kqueue            |\n| \u003cb\u003eWindows\u003c/b\u003e | select, poll, iocp, GUI Message |\n\n## 3 SAMPLES\n\n### 3.1 One server sample with C API\n\n```C\n// fiber_server.c\n\n#include \u003cstdio.h\u003e\n#include \u003cstdlib.h\u003e\n#include \u003cassert.h\u003e\n#include \"fiber/lib_fiber.h\"\n#include \"patch.h\" // in the samples' path\n\nstatic size_t      __stack_size  = 128000;\nstatic const char *__listen_ip   = \"127.0.0.1\";\nstatic int         __listen_port = 9001;\n\n// Set read/write timeout with setsockopt API.\nstatic int set_timeout(SOCKET fd, int opt, int timeo) {\n# if defined(_WIN32) || defined(_WIN64)\n    timeout *= 1000; // From seconds to millisecond.\n    if (setsockopt(fd, SOL_SOCKET, opt, (const char*) \u0026timeo, sizeof(timeo)) \u003c 0) {\n        printf(\"setsockopt error=%s, timeout=%d, opt=%d, fd=%d\\r\\n\",\n            strerror(errno), timeo, opt, (int) fd);\n\t\treturn -1;\n\t}\n# else   // Must be Linux or __APPLE__.\n    struct timeval tm;\n    tm.tv_sec  = timeo;\n    tm.tv_usec = 0;\n\n    if (setsockopt(fd, SOL_SOCKET, opt, \u0026tm, sizeof(tm)) \u003c 0) {\n        printf(\"setsockopt error=%s, timeout=%d, opt=%d, fd=%d\\r\\n\",\n            strerror(errno), timeo, opt, (int) fd);\n        return -1;\n    }\n# endif\n    return 0;\n}\n\nstatic int set_rw_timeout(SOCKET fd, int timeo) {\n    if (set_timeout(fd, SO_RCVTIMEO, timeo) == -1 \n       || set_timeout(fd, SO_SNDTIMEO, timeo) == -1) {\n        return -1;\n    }\n    return 0;\n}\n\nstatic void fiber_client(ACL_FIBER *fb, void *ctx) {\n    SOCKET *pfd = (SOCKET *) ctx;\n    char buf[8192];\n\n    // Set the socket's read/write timeout.\n    set_rw_timeout(*pfd, 10);\n\n    while (1) {\n#ifdef _WIN32\n        int ret = acl_fiber_recv(*pfd, buf, sizeof(buf), 0);\n#else\n        int ret = recv(*pfd, buf, sizeof(buf), 0);\n#endif\n        if (ret == 0) {\n            break;\n        } else if (ret \u003c 0) {\n            if (acl_fiber_last_error() == FIBER_EINTR) {\n                continue;\n            }\n            break;\n        }\n#ifdef _WIN32\n        if (acl_fiber_send(*pfd, buf, ret, 0) \u003c 0) {\n#else\n        if (send(*pfd, buf, ret, 0) \u003c 0) {\n#endif\t\t\t\n            break;\n        }\n    }\n\n    socket_close(*pfd);\n    free(pfd);\n}\n\nstatic void fiber_accept(ACL_FIBER *fb, void *ctx) {\n    const char *addr = (const char *) ctx;\n    SOCKET lfd = socket_listen(__listen_ip, __listen_port);\n\n    assert(lfd \u003e= 0);\n\n    for (;;) {\n        SOCKET *pfd, cfd = socket_accept(lfd);\n        if (cfd == INVALID_SOCKET) {\n            printf(\"accept error %s\\r\\n\", acl_fiber_last_serror());\n            break;\n        }\n        pfd = (SOCKET *) malloc(sizeof(SOCKET));\n        *pfd = cfd;\n\n        // create and start one fiber to handle the client socket IO\n        acl_fiber_create(fiber_client, pfd, __stack_size);\n    }\n\n    socket_close(lfd);\n    exit (0);\n}\n\n// FIBER_EVENT_KERNEL represents the event type on\n// Linux(epoll), BSD(kqueue), Mac(kqueue), Windows(iocp)\n// FIBER_EVENT_POLL: poll on Linux/BSD/Mac/Windows\n// FIBER_EVENT_SELECT: select on Linux/BSD/Mac/Windows\n// FIBER_EVENT_WMSG: Win GUI message on Windows\n// acl_fiber_create/acl_fiber_schedule_with are in `lib_fiber.h`.\n// socket_listen/socket_accept/socket_close are in patch.c of the samples' path.\n\nint main(void) {\n    int event_mode = FIBER_EVENT_KERNEL;\n\n#ifdef _WIN32\n    socket_init();\n#endif\n\n    // create one fiber to accept connections\n    acl_fiber_create(fiber_accept, NULL, __stack_size);\n\n    // start the fiber schedule process\n    acl_fiber_schedule_with(event_mode);\n\n#ifdef _WIN32\n    socket_end();\n#endif\n\n    return 0;\n}\n```\n\n### 3.2 One client sample with C API\n\n```C\n// fiber_client.c\n\n#include \u003cstdio.h\u003e\n#include \u003cstdlib.h\u003e\n#include \u003cstring.h\u003e\n#include \u003cassert.h\u003e\n#include \"fiber/lib_fiber.h\"\n#include \"patch.h\" // in the samples' path\n\nstatic const char *__server_ip   = \"127.0.0.1\";\nstatic int         __server_port = 9001;\n\n// socket_init/socket_end/socket_connect/socket_close are in patch.c of the samples path\n\nstatic void fiber_client(ACL_FIBER *fb, void *ctx) {\n    SOCKET cfd = socket_connect(__server_ip, __server_port);\n    const char *s = \"hello world\\r\\n\";\n    char buf[8192];\n    int i, ret;\n\n    if (cfd == INVALID_SOCKET) {\n        return;\n    }\n\n    for (i = 0; i \u003c 1024; i++) {\n#ifdef _WIN32\n        if (acl_fiber_send(cfd, s, strlen(s), 0) \u003c= 0) {\n#else\n        if (send(cfd, s, strlen(s), 0) \u003c= 0) {\n#endif\t\t\t\n            printf(\"send error %s\\r\\n\", acl_fiber_last_serror());\n            break;\n        }\n\n#ifdef _WIN32\n        ret = acl_fiber_recv(cfd, buf, sizeof(buf), 0);\n#else\n        ret = recv(cfd, buf, sizeof(buf), 0);\n#endif\t\t\n        if (ret \u003c= 0) {\n            break;\n        }\n    }\n\n#ifdef _WIN32\n    acl_fiber_close(cfd);\n#else\n    close(cfd);\n#endif\n}\n\nint main(void) {\n    int event_mode = FIBER_EVENT_KERNEL;\n    size_t stack_size = 128000;\n\n    int i;\n\n#ifdef _WIN32\n    socket_init();\n#endif\n\n    for (i = 0; i \u003c 100; i++) {\n        acl_fiber_create(fiber_client, NULL, stack_size);\n    }\n\n    acl_fiber_schedule_with(event_mode);\n\n#ifdef _WIN32\n    socket_end();\n#endif\n\n    return 0;\n}\n```\n\n### 3.3 Resolve domain address in coroutine\n\nThe rfc1035 for DNS has been implement in libfiber, so you can call gethostbyname or getaddrinfo to get the givent domain's IP addresses in coroutine.\n```C\n#include \u003cstdio.h\u003e\n#include \u003cstdlib.h\u003e\n#include \u003cstring.h\u003e\n#include \u003cnetdb.h\u003e\n#include \"fiber/lib_fiber.h\"\n\nstatic void lookup(ACL_FIBER *fiber, void *ctx) {\n    char *name = (char *) ctx;\n    struct addrinfo hints, *res0;\n    int ret;\n\n    (void) fiber; // avoid compiler warning\n\n    memset(\u0026hints, 0, sizeof(hints));\n    hints.ai_family = PF_UNSPEC;\n    hints.ai_socktype = SOCK_STREAM;\n    hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;\n\n    ret = getaddrinfo(name, \"80\", \u0026hints, \u0026res0);\n    free(name);\n\n    if (ret != 0) {\n        printf(\"getaddrinfo error %s\\r\\n\", gai_strerror(ret));\n    } else {\n        printf(\"getaddrinfo ok\\r\\n\");\n        freeaddrinfo(res0);\n    }\n}\n\nint main(void) {\n    char *name1 = strdup(\"www.iqiyi.com\");\n    char *name2 = strdup(\"www.baidu.com\");\n\n    acl_fiber_create(lookup, name1, 128000);\n    acl_fiber_create(lookup, name2, 128000);\n\n    acl_fiber_schedule();\n    return 0;\n}\n```\n\n### 3.4 Create fiber with standard C++ API\n\nYou can create one coroutine with standard C++ API in libfiber:\n```C\n#include \u003ccstdio\u003e\n#include \"fiber/libfiber.hpp\"\n\nclass myfiber : public acl::fiber {\npublic:\n    myfiber() {}\n\nprivate:\n    ~myfiber() {}\n\nprotected:\n    // @override from acl::fiber\n    void run() {\n        printf(\"hello world!\\r\\n\");\n        delete this;\n    }\n};\n\nint main() {\n    for (int i = 0; i \u003c 10; i++) {\n        acl::fiber* fb = new myfiber();\n        fb-\u003estart();\n    }\n\n    acl::fiber::schedule();\n    return 0;\n}\n```\n\n### 3.5 Create fiber with C++1x API\n\nYou can also create one coroutine with c++11 API in libfiber:\n```C\n#include \u003ccstdio\u003e\n#include \"fiber/libfiber.hpp\"\n#include \"fiber/go_fiber.hpp\"\n\nstatic void fiber_routine(int i) {\n    printf(\"hi, i=%d, curr fiber=%u\\r\\n\", i, acl::fiber::self());\n}\n\nint main() {\n    for (int i = 0; i \u003c 10; i++) {\n        go[=] {\n            fiber_routine(i);\n        };\n    }\n\n    acl::fiber::schedule();\n    return 0;\n}\n```\n\n### 3.6 Create shared stack fiber\n\nYou can create fiber in shared stack mode to decrease the memory's size.\n```c++\n#include \u003ccstdio\u003e\n#include \u003ccstdlib\u003e\n#include \u003cmemory\u003e\n#include \"fiber/go_fiber.hpp\"\n\nvoid test_shared_stack() {\n   std::shared_ptr\u003cint\u003e count(new int);\n   for (int i = 0; i \u003c 10; i++) {\n       go_share(1024)[count] {\n           (*count)++;\n       }; \n   }\n   \n   acl::fiber::schedule();\n   printf(\"At last the count is %d\\r\\n\", *count);\n}\n\n```\n\n### 3.7 Sync between fibers and threads\n\nfiber_mutex can be used to sync between different fibers and threads:\n```c++\n#include \u003cthread\u003e\n#include \"fiber/go_fiber.hpp\"\n#include \"fiber/fiber_mutex.hpp\"\n\nvoid test_mutex() {\n    // Create one fiber mutex can be shared between different fibers and threads.\n    std::shared_ptr\u003cacl::fiber_mutex\u003e mutex(new acl::fiber_mutex);\n    \n    // Create one fiber to use fiber mutex.\n    go[mutex] {\n        mutex-\u003elock();\n        ::sleep(1);\n        mutex-\u003eunlock();\n    };\n\n    // Create one thread to use fiber mutex.\n    std::thread([mutex] {\n        mutex-\u003elock();\n        ::sleep(1);\n        mutex-\u003eunlock();\n    }).detach();\n\n    // Create one thread and one fiber in it to use fiber mutex.\n    std::thread([mutex] {\n        go[mutex] {\n            mutex-\u003elock();\n            ::sleep(1);\n            mutex-\u003eunlock();\n        };\n        acl::fiber::schedule();\n    }).detach();\n    \n    // Start the current thread's schedule.\n    acl::fiber::schedule();\n}\n```\n\n### 3.8 Transfer objects through box\n\nYou can use fiber_tbox or fiber_tbox2 to transfer objs between different fibers and threads:\n```c++\n#include \u003cmemory\u003e\n#include \u003cthread\u003e\n#include \"fiber/fiber_tbox.hpp\"\n\nclass myobj {\npublic:\n    myobj() = default;\n    ~myobj() = default;\n    void run() { printf(\"hello world!\\r\\n\"); }\n};\n\nvoid test_tbox() {\n    std::shared_ptr\u003cacl::fiber_tbox\u003cmyobj\u003e\u003e box(new acl::fiber_tbox\u003cmyobj\u003e);\n    go[box] {\n        myobj *o = box-\u003epop();\n        o-\u003erun();\n        delete o;\n    };\n    go[box] {\n        myobj *o = new myobj;\n        box-\u003epush(o);\n    };\n    \n    go[box] {\n        myobj *o = box-\u003epop();\n        o-\u003erun();\n        delete o;\n    };\n    std::thread thread([box] {\n        myobj *o = new myobj;\n        box-\u003epush(o);\n    });\n    thread.detach();\n}\n```\n\n### 3.9 Using wait_group to wait for the others done\n\nYou can use wait_group to wait for the other tasks:\n```c++\n#include \"fiber/go_fiber.hpp\"\n#include \"fiber/wait_group.hpp\"\n\nvoid wait_others() {\n    acl::wait_group wg;\n    wg.add(2);\n\n    std::thread thr([\u0026wg]{\n        ::sleep(1);\n        wg.done();\n    });\n    thr.detach();\n\n    go[\u0026wg] {\n        ::sleep(1);\n        wg.done();\n    };\n    \n    wg.wait();\n}\n```\n\n### 3.10 Using fiber_pool to execute different tasks\n\nYou can use fiber_pool to run multiple tasks with high performance:\n```c++\n#include \u003ccstdio\u003e                                                             \n#include \u003ccstdlib\u003e                                                             \n#include \u003cacl-lib/acl_cpp/lib_acl.hpp\u003e                                         \n#include \u003cacl-lib/fiber/libfiber.hpp\u003e\n\nstatic void mytest(acl::wait_group\u0026 sync, int i) {\n   printf(\"Task %d is running\\n\", i);\n   sync.done();\n}\n\nint main() {\n    // Create one fiber pool with min=1, max=20, idle=30s, buf=500, stack=64000.\n    acl::fiber_pool pool(1, 20, 30, 500, 64000, false);\n    acl::wait_group sync;\n    int i = 0;\n                                                                               \n    sync.add(1);\n    // Run the first task.\n    pool.exec([\u0026sync, i]() {\n        printf(\"Task %d is running\\n\", i);\n        sync.done();\n    });\n    i++;\n                                                                               \n    sync.add(1);\n    // Run the second task.\n    pool.exec([\u0026sync](int i) {\n       printf(\"Task %d is running\\n\", i);\n       sync.done();\n    }, i);\n    i++;\n\n    sync.add(1);\n    // Run the third task.\n    pool.exec(mytest, std::ref(sync), i);\n\n    // Create one fiber to wait for all tasks done and stop the fiber pool.\n    go[\u0026sync, \u0026pool] {\n        sync.wait();\n        pool.stop();\n    };\n\n    acl::fiber::schedule();\n    return 0;\n }\n```\n\n### 3.11 Wait for the result from a thread\n\n```C\n#include \u003ccstdio\u003e\n#include \u003cunistd.h\u003e\n#include \"fiber/go_fiber.hpp\"\n\nstatic void fiber_routine(int i) {\n    go_wait[\u0026] {\t// running in another thread\n        i += 100;\n        ::usleep(10000);\n    };\n\n    printf(\"i is %d\\r\\n\", i);\n}\n\nint main() {\n    // create ten fibers\n    for (int i = 0; i \u003c 10; i++) {\n        go[=] {\n            fiber_routine(i);\n        };\n    }\n\n    acl::fiber::schedule();\n    return 0;\n}\n```\n\n### 3.12 Http server supporting http url route\n\nOne http server written with libfiber and http module of [acl](https://github.com/acl-dev/acl) supports http handler route which is in [http server](https://github.com/acl-dev/acl/tree/master/lib_fiber/samples-c%2B%2B1x/httpd).\n\n```C\n#include \u003cacl-lib/acl_cpp/lib_acl.hpp\u003e          // must before http_server.hpp\n#include \u003cacl-lib/fiber/http_server.hpp\u003e\n\nstatic char *var_cfg_debug_msg;\nstatic acl::master_str_tbl var_conf_str_tab[] = {\n        { \"debug_msg\", \"test_msg\", \u0026var_cfg_debug_msg },\n        { 0, 0, 0 }\n};\n\nstatic int  var_cfg_io_timeout;\nstatic acl::master_int_tbl var_conf_int_tab[] = {\n        { \"io_timeout\", 120, \u0026var_cfg_io_timeout, 0, 0 },\n        { 0, 0 , 0 , 0, 0 }\n};\n\nint main(d) {\n    acl::acl_cpp_init();\n    acl::http_server server;\n\n    // set the configure variables\n    server.set_cfg_int(var_conf_int_tab)\n          .set_cfg_str(var_conf_str_tab);\n\n    // set http handler route\n    server.Get(\"/\", [](acl::HttpRequest\u0026, acl::HttpResponse\u0026 res) {\n        acl::string buf(\"hello world1!\\r\\n\");\n        res.setContentLength(buf.size());\n        return res.write(buf.c_str(), buf.size());\n    }).Post(\"/ok\", [](acl::HttpRequest\u0026 req, acl::HttpResponse\u0026 res) {\n        acl::string buf;\n        req.getBody(buf);\n        res.setContentLength(buf.size());\n        return res.write(buf.c_str(), buf.size());\n    }).Get(\"/json\", [\u0026](acl::HttpRequest\u0026, acl::HttpResponse\u0026 res) {\n        acl::json json;\n        acl::json_node\u0026 root = json.get_root();\n        root.add_number(\"code\", 200)\n            .add_text(\"status\", \"+ok\")\n            .add_child(\"data\",\n                json.create_node()\n                    .add_text(\"name\", \"value\")\n                    .add_bool(\"success\", true)\n                    .add_number(\"number\", 200));\n        return res.write(json);\n    });\n\n    // start the server in alone mode\n    server.run_alone(\"0.0.0.0|8194, 127.0.0.1|8195\", \"./httpd.cf\");\n    return 0;\n}\n```\n\n### 3.13 Windows GUI sample\n\nThere is one Windows GUI sample with libfiber in [directory](samples/c/WinEchod). The screenshot is ![here](res/winecho.png)  \n\nThe server coroutine and client coroutine are all running in the same thread as the GUI, so you can operate the GUI object in server and client coroutine without worrying about the memory collision problem. And you can write network process with sequence way, other than asynchronus callback way which is so horrible. With the libfirber for Windows GUI, the asynchronous API like CAsyncSocket should be discarded. The network APIs are intergrated with the Windows GUI seamlessly because the libfiber using GUI message pump as event driven internal.\n\n### 3.14 More SAMPLES\n\nYou can get more samples in [samples](samples/), which use many APIs in [acl project](https://github.com/acl-dev/acl/tree/master/lib_fiber/samples) library.\n## 4 BUILDING\n### 4.1 On Unix\n\n```\n$cd libfiber\n$make\n$cd samples\n$make\n```\n\n\u003cb\u003eThe simple Makefile shown below:\u003c/b\u003e\n\n```\nfiber_server: fiber_server.c\n\tgcc -o fiber_server fiber_server.c patch.c -I{path_of_fiber_header} -L{path_of_fiber_lib) -lfiber -ldl -lpthread\n\nfiber_client: fiber_client.c\n\tgcc -o fiber_client fiber_client.c patch.c -I{path_of_fiber_header} -L{path_of_fiber_lib) -lfiber -ldl -lpthread\n```\n\n### 4.2 On Windows\n\nYou can open the [fiber_vc2012.sln](c/fiber_vc2012.sln)/ [fiber_vc2013.sln](c/fiber_vc2013.sln)/[c/fiber_vc2015.sln](fiber_vc2015.sln) with vc2019, and build the libfiber library and the [samples](samples) included.\n\n## 5 Benchmark\n\nThe picture below show the IOPS (io echo per-second) benchmark written by libfiber, comparing with the samples writen by [libmill](https://github.com/sustrik/libmill), golang and [libco](https://github.com/Tencent/libco). The samples written by libmill and libco are in [directory](benchmark), the sample written by golang is in [here](https://github.com/acl-dev/master-go/tree/master/examples/echo), and the sample written by libfiber is in [server sample directory](samples/c/server). The testing client is in [here](https://github.com/acl-dev/acl/tree/master/lib_fiber/samples/client2) from the [acl project](https://github.com/acl-dev/acl/).\n\n![Benchmark](res/benchmark.png)\n\n## 6 API support  \n\n### 6.1 Base API\n\n- acl_fiber_create  \n- acl_fiber_self  \n- acl_fiber_status  \n- acl_fiber_kill   \n- acl_fiber_killed  \n- acl_fiber_signal  \n- acl_fiber_yield  \n- acl_fiber_ready  \n- acl_fiber_switch  \n- acl_fiber_schedule_init  \n- acl_fiber_schedule  \n- acl_fiber_schedule_with  \n- acl_fiber_scheduled  \n- acl_fiber_schedule_stop  \n- acl_fiber_set_specific  \n- acl_fiber_get_specific  \n- acl_fiber_delay  \n- acl_fiber_last_error  \n- acl_fiber_last_serror  \n\n### 6.2 IO API\n\n- acl_fiber_recv  \n- acl_fiber_recvfrom  \n- acl_fiber_read  \n- acl_fiber_readv  \n- acl_fiber_recvmsg  \n- acl_fiber_write  \n- acl_fiber_writev  \n- acl_fiber_send  \n- acl_fiber_sendto  \n- acl_fiber_sendmsg  \n- acl_fiber_select  \n- acl_fiber_poll  \n- acl_fiber_close  \n\n### 6.3 Net API\n\n- acl_fiber_socket  \n- acl_fiber_listen  \n- acl_fiber_accept  \n- acl_fiber_connect  \n- acl_fiber_gethostbyname_r\n- acl_fiber_getaddrinfo\n- acl_fiber_freeaddrinfo\n\n### 6.4 Channel API  \n\n- acl_channel_create  \n- acl_channel_free  \n- acl_channel_send  \n- acl_channel_send_nb  \n- acl_channel_recv  \n- acl_channel_recv_nb  \n- acl_channel_sendp  \n- acl_channel_recvp  \n- acl_channel_sendp_nb  \n- acl_channel_recvp_nb  \n- acl_channel_sendul  \n- acl_channel_recvul  \n- acl_channel_sendul_nb  \n- acl_channel_recvul_nb  \n\n### 6.5 Sync API\n\n\u003cb\u003eACL_FIBER_MUTEX\u003c/b\u003e  \n- acl_fiber_mutex_create  \n- acl_fiber_mutex_free  \n- acl_fiber_mutex_lock  \n- acl_fiber_mutex_trylock  \n- acl_fiber_mutex_unlock  \n\n\u003cb\u003eACL_FIBER_RWLOCK\u003c/b\u003e  \n- acl_fiber_rwlock_create  \n- acl_fiber_rwlock_free  \n- acl_fiber_rwlock_rlock  \n- acl_fiber_rwlock_tryrlock  \n- acl_fiber_rwlock_wlock  \n- acl_fiber_rwlock_trywlock  \n- acl_fiber_rwlock_runlock  \n- acl_fiber_rwlock_wunlock  \n\n\u003cb\u003eACL_FIBER_EVENT\u003c/b\u003e  \n- acl_fiber_event_create  \n- acl_fiber_event_free  \n- acl_fiber_event_wait  \n- acl_fiber_event_trywait  \n- acl_fiber_event_notify  \n\n\u003cb\u003eACL_FIBER_SEM\u003c/b\u003e  \n- acl_fiber_sem_create  \n- acl_fiber_sem_free  \n- acl_fiber_sem_wait  \n- acl_fiber_sem_post  \n- acl_fiber_sem_num  \n\n## 7 About API Hook\n\nOn Linux/BSD/Mac, many IO and Net APIs are hooked. So you can just use the System standard APIs in your applications with libfiber, the hooked APIs will be replaced with libfiber APIs. In this case, you can \u003cb\u003e`coroutine`\u003c/b\u003e your DB application with mysql driven and change nothing in mysql driven.  \nThe standard APIs been hooked are shown below:\n- close\n- sleep\n- read\n- readv\n- recv\n- recvfrom\n- recvmsg\n- write\n- writev\n- send\n- sendto\n- sendmsg\n- sendfile64\n- socket\n- listen\n- accept\n- connect\n- select\n- poll\n- epoll: epoll_create, epoll_ctl, epoll_wait\n- gethostbyname(_r)\n- getaddrinfo/freeaddrinfo\n\n## 8 FAQ\n\n1. \u003cb\u003eIs the coroutine schedule in multi-threads?\u003c/b\u003e  \nNo. The coroutine schedule of libfiber is in one single thread. But you can start multiple threads that one thread has one schedule process.  \n2. \u003cb\u003eHow are the multi-cores of CPU used?\u003c/b\u003e  \nmultiple threads can be started with its own coroutine schedule, each thread can ocpupy one CPU.  \n3. \u003cb\u003eHow does different threads mutex in coroutine schedule status?\u003c/b\u003e  \nEven though the OS system mutex APIs, such as pthread_mutex_t's APIs can be used, the ACL_FIBER_EVENT's APIs are recommended. It's safety when the OS system mutex APIs are used in short time without recursive invocation. But its unsafely using system mutex APIs in this case: One coroutine A1 of thread A had locked the thread-mutex-A, the coroutine A2 of thread A wanted to lock the thread-mutex-B which had been locked by one coroutine B1 of thread B, when the coroutine B2 of thread B wanted to lock the thread-mutex-A, thread deadlock happened! So, the coroutine mutex for threads and coroutines named ACL_FIBER_EVENT's APIs of libfiber were created, which can be used to make critical region between multiple coroutines in different threads(multiple continues in the same thread or not; it can also be used for different threads without coroutines).  \n4. \u003cb\u003eShould the mysql-driven source codes be changed when used with libfiber?\u003c/b\u003e  \nIn UNIX OS, the System IO APIs are hooked by libfiber, so nothing should be changed in mysql-driven.  \n5. \u003cb\u003eHow to avoid make the mysqld overloaded when many coroutines started?\u003c/b\u003e  \nThe ACL_FIBER_SEM's APIs can be used to protect the mysqld being overloaded by many connections of many coroutines. These APIs can limit the connections number to the mysqld from coroutines.  \n6. \u003cb\u003eDoes the DNS domain resolving block the coroutine schedule?\u003c/b\u003e  \nNo, because the System domain-resolving APIs such as gethostbyname(_r) and getaddrinfo are also hooked in libfiber.  \n","funding_links":[],"categories":["Projects"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Facl-dev%2Flibfiber","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Facl-dev%2Flibfiber","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Facl-dev%2Flibfiber/lists"}