Skip to content
/ co Public
forked from idealvin/coost

A golang-style C++ coroutine library and more.

License

Notifications You must be signed in to change notification settings

nishuihan/co

 
 

Repository files navigation

Basic (中文)

CO is an elegant and efficient C++ base library that supports Linux, Windows and Mac platforms. It pursues simplicity and efficiency, and does not rely on third-party libraries such as boost, and provides optional support for ssl, http and https with libcurl & openssl.

CO includes coroutine library, network library, log library, command line and configuration file parsing library, unit test framework, json library, etc.

Documents

Highlights

Coroutine (co)

co is a golang-style C++ coroutine library with the following features:

  • Multi-thread scheduling, the default number of threads is the number of system CPU cores.

  • Coroutines share the thread stack (default size is 1MB), and the memory footprint is low, a single machine can easily create millions of coroutines.

  • System api hook (Linux & Mac).

  • Coroutine lock co::Mutex.

  • Coroutine synchronization event co::Event.

  • Coroutine Pool co::Pool.

  • Coroutineized socket API.

  • create coroutine with go():

    void f() {
        LOG << "hello world";
    }
    
    void g(int v) {
        LOG << "hello "<< v;
    }
    
    go(f);
    go(g, 777);

Network (so)

so is a C++ network library based on coroutines. It provides a general ipv6-compatible TCP framework and implements a simple json-based rpc framework, and also provides an optional support for HTTP, HTTPS and SSL.

  • Simple static web server

    #include "co/flag.h"
    #include "co/log.h"
    #include "co/so.h"
    
    DEF_string(d, ".", "root dir"); // Specify the root directory of the web server
    
    int main(int argc, char** argv) {
        flag::init(argc, argv);
        log::init();
    
        so::easy(FLG_d.c_str()); // mum never have to worry again
    
        return 0;
    }
  • http server (openssl required for https)

    http::Server serv;
    
    serv.on_req(
        [](const http::Req& req, http::Res& res) {
            if (req.is_method_get()) {
                if (req.url() == "/hello") {
                    res.set_status(200);
                    res.set_body("hello world");
                } else {
                    res.set_status(404);
                }
            } else {
                res.set_status(405); // method not allowed
            }
        }
    );
    
    serv.start("0.0.0.0", 80);                                    // http
    serv.start("0.0.0.0", 443, "privkey.pem", "certificate.pem"); // https
  • http client (libcurl & zlib required)

    http::Client c("http://127.0.0.1:7777"); // http
    http::Client c("https://github.com");    // https, openssl required
    c.add_header("hello", "world");          // add headers here
    
    c.get("/");
    LOG << "response code: "<< c.response_code();
    LOG << "body size: "<< c.body_size();
    LOG << "Content-Length: "<< c.header("Content-Length");
    LOG << c.header();
    
    c.post("/hello", "data xxx");
    LOG << "response code: "<< c.response_code();

Log library (log)

log is a high-performance local log system.

  • Print logs

    LOG << "hello " << 23; // info
    DLOG << "hello" << 23; // debug
    WLOG << "hello" << 23; // warning
    ELOG << "hello again"; // error
  • Performance vs glog

    log vs glog google glog co/log
    win2012 HHD 1.6MB/s 180MB/s
    win10 SSD 3.7MB/s 560MB/s
    mac SSD 17MB/s 450MB/s
    linux SSD 54MB/s 1023MB/s

The above table is the test result of one million info logs (about 50 bytes each) continuously printed by a single thread. The co/log is almost two orders of magnitude faster than glog.

Why is it so fast? The first is that it is based on fastream that is 8-25 times faster than sprintf. The second is that it has almost no memory allocation operations.

Command line and configuration file parsing (flag)

flag is a convenient and easy-to-use command line and configuration file parsing library that supports automatic generation of configuration files.

  • Code example

    #include "co/flag.h"
    
    DEF_int32(i, 32, "comments");
    DEF_string(s, "xxx", "string type");
    
    int main(int argc, char** argv) {
        flag::init(argc, argv);
        std::cout << "i: "<< FLG_i << std::endl;
        std::cout << "s: "<< FLG_s << std::endl;
        return 0;
    }
  • Build and run

    ./xx                         # start with default config values
    ./xx -i=4k -s="hello world"  # integer types can take units k,m,g,t,p, non-case sensitive
    ./xx -i 4k -s "hello world"  # same as above
    ./xx --mkconf                # generate configuration file xx.conf
    ./xx xx.conf                 # start from configuration file
    ./xx -config xx.conf         # start from configuration file

json

json is an easy-to-use, high-performance json library. The latest version stores the Json object in a piece of contiguous memory, nearly no memory allocation is needed during pasing Json from a string, which greatly improves the parsing speed(GB per second).

  • Code example
    #include "co/json.h"
    
    // Json: {"hello":"json", "array":[123, 3.14, true, "nice"]}
    json::Root r;
    r.add_member("hello", "json");        // add key:value pair
    
    json::Value a = r.add_array("array"); // add key:array
    a.push_back(123, 3.14, true, "nice"); // push value to array, accepts any number of parameters
    
    COUT << a[0].get_int();               // 123
    COUT << r["array"][0].get_int();      // 123
    COUT << r["hello"].get_string();      // "json"
    
    fastring s = r.str();                 // convert Json to string
    fastring p = r.pretty();              // convert Json to human-readable string
    json::Root x = json::parse(s);        // parse Json from a string

Code composition

  • co/include

    Header files of libco.

  • co/src

    Source files of libco.

  • co/test

    Some test codes, each .cc file will be compiled into a separate test program.

  • co/unitest

    Some unit test codes, each .cc file corresponds to a different test unit, and all codes will be compiled into a single test program.

  • co/gen

    A code generation tool automatically generates rpc framework code according to the proto file.

Building

xmake

CO recommends using xmake as the build tool.

  • Compiler

  • Install xmake

    For windows, mac and debian/ubuntu, you can go directly to the release page of xmake to get the installation package. For other systems, please refer to xmake's Installation instructions.

    Xmake disables compiling as root by default on linux. ruki says it is not safe. You can add the following line to ~/.bashrc to enable it:

    export XMAKE_ROOT=y
  • Quick start

    # All commands are executed in the root directory of co (the same below)
    xmake      # build libco and gen by default
    xmake -a   # build all projects (libco, gen, co/test, co/unitest)
  • build libco

    xmake build libco     # build libco only
    xmake -b libco        # same as above
  • build and run unitest code

    co/unitest contains some unit test codes, which are used to check the correctness of the functionality of libco.

    xmake build unitest    # build can be abbreviated as -b
    xmake run unitest -a   # run all unit tests
    xmake r unitest -a     # same as above
    xmake r unitest -os    # run unit test os
    xmake r unitest -json  # run unit test json
  • build and run test code

    co/test contains some test codes. You can easily add a source file like xxx.cc in the directory co/test or its subdirectories, and then run xmake build xxx to build it.

    xmake build flag             # flag.cc
    xmake build log              # log.cc
    xmake build json             # json.cc
    xmake build rpc              # rpc.cc
    xmake build easy             # so/easy.cc
    
    xmake r flag -xz             # test flag
    xmake r log                  # test log
    xmake r log -cout            # also log to terminal
    xmake r log -perf            # performance test
    xmake r json                 # test json
    xmake r rpc                  # start rpc server
    xmake r rpc -c               # start rpc client
    xmake r easy -d xxx          # start web server
  • build gen

    # It is recommended to put gen in the system directory (e.g. /usr/local/bin/).
    xmake build gen
    gen hello_world.proto

    Proto file format can refer to hello_world.proto.

  • Installation

    # Install header files, libco, gen by default.
    xmake install -o pkg         # package related files to the pkg directory
    xmake i -o pkg               # the same as above
    xmake install -o /usr/local  # install to the /usr/local directory

cmake

izhengfan helped provide cmake support:

  • By default, only libco and gen are build.

  • The library files are in the build/lib directory, and the executable files are in the build/bin directory.

  • You can use BUILD_ALL to compile all projects.

  • You can use CMAKE_INSTALL_PREFIX to specify the installation directory.

    mkdir build && cd build
    cmake ..
    cmake .. -DBUILD_ALL=ON -DCMAKE_INSTALL_PREFIX=pkg
    make -j8
    make install

License

The MIT license. CO contains codes from some other projects, which have their own licenses, see details in LICENSE.md.

Special thanks

  • The code of co/context is from tbox by ruki, special thanks!
  • The English reference documents of CO are translated by Leedehai (1-10), daidai21 (11-15) and google, special thanks!
  • ruki has helped to improve the xmake building scripts, thanks in particular!
  • izhengfan provided cmake building scripts, thank you very much!

Donate

Goto the Donate page.

About

A golang-style C++ coroutine library and more.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C++ 88.6%
  • Assembly 9.3%
  • C 1.2%
  • Other 0.9%