All Projects → idealvin → Co

idealvin / Co

Licence: other
Art of C++. Flag, logging, unit-test, json, go-style coroutine and more.

Programming Languages

C++
36643 projects - #6 most used programming language
assembly
5116 projects
c
50402 projects - #5 most used programming language
CMake
9771 projects
lua
6591 projects
Makefile
30231 projects

Projects that are alternatives of or similar to Co

cocoyaxi
A go-style coroutine library in C++11 and more.
Stars: ✭ 2,392 (+5.65%)
Mutual labels:  config, ssl, rpc, coroutine, unit-test, libco
Getty
a netty like asynchronous network I/O library based on tcp/udp/websocket; a bidirectional RPC framework based on JSON/Protobuf; a microservice framework based on zookeeper/etcd
Stars: ✭ 532 (-76.5%)
Mutual labels:  rpc, json-rpc, json, tcp
Airframe
Essential Building Blocks for Scala
Stars: ✭ 442 (-80.48%)
Mutual labels:  rpc, config, json, command-line-parser
Izumi
Productivity-oriented collection of lightweight fancy stuff for Scala toolchain
Stars: ✭ 423 (-81.32%)
Mutual labels:  rpc, config, logging
Jstp
Fast RPC for browser and Node.js based on TCP, WebSocket, and MDSF
Stars: ✭ 132 (-94.17%)
Mutual labels:  rpc, json, tcp
Microwebsrv2
The last Micro Web Server for IoTs (MicroPython) or large servers (CPython), that supports WebSockets, routes, template engine and with really optimized architecture (mem allocations, async I/Os). Ready for ESP32, STM32 on Pyboard, Pycom's chipsets (WiPy, LoPy, ...). Robust, efficient and documented!
Stars: ✭ 295 (-86.97%)
Mutual labels:  web-server, ssl, https
libcorpc
Libcorpc is a high performance coroutine base RPC framework
Stars: ✭ 20 (-99.12%)
Mutual labels:  rpc, coroutine, libco
Logstash Logger
Ruby logger that writes logstash events
Stars: ✭ 442 (-80.48%)
Mutual labels:  json, tcp, logging
Log4rs
A highly configurable logging framework for Rust
Stars: ✭ 483 (-78.67%)
Mutual labels:  json, logging, log
Simpletcp
Simple wrapper for TCP client and server in C# with SSL support
Stars: ✭ 99 (-95.63%)
Mutual labels:  rpc, tcp, ssl
Beetlex
high performance dotnet core socket tcp communication components, support TLS, HTTP, HTTPS, WebSocket, RPC, Redis protocols, custom protocols and 1M connections problem solution
Stars: ✭ 802 (-64.58%)
Mutual labels:  tcp, ssl, https
Logger json
JSON console backend for Elixir Logger.
Stars: ✭ 108 (-95.23%)
Mutual labels:  json, logging, log
Stubmatic
Mock HTTP calls without coding. Designed specially for testing and testers.
Stars: ✭ 118 (-94.79%)
Mutual labels:  ssl, tcp, https
Hp Socket
High Performance TCP/UDP/HTTP Communication Component
Stars: ✭ 4,420 (+95.23%)
Mutual labels:  tcp, ssl, https
FuckDPI V2
FuckDPIv2 can fuck the Korean Government's internet censorship by fragmenting SSL ClientHello.
Stars: ✭ 44 (-98.06%)
Mutual labels:  ssl, tcp, https
Jsonrpc
The jsonrpc package helps implement of JSON-RPC 2.0
Stars: ✭ 143 (-93.68%)
Mutual labels:  rpc, json-rpc, json
SuperSimpleTcp
Simple wrapper for TCP client and server in C# with SSL support
Stars: ✭ 263 (-88.38%)
Mutual labels:  ssl, tcp, rpc
server-framework
纯C的分布式服务器框架通用模板,跨平台,模块动态加载,tcp/可靠UDP,协程RPC,日志,集群建立
Stars: ✭ 24 (-98.94%)
Mutual labels:  tcp, coroutines, rpc
Libjson Rpc Cpp
C++ framework for json-rpc (json remote procedure call)
Stars: ✭ 653 (-71.16%)
Mutual labels:  rpc, json-rpc, json
Fenix
A simple and visual static web server with collaboration features.
Stars: ✭ 1,559 (-31.14%)
Mutual labels:  web-server, ssl, https
A go-style C++ coroutine library and more.

Basic (中文)

CO is an elegant and efficient C++ base library that supports Linux, Windows and Mac platforms. It implements a series of high-quality base components, such as go-style coroutine, coroutine-based network programming framework, command line parameter and config file parsing library, high-performance log library, unit testing framework, JSON library, etc.

Sponsor

If you like CO, you may consider becoming a sponsor, or make me a cup of coffee. Thanks very much!

Special sponsors

CO is specially sponsored by the following companies, thank you very much!

Documents

Core features

Coroutine

CO has implemented a go-style coroutine, which has the following features:

  • Multi-thread scheduling, the default number of threads is the number of system CPU cores.
  • Shared stack, coroutines in the same thread share several stacks (the default size is 1MB), and the memory usage is low. Simple test on Linux shows that 10 millions of coroutines only take 2.8G of memory (for reference only).
  • There is a flat relationship between coroutines, and new coroutines can be created from anywhere (including in coroutines).
  • Support system API hook (Windows/Linux/Mac), you can directly use third-party network library in coroutine.
  • Coroutineized socket API.
  • Coroutine synchronization event co::Event.
  • Coroutine lock co::Mutex.
  • Coroutine pool co::Pool.
  • channel co::Chan.
  • waitgroup co::WaitGroup.

Create a coroutine

go(ku);           // void ku();
go(f, 7);         // void f(int);
go(&T::f, &o);    // void T::f(); T o;
go(&T::f, &o, 7); // void T::f(int); T o;
go([](){
    LOG << "hello go";
});

The above is an example of creating coroutines with go(). go() is a function that accepts 1 to 3 parameters. The first parameter f is any callable object, as long as f(), (*f)(), f(p), (*f)(p), (o->*f)() or (o->*f)(p) can be called.

The coroutines created by go() will be evenly distributed to different scheduling threads. If users want some coroutines to run in the same thread, they can create coroutines in the following way:

auto s = co::next_scheduler();
s->go(f1);
s->go(f2);

If users want to create coroutine in all scheduling threads, the following way can be used:

auto& s = co::all_schedulers();
for (size_t i = 0; i < s.size(); ++i) {
    s[i]->go(f);
}

channel

co::Chan, similar to the channel in golang, can be used to transfer data between coroutines.

#include "co/co.h"

DEF_main(argc, argv) {
    co::Chan<int> ch;
    go([ch]() {
        ch << 7;
    });

    int v = 0;
    ch >> v;
    LOG << "v: " << v;

    return 0;
}

The read and write operations of channel must be performed in coroutine, so the main function is defined with DEF_main in above code, so that code in the main function also runs in coroutine.

The channel object in the code is on the stack, while CO uses a shared stack implementation. Data on the stack of one coroutine may be overwritten by other coroutines. Generally, we cann't share data on stack between coroutines. Therefore, we capture by value in the lambda to copy the channel and pass it to the newly created coroutine. The copy operation just increases the internal reference count by 1 and will not affect the performance.

When creating a channel, we can add a timeout as follows:

co::Chan<int> ch(8, 1000);

After read or write operation, we can call co::timeout() to determine whether it has timed out. This method is simpler than the select-based implementation in golang.

The channel in CO is implemented based on memory copy. The data type passed can be a built-in type, a pointer type, or a structure type with simple memory copy semantics for the copy operation. Like std::string or container types in STL, the copy operation is not a simple memory copy, and generally cannot be passed directly in channel. For details, see Document of co::Chan.

waitgroup

co::WaitGroup, similar to sync.WaitGroup in golang, can be used to wait for the exit of coroutines or threads.

#include "co/co.h"

DEF_main(argc, argv) {
    FLG_cout = true;

    co::WaitGroup wg;
    wg.add(8);

    for (int i = 0; i < 8; ++i) {
        go([wg]() {
            LOG << "co: " << co::coroutine_id();
            wg.done();
        });
    }

    wg.wait();
    return 0;
}

network programming

CO provides a set of coroutineized socket APIs, most of them are consistent with the native socket APIs in form. In addition, CO has also implemented higher-level network programming components, including TCP, HTTP and RPC framework based on JSON, they are IPv6-compatible and support SSL at the same time, which is more convenient than socket APIs. Here is just a brief demonstration of the usage of HTTP, and the rest can be viewed in the documents.

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

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

void f() {
    http::Client c("https://github.com");

    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();
}

go(f);

co/flag

co/flag is a simple and easy-to-use command line and config file parsing library. Some components in CO use it to define config items.

co/flag provides a default value for each config item. Without config parameters, the program can run with the default config. Users can also pass in config parameters from command line or config file. When a config file is needed, users can run ./exe -mkconf to generate a config file.

// xx.cc
#include "co/flag.h"
#include "co/cout.h"

DEF_bool(x, false, "bool x");
DEF_bool(y, false, "bool y");
DEF_uint32(u32, 0, "...");
DEF_string(s, "hello world", "string");

int main(int argc, char** argv) {
    flag::init(argc, argv);

    COUT << "x: "<< FLG_x;
    COUT << "y: "<< FLG_y;
    COUT << "u32: "<< FLG_u32;
    COUT << FLG_s << "|" << FLG_s.size();

    return 0;
}

The above is an example of using co/flag. The macro at the beginning of DEF_ in the code defines 4 config items. Each config item is equivalent to a global variable. The variable name is FLG_ plus the config name. After the above code is compiled, it can be run as follows:

./xx                  # Run with default configs
./xx -xy -s good      # single letter named bool flags, can be set to true together
./xx -s "I'm ok"      # string with spaces
./xx -u32 8k          # Integers can have units: k,m,g,t,p, not case sensitive

./xx -mkconf          # Automatically generate a config file: xx.conf
./xx xx.conf          # run with a config file
./xx -config xx.conf  # Same as above

co/log

co/log is a high-performance and memory-friendly local log library, which nearly needs no memory allocation. Some components in CO will use it to print logs.

co/log divides the log into five levels: debug, info, warning, error, and fatal. Printing a fatal level log will terminate the program. Users can print logs of different levels as follows:

DLOG << "hello " << 23; // debug
LOG << "hello " << 23;  // info
WLOG << "hello " << 23; // warning
ELOG << "hello " << 23; // error
FLOG << "hello " << 23; // fatal

co/log also provides a series of CHECK macros, which can be regarded as an enhanced version of assert, and they will not be cleared in debug mode.

void* p = malloc(32);
CHECK(p != NULL) << "malloc failed..";
CHECK_NE(p, NULL) << "malloc failed..";

When the CHECK assertion failed, co/log will print the function call stack information, and then terminate the program. On linux and macosx, make sure you have installed libbacktrace on your system.

stack

co/log is very fast. The following are some test results, for reference only:

  • co/log vs glog (single thread)

    platform 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
  • co/log vs spdlog (Windows)

    threads total logs co/log time(seconds) spdlog time(seconds)
    1 1000000 0.103619 0.482525
    2 1000000 0.202246 0.565262
    4 1000000 0.330694 0.722709
    8 1000000 0.386760 1.322471
  • co/log vs spdlog (Linux)

    threads total logs co/log time(seconds) spdlog time(seconds)
    1 1000000 0.096445 2.006087
    2 1000000 0.142160 3.276006
    4 1000000 0.181407 4.339714
    8 1000000 0.303968 4.700860

co/unitest

co/unitest is a simple and easy-to-use unit test framework. Many components in CO use it to write unit test code, which guarantees the stability of CO.

#include "co/unitest.h"
#include "co/os.h"

namespace test {
    
DEF_test(os) {
    DEF_case(homedir) {
        EXPECT_NE(os::homedir(), "");
    }

    DEF_case(cpunum) {
        EXPECT_GT(os::cpunum(), 0);
    }
}
    
} // namespace test

The above is a simple example. The DEF_test macro defines a test unit, which is actually a function (a method in a class). The DEF_case macro defines test cases, and each test case is actually a code block. Multiple test units can be put in the same C++ project, the main function is simple as below:

#include "co/unitest.h"

int main(int argc, char** argv) {
    flag::init(argc, argv);
    unitest::run_all_tests();
    return 0;
}

co/unitest contains the unit test code in CO. Users can run unitest with the following commands:

xmake r unitest -a   # Run all test cases
xmake r unitest -os  # Run test cases in the os unit

Code composition

  • co/include

    Header files of libco.

  • co/src

    Source files of libco.

  • co/test

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

  • co/unitest

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

  • co/gen

    A code generator for the RPC framework.

Building

Compilers required

xmake

co recommends using xmake as the build tool.

Quick start

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

Build shared library

xmake f -k shared
xmake -v

Build with mingw

xmake f -p mingw
xmake -v

Enable HTTP & SSL features

xmake f --with_libcurl=true --with_openssl=true
xmake -a

Install libco

# Install header files and libco 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

Install libco from xmake repo

xrepo install -f "openssl=true,libcurl=true" co

cmake

izhengfan helped to provide cmake support:

Build libco by default

mkdir build && cd build
cmake ..
make -j8

Build all projects

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

Build with libcurl & openssl (openssl 1.1.0 or above required)

mkdir build && cd build
cmake .. -DBUILD_ALL=ON -DCMAKE_INSTALL_PREFIX=/usr/local
make -j8
make install

Build shared library

cmake .. -DBUILD_SHARED_LIBS=ON

install libco from vcpkg

vcpkg install co:x64-windows

# HTTP & SSL support
vcpkg install co[libcurl,openssl]:x64-windows

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!
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].