当前位置: 首页 > news >正文

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_firstNULL,表示队列当前没有任何元素,是空的。
  • (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 是一个宏或函数,通常用于提示编译器某个条件不太可能发生,这可以帮助编译器优化代码。这里的意思是,如果条件 condfalse(即条件不满足),则执行后续代码。
    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 用于指定链表结构体成员的修饰符(它可以是 constvolatile 或其他限定符。)

  • 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. 对称二叉树思路&#xff1a;递归&#xff0c;对称即两个子树的左边和右边分别一样&#xff1b;一个子树是左中右遍历&#xff0c;另一个是右中左遍历&#xff1b;写的时候可以分三步&#xff0c;确定函数参数以及返回类型&#xff0c;确定终止条件&#…...

机器人顶刊IEEE T-RO发布无人机动态环境高效表征成果:基于粒子的动态环境连续占有地图

摘要&#xff1a;本研究有效提高了动态环境中障碍物建模的精度和效率。NOKOV度量动作捕捉系统助力评估动态占用地图在速度估计方面的性能。 近日&#xff0c;上海交通大学、荷兰代尔夫特理工研究团队在机器人顶刊IEEE T-RO上发表题为Continuous Occupancy Mapping in Dynamic …...

spring-boot web + vue

依赖的软件 maven 1. 官网下载zip 文件&#xff0c;比如apache-maven-3.9.9-bin.zip 2. 解压到某个盘符&#xff0c;必须保证父亲目录的名字包含英文&#xff0c;数字&#xff0c;破折号&#xff08;-&#xff09; 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 语句的语法如下&#xff1a; if 布尔表达式 {/* 在布尔表达式为 true 时执行 */ }例如&#xff1a; package mainimport "fmt"func main() {va…...

无人机在救灾方面的应用!

一、灾害监测与评估 实时监测与评估&#xff1a;无人机可以快速到达灾害现场&#xff0c;通过搭载的高清摄像头、红外热成像仪等设备&#xff0c;对灾区进行实时监测和灾情评估。根据捕捉到的受灾范围、火势大小、建筑物损坏情况等关键信息&#xff0c;为救援行动提供决策依据…...

面试知识点总结篇一

一、C语言和C有什么区别 C语言是面向过程&#xff0c;强调用函数将问题分解为多个子任务&#xff0c;按顺序逐步进行。数据和操作分开C则是面向对象&#xff0c;面向对象是一种基于对象和类的编程范式&#xff0c;关注如何利用对象来抽象和模拟现实世界的实体。因此引入了类&a…...

【计算机网络 - 基础问题】每日 3 题(二十五)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏&…...

【第十八章:Sentosa_DSML社区版-机器学习之协同过滤】

【第十八章&#xff1a;Sentosa_DSML社区版-机器学习之协同过滤】 1.算子介绍 协同过滤是推荐系统中常用的一种方法。该算法旨在填补用户-产品关联矩阵中缺少的项。在算法中&#xff0c;用户和产品都是通过一组少量的潜在因素描述&#xff0c;这些潜在因素可以用于预测用户-产…...

TDOA方法求二维坐标的MATLAB代码演示与讲解

引言 时间差定位(Time Difference of Arrival, TDOA)是一种用于确定信号源位置的技术,广泛应用于无线通信、声学定位等领域。通过测量信号到达多个接收器的时间差,可以计算出信号源的二维坐标。本文将通过MATLAB代码演示如何使用TDOA方法来求解二维坐标。 TDOA原理 TDOA…...

基于微信的原创音乐小程序的设计与实现+ssm论文源码调试讲解

第二章 开发工具及关键技术介绍 2.1 JAVA技术 Java主要采用CORBA技术和安全模型&#xff0c;可以在互联网应用的数据保护。它还提供了对EJB&#xff08;Enterrise JavaBeans&#xff09;的全面支持&#xff0c;java servlet AI&#xff0c;JS&#xff08;java server ages&…...

基于大数据技术的颈椎病预防交流与数据分析及可视化系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…...

Spring MVC中实现一个文件上传和下载功能

说到文件上传和下载&#xff0c;相信每个开发者都有或多或少的接触过文件上传的功能吧&#xff0c;文件上传和下载是我们在学习计算机网络应用常见的一个功能&#xff0c;主要涉及到用户和服务器之间的数据传输。 我们来对文件上传和下载功能的进行相关概述吧&#xff01; 文…...

Webpack 介绍

Webpack 介绍 Date: August 29, 2024 全文概要 Webpack概念&#xff1a; Webpack是一个静态的模块化的打包工具&#xff0c;可以为现代的 JavaSript 应用程序进行打包。 1-静态&#xff1a;Webpack可以将代码打包成最终的静态资源 2-模块化&#xff1a;webpack支持各种模块…...

在Linux实时监控某个应用是否运行,未运行,执行运行命令

1、shell脚本(每隔30秒检测一次) 脚本要注意的地方是&#xff1a;在Nodepad编辑的时候要使用Unix&#xff08;LF&#xff09;格式&#xff0c;避免在Linux无法执行命令 #!/bin/bash# RabbitMQ进程名称&#xff08;可能需要根据你的安装进行调整&#xff09; RABBITMQ_PROCE…...

Serilog文档翻译系列(六) - 可用的接收器、增强器、格式化输出

01、提供的接收器 Serilog 使用接收器将日志事件以各种格式写入存储。许多接收器由更广泛的 Serilog 社区开发和支持&#xff1b;可以通过在 NuGet 上搜索 serilog 标签找到。 02、增强器 日志事件可以通过多种方式增强属性。通过 NuGet 提供了一些预构建的增强器&#xff…...

傅里叶级数在机器人中的应用(动力学参数辨识)

B站首发&#xff01;草履虫都能看懂的【傅里叶变换】讲解&#xff0c;清华大学李永乐老师教你如何理解傅里叶变换&#xff0c;辨清美颜和变声原理&#xff0c;&#xff01;&#xff01;_哔哩哔哩_bilibiliB站首发&#xff01;草履虫都能看懂的【傅里叶变换】讲解&#xff0c;清…...

前端框架Vue、React、Angular、Svelte对比

在对比 React、Vue.js、Angular 和 Svelte 时&#xff0c;除了在高层次的特性上有显著差异&#xff0c;它们在核心设计理念和底层实现机制上也有明显的不同。为了清晰地理解这些框架&#xff0c;我们可以从以下几个方面来分析它们的核心不同点和底层不同点。 1. 框架类型和设计…...

深度学习后门攻击分析与实现(二)

前言 在本系列的第一部分中&#xff0c;我们已经掌握了深度学习中的后门攻击的特点以及基础的攻击方式&#xff0c;现在我们在第二部分中首先来学习深度学习后门攻击在传统网络空间安全中的应用。然后再来分析与实现一些颇具特点的深度学习后门攻击方式。 深度学习与网络空间…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...