WebServer:log

超时锁的编写

这个问题处于blockqueue.h文件中,内容如下:

template<class T>
bool BlockDeque<T>::pop(T& item, int timeout) {std::unique_lock<std::mutex> locker(mtx_);while(deq_.empty()) {if(condConsumer_.wait_for(locker, std::chrono::seconds(timeout))== std::cv_status::timeout) {return false;}if(isClose_) {return false;}}item = deq_.front();deq_.pop_front();condProducer_.notify_one();return true;
}

在if的判断中,学习到了关于超时判定部分:

if(condConsumer_.wait_for(locker, std::chrono::seconds(timeout))== std::cv_status::timeout) {...
}

wait_for已经知道是循环等待了,这在之前关于C++多线程的笔记中有写,这里面有疑惑的主要是这个std::cv_status是什么东西。C++参考手册中有相应的内容:

enum class cv_status {no_timeout,timeout  
};

可以看到,它其实就是一个很简单的枚举类,用于判断是否超时。
查看有关wait_for相关的内容也可发现以下内容:
在这里插入图片描述

类的static关键字

我对这点有点忘记了,先描述一下static成员所具有的特点吧:

  1. 静态成员函数只能访问静态成员变量
  2. 静态成员变量不能够使用this指针,因为静态成员变量属于类而不属于类的实例
  3. 静态成员变量需要在类内声明,但是在类外初始化,如:
    class Temp {
    private:static int num;
    };int Temp::num = 10;
    
    有几点我现在还是有点不是很理解:
    • 为什么在类外初始化的时候还是需要加上该变量的类型?就是说在我的想法中,由于在类内中我已经声明了这个变量Temp::num是int类型的,所以我在初始化的时候不应该再进行一个小的声明:
      Temp::num = 10;
      
    • 为什么一定要在类外初始化?(静态成员变量不能在类内初始化
  4. 静态成员在某种意义上和全局变量很相似,它的生命周期是整个程序的运行周期。

局部静态变量

局部静态变量同时具有局部变量静态变量的性质:

  1. 具有局部性:该变量只有在函数内部可使用
  2. 具有全局性:该变量的生命周期是程序的运行周期
  3. 静态:只会被初始化一次
void func() {static int num = 0;return num++;
}int main() {cout << func() << endl;cout << func() << endl;cout << func() << endl;
}

通过运行这段简单的程序就能够理解了。

FILE类

这个项目中使用的是FILE,这个是C/C++官方提供的一个抽象接口,是比文件描述符fd更高一级的接口:

struct _IO_FILE;
typedef struct _IO_FILE FILE;

从源文件中只能找到这一步,再往上走关于_TO_FILE的定义我就没找到了。

C++参考手册,其中对FILE这个结构体进行了部分描述,由于该结构体是一个不透明的文件流,所以在参考手册中对其也没有很明确的描述,只需要怎么使用它就行了。
相关的常用函数如下:

FILE *fopen(const char *filename, const char *mode);
int fclose(FILE *stream);
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
int fgetc(FILE *stream);
int fputc(int c, FILE *stream);
long ftell(FILE *stream);
int fseek(FILE *stream, long offset, int whence);
void rewind(FILE *stream);
int feof(FILE *stream);
int ferror(FILE *stream);
void clearerr(FILE *stream);

接下来给一段实例代码,用于展示FILE对文件的操作:

#include <stdio.h>int main() {// 打开文件以进行写入FILE *file = fopen("example.txt", "w");if (file == NULL) {perror("Error opening file");return 1;}// 写入数据fprintf(file, "Hello, world!\n");fclose(file); // 关闭文件// 打开文件以进行读取file = fopen("example.txt", "r");if (file == NULL) {perror("Error opening file");return 1;}// 读取并打印数据char buffer[256];while (fgets(buffer, sizeof(buffer), file) != NULL) {printf("%s", buffer);}fclose(file); // 关闭文件return 0;
}

我觉得FILE有点难用(毕竟刚开始)

time_t

time_t通常用来存储自1970年1月1日00:00:00 UTC以来经过的秒数,通常需要转换为tm以便更好地进行表示
在以下代码中:

#include <ctime>time_t timer = time(nullptr); // 用于获取当前时间
struct tm* sysTime = localtime(&timer); // 将time_t转换为tm格式
struct tm t = *sysTime;

time_t在探查之后发现它是一个long int类型,而tm才是我们坑看懂的类型。

time_t time(time_t *t); // 获取当前时间的time_t值
struct tm *localtime(const time_t *timep); // 将time_t转换为tm,表示为本地时间
struct tm *gmtime(const time_t *timep); // 将time_t转换为tm,表示为UTC时间

tm

time_t只是一个数字,用于表示秒数,这个数字我们人来看是不能直接读懂的,因此需要转换为人能读懂的格式,即:tm

struct tm
{int tm_sec;			/* Seconds.	[0-60] (1 leap second) */int tm_min;			/* Minutes.	[0-59] */int tm_hour;			/* Hours.	[0-23] */int tm_mday;			/* Day.		[1-31] */int tm_mon;			/* Month.	[0-11] */int tm_year;			/* Year	- 1900.  */int tm_wday;			/* Day of week.	[0-6] */int tm_yday;			/* Days in year.[0-365]	*/int tm_isdst;			/* DST.		[-1/0/1]*/# ifdef	__USE_MISClong int tm_gmtoff;		/* Seconds east of UTC.  */const char *tm_zone;		/* Timezone abbreviation.  */
# elselong int __tm_gmtoff;		/* Seconds east of UTC.  */const char *__tm_zone;	/* Timezone abbreviation.  */
# endif
};

而转换主要使用两个函数:

struct tm *localtime(const time_t *timep); // 将time_t转换为tm,表示为本地时间
struct tm *gmtime(const time_t *timep); // 将time_t转换为tm,表示为UTC时间

格式化字符串的使用

在使用snprintf的时候使用了以下格式化字符串:

"%s/%04d_%02d_%02d%s"

对这个我不是很懂,所以就查了下:

  • %s:这个很常用,字符串占位符,不多说了
  • %04d:%d都知道是表示的整数,%04d则是对这个整数还进行了一个约束:这个整数是四位数,若不是四位数在高位补0
  • %02d:类似与%04d

这里我们可以用一段简短的代码试一试:

#include <cstdio>int main() {printf("%04d\n%4d", 1, 1);
}

这段代码中,两种占位符稍有不同:一种是04另一种就是4,后者的输出会保持四位,但是不会补0,而前者会补0

00011

timeval

在上面使用了[[#time_t]],这里却又使用的是tiemval,这两个都是和时间相关的结构体,但是它们之间还是有区别的:

time_t是C标准库提供的
timeval是POSIX标准提出的

timeval的精度要高于time_t,前者可以达到微秒级,后者则是秒

#include <sys/time.h>int settimeofday(const struct timeval *tv, const struct timezone *tz);
  • tv:用于接收时间的变量
  • tz:用于设置时区的变量(现已抛弃,直接传入nullptr就好)
struct timeval {time_t      tv_sec;  // 从1970年1月1日00:00:00 UTC到当前时间的秒数suseconds_t tv_usec; // 当前时间的微秒数
};

C语言的可变参数

这个是C语言的一种写法,C++的写法不太一样,有点类似于递归。
va_list的具体用法如下:

#include <stdio.h>
#include <stdarg.h>// 自定义的函数,接受一个整数和可变数量的整数参数
void printNumbers(int count, ...) {va_list args;va_start(args, count);  // 初始化 va_listfor (int i = 0; i < count; i++) {int num = va_arg(args, int);  // 访问下一个参数printf("%d ", num);}va_end(args);  // 清理 va_listprintf("\n");
}int main() {printNumbers(3, 1, 2, 3);        // 输出: 1 2 3printNumbers(5, 10, 20, 30, 40, 50);  // 输出: 10 20 30 40 50return 0;
}

其中的count表示的是该函数的最后一个固定参数。

上述代码是它的最基础使用,接下来详细说说stdarg.h的内容:

  • 声明一个va_list类型的变量,用于存储可变参数
  • va_start用于初始化上面声明的va_list
    void va_start(va_list ap, last);
    
    1. ap:va_start 将在这个变量中初始化可变参数的访问。
    2. last:这是最后一个固定参数的名称,va_start 用这个参数来确定可变参数列表的开始位置。
  • va_arg:用于访问可变参数
  • va_end:结束对va_list的访问(若是没有结束会引起资源泄漏问题

接下来再给一段更好理解的小程序:

#include <stdio.h>
#include <stdarg.h>void temp(int last, ...) {va_list valist;va_start(valist, last);char msg[256] = {};vsnprintf(msg, 256, "%s, %s", valist);printf("%s", msg);va_end(valist);
}int main() {temp(1, "hello", "world");
}

上i满这段代码使用了一个新的函数:vsnprintfsnprintf之前已经知道,就是用于格式化字符串,该函数同样是格式化字符串,只不过它传入的参数有va_list类型的,也就是说,它能够很好地处理可变参数的情况。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/144976.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

分享每天开发100个WhatsApp客户方法

获取WhatsApp账号的方式有很多&#xff0c;因为WhatsApp跟微信差不多&#xff0c;可以说是国际版的微信&#xff0c;很多电话就是WhatsApp。所以说收集WhatsApp基本上就跟收集收集号码的方式大同小异&#xff0c;谷歌开发客户是做外贸的基本功之一了&#xff0c;要会谷歌开发客…

百元头戴式蓝牙耳机哪个牌子好?四大优质百元机型推荐

在寻找性价比高的百元头戴式蓝牙耳机时&#xff0c;消费者往往面临众多品牌和型号的选择&#xff0c;市场上的竞争异常激烈&#xff0c;不同品牌推出的产品在功能、音质、舒适度以及续航能力等方面各有千秋&#xff0c;那么百元头戴式蓝牙耳机哪个牌子好&#xff1f;对于那些不…

C++STL的Stack的使用:STL栈和队列的使用介绍、leecode---最小栈、nowcoder---栈的压入、弹出序列等的介绍

文章目录 前言一、STL栈和队列的使用二、leetcode---最小栈三、nowcoder---栈的压入、弹出序列总结 前言 CSTL的Stack的使用&#xff1a;STL栈和队列的使用介绍、leecode—最小栈、nowcoder—栈的压入、弹出序列等的介绍 一、STL栈和队列的使用 #include <iostream> #in…

idea插件之google-java-format

google-java-format插件可用于重新格式化 Java 源代码 统一代码格式 不同的人提交的代码格式化不一样将导致 merge 代码造成大概率冲突&#xff0c;而统一的代码风格无论对项目的可维护性&#xff0c;还是降低 merge 冲突都极为重要。 广泛使用的两种 Java 代码规范&#xf…

ELK环境部署

目录 环境准备 Elasticsearch 部署 安装Elasticsearch Elasticsearch-head 插件 安装node 安装 phantomjs 安装 Elasticsearch-head Logstash 安装部署 Kibana 安装部署 ELFK 本章纯搭建过程&#xff0c;几乎无任何注释解释 环境准备 ELK的搭建和测试&#xff0c;…

数据飞轮:打造业务增长的持续循环

在当今数据驱动的世界中&#xff0c;企业必须利用数据的力量才能保持竞争力。然而&#xff0c;仅仅收集和分析数据是不够的&#xff1b;企业必须能够从他们的数据中创造一个持续增长的循环&#xff0c;才能保持成功。其中一种方法就是创建数据飞轮。接下来让我们来探讨一下什么…

2024.9.20 Python模式识别新国大EE5907,PCA主成分分析,LDA线性判别分析,GMM聚类分类,SVM支持向量机

1.PCA 主成分分析用于特征提取、可视化和分类 根据要求&#xff0c;我在第一个代码框中完成了从指定路径提取图像数据&#xff0c;将其转换为灰度图像并将其展平。在这里&#xff0c;我将数字 88 设置为我的照片的标签&#xff0c;然后将所有 10 张照片传入代码。然后我定义了…

在渗入测试和峰谷测试中选Flat还是Ramp-up?

前面的一篇文章中我们为大家介绍了在基准测试和规划测试中选Flat还是Ramp-up&#xff0c;具体应该怎么配置&#xff0c;在这篇文章里&#xff0c;我们继续为大家介绍在渗入测试和峰谷测试中选Flat还是Ramp-up&#xff1f; 渗入测试&#xff08;疲劳强度测试&#xff09; 使用固…

全球多个知名社媒平台长期监视青少年儿童用户,每年赚取数十亿美元

根据美国联邦贸易委员会&#xff08;FTC&#xff09;工作人员的一份报告显示&#xff0c;社交媒体和视频流媒体公司一直在对用户&#xff0c;尤其是儿童和青少年进行广泛的监控&#xff0c;隐私保护不足&#xff0c;并通过数据货币化每年赚取数十亿美元。 此调查始于2020 年 1…

Oracle数据库逻辑与物理结构操作

一、实验步骤 1、查询所有DBA和USER开头的静态数据字典 2、查询所有V$动态性能视图 3、查询当前数据库中的表空间信息 ①查询和TABLESPACE相关的数据字典 ②通过动态性能视图查询表空间信息 ③通过数据字典查询表空间信息 4、操作数据文件 &#xff08;1&#xff09;向 ORC…

Machine Learning Specialization 学习笔记(3)

文章目录 前言一、神经网络基本概念基本组成工作流程训练过程类型应用举例不同层次特征的学习 为什么从基础特征到复杂特征逐渐推进什么是感受野更简单的解释具体示例总结 二、TensorFlow实现简单神经网络安装及环境配置数据预处理标准化 Dense层Convolutional Layer训练DEBUG …

Windows环境下搭建MySQL主从同步实现读写分离

文章目录 前言读写分离的基本原理 环境介绍及说明主库my.ini初始配置创建用于同步的数据库和表 一、新增mysql从库1.复制mysql文件夹2.修改从库的my.ini3.安装到windows服务 二、在my.ini中配置主、从库相关参数1.主库新增配置参数不同版本参数不同问题 2.从库新增配置参数3.删…

CSS 复合选择器简单学习

目录 1. Emmet 语法 1.1 快速生成 HTML 结构语法 1.2 快速生成 CSS 样式 1.3 格式化工具 2. 调试 2.1 打开调试工具 2.2 使用调试工具 3. 复合选择器 3.1 后代选择器 3.2 子选择器 3.3 并集选择器 3.4 伪类选择器 3.3.1 链接伪类选择器 3.3.2 :focus 伪类选择器 …

7--SpringBoot-后端开发、原理详解(面试高频提问点)

目录 SpringBoot原理 起步依赖 自动配置 配置优先级 Bean设置 获取Bean 第三方Bean SpringBoot原理 内容偏向于底层的原理分析 基于Spring框架进行项目的开发有两个不足的地方&#xff1a; 在pom.xml中依赖配置比较繁琐&#xff0c;在项目开发时&#xff0c;需要自己去找…

VuePress搭建文档网站/个人博客(详细配置)主题配置-侧边栏配置

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

洞悉市场先机,Vatee万腾平台助力企业精准决策

在瞬息万变的商业环境中&#xff0c;每一个市场动向都可能成为企业兴衰的关键。因此&#xff0c;洞悉市场先机&#xff0c;做出精准决策&#xff0c;成为了企业持续发展和保持竞争力的核心要素。Vatee万腾平台&#xff0c;凭借其强大的数据分析能力和智能化技术&#xff0c;正成…

生信初学者教程(八):数据收集

文章目录 数据分布表达谱数据最终数据分布自动下载GSE14520下载GSE149614下载其它数据在确定研究疾病为肝细胞癌**(Liver Hepatocellular Carcinoma: HCC)**后,系统地进行了文献回顾,专注于搜索与HCC相关的荟萃分析文章,以获取该领域的研究动态和已有成果。为了支持的研究…

dev c++输出中文乱码解决 printf乱码解决

把编码换成utf8就行 打开eiditor options

数据结构修炼——顺序表和链表的区别与联系

目录 一、线性表二、顺序表2.1 概念及结构2.2 接口实现2.3 一些思考以及顺序表的缺点 三、链表3.1 概念及结构3.2 链表的分类3.3 链表的实现3.3.1 无头单向非循环链表3.3.2 带头双向循环链表 四、顺序表和链表的区别 一、线性表 线性表&#xff08;linear list&#xff09;是n…

叶片检测系统源码分享

叶片检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …