c++ - 在单个线程中使用信号量模拟多线程
问题描述
我想在 Windows 机器 (C++) 上模拟嵌入式设备的固件 (C++)。固件在微控制器 (nRF5340) 上运行,并将 Zephyr 作为操作系统运行。在真正的固件中有多个任务。
现在的挑战是:我希望能够创建一个虚拟设备的多个实例,但每个设备只能在一个线程中运行。
信号量用于多线程(在固件中),它们被阻塞或释放。有没有办法可以在单个线程中使用信号量并实现一种上下文切换?
因此,例如,调用一个贯穿信号量的函数。当达到信号量时,可以调用一个新函数来释放先前的信号量,以便原始函数可以继续(但都在一个线程中)。
解决方案
这可以通过协程来完成。协程就像一个函数,但在程序体中的某个点上程序员会调用 yield。这保存了协程的状态。它可以稍后在它产生的点恢复。
协程被添加到 C++20。但是,他们还没有为任务管理库添加规范。自己实现将是大量的工作。你可以找到第 3 方的。Boost 还有 3 个早于 C++20 的协程库(1 个旧的、1 个当前的和 1 个专门用于 Asio)。使用 3rd 方任务管理库可能是更好的方法,但您必须使用 C++20并学习一个可能很快就会过时的新库。
或者,如果您允许每个虚拟设备为其每个模拟线程生成一个实际线程,然后编写某种同步方式,以便每个虚拟设备在任何给定时间仅运行 1 个线程,您也可以进行变通。您实际上是在利用一个真正的线程内置了上下文切换这一事实。我会使用这种方法,因为它避免了在与您的项目相切的事情上进行大量开发,而且我已经知道如何使用线程工具。
最后,您可以为每个模拟线程创建一个“堆栈”并自己进行上下文切换。你会失去便携性。基本上,您正在编写自己的协程库,但它是针对您的用例量身定制的,因此更易于使用。但是,开发时间可能会与仅学习如何使用现有库相平衡。
回到中间方法(每个模拟线程的真实线程)......你的屈服函数可能看起来像:
每个模拟线程都有自己的信号量(因此您可以指定调用哪个):
void switch_to(T& other)
{
other.up()
me.down();
}
或者虚拟设备上的所有模拟线程共享一个信号量:
void switch()
{
sem.up();
sem.down();
}
(这种方法只有在信号量实现公平的情况下才有效。)
两种方式,您都使用 0 次传递来初始化信号量,并让每个线程在信号量上调用 down() 作为其第一个操作(这会将每个线程初始化为阻塞状态)。
C++ 没有标准的信号量,但您可以使用条件变量来实现。
推荐阅读
- reactjs - 我想要反应钩级联选择选项
- perl - 如何有条件地匹配一行的最后一部分?
- python - AWS CustomeResource 卡在更新过程中
- python - Matterport-Mask RCNN 中每个时期的步骤/验证步骤
- java - Spring Boot 应用程序不提供 Web 内容
- c# - 使用 linq 查询创建列表时出现 IGrouping 错误
- typescript - Firebase中用于设置数据的困难结构定义
- angular - node_modules/ionic-angular/umd/components/action-sheet/action-sheet-component.d.ts:1:22 中的错误 - 错误 TS2724
- spring - Hibernate x Multithreading = org.hibernate.HibernateException:实例的标识符从 97 更改为 96
- export - MarkLogic 查询的导出结果(mlcp、xdmp.save)