C++ 中文周刊 第139期

2024-07-30 14:43:22 浏览数 (2)

周刊项目地址[1]

RSS https://github.com/wanghenshui/cppweeklynews/releases.atom

欢迎投稿,推荐或自荐文章/软件/资源等

请提交 issue[3]

最近在找工作准备面试题,更新可能有些拖沓,见谅

本周内容比较少

本期文章由 Amnesia Captain 黄亮 Anein Jerry 赞助

资讯

标准委员会动态/ide/编译器信息放在这里

编译器信息最新动态推荐关注hellogcc公众号 OSDT Weekly 2023-11-22 第229期

boost 有个scope库正在评审中 https://lastique.github.io/scope/libs/scope/doc/html/scope/scope_guards.html

简单来说又是个scope guard

文章

  • • A Concise Introduction to Coroutines by Dian-Lun Lin[4]

还是coroutine介绍。懂得可以跳过了

代码语言:javascript复制
#include <coroutine>
#include <iostream>

struct MyCoroutine {                             // (1)
    struct promise_type {
        MyCoroutine get_return_object() {
            return std::coroutine_handle<promise_type>::from_promise(*this);
        }
        std::suspend_always initial_suspend() {
            return {};
        }
        std::suspend_always final_suspend() noexcept {
            return {};
        }
void return_void() {}
        void unhandled_exception() {}
    };
    MyCoroutine(std::coroutine_handle<promise_type> handle): handle{handle} {}
    
    void resume() { 
        handle.resume(); 
    }
    void destroy() { 
        handle.destroy(); 
    }
    
    std::coroutine_handle<promise_type> handle;
};

MyCoroutine simpleCoroutine() {                      // (2)
    std::cout << "Start coroutinen";
    co_await std::suspend_always{};
    std::cout << "Resume coroutinen";
}

int main() {
    MyCoroutine coro = simpleCoroutine();
    std::cout << "Coroutine is not executed yetn";
    coro.resume();
    std::cout << "Suspend coroutinen";
    coro.resume();
    coro.destroy();
    return 0;
}

实际上是这样的,注意对应关系。还是比较简单的

代码语言:javascript复制
MyCoroutine simpleCoroutine() {
    MyCoroutine::promise_type p();
    MyCoroutine coro_obj = p.get_return_object();

    try {
      co_await p.inital_suspend();
      std::cout << "Start coroutinen";
      co_await std::suspend_always{};
      std::cout << "Resume coroutinen";
    } catch(...) {
      p.unhandled_exception();
    }
    co_await p.final_suspend();
}
代码语言:javascript复制

理解Awaitable,suspend_always就是内建的一个简单awaitable

代码语言:javascript复制
struct suspend_always {
    constexpr bool await_ready() const noexcept { return false; }
    constexpr void await_suspend(coroutine_handle<>) const noexcept {}
    constexpr void await_resume() const noexcept {}
};
代码语言:javascript复制

co_await suspend_always 相当于

代码语言:javascript复制
auto&& awaiter = std::suspend_always{};
  if(!awaiter.await_ready()) {
    awaiter.await_suspend(std::coroutine_handle<>...);
    //<suspend/resume>
  }
awaiter.await_resume();
代码语言:javascript复制

这样最重要的co_await功能大概你就明白了

好了,来点复杂的

代码语言:javascript复制
#include <coroutine>
#include <iostream>
#include <queue>


struct Task {

  struct promise_type {
    std::suspend_always initial_suspend() noexcept { return {}; }
    std::suspend_always final_suspend() noexcept { return {}; }

    Task get_return_object() { 
        return std::coroutine_handle<promise_type>::from_promise(*this); 
    }
    void return_void() {}
    void unhandled_exception() {}
  };

  Task(std::coroutine_handle<promise_type> handle): handle{handle} {}

  auto get_handle() { return handle; }

  std::coroutine_handle<promise_type> handle;
};
class Scheduler {

  std::queue<std::coroutine_handle<>> _tasks;

  public: 

    void emplace(std::coroutine_handle<> task) {
      _tasks.push(task);
    }

    void schedule() {
      while(!_tasks.empty()) {
        auto task = _tasks.front();
        _tasks.pop();
        task.resume();

        if(!task.done()) { 
          _tasks.push(task);
        }
        else {
          task.destroy();
        }
      }
    }
    auto suspend() {
      return std::suspend_always{};
    }
};


Task TaskA(Scheduler& sch) {
  std::cout << "Hello from TaskAn";
  co_await sch.suspend();
  std::cout << "Executing the TaskAn";
  co_await sch.suspend();
  std::cout << "TaskA is finishedn";
}

Task TaskB(Scheduler& sch) {
  std::cout << "Hello from TaskBn";
  co_await sch.suspend();
  std::cout << "Executing the TaskBn";
  co_await sch.suspend();
  std::cout << "TaskB is finishedn";
}
int main() {
  std::cout << 'n';
  Scheduler sch;
  sch.emplace(TaskA(sch).get_handle());
  sch.emplace(TaskB(sch).get_handle());
  std::cout << "Start scheduling...n";
  sch.schedule();
  std::cout << 'n';
}

可以了。你已经入门了。接下来可以看seastar代码了

或者先看这个 https://github.com/andreasbuhr/cppcoro

  • • Formatting Custom types with std::format from C 20[5]

简单玩法

代码语言:javascript复制
struct Color {
   uint8_t r{ 0 };
   uint8_t g{ 0 };
   uint8_t b{ 0 };
};
template <>
struct std::formatter<Color> {
   constexpr auto parse(std::format_parse_context& ctx) {
       return ctx.begin();
   }

   auto format(const Color& col, std::format_context& ctx) const {
       return std::format_to(ctx.out(), "({}, {}, {})", col.r, col.g, col.b);
   }
};

恐怖玩法

代码语言:javascript复制
template <>
struct std::formatter<Color> : std::formatter<string_view> {
    auto format(const Color& col, std::format_context& ctx) const {
        std::string temp;
        std::format_to(std::back_inserter(temp), "({}, {}, {})", 
                       col.r, col.g, col.b);
        return std::formatter<string_view>::format(temp, ctx);
    }
};

满头大汗玩法

代码语言:javascript复制
template <>
struct std::formatter<Color> {
    constexpr auto parse(std::format_parse_context& ctx){
        auto pos = ctx.begin();
        while (pos != ctx.end() && *pos != '}') {
            if (*pos == 'h' || *pos == 'H')
                isHex_ = true;
              pos;
        }
        return pos;  // expect `}` at this position, otherwise, 
                      // it's error! exception!
    }

    auto format(const Color& col, std::format_context& ctx) const {
        if (isHex_) {
            uint32_t val = col.r << 16 | col.g << 8 | col.b;
            return std::format_to(ctx.out(), "#{:x}", val);
        }
        
        return std::format_to(ctx.out(), "({}, {}, {})", col.r, col.g, col.b);
    }

    bool isHex_{ false };
};

// std::cout << std::format("col {}n", Color{ 100, 200, 255 });
// std::cout << std::format("col {:h}n", Color{ 100, 200, 255 });
// col (100, 200, 255)
// col #64c8ff
  • • C needs undefined behavior, but maybe less[6]

c 和编译器结合太深了。但有些知识并不是都知道,导致错误触发未定义行为

  • • 现代C 性能优化[7]

这个基本上是去年cppcon的总结,挺好的。值得看看,基本名词都点到了

  • • C 20使用pfr库遍历[8]

这个pfr magic_get希望大家都掌握。起码嘴了十几次了

  • • 基于 Glibc 版本升级的 DolphinDB 数据查询性能优化实践[9]

patchelf实践还是比较少见的。挺有意思

  • • Struct initialization[10]
代码语言:javascript复制
#include <iostream>
#include <string>

struct S {
    int m_num;
    std::string m_text;
};

int main() {
    S s{42};
    std::cout << "s.m_num: " << s.m_num << ", s.m_text: " << s.m_text << 'n';
}

这种构造有字段没初始化,加告警-Wmissing-field-initializers

开源项目介绍

  • • asteria[11] 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线

最近进展,发现自旋竟然比metux还慢,还在研究,改掉原子锁性能提升明显

感觉和业务相关

  • • Unilang[12] deepin的一个通用编程语言,点子有点意思,也缺人,感兴趣的可以github讨论区或者deepin论坛看一看。这里也挂着长期推荐了
  • • https://gitee.com/okstar-org/ok-edu-desktop 一个IM通信软件,做IM的可以关注,现在正在做全面整合阶段,开始组建商业团队阶段,年底开始融资,你参加了就快发财了,会的快来
  • • https://github.com/sharkdp/minicpp 基于inotify的一个repl c 环境

简单说就是你的文件更改了 触发inotify 然后 回调一下make

这可比cling简单多了

  • • https://github.com/batterycenter/embed

又一个embed库。std::embed还没影呢,凑活用的东西

  • • https://github.com/stephenberry/glaze

很快,但没有和sonic-cpp的对比。我本来想比一下

我折腾了半天sonic-cpp编译。ubuntu 2204 zen4. 各种编不过。放弃了我靠

跑了glaze自带的压测

比yyjson快。性能不错,和simdjson也有一拼。另外就是还用上了最新反射技术。实践挺深的

数据贴这里[13],感兴趣的自己看吧

招聘

无锡编译期HPC AI创业 需要会LLVM gcc的 https://mp.weixin.qq.com/s/qkwjICB_fzzMJErXmbKBBw

互动环节

哎,再也不喝冰美式。一宿没睡着我靠,发现楼下凌晨一点炒米粉,离谱

之前收集了一波读者投票,关于周更其余实践插一些别的内容

能看到大家投票的重点在代码介绍代码走读。这里搞点素材给大家逼逼两句。类似lighting talk,5页10页ppt

另外也收集收集大家的其他意见以及投稿。能投稿广告收益都给你。咱们公众号每篇文章稳定收益7块,加个鸡腿没啥问题

本周内容不多啊,还是希望大家多多互动

引用链接

[1] 周刊项目地址: https://github.com/wanghenshui/cppweeklynews [2] 手机qq点击进入: https://qm.qq.com/q/6NGizNPyG4 [3] 提交 issue: https://github.com/wanghenshui/cppweeklynews/issues [4] A Concise Introduction to Coroutines by Dian-Lun Lin: https://www.modernescpp.com/index.php/a-concise-introduction-to-coroutines-by-dian-lun-li/ [5] Formatting Custom types with std::format from C 20: https://www.cppstories.com/2022/custom-stdformat-cpp20/ [6] C needs undefined behavior, but maybe less: https://www.think-cell.com/en/career/devblog/cpp-needs-undefined-behavior-but-maybe-less [7] 现代C 性能优化: https://zhuanlan.zhihu.com/p/663843832 [8] C 20使用pfr库遍历: https://zhuanlan.zhihu.com/p/668536219 [9] 基于 Glibc 版本升级的 DolphinDB 数据查询性能优化实践: https://zhuanlan.zhihu.com/p/667724630 [10] Struct initialization: https://www.sandordargo.com/blog/2023/11/22/struct-initialization [11] asteria: https://github.com/lhmouse/asteria [12] Unilang: https://github.com/linuxdeepin/unilang [13] 数据贴这里: https://github.com/wanghenshui/wanghenshui.github.io/issues/97

0 人点赞