libco 宏分析

c/c++巧用宏计算不定参数个数【不定参数】【宏】【#define】 背景 用过Go、py一类的可能都有所感受,对于不定参数的使用很多时候代码中真的很爽。让你原地起飞。 遗憾的是,c或者c++关于不定参数的使用实际是基于参数栈计算偏移获取值的一个过程。不过这也有好的一点,效率还是不错的。 其中最大的问题莫过于既然是计算便宜我们在不定参函数内部是不知道参数的个数的,因此我们必须使用参数也好传值或者其他间接传值让函数内部的参数长度得到指定,之后才可以愉快地取参。 正题开始 但是,c或者cplus里存在一个叫... 阅读详情
// 下面是从libco中导出的宏
#include <iostream>
using namespace std;

/*
	以下是计算参数的个数,最多支持7个参数
*/
#define comac_get_args_cnt( ... ) comac_arg_n( __VA_ARGS__ )
#define comac_arg_n( _0,_1,_2,_3,_4,_5,_6,_7,N,...) N
#define comac_args_seqs() 7,6,5,4,3,2,1,0
#define comac_join_1( x,y ) x##y // 将两个名字变成一个字符串"xy"

#define comac_argc( ... ) comac_get_args_cnt( 0,##__VA_ARGS__,comac_args_seqs() )
#define comac_join( x,y) comac_join_1( x,y )

// 以下是用作重复,fun是下面typeof中的一种,重复次数取决去参数个数
#define repeat_0( fun,a,... ) 
#define repeat_1( fun,a,... ) fun( 1,a,__VA_ARGS__ ) repeat_0( fun,__VA_ARGS__ )
#define repeat_2( fun,a,... ) fun( 2,a,__VA_ARGS__ ) repeat_1( fun,__VA_ARGS__ )
#define repeat_3( fun,a,... ) fun( 3,a,__VA_ARGS__ ) repeat_2( fun,__VA_ARGS__ )
#define repeat_4( fun,a,... ) fun( 4,a,__VA_ARGS__ ) repeat_3( fun,__VA_ARGS__ )
#define repeat_5( fun,a,... ) fun( 5,a,__VA_ARGS__ ) repeat_4( fun,__VA_ARGS__ )
#define repeat_6( fun,a,... ) fun( 6,a,__VA_ARGS__ ) repeat_5( fun,__VA_ARGS__ )

#define repeat( n,fun,... ) comac_join( repeat_,n )( fun,__VA_ARGS__)

// 以下是功能
/*
	decl_typeof宏的作用是为参数类型取别名
	impl_typeof 是创建对应类型的引用
	impl_typeof_cpy 是创建类型对象
	con_param_typeof 是创建变量名
	param_init_typeof 是通过初始化列表初始化变量
*/
#if __cplusplus <= 199711L
#define decl_typeof( i,a,... ) typedef typeof( a ) typeof_##a;
#else
#define decl_typeof( i,a,... ) typedef decltype( a ) typeof_##a;
#endif
#define impl_typeof( i,a,... ) typeof_##a & a;
#define impl_typeof_cpy( i,a,... ) typeof_##a a;
#define con_param_typeof( i,a,... ) typeof_##a & a##r,
#define param_init_typeof( i,a,... ) a(a##r),


#define co_ref( name,... ) \
repeat( comac_argc(__VA_ARGS__) ,decl_typeof,__VA_ARGS__ ) \
class type_##name \
{ \
public: \
	repeat( comac_argc(__VA_ARGS__) ,impl_typeof,__VA_ARGS__ ) \
	int _member_cnt; \
	type_##name( \
		repeat( comac_argc(__VA_ARGS__),con_param_typeof,__VA_ARGS__ ) ... ): \
		repeat( comac_argc(__VA_ARGS__),param_init_typeof,__VA_ARGS__ ) _member_cnt(comac_argc(__VA_ARGS__)) \
	{} \
} name( __VA_ARGS__ )


int main(int argc, char **argv)
{
    int total = 100;
	co_ref(ref, total);

    cout << ref.total << endl;
    cout << comac_argc( 0, 1, 2) << endl;
    return 0;
}

运行后结果
在这里插入图片描述

// 预处理后
typedef decltype( total ) typeof_total;
class type_ref {
public: 
  typeof_total & total; 
  int _member_cnt; 
  type_ref( typeof_total & totalr, ... ): total(totalr), _member_cnt(1) {}
} ref( total );

cout << ref.total << endl;
cout << 3 << endl;

下面详细解释下如何计算参数个数的

// 重点就在这三个宏
#define comac_get_args_cnt( ... ) comac_arg_n( __VA_ARGS__ )
#define comac_arg_n( _0,_1,_2,_3,_4,_5,_6,_7,N,...) N
#define comac_args_seqs() 7,6,5,4,3,2,1,0

// 这个宏是为了方便使用而写的
#define comac_argc( ... ) comac_get_args_cnt( 0,##__VA_ARGS__,comac_args_seqs())

原理就是占位,前面的参数占位后,会将comac_args_seqs()往后移动,占用几位会移动几位
这样就会使用N永远对应着正确的数字,如果想要在增加想要计算的参数个数,可以如下
#define comac_arg_n( _0,_1,_2,_3,_4,_5,_6,_7,_8, N,...) N
#define comac_args_seqs() 8,7,6,5,4,3,2,1,0
comac_get_args_cnt( 0,##__VA_ARGS__,comac_args_seqs())这个宏的第一个参数是0,意味着当无参数时会主动占用一位,此时N对应的正好是0

// 下面一步一步的展示预处理结果
comac_argc(); // 无参情况下计算参数个数
// 预处理
comac_get_args_cnt(0, comac_args_seqs())
// 预处理
//comac_arg_n(_0,_1,_2,_3,_4,_5,_6,_7, N,...)
  comac_arg_n( 0, 7, 6, 5, 4, 3, 2, 1, 0);
// 此时N对应的数字正好是0,所以comac_argc()返回的结果就是0
// 当为一个参数时
comac_argc("Hello World");

comac_get_args_cnt(0,"Hello World", comac_args_seqs());

//comac_arg_n(_0,            _1,_2,_3,_4,_5,_6,_7, N,...)
  comac_arg_n( 0, "Hello World", 7, 6, 5, 4, 3, 2, 1, 0);

// 此时N对应的数字正好是1

后记
当第一次看见这个宏时还不清楚是干什么的,所以未在意,但是在读源码过程中发现必须得先清楚的了解这个宏后才能继续读,所以进行了分析。起初是先自行分析,发现进展不大,就写代码,预处理
但是对于comac_argc这个宏来说预处理结果就是一个数字,所以自己只能通过一步一步的替换来分析,好在功夫不负有心人,弄明白了。最后再说下libco写下这个宏的作用,其实上述是经过我删减的,libco中co_func是一个函数宏,就是给定函数名,函数体由自己实现,这个宏的作用是为协程创建闭包用的

int total = 100;
vector<int> v2;
co_ref(ref, total, v2, m);
for (int i = 0; i < 10; i++)
{
	co_func(f, ref, i)
	{
		printf("tid: %d; ref.total %d i %d\n", gettid(), ref.total, i);
		// lock
		pthread_mutex_lock(&ref.m);
		ref.v2.push_back(i);
		pthread_mutex_unlock(&ref.m);
		// unlock
	}
	co_func_end;
	v.push_back(new f(ref, i));
}
C++利用宏实现统计运行时间工具 背景 OSRM backend 代码中有一个timing_util.hpp的头文件,利用宏以及c++11 chrono 实现了统计代码运行时间的工具。 在工程中统计代码运行时间非常常用,本文介绍OSRM timing_util的实现原理,并用示例来说明。 实现解析 #ifndef TIMING_UTIL_HPP #define TIMING_UTIL_HPP #include &amp;amp;amp;lt... 阅读详情

相关推荐

libco源代码分析(01) -- Closure源代码分析

libco中提供了一份简单的闭包实现。代码片段一:#ifndef __CO_CLOSURE_H__ #define __CO_CLOSURE_H__ struct stCoClosure_t { public: virtual void exec() = 0; };

MakeZero的博客 1400

C++利用不定参数宏计算不定参数的个数

C++利用不定参数宏函数计算输入参数的个数。

weixin_43354152的博客 680

Libco 分析笔记

libco 是腾讯的一款开源库,在通读其中主要的 co_routine.c 文件后,我按照自己的理解和知识体系做了总结。

m0_37749564的博客 777

xpack宏魔法揭秘:XPACK宏展开原理与C++模板元编程实战

xpack 是一个纯头文件的开源 C++ 序列化库,只需在结构体末尾写一行 XPACK 宏,就能让 C++ 结构体与 JSON、XML、YAML、BSON 等格式自由互转。本文为你揭秘 XPACK 宏展开原理,并手把手带你实战 C++ 模板元编程——从参数计数宏到 SFINAE 编译期调度,读懂这套"零反射"宏魔法的完整运作机制。 ## 一行宏的魔力:xpack 到底做了什么 先看 xpack

gitblog_00650的博客 411

libco example_cond.cpp分析

腾讯libco库的example分析 可以参考https://github.com/zhoudayang/libco example_cond.cpp /* 生产者消费者模型 */ #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <queue> #inc...

qq_38391187的博客 333

AI驱动Spine骨骼动画生成:从图像拆分到动画自动化的全流程解析

计算机视觉与生成式AI技术正深度赋能传统数字内容生产流程。在2D动画制作领域,骨骼动画技术通过模拟真实生物关节运动,实现了角色动画的高效制作与灵活控制。其核心原理在于将角色拆分为独立部件,通过骨骼层级关系驱动部件变换,结合关键帧插值算法生成流畅动作。这项技术的工程价值在于大幅降低动画制作门槛,提升内容生产效率,尤其适用于游戏开发、影视预演、广告设计等需要快速原型迭代的场景。本文聚焦于如何利用SIFT特征匹配、RANSAC几何验证等CV算法实现部件自动对位,并结合动画12原则的程序化实现,构建从单张角色立绘到

weixin_28696185的博客 1519

libco简介

好久都没在优快云上发博客了,大概两年了吧,看着以前写的博客,感觉自己更像是个前端工程师了,其实工作上我应该算是后端的吧。最近换了一份工作,新公司用到一个叫Colib的库,也在GitHub上开源了,虽然开源之后并没有人怎么维护,但这里面的代码的确也在线上用,这里面的思想也是挺有趣儿的,就研究了一下,也算是和后端相关了 https://github.com/Tencent/libco  1. 协...

ZZ的博客 1万+

LCD工程师必看:Pixelclock、Mipi Clk计算全解析(附实用公式)

本文为LCD工程师详细解析了像素时钟(Pixelclock)与MIPI时钟(Mipi Clk)的核心计算方法。文章从时序参数构成入手,通过实战公式推导,系统阐述了从屏幕分辨率、刷新率到最终MIPI速率的高效计算链路,并提供了实用的调试思路与排查清单,帮助工程师快速解决画面撕裂、闪烁等常见问题。

weixin_29266679的博客 388

C++ libco 介绍与应用

文章目录导论准备知识协程的背景libco 使用简介libco 协程关键数据结构及其关系libco 协程的生命周期事件驱动与协程调度libco 总结 导论   使用 C++ 来编写高性能的网络服务器程序,从来都不是一件很容易的事。   在没有应用任何网络框架的情况下,从 epoll/kqueue 直接码起的时候更是如此。即便使用 libevent、libev 这样事件驱动的网络框架去构建你的服务,程序结构依然不会简单。   为何会这样?因为这类框架提供的都是非阻塞式的、异步的编程方式,这需要思维方式的转变。

qq_41033011的博客 6559

Java后端中的链路追踪:使用OpenTelemetry实现全链路监控

在现代的微服务架构中,链路追踪是监控和优化系统性能的关键技术。通过链路追踪,我们可以跟踪请求在系统中的流转,识别性能瓶颈,定位问题根源。本文将介绍如何在Java后端应用中使用OpenTelemetry实现全链路监控,包括具体的实现步骤和代码示例。通过集成OpenTelemetry,您可以实现全面的链路追踪,帮助您识别瓶颈和潜在问题,从而提升系统的可靠性和用户体验。OpenTelemetry是一个开源项目,旨在提供统一的工具集来收集、处理和导出应用程序的遥测数据,包括跟踪、度量和日志。

聚娃科技开发者博客 1727

Win10家庭版中文用户名改英文全攻略:从注册表到环境变量一步不落

本文详细介绍了Windows 10家庭版中文用户名改为英文的完整流程,包括注册表编辑、环境变量调整等关键步骤。通过激活管理员账户、重命名用户文件夹、修改注册表键值等操作,彻底解决因中文路径导致的软件兼容性问题,并提供常见错误解决方案和系统维护建议。

weixin_29227425的博客 427

腾讯Libco协程开源库 源码分析(一)---- 下载Libco 编译安装 尝试运行示例代码

文章目录 前引 腾讯Libco协程开源库 源码分析(一)---- 下载Libco 编译安装 尝试运行示例代码 1、获得Libco源代码 2、编译Libco 得到示例文件 1、cmake编译 2、makefile 编译 3、尝试运行示例文件 浅看一下示例代码 1、example_echosvr.cpp 2、尝试运行example_echosvr 结束语......

Love 6's Private Blog 2170

openEuler 欧拉 安装Oracle19c数据库RPM包安装

欧拉系统安装部署oracle 19c rpm方式

陈苏漾的IT生涯 6893

libco

1.libco协程客户端 场景如下: tcp_sever:接受客户端连接,处理客户端请求,5s后回包,模拟rpc阻塞式调用服务 tcp_client:连接tcp服务器,发送请求,等待回包,这里qps! 0.2/s libco_echocli:连接tcp服务器,起n个协程,qps! 0.2*n/s 注意: 1)这里把tcp_server的处理时间设置为了5分钟,所以libco库的读写超时...

aa838260772的专栏 510

波克 上海 Unity开发笔试题 2024

主要分为四部分,如果没有准备好,不要点击笔试链接,进入就会自动开始。

z2014z的博客 3394

NSX-T 4.1部署搭建

NSX-T4.1 部署搭建

weixin_58250887的博客 564

协程库libco学习使用入门示例

简介 libco是微信后台大规模使用的c/c++协程库,2013年至今稳定运行在微信后台的数万台机器上。 libco通过仅有的几个函数接口 co_create/co_resume/co_yield 再配合 co_poll,可以支持同步或者异步的写法,如线程库一样轻松。同时库里面提供了socket族函数的hook,使得后台逻辑服务几乎不用修改逻辑代码就可以完成异步化改造。 libco是一个源码简洁而...

Arbboter的专栏 7829

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

libco协程切换原理详解

一 备用知识 之前不止一次的把libco的源码下下来看,但是每次看到协程切换汇编部分都放弃了,大学那点仅有的汇编基础也忘的一干二净,更不堪的是百度搜到的libco相关文章也看不懂,最近决定静下心来看一些相关的东西,终于像啃骨头一样把这块东西搞明白了。在网下阅读之前请先务必看懂下面的内容。 第一部分 汇编基础 1 CSAPP阅读笔记-汇编语言初探(数据传送类指令):CSAPP阅读笔记-汇编语言初探(数据传送类指令) 2 CSAPP阅读笔记-汇编语言初探(算术和逻辑操作类指令)...

D_Guco的专栏 2425

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

libco example_echosvr.cpp分析

参考 程序分析 /* **读取客户端的请求,然后按原样返回给客户端 */ #include "co_routine.h" #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <sys/time.h> #include <stack> #incl...

qq_38391187的博客 312

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

腾讯Libco协程开源库 源码分析 全系列总结博客

文章目录 前引 腾讯Libco协程开源库 源码分析 全系列总结博客 前引 由于这段时间准备面试 看到面经中有问到协程的问题 在此之前 我没有接触过协程 听闻C++20 中有协程库 而且也听闻腾讯微信竟然在用自己开发的协程库 支持单机千万并发 于是就花了接近一天的时间研究了协程库 发现代码长度也不长 于是自己就写下了这三篇博客 后面可能等找到实习后 自己会按照Libco的实现思路 实现一个协程库 那这篇就写到这里吧 腾讯Libco协程开源......

Love 6's Private Blog 1612

libco协程库原理解析与应用

       最近在准备一个libco协程库原理简析与应用的分享,顺便就整理下写个博客,一方面加深下自己对协程库的理解,另一方面也希望能对想了解协程的学者有所帮助。废话不多说了,言归正传吧。        想去剖析libco协程库的实现原理,首先我们要了解下什么是协程。维基百科上给协程的定义是协程(coroutine)又称微线程,是一个无优先级的子程序(函数)调度组件,允许子程序在特定的地方挂起和...

hhyjiayou的博客 3632

libco —— 协程调度(libco终章)

文章目录协程的阻塞和线程的阻塞主协程和协程调度的关系再看协程的挂起和恢复执行参考文献 呼,整个libco库终于快是要剖析完了。整个人算是对协程以及操作系统的调度有了新的认识。 协程的阻塞和线程的阻塞 之前的博客,我们分析了libco的协程从创建到启动,挂起以及最后退出的一个过程。同时,我们也认识到,协程本质的执行是串行的。 在之前协程的安装与使用中,我们提到了一个生产者消费者例子。在producer协程函数中,最后会调用poll函数等待一秒,comsumer函数也会调用co_cond_timedwait函数

0 error(s) 972

libco简要分析(待更)

文章目录源码分析co_routine.h 本篇分析分为两个部分。libco源码分析。libco例子分析。首先进行源码的分析。 分析之前需要了解一下前置知识 1.什么是协程? 2.什么是共享栈? 源码分析思路:对每个.h.cpp进行分析,先分析.h再分析对应的.cpp。 建议阅读顺序:结构体->与结构体关系紧密的函数->其他函数 建议例子和源码分析一起阅读,阅读体验更佳。另外参考了大量其...

practer的博客 333

libco源码学习解读

libco源码学习解读 简介 顺着上一篇文章示例,这里对文章中所涉及的函数及数据类型逐一进行深入分析,以期深入学习理解libco的实现原理,帮助我们加深对协程的理解,并帮助我们更加有效地使用libco协程库并排查问题。 创建协程co_create 该函数用于创建一个协程对象,其实现源码如下: int co_create(stCoRoutine_t** ppco, const stCoRoutine...

Arbboter的专栏 1038

[libco] libco 定时器(时间轮)

libco 定时器核心数据结构:数组 + 链表,有点像哈希表,通过空间换时间。libco 定时器也被称为时间轮,我们看看这个 “轮” 是怎么转的。 文章来源: [libco] libco 定时器(时间轮) 1. 概述 libco 定时器核心数据结构:数组 + 双向链表(左图)。 数组以毫秒为单位,默认大小 60 * 1000,主要保存一分钟以内到期的事件数据。相同到期时间的事件,会保存在双向链表里,当时间到期时,到期事件链表会一起取出来。 当然超过一分钟的到期事件也支持保存,通过取模路由,有

wenfh2020的专栏 662
上一篇: STUN协议简介
下一篇: C++代码规范
山有木兮啊
博客等级 码龄8年 135粉丝 132原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值