libevent - Macro function
TAILQ_INIT
/** Tail queue functions.* 尾队列的头结点初始化为空队列。*/
#define TAILQ_INIT(head) do { \(head)->tqh_first = NULL; \(head)->tqh_last = &(head)->tqh_first; \
} while (/*CONSTCOND*/0)
TAILQ_INIT 宏是一个用于初始化尾队列头部的工具,它通过将 tqh_first 设置为 NULL 并将 tqh_last 设置为指向 tqh_first 的地址,确保队列可以从空状态正确地过渡到非空状态。这个设计使用了二级指针的概念,使得尾部插入操作更为高效和直接。这种结构广泛应用于需要动态管理链表的系统编程场景中。
do { ... } while (0):
-
这种结构确保了宏在使用时会像一个普通的语句一样执行,而不会引起语法错误。例如,用户可以安全地在
if语句中使用这个宏,而不会因为缺少大括号导致错误 -
(head)->tqh_first = NULL;:- 初始化
tqh_first为NULL,表示队列当前没有任何元素,是空的。
- 初始化
-
(head)->tqh_last = &(head)->tqh_first;:- 初始化
tqh_last使其指向tqh_first的地址。这样做的目的是为了方便在队列末尾进行插入操作。具体来说,如果队列是空的,tqh_last会指向tqh_first,这意味着下一次插入的元素将成为新的第一个元素
- 初始化
EVUTIL_ASSERT
#define EVUTIL_ASSERT(cond) \do { \if (EVUTIL_UNLIKELY(!(cond))) { \event_errx(EVENT_ERR_ABORT_, \"%s:%d: Assertion %s failed in %s", \__FILE__,__LINE__,#cond,__func__); \/* In case a user-supplied handler tries to */ \/* return control to us, log and abort here. */ \(void)fprintf(stderr, \"%s:%d: Assertion %s failed in %s", \__FILE__,__LINE__,#cond,__func__); \abort(); \} \} while (0)
EVUTIL_ASSERT 是一个用于断言条件的宏,在条件不满足时会中止程序运行,并打印相关的调试信息。
do { ... } while (0) 结构:
-
这是一个常见的宏包装技巧,用于确保宏在使用时能够像普通语句一样执行,不会因为缺少分号或其他语法问题导致错误。
if (EVUTIL_UNLIKELY(!(cond))) { ... }: -
EVUTIL_UNLIKELY是一个宏或函数,通常用于提示编译器某个条件不太可能发生,这可以帮助编译器优化代码。这里的意思是,如果条件cond为false(即条件不满足),则执行后续代码。
event_errx(EVENT_ERR_ABORT_, "%s:%d: Assertion %s failed in %s", __FILE__, __LINE__, #cond, __func__);: -
event_errx是一个函数,用于打印错误信息并终止程序。它会输出文件名(__FILE__)、行号(__LINE__)、断言失败的条件(#cond),以及当前函数的名称(__func__)。 -
#cond是将cond转换为字符串的预处理器操作,这样可以打印出具体的条件表达式。 -
EVENT_ERR_ABORT_通常是一个预定义的常量,用于指示错误类型,
fprintf(stderr, "%s:%d: Assertion %s failed in %s", __FILE__, __LINE__, #cond, __func__);: -
在调用
event_errx后,再次使用fprintf将相同的错误信息输出到标准错误输出(stderr)。这是为了防止用户自定义的错误处理程序可能试图返回控制权,确保错误信息一定会被输出。
最后,调用abort()函数立即终止程序的执行。abort()会导致程序异常退出,并生成一个核心转储(如果系统配置允许)
void event_errx(int eval, const char *fmt, ...)
{va_list ap;// 初始化可变参数列表va_start(ap, fmt);// 使用可变参数列表将格式化的错误信息输出到日志event_logv_(EVENT_LOG_ERR, NULL, fmt, ap);va_end(ap);// 结束可变参数处理// 退出程序并返回指定的错误码event_exit(eval);
}
该函数是可变参函数,相关注解见: [[可变参数]]
voidevent_logv_(int severity, const char *errstr, const char *fmt, va_list ap){char buf[1024];size_t len;if (severity == EVENT_LOG_DEBUG && !event_debug_get_logging_mask_())return;if (fmt != NULL)evutil_vsnprintf(buf, sizeof(buf), fmt, ap);elsebuf[0] = '\0';if (errstr) {len = strlen(buf);if (len < sizeof(buf) - 3) {evutil_snprintf(buf + len, sizeof(buf) - len, ": %s", errstr);}}event_log(severity, buf);}
EVBASE_ACQUIRE_LOCK N_ACTIVE_CALLBACKS
/** Lock an event_base, if it is set up for locking. Acquires the lockin the base structure whose field is named 'lockvar'. */
#define EVBASE_ACQUIRE_LOCK(base, lockvar) do { \EVLOCK_LOCK((base)->lockvar, 0); \} while (0)
#define N_ACTIVE_CALLBACKS(base) \((base)->event_count_active) //最大事件数量
/** Largest number of priorities that Libevent can support. */
#define EVENT_MAX_PRIORITIES 256
/**Set the number of different event prioritiesBy default Libevent schedules all active events with the same priority.However, some time it is desirable to process some events with a higherpriority than others. For that reason, Libevent supports strict priorityqueues. Active events with a lower priority are always processed beforeevents with a higher priority.The number of different priorities can be set initially with theevent_base_priority_init() function. This function should be calledbefore the first call to event_base_dispatch(). Theevent_priority_set() function can be used to assign a priority to anevent. By default, Libevent assigns the middle priority to all eventsunless their priority is explicitly set.Note that urgent-priority events can starve less-urgent events: afterrunning all urgent-priority callbacks, Libevent checks for more urgentevents again, before running less-urgent events. Less-urgent eventswill not have their callbacks run until there are no events more urgentthan them that want to be active.@param eb the event_base structure returned by event_base_new()@param npriorities the maximum number of priorities@return 0 if successful, or -1 if an error occurred@see event_priority_set()
TAILQ_ENTRY
//通过使用 TAILQ_ENTRY 宏,可以为指定的数据类型创建一个双向链表的入口和出口结构体,方便在链表中进行插入、删除和遍历等操作。
#define _TAILQ_ENTRY(type, qual) \
struct { \qual type *tqe_next; /* next element */ \qual type *qual *tqe_prev; /* address of previous next element */\
}
#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,)
qual 用于指定链表结构体成员的修饰符(它可以是 const、volatile 或其他限定符。)
-
tqe_next:指向链表中下一个元素的指针。 -
tqe_prev:指向链表中上一个元素的指针的地址。这里使用了一个指向指针的指针,即二级指针,用于在删除元素时修改前一个元素的tqe_next指针。
TAILQ_HEAD
#define TAILQ_HEAD(name, type) \
struct name { \struct type *tqh_first; /* 指向链表的第一个元素 */ \struct type **tqh_last; /* 指向链表的最后一个元素的指针的指针 */ \
}
TAILQ_HEAD 是用于定义双向链表头结构的宏,使得管理链表的操作更加简单
-
tqh_first: 指向链表的第一个元素。对于空链表,它是NULL。 -
tqh_last: 指向链表的最后一个元素的指针的指针。在链表的最后一个元素中,tqh_last指向链表中最后一个元素的指针(也就是指向该元素的指针的指针)。对于空链表,它指向&tqh_first,即链表头结构中的tqh_first。
EVBASE_NEED_NOTIFY
/** Return true iff we need to notify the base's main thread about changes to* its state, because it's currently running the main loop in another* thread. Requires lock. */#define EVBASE_NEED_NOTIFY(base) \
(evthread_id_fn_ != NULL && \(base)->running_loop && \(base)->th_owner_id != evthread_id_fn_())
-
evthread_id_fn_: 一个函数指针,用于获取当前线程的 ID。它用于确定事件循环是否在另一个线程中运行。 -
(base)->running_loop: 表示事件基础是否正在运行主事件循环。如果为true,表示主循环正在运行中。 -
(base)->th_owner_id: 存储主事件循环线程的 ID。这个 ID 是在事件循环开始时设置的。 -
evthread_id_fn_(): 调用evthread_id_fn_函数来获取当前线程的 ID。
-
evthread_id_fn_ != NULL: 确保线程 ID 函数指针有效,这意味着线程 ID 函数已经设置并可用。 -
(base)->running_loop: 确保事件循环确实在运行中。 -
(base)->th_owner_id != evthread_id_fn_(): 确保当前线程的 ID 与事件循环主线程的 ID 不同,表明主循环在另一个线程中运行。
这个宏的作用是检查是否需要通知主线程关于状态的变化,因为事件基础的主线程可能在不同的线程中运行。如果条件满足(即事件循环在另一个线程中运行且当前线程不是主线程),则返回 true,表示需要通知主线程。否则返回 false。
EVBASE_RELEASE_LOCK EVLOCK_UNLOCK
/** Unlock an event_base, if it is set up for locking. */#define EVBASE_RELEASE_LOCK(base, lockvar) do { \
EVLOCK_UNLOCK((base)->lockvar, 0); \} while (0)
/** Release a lock */#define EVLOCK_UNLOCK(lockvar,mode) \
do { \if (lockvar) \evthread_lock_fns_.unlock(mode, lockvar); \} while (0)
-
lockvar: 具体的锁变量。这个变量是锁的实际对象,用于加锁和解锁。 -
mode: 解锁模式,这个参数通常用于指定解锁的方式,但在这段代码中它被设置为0,具体模式取决于锁的实现。 -
evthread_lock_fns_.unlock: 这是一个函数指针,指向实际的解锁函数。evthread_lock_fns_是一个结构体,包含了各种锁操作的函数指针(例如加锁、解锁等)。 -
EVBASE_RELEASE_LOCK(base, lockvar): 这是一个高层次的宏,用于释放event_base的锁。它通过调用EVLOCK_UNLOCK实现具体的解锁操作。 -
EVLOCK_UNLOCK(lockvar, mode): 这是一个底层宏,实际执行解锁操作。它使用evthread_lock_fns_.unlock函数指针来解锁。mode参数通常用于指定解锁的详细模式,但在这段代码中,它被设置为0。
相关文章:
libevent - Macro function
TAILQ_INIT /** Tail queue functions.* 尾队列的头结点初始化为空队列。*/ #define TAILQ_INIT(head) do { \(head)->tqh_first NULL; \(head)->tqh_last &(head)->tqh_first; \ } while (/*CONSTCOND*/0)TAILQ_INIT 宏是一个用于初始化尾队列头部…...
408算法题leetcode--第17天
101. 对称二叉树 101. 对称二叉树思路:递归,对称即两个子树的左边和右边分别一样;一个子树是左中右遍历,另一个是右中左遍历;写的时候可以分三步,确定函数参数以及返回类型,确定终止条件&#…...
机器人顶刊IEEE T-RO发布无人机动态环境高效表征成果:基于粒子的动态环境连续占有地图
摘要:本研究有效提高了动态环境中障碍物建模的精度和效率。NOKOV度量动作捕捉系统助力评估动态占用地图在速度估计方面的性能。 近日,上海交通大学、荷兰代尔夫特理工研究团队在机器人顶刊IEEE T-RO上发表题为Continuous Occupancy Mapping in Dynamic …...
spring-boot web + vue
依赖的软件 maven 1. 官网下载zip 文件,比如apache-maven-3.9.9-bin.zip 2. 解压到某个盘符,必须保证父亲目录的名字包含英文,数字,破折号(-) 3. 设置环境变量M2_HOME, 并将%M2_HOME%\bin添加到windown…...
HDFS分布式文件系统01-HDFS架构与SHELL操作
HDFS分布式文件系统 学习目标第一课时知识点1-文件系统的分类单机文件系统网络文件系统分布式文件系统 知识点2-HDFS架构知识点3-HDFS的特点知识点4-HDFS的文件读写流程知识点5-HDFS的健壮性 第二课时知识点1-HDFS的Shell介绍HDFS Shell的语法格式如下。HDFS Shell客户端命令中…...
Go语言流程控制
Go语言流程控制 1.IF-ELSE2.Switch-Caseswitch 语句Type Switch 3.select 语句4.循环语句 1.IF-ELSE Go 编程语言中 if 语句的语法如下: if 布尔表达式 {/* 在布尔表达式为 true 时执行 */ }例如: package mainimport "fmt"func main() {va…...
无人机在救灾方面的应用!
一、灾害监测与评估 实时监测与评估:无人机可以快速到达灾害现场,通过搭载的高清摄像头、红外热成像仪等设备,对灾区进行实时监测和灾情评估。根据捕捉到的受灾范围、火势大小、建筑物损坏情况等关键信息,为救援行动提供决策依据…...
面试知识点总结篇一
一、C语言和C有什么区别 C语言是面向过程,强调用函数将问题分解为多个子任务,按顺序逐步进行。数据和操作分开C则是面向对象,面向对象是一种基于对象和类的编程范式,关注如何利用对象来抽象和模拟现实世界的实体。因此引入了类&a…...
【计算机网络 - 基础问题】每日 3 题(二十五)
✍个人博客:Pandaconda-CSDN博客 📣专栏地址:http://t.csdnimg.cn/fYaBd 📚专栏简介:在这个专栏中,我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞👍收藏&…...
【第十八章:Sentosa_DSML社区版-机器学习之协同过滤】
【第十八章:Sentosa_DSML社区版-机器学习之协同过滤】 1.算子介绍 协同过滤是推荐系统中常用的一种方法。该算法旨在填补用户-产品关联矩阵中缺少的项。在算法中,用户和产品都是通过一组少量的潜在因素描述,这些潜在因素可以用于预测用户-产…...
TDOA方法求二维坐标的MATLAB代码演示与讲解
引言 时间差定位(Time Difference of Arrival, TDOA)是一种用于确定信号源位置的技术,广泛应用于无线通信、声学定位等领域。通过测量信号到达多个接收器的时间差,可以计算出信号源的二维坐标。本文将通过MATLAB代码演示如何使用TDOA方法来求解二维坐标。 TDOA原理 TDOA…...
基于微信的原创音乐小程序的设计与实现+ssm论文源码调试讲解
第二章 开发工具及关键技术介绍 2.1 JAVA技术 Java主要采用CORBA技术和安全模型,可以在互联网应用的数据保护。它还提供了对EJB(Enterrise JavaBeans)的全面支持,java servlet AI,JS(java server ages&…...
基于大数据技术的颈椎病预防交流与数据分析及可视化系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏:Java精选实战项目…...
Spring MVC中实现一个文件上传和下载功能
说到文件上传和下载,相信每个开发者都有或多或少的接触过文件上传的功能吧,文件上传和下载是我们在学习计算机网络应用常见的一个功能,主要涉及到用户和服务器之间的数据传输。 我们来对文件上传和下载功能的进行相关概述吧! 文…...
Webpack 介绍
Webpack 介绍 Date: August 29, 2024 全文概要 Webpack概念: Webpack是一个静态的模块化的打包工具,可以为现代的 JavaSript 应用程序进行打包。 1-静态:Webpack可以将代码打包成最终的静态资源 2-模块化:webpack支持各种模块…...
在Linux实时监控某个应用是否运行,未运行,执行运行命令
1、shell脚本(每隔30秒检测一次) 脚本要注意的地方是:在Nodepad编辑的时候要使用Unix(LF)格式,避免在Linux无法执行命令 #!/bin/bash# RabbitMQ进程名称(可能需要根据你的安装进行调整) RABBITMQ_PROCE…...
Serilog文档翻译系列(六) - 可用的接收器、增强器、格式化输出
01、提供的接收器 Serilog 使用接收器将日志事件以各种格式写入存储。许多接收器由更广泛的 Serilog 社区开发和支持;可以通过在 NuGet 上搜索 serilog 标签找到。 02、增强器 日志事件可以通过多种方式增强属性。通过 NuGet 提供了一些预构建的增强器ÿ…...
傅里叶级数在机器人中的应用(动力学参数辨识)
B站首发!草履虫都能看懂的【傅里叶变换】讲解,清华大学李永乐老师教你如何理解傅里叶变换,辨清美颜和变声原理,!!_哔哩哔哩_bilibiliB站首发!草履虫都能看懂的【傅里叶变换】讲解,清…...
前端框架Vue、React、Angular、Svelte对比
在对比 React、Vue.js、Angular 和 Svelte 时,除了在高层次的特性上有显著差异,它们在核心设计理念和底层实现机制上也有明显的不同。为了清晰地理解这些框架,我们可以从以下几个方面来分析它们的核心不同点和底层不同点。 1. 框架类型和设计…...
深度学习后门攻击分析与实现(二)
前言 在本系列的第一部分中,我们已经掌握了深度学习中的后门攻击的特点以及基础的攻击方式,现在我们在第二部分中首先来学习深度学习后门攻击在传统网络空间安全中的应用。然后再来分析与实现一些颇具特点的深度学习后门攻击方式。 深度学习与网络空间…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...
保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...
沙箱虚拟化技术虚拟机容器之间的关系详解
问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西,但是如果把三者放在一起,它们之间到底什么关系?又有什么联系呢?我不是很明白!!! 就比如说: 沙箱&#…...
GraphQL 实战篇:Apollo Client 配置与缓存
GraphQL 实战篇:Apollo Client 配置与缓存 上一篇:GraphQL 入门篇:基础查询语法 依旧和上一篇的笔记一样,主实操,没啥过多的细节讲解,代码具体在: https://github.com/GoldenaArcher/graphql…...
从实验室到产业:IndexTTS 在六大核心场景的落地实践
一、内容创作:重构数字内容生产范式 在短视频创作领域,IndexTTS 的语音克隆技术彻底改变了配音流程。B 站 UP 主通过 5 秒参考音频即可克隆出郭老师音色,生成的 “各位吴彦祖们大家好” 语音相似度达 97%,单条视频播放量突破百万…...
