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

【p2p、分布式,区块链笔记 UPNP】: Libupnp的线程池简述

  • 线程池在网络编程中是一个关键的组成部分,尤其是处理高并发请求时,线程池可以显著提高系统的性能和资源利用效率。它的关键组成部分包括以下几个要素:
  • 任务队列:一个(或多个)用于存放待执行任务的队列。任务通常以函数指针或任务对象的形式存储在队列中。
  • 生产者: 负责生成任务并将任务提交到线程池的任务队列中。
  • 消费者: 从任务队列中获取任务并进行处理。

线程池结构

  • 线程池由各种任务队列、用到的锁和一些属性组成。
  • https://github1s.com/pupnp/pupnp/blob/branch-1.14.x/upnp/src/threadutil/ThreadPool.h
typedef struct THREADPOOL
{
       
    FreeList jobFreeList;                /*! 任务的空闲列表。 */
    LinkedList lowJobQ;                  /*! 低优先级任务队列。 */
    LinkedList medJobQ;                  /*! 中等优先级任务队列。 */
    LinkedList highJobQ;                 /*! 高优先级任务队列。 */
    ThreadPoolJob *persistentJob;        /*! 持久任务。 */

    ithread_mutex_t mutex;              /*! 保护任务队列的互斥锁。*/
    ithread_cond_t condition;           /*! 用于任务队列信号的条件变量。*/
    ithread_cond_t start_and_shutdown;  /*! 用于启动和关闭的条件变量。 */
    
    // 该变量只在 创建消费者线程CreateWorker 时使用,为1时阻塞其他线程,创建完成后通过start_and_shutdown通知其他继续运行
    int pendingWorkerThreadStart;       /*! 是否在等待新工作线程启动。 */
    
    int lastJobId;                      /*! 任务ID计数器。 */
    int shutdown;                       /*! 标识线程池是否正在关闭。 */
    int totalThreads;                   /*! 线程总数。 */
    int busyThreads;                    /*! 当前正在执行任务的线程数量。 */
    int persistentThreads;              /*! 持久线程的数量。 */
    ThreadPoolAttr attr;                /*! 线程池的属性。 */
    ThreadPoolStats stats;              /*! 统计数据。 */
} ThreadPool;

线程池的任务队列结构(以LINKEDLIST 为例)

  • LINKEDLIST :生产者和消费者共同操作的任务队列,线程池中一般存在多个生产者和多个消费者(共同push、pop),所以操作时要加锁。
  • 在LinkedList.h中也定义了链表的创建(ListInit)、插入(ListAddTail)和删除 (ListDelNode)函数。
  • 另外需要注意的是,当void *ListDelNode(LinkedList *list, ListNode *dnode, int freeItem)的freeItem == 0,则节点中的项会从链表中移除但不会被释放。其地址作为函数的返回值。
/*!
 * 如果 head->next = tail,那么链表为空。
 *
 * 要遍历链表,可以使用如下代码:
 *  LinkedList g;ListNode *temp = NULL;for (temp = ListHead(g); temp != NULL; temp = ListNext(g, temp)) {}
 */
typedef struct LINKEDLIST {
	ListNode head; // 链表的头节点,实际第一个数据节点存储在 head->next 中
	ListNode tail; // 链表的尾节点,实际最后一个数据节点存储在 tail->prev 中
	long size; // 链表的当前大小(节点个数)

	FreeList freeNodeList;  // 空闲节点列表,用于回收和重用内存
	free_function free_func; // 释放节点时使用的函数指针,ListInit时确定
	cmp_routine cmp_func; // 比较两个节点数据时使用的函数指针
} LinkedList;
  • ThreadPoolAdd函数调用ListAddTail将通过TPJobInit等函数创建并配置的ThreadPoolJob *对象加入到目标队列中。
  • 生产者的调用过程可见(【p2p、分布式,区块链笔记 UPNP】: Libupnp sample 02 tv_device)。其中的TimerThreadSchedule(&gTimerThread, timeTillRead, REL_SEC, &job, SHORT_TERM, id);通过ListAddBefore函数将job添加到gTimerThread,最终通过TimerThreadWorker调用ThreadPoolAdd添加任务队列。
    在这里插入图片描述
  • 消费者从队列中获取任务head = ListHead(&tp->lowJobQ);job = (ThreadPoolJob *)head->item;并删除节点ListDelNode(&tp->lowJobQ, head, 0);。然后通过job->func(job->arg);执行回调函数。消费者的调用过程见 【p2p、分布式,区块链笔记 UPNP】: Libupnp test_init.c 03 初始化SDK — 线程池初始化(UpnpInitThreadPools)的WorkerThread 。
ListNode
typedef struct LISTNODE {
    struct LISTNODE *prev;  // 指向前一个节点的指针
    struct LISTNODE *next;  // 指向下一个节点的指针
    void *item;             // 指向节点中存储的通用数据(任意类型的项,当前示例为指向ThreadPoolJob的指针)
} ListNode;
  • 下面的例子中highJobQ的head为ListNode类型,其中的item为ThreadPoolJob类型
// https://github1s.com/pupnp/pupnp/blob/branch-1.14.x/upnp/src/threadutil/ThreadPool.c#L547-L556
// 依次尝试从高、中、低优先级队列中取作业
				if (tp->highJobQ.size > 0) {
					head = ListHead(&tp->highJobQ);
					if (head == NULL) {
						tp->stats.workerThreads--;
						goto exit_function;
					}
					job = (ThreadPoolJob *)head->item;
					CalcWaitTime(tp, HIGH_PRIORITY, job);
					ListDelNode(&tp->highJobQ, head, 0);
ThreadPoolJob
/*! Internal ThreadPool Job. */
typedef struct THREADPOOLJOB
{
	start_routine func;
	void *arg;
	free_routine free_func;
	struct timeval requestTime;
	ThreadPriority priority;
	int jobId;
} ThreadPoolJob;

在这里插入图片描述


http://www.kler.cn/news/340235.html

相关文章:

  • MFC项目如何使用hiredis库连接redis
  • 【aws】从s3里拉取驱动 需要后台创建凭证
  • springboot 整合 rabbitMQ(1)
  • 西门子模块6ES7336-4GE00-0AB0
  • 相机光源选型速记
  • 如何版本REST API:综合指南
  • Vue3+TS项目 - ref和useTemplateRef获取组件实例
  • 清韵千言APP:一款基于RNN架构并深度优化的语言模型应用
  • Gated Transformer Networks for Multivariate Time Series Classification
  • PCL 点云SUAN关键点提取
  • ADAS中的安全性功能与舒适性功能总结
  • Python可变映射类型MutableMapping
  • 单细胞转录组 —— Cell Ranger 原始数据处理
  • 【深度学习基础模型】极限学习机(Extreme Learning Machines, ELM)详细理解并附实现代码。
  • 进程的状态的理解(概念+Linux)
  • 手搓一个Eval#Datawhale组队学习大模型任务Task4
  • 问卷的二维码怎么做?教你一招快速在线制作表单二维码
  • 【基于YOLOv5的反光衣检测预警系统】可检测图片、视频、摄像头,支持GPU加速检测以及语音播报预警
  • PHP函数 strstr() 和 stristr() 有什么区别
  • 反应香精市场报告:预计2030年全球市场规模将达到264.3亿美元