1. 0

coost is an elegant and efficient cross-platform C++ base library. Its goal is to create a sword of C++ to make C++ programming easy and enjoyable.

coost is like boost, but more lightweight, the static library built on linux or mac is only about 1MB in size. However, it still provides enough powerful features:

  • Command line and config file parser (flag)
  • High performance log library (log)
  • Unit testing framework
  • go-style coroutine
  • Coroutine-based network library
  • Efficient JSON library
  • JSON RPC framework
  • Atomic operation (atomic)
  • Efficient stream (fastream)
  • Efficient string (fastring)
  • String utility (str)
  • Time library (time)
  • Thread library (thread)
  • Timed Task Scheduler
  • God-oriented programming
  • LruMap
  • hash library
  • path library
  • File utilities (fs)
  • System operations (os)
  • Fast memory allocator
Documents Core features
God-oriented programming

co/god.h provides some features based on templates.

#include "co/god.h"

void f() {
    god::align_up<8>(31); // -> 32
    god::is_same<T, int, bool>(); // T is int or bool?

flag is a command line and config file parser. It is similar to gflags, but more powerful:

  • Support parameters from both command-line and config file.
  • Support automatic generation of the config file.
  • Support flag aliases.
  • Flag of integer type, the value can take a unit k,m,g,t,p.
#include "co/flag.h"
#include "co/cout.h"

DEF_bool(x, false, "x");
DEF_bool(debug, false, "dbg", d);
DEF_uint32(u, 0, "xxx");
DEF_string(s, "", "xx");

int main(int argc, char** argv) {
    flag::init(argc, argv);
    COUT << "x: " << FLG_x;
    COUT << "y: " << FLG_y;
    COUT << "debug: " << FLG_debug;
    COUT << "u: " << FLG_u;
    COUT << FLG_s << "|" << FLG_s.size();
    return 0;

In the above example, the macros start with DEF_ define 4 flags. Each flag corresponds to a global variable, whose name is FLG_ plus the flag name. The flag debug has an alias d. After building, the above code can run as follow:

./xx                  # Run with default configs
./xx -x -s good       # x -> true, s -> "good"
./xx -debug           # debug -> true
./xx -xd              # x -> true, debug -> true
./xx -u 8k            # u -> 8192

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

log is a high-performance log library, some components in coost use it to print logs.

log supports two types of logs: one is level log, which is divided into 5 levels: debug, info, warning, error and fatal, printing a fatal log will terminate the program; the other is topic log, logs are grouped by topic, and logs of different topics are written to different files.

#include "co/log.h"

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

    TLOG("xx") << "s" << 23; // topic log
    DLOG << "hello " << 23;  // debug
    LOG << "hello " << 23;   // info
    WLOG << "hello " << 23;  // warning
    ELOG << "hello " << 23;  // error
    FLOG << "hello " << 23;  // fatal

    return 0;

co/log also provides a series of CHECK macros, which is 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..";

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

#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. The main function is simple as below:

#include "co/unitest.h"

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

The directory unitest contains the unit test code in coost. Users can run unitest with the following commands:

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

In coost v3.0, Json provides fluent APIs, which is more convenient to use.

// {"a":23,"b":false,"s":"123","v":[1,2,3],"o":{"xx":0}}
Json x = {
    { "a", 23 },
    { "b", false },
    { "s", "123" },
    { "v", {1,2,3} },
    { "o", {
        {"xx", 0}

// equal to x
Json y = Json()
    .add_member("a", 23)
    .add_member("b", false)
    .add_member("s", "123")
    .add_member("v", Json().push_back(1).push_back(2).push_back(3))
    .add_member("o", Json().add_member("xx", 0));

x.get("a").as_int();       // 23
x.get("s").as_string();    // "123"
x.get("s").as_int();       // 123, string -> int
x.get("v", 0).as_int();    // 1
x.get("v", 2).as_int();    // 3
x.get("o", "xx").as_int(); // 0

x["a"] == 23;          // true
x["s"] == "123";       // true
x.get("o", "xx") != 0; // false

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

  • Support 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.
  • There is a flat relationship between coroutines, and new coroutines can be created from anywhere (including in coroutines).
  • Support coroutine synchronization events, coroutine locks, channels, and waitgroups.
#include "co/co.h"

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

    co::WaitGroup wg;

        LOG << "hello world";

        LOG << "hello again";

    return 0;

In the above code, the coroutines created by go() will be evenly distributed to different scheduling threads. Users can also control the scheduling of coroutines by themselves:

// run f1 and f2 in the same scheduler
auto s = co::next_scheduler();

// run f in all schedulers
for (auto& s : co::schedulers()) {
network programming

coost provides a coroutine-based network programming framework, which can be roughly divided into 3 parts:

  • coroutineized socket API, similar in form to the system socket API, users familiar with socket programming can easily write high-performance network programs in a synchronous manner.
  • TCP, HTTP, RPC and other high-level network programming components, compatible with IPv6, also support SSL, it is more convenient to use than socket API.
  • System API hook, with which, third-party network libraries can be used directly in coroutines.

RPC server

#include "co/co.h"
#include "co/rpc.h"
#include "co/time.h"

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

        .add_service(new xx::HelloWorldImpl)
        .start("", 7788, "/xx");

    for (;;) sleep::sec(80000);
    return 0;

rpc::Server also supports HTTP protocol, you may use the POST method to call the RPC service:

curl --request POST --data '{"api":"ping"}'

Static web server

#include "co/flag.h"
#include "co/http.h"

DEF_string(d, ".", "root dir"); // docroot for the web server

int main(int argc, char** argv) {
    flag::init(argc, argv);
    so::easy(FLG_d.c_str()); // mum never have to worry again
    return 0;

HTTP server

void cb(const http::Req& req, http::Res& res) {
    if (req.is_method_get()) {
        if (req.url() == "/hello") {
            res.set_body("hello world");
        } else {
    } else {
        res.set_status(405); // method not allowed

// http
http::Server().on_req(cb).start("", 80);

// https
    "", 443, "privkey.pem", "certificate.pem"

HTTP client

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

    LOG << "response code: "<< c.status();
    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.status();

  1. 3

    Not sure if you can use the story description to promote the content, @pushcx? (Reason: Please don’t use the story text to write comments.). The below linked reddit thread also goes in to a bit of self-promotion suggestion that the repository has bought stars / forks.

    Quiting a reddit comment: https://www.reddit.com/r/cpp/comments/xxoz29/coost_a_fantastic_c_library/

    FriendlyRollOfSushi - 3 hr. ago

    Holy Bjarne on a bicycle.

    There is this amusing trend that codebases where everything is named “fast” are often the slowest ones by far, ones where everything is “safe” tend to barely work at all, etc. Looks like this library is no exception. I looked at one class and its parents so far, and it was one heck of a ride:

    • fastring. Okay, a bit foreshadowing…

    • No SSO in any way, shape, or form, because who needs performance anyway? We named it fast, it should be enough, right?

    • Crashes on self-appends. But that’s okay, it’s named fast, not working.

    • No asserts anywhere where you typically expect them, like front() etc. I guess the user is expected to call god::bless_no_bugs(); a few more times instead if they want to debug anything.

    • safe_clear(), just like the naming convention suggests, won’t do it’s only job if the compiler figures out that we are about to deallocate the memory (I didn’t check whether deallocation is currently obfuscated enough to avoid optimizing memset out). Stuff like SecureZeroMemory exists for a reason.

    • resize() doesn’t clear the memory if the size was increased. 0 lines of documentation to note this anywhere. Okay.

    • ensure() potentially overflows in if (_cap < _size + n), because of course it does. We have the invariant _size <= _cap, so if (_cap - _size < n) would work correctly and always be safe, and it’s neither longer nor slower, but, like… Sigh…

    • Mutating c_str() that invalidates data(). What’s even funnier, is that the terminating zero counts against the capacity, so if you had 100 bytes of data, reserved for exactly 100 symbols, appended and called c_str(), it will reallocate. Presumably the way to avoid this is to sprinkle + 1 everywhere manually on the user’s side. I like how the file is named fast.h.

    • What makes it absolutely hilarious is that find()/rfind() are also mutating and invalidating pointers (they call c_str() internally), potentially including the one you used for the search. I don’t even.

    • operator= re-constructs the string in-place without destroying it first. The standard is probably like: “Am I a joke to you?”

    • O(s.size()) cost of s == s for any fastring s. Gotta go fast.

    • O(strlen(b)) cost of operator<(const fastring& a, const char* b) even against an empty a. This one is a bit of a nitpick, because who uses const char* in 2022 outside of the context of communicating with legacy APIs anyway.

    Speaking of comparators. How on Earth did we end up with emitting two memcmp calls inside one operator< everywhere? I’m not even mad, that’s bloody impressive.

    I don’t know if it’s a self-promotion post, but:

    • If it’s not, please consider reviewing the code before advertising it as “fantastic”. Although it is fantastic in its own ways.

    • If it is a self-promotion post, then, well, good luck. god::bless_no_bugs(); is funny, though, so kudos for that.

    1. 2

      I don’t know if it’s a self-promotion post, but:

      It says ‘authored by’ in the submission and the github username of the project matches the submitter, so I’m fairly confident it is. The author has submitted six things here and three have been links to things that they’ve worked on, two have been a replies to comments on their submitted stories, only one has been about something that isn’t self promotion, so I’m going to lean towards spammer.

      If it is a self-promotion post, then, well, good luck. god::bless_no_bugs(); is funny, though, so kudos for that.

      I honestly thought that this was satire. The ‘god mode’ bits looked like a joke, some of the rest of the code is astonishingly bad. I clicked on a few random files and each one had a WTF in the first place I randomly scrolled to.