嵌入式事件框架

Content

  • 0x00 前言
  • 0x01 不带优先级
  • 0x02 区分优先级

0x00 前言

事件是系统中发生的某种情况或状态变化,通常由用户操作(如点击按钮、键盘输入)或系统状态变化(如传感器数据更新)引发。

事件可以有多种类型,例如用户输入事件(按钮按下、鼠标移动)、系统事件(定时器超时、数据接收)等任何可以产生的。

事件处理器是响应特定事件的函数或方法。当事件发生时,框架会调用相应的事件处理器来处理该事件。

事件框架通常使用事件队列来存储待处理的事件。事件可以按发生的顺序或优先级存储在队列中,确保它们在适当的时机被处理。

事件循环是框架的核心部分,它不断检查事件队列,处理待处理的事件,并调用相应的事件处理器。事件循环通常在主线程中运行,确保系统能够实时响应事件。

举个通俗的例子,正在玩电脑游戏的一名同学,按下了向左移动的按键,那么这就是"事件发生",随后会将这个事件添加到"事件队列",再随后事件处理器会根据"事件类型"去进行不同的反应,比如左键右键要分别对应向左向右移动。

事件框架将事件的生成和处理分离,使得系统的各个部分可以独立开发和维护。并且可以轻松添加新的事件类型和处理器,而不需要修改现有代码。通过事件驱动的方式,系统可以在事件发生时立即响应,而不是通过轮询等方式。由于事件处理函数是独立的,可以单独测试每个事件处理函数,简化了调试和测试过程。

0x01 不带优先级

以下是一个无优先级区分的框架,如果功能并无先后之分,可以使用以下案例来实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_EVENTS 100
#define MAX_HANDLERS 10

// 事件类型枚举
typedef enum {
    EVENT_BUTTON_PRESS,
    EVENT_MOUSE_MOVE,
    EVENT_KEYBOARD_INPUT,
} EventType;

// 事件结构体
typedef struct {
    EventType type;
    void* data;
} Event;

// 事件队列
Event eventQueue[MAX_EVENTS];
int eventCount = 0;

// 事件处理函数类型
typedef void (*EventHandler)(Event*);

// 事件处理器数组
EventHandler handlers[MAX_HANDLERS];
int handlerCount = 0;

// 添加事件到队列
void addEvent(EventType type, void* data) {
    if (eventCount < MAX_EVENTS) {
        eventQueue[eventCount].type = type;
        eventQueue[eventCount].data = data;
        eventCount++;
    } else {
        printf("EVENT QUEUE IS FULL\n");
    }
}

// 注册事件处理函数
void registerHandler(EventHandler handler) {
    if (handlerCount < MAX_HANDLERS) {
        handlers[handlerCount++] = handler;
    } else {
        printf("HANDLER COUNT IS MAX\n");
    }
}

// 处理所有事件
void processEvents() {
    for (int i = 0; i < eventCount; i++) {
        for (int j = 0; j < handlerCount; j++) {
            handlers[j](&eventQueue[i]);
        }
    }
    eventCount = 0; // 清空事件队列
}

// 示例事件处理函数
void handleButtonPress(Event* event) {
    if (event->type == EVENT_BUTTON_PRESS) {
        printf("BUTTON IS PRESS\n");
    }
}

void handleMouseMove(Event* event) {
    if (event->type == EVENT_MOUSE_MOVE) {
        printf("MOUSE IS MOVE\n");
    }
}

int main() {
    // 注册事件处理函数
    registerHandler(handleButtonPress);
    registerHandler(handleMouseMove);

    // 模拟添加事件
    addEvent(EVENT_BUTTON_PRESS, NULL);
    addEvent(EVENT_MOUSE_MOVE, NULL);

    // 主循环
    while (1) {
		// 事件发生

        // 处理所有待处理的事件
        processEvents();
        addEvent(EVENT_MOUSE_MOVE, NULL);
        addEvent(EVENT_MOUSE_MOVE, NULL);
        addEvent(EVENT_MOUSE_MOVE, NULL);
        addEvent(EVENT_MOUSE_MOVE, NULL);
    }

    return 0;
}

0x02 区分优先级

那么接下来就是一个带优先级的框架了,这个框架与以上框架不同的是,以上代码是先到先处理的方式去做,顺序执行,与轮询不同的是响应会更加即时,并且会限制事件发生数,可以限制内存的使用。

而以下这段代码,在执行之前会先对队列中的优先级进行扫描,从而先处理优先级较高的事件。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_EVENTS 100
#define MAX_HANDLERS 10
#define PRIORITY_LEVELS 3

// 事件类型枚举
typedef enum {
    EVENT_BUTTON_PRESS,
    EVENT_MOUSE_MOVE,
    EVENT_KEYBOARD_INPUT,
} EventType;

// 事件结构体
typedef struct {
    EventType type;
    void* data;
    int priority;  // 新增:优先级字段
} Event;

// 事件队列
Event eventQueue[PRIORITY_LEVELS][MAX_EVENTS];
int eventCount[PRIORITY_LEVELS] = {0};

// 事件处理函数类型
typedef void (*EventHandler)(Event*);

// 事件处理器数组
EventHandler handlers[MAX_HANDLERS];
int handlerCount = 0;

// 添加事件到队列
void addEvent(EventType type, void* data, int priority) {
    if (priority < 0 || priority >= PRIORITY_LEVELS) {
        printf("Invalid priority level\n");
        return;
    }
    if (eventCount[priority] < MAX_EVENTS) {
        eventQueue[priority][eventCount[priority]].type = type;
        eventQueue[priority][eventCount[priority]].data = data;
        eventQueue[priority][eventCount[priority]].priority = priority;
        eventCount[priority]++;
    } else {
        printf("Event queue is full for priority %d\n", priority);
    }
}

// 注册事件处理函数
void registerHandler(EventHandler handler) {
    if (handlerCount < MAX_HANDLERS) {
        handlers[handlerCount++] = handler;
    } else {
        printf("HANDLER COUNT IS MAX\n");
    }
}

// 处理所有事件
void processEvents() {
    for (int p = PRIORITY_LEVELS - 1; p >= 0; p--) {  // 从高优先级到低优先级处理
        for (int i = 0; i < eventCount[p]; i++) {
            for (int j = 0; j < handlerCount; j++) {
                handlers[j](&eventQueue[p][i]);
            }
        }
        eventCount[p] = 0; // 清空该优先级的事件队列
    }
}

// 示例事件处理函数
void handleButtonPress(Event* event) {
    if (event->type == EVENT_BUTTON_PRESS) {
        printf("BUTTON IS PRESS\n");
    }
}

void handleMouseMove(Event* event) {
    if (event->type == EVENT_MOUSE_MOVE) {
        printf("MOUSE IS MOVE\n");
    }
}

int main() {
    // 注册事件处理函数
    registerHandler(handleButtonPress);
    registerHandler(handleMouseMove);

    // 模拟添加事件及优先级
    addEvent(EVENT_MOUSE_MOVE, NULL, 0);    // 低优先级
    addEvent(EVENT_BUTTON_PRESS, NULL, 2);  // 高优先级

    // 主循环
    while (1) {
        //处理所有待处理的事件
        processEvents();

    }

    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024互联网大厂营收排名:京东/阿里/华为前三,超多技术岗都在热招!

2024年已经过去一大半&#xff0c;各大互联网大厂的竞争如火如荼&#xff0c;营收都取得了不俗的成绩&#xff0c;京东、阿里、华为分别占领前三&#xff01; 第四第五名则为华为和拼多多。 根据排行榜里的公司名单&#xff0c;小码特意为大家整理了一批各大厂的招聘岗位。 阿…

信息学奥赛复赛复习18-CSP-J2023-01小苹果-向上取整、向下取整、模拟算法

PDF文档回复:20241021 1 P9748 [CSP-J 2023] 小苹果 [题目描述] 小 Y 的桌子上放着 n 个苹果从左到右排成一列&#xff0c;编号为从 1 到 n。 小苞是小 Y 的好朋友&#xff0c;每天她都会从中拿走一些苹果。 每天在拿的时候&#xff0c;小苞都是从左侧第 1 个苹果开始、每隔…

微信碰一碰支付系统有哪些好的?教程详解抢先看!

支付宝“碰一碰支付”的风刚刚刮起来&#xff0c;它的老对手微信便紧随其后&#xff0c;推出了自己的碰一碰支付设备&#xff0c;再次印证了这个项目市场前景广阔的同时&#xff0c;也让与碰一碰支付系统相关问题的热度又上了一层楼&#xff0c;尤其是微信碰一碰支付系统有哪些…

设计模式(UML图、类之间关系、设计原则)

目录 一.类的UML图 1.类的UML图 2.类之间的关系 2.1 继承关系&#xff1a; 2.2关联关系 2.2.1单项关联 2.2.2双向关联 2.2.3自关联 2.3聚合关系 2.4组合模式 2.5依赖关系 二、设计三原则 2.1单一职责原则 2.2开放封闭原则 2.3依赖倒转原则 一.类的UML图 1.类的…

Originlab正态分布处理数据

一、图线绘制 首先&#xff0c;导入数据 点击左下角生成柱状图 绘制完成后&#xff0c;点击菜单栏【分析】-【拟合】-【非线性曲线拟合】-【打开对话框】 在函数中选择高斯即可 二、设置画布 宽、高为300.02 三、坐标轴格式 显示&#xff1a;上下左右轴 刻度线标签&#…

网络编程中容易踩的坑罗列,谨记!

1、TCP没考虑粘包分包 TCP是面向连接的可靠协议&#xff0c;TCP是流式协议&#xff0c;创建TCP套接字的类型为SOCK_STREAM int sockfd socket(AF_INET, SOCK_STREAM, 0);很多同学面试时对书上的话背诵如流&#xff0c;在实际TCP编程中却没有处理粘包和分包的代码&#xff0c;以…

十年编程路,一生踏征途

时光荏苒流逝&#xff0c;白驹匆匆过隙&#xff0c;不知不觉间&#xff0c;我已经在程序开发这条道路上走过了整整十年。从最初的求学&#xff0c;到如今成为一名较为资深的职业开发者&#xff0c;这一路充满了挑战、学习、成长与感动。在这1024程序员节的特殊时刻&#xff0c;…

mysql5.7.30绿色版安装

下载地址&#xff1a;MySQL :: Download MySQL Community Server (Archived Versions) 参考&#xff1a;【绿色版】Mysql下载、安装、配置与使用&#xff08;保姆级教程&#xff09;_mysql 绿色安装-CSDN博客 从下载地址中下载mysql&#xff0c;解压zip安装包&#xff0c;到想…

A Graph-Transformer for Whole SlideImage Classification文献笔记

基本信息 原文链接&#xff1a;[2205.09671] A graph-transformer for whole slide image classification (arxiv.org) 源码&#xff1a;https://github.com/vkola-lab/tmi2022 提出了一种融合了基于图的WSI表示和用于处理病理图像的视觉转换器&#xff0c;称为GTP&#xff…

听说现在二建不值钱了,还有必要考吗?

面对这样的现状&#xff0c;新手们都会不禁要问:考证真的有用吗?它是否值得我们投入时间和精力?首先&#xff0c;我觉得我们需要对自己有一个清晰的认识&#xff0c;包括你的就业状况。 ①如果你已经在事业单位工作&#xff0c;那么考证可能对你来说并不是那么必要 在事业单…

图片写入GPS经纬高信息

近期项目中需要往java平台传输图片&#xff0c;直接使用QNetworkAccessManager和QHttpMultipart类即可&#xff0c;其他博文中有分享。 主要是平台接口对所传输图片有要求&#xff1a;需要包含GPS信息&#xff08;经度、纬度、高度&#xff09;。 Qt无法直接实现&#xff0c;…

【React】React18核心源码解读

前言 本文使用 React18.2.0 的源码&#xff0c;如果想回退到某一版本执行git checkout tags/v18.2.0即可。如果打开源码发现js文件报ts类型错误请看本人另一篇文章&#xff1a;VsCode查看React源码全是类型报错如何解决。 阅读源码的过程&#xff1a; 下载源码 观察 package…

智源重磅发布 Emu3:颠覆AI多模态领域的革命性多模态大模型

在2024年10月21日&#xff0c;智源研究院正式发布了新一代的革命性多模态大模型——Emu3。这一突破标志着AI生成技术进入一个全新阶段&#xff0c;它不仅颠覆了当前的主流扩散模型&#xff08;例如Stable Diffusion&#xff09;&#xff0c;还为图像、文本和视频生成任务带来了…

HTML+CSS实现点赞效果

效果演示 HTMLCSS实现点赞效果 HTML <div class"heart-container" title"Like"><input type"checkbox" class"checkbox" id"Give-It-An-Id"><div class"svg-container"><svg viewBox&qu…

1.前提配置 关防火墙 关selinux

1.前提配置 关防火墙 关selinux 2.安装web服务程序nginx 未安装则需重新设置挂载点 若已安装&#xff0c;则查看系统中是否存在 3.当前主机添加多地址&#xff08;ip a&#xff09; 配置了三个IP地址 查看IP地址是否配置成功 4.自定义nginx配置文件通过多地址区分多网站 /…

MySQL中的优先规则

在图片的例子中&#xff0c;有两个条件&#xff1a; 第一个条件是job_id是AD_PRES并且薪水高于15,000。 第二个条件是job_id是SA_REP。 在图片中的例子有两个条件&#xff1a; 第一个条件是job_id是AD_PRES或者SA_REP。 第二个条件是薪水高于$15,000。

java如何部署web后端服务

java如何部署web后端服务 简单记录一下&#xff0c;方便后续使用。 部署流程 1.web打包 2.关掉需要升级的运行中的服务 /microservice/hedgingcustomer-0.0.1-SNAPSHOT/conf/bin/ 执行脚本 sh shutdown.sh 3.解压文件 返回到/microservice 将升级包上传到该路径&#x…

分布式ID多种生成方式

分布式ID 雪花算法&#xff08;时间戳41机器编号10自增序列号10&#xff09; 作用&#xff1a;希望ID按照时间进行有序生成 原理&#xff1a; 即一台带有编号的服务器在毫秒级时间戳内生成带有自增序号的ID,这个ID保证了自增性和唯一性 雪花算法根据结构的生成ID个数的上线时…

数字图像处理:图像分割应用

数字图像处理&#xff1a;图像分割应用 图像分割是图像处理中的一个关键步骤&#xff0c;其目的是将图像分成具有不同特征的区域&#xff0c;以便进一步的分析和处理。 1.1 阈值分割法 阈值分割法&#xff08;Thresholding&#xff09;是一种基于图像灰度级或颜色的分割方法&…

PHP短视频实训平台系统小程序源码

&#x1f3a5;短视频新纪元&#xff01;短视频实训平台系统&#xff0c;解锁创作新技能&#x1f511; &#x1f680;一键入门&#xff0c;创作无界&#x1f310; 想要玩转短视频&#xff0c;却不知从何下手&#xff1f;短视频实训平台系统是你的创意启航站&#xff01;平台内…