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. 框架类型和设计…...

深度学习后门攻击分析与实现(二)
前言 在本系列的第一部分中,我们已经掌握了深度学习中的后门攻击的特点以及基础的攻击方式,现在我们在第二部分中首先来学习深度学习后门攻击在传统网络空间安全中的应用。然后再来分析与实现一些颇具特点的深度学习后门攻击方式。 深度学习与网络空间…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...

Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
文章目录 一、开启慢查询日志,定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...
《Offer来了:Java面试核心知识点精讲》大纲
文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...