c++ 中的多线程线程安全动画建议

发布于 2024-11-14 11:58:04 字数 1438 浏览 3 评论 0原文

我有一个基于计时器的动画程序,该程序计划在工作线程中运行。该程序被设计为在启动时始终运行。我还有一个图像生成线程,它负责图像处理,然后将每个处理后的图像(JPEG/PNG 格式)提供给动画线程以参与图像循环,无需用户干预。

这是一个典型的基于内存的图像循环程序。也就是说,所有用户选择的图像都被预先加载到RAM中。我使用映射容器来管理图像序列,以 std::map 的格式声明,它将 Key 类型的图像文件名与 Data 类型的 CBitmap 指针关联起来。我还使用向量字符串(如 std::vector 声明)以与上述映射键列表相对应的排序顺序保存图像文件列表的副本,以便按顺序号迭代每个图像。这可能没有必要。

关于动画控制,允许执行以下类似信息亭的操作(有些操作带有各自的变量声明):

bool m_bPlay;   // Play forward
bool m_bPause; // Pause animation
bool m_bStop;  // Stop animation
bool m_bReverse; // Play backward
bool m_bRepeat; // Repeated play when reaching to last image
DWORD m_dwFrom;  // Starting image number
DWORD m_dwTo;    // Ending image number
DWORD m_dwCurrent;  // Current image number
DWORD m_dwFPS;   // Frames per second


其中 m_dwTo 变量可以由用户通过使用嵌入在主 GUI 窗口顶部的工具栏中的旋转按钮来更改,或者每次将新处理的图像添加到上述地图中时由应用程序自动增加,如下所示以及矢量容器。类似地,m_dwFrom 变量也可以像 m_dwTo 一样手动更改,或者根据用户定义的滚动存档配置(例如,keep 3天内),同时应将过期的图像从上述地图和矢量容器中删除。用户可以在图像循环过程中随时更改 m_dwFPS 变量,并在主 GUI 窗口顶部的工具栏中嵌入一个下拉列表框。

感谢您花时间阅读我想做的长篇解释。我希望它能帮助您回答我的以下问题:

  1. 为了使 m_dwFrom、m_dwTo、m_dwCurrent 和 m_dwFPS 线程安全,使用 InterlockedExchange 或 InterlockedCompareExchange 是否比使用其他锁更高效且性能提升比如 CriticalSection、Mutex 等?
  2. 如何使 std::map 和 std::vector 线程安全?仅使用传统锁,还是与编译器重新排序屏障(例如,Visual C++ 的 _ReadWriteBarrier)和/或 CPU 重新排序屏障(例如 MemoryBarrier x86 和 x64 CPU 系列)结合使用更好?

我期待看到您的建议。代码或虚假代码片段受到高度赞赏。预先感谢您!

金李

I have a timer-based animation program, which was scheduled to be run in a worker thread. The program was designed to run operationally all the time on startup. I also have an image production thread, which is responsible for image processing, and then feeds each processed image (in JPEG/PNG format) to the animation thread to take part in image looping without user intervention.

That's a typical memory-based image looping program. That is to say, all user-selected images are loaded into RAM in advance. I use a map container to manage the image sequence, declared in the format of std::map, which associates image file names of type Key with CBitmap pointers of type Data. I also use a vecter string (declared like std::vector) to keep a copy of the image file list in a sorted order corresponding to the aforesaid map key list in order to iterate each image by is sequential number. That's may be not necessary.

With regard to animaion control, the following kiosk-like operations (some accompanied with their respectve variables declarations) are allowed:

bool m_bPlay;   // Play forward
bool m_bPause; // Pause animation
bool m_bStop;  // Stop animation
bool m_bReverse; // Play backward
bool m_bRepeat; // Repeated play when reaching to last image
DWORD m_dwFrom;  // Starting image number
DWORD m_dwTo;    // Ending image number
DWORD m_dwCurrent;  // Current image number
DWORD m_dwFPS;   // Frames per second

Where m_dwTo variable can be changed by a user through the use of a spin button embedded in a toolbar doakced on the top of the main GUI window, or increased automatically by the application each time a newly processed image added into the above-mentioned map as well as vector containers. Similarly, m_dwFrom variable can also be changed manually in the same way as m_dwTo, or reduced automatically by the application whenever one or more than one in-play images are expired on the basis of the user-defined rolling archive configuration (for example, keep images in 3 days), and at the same time, the overdue image(s) should be removed from the above-mentioned map and vector containers. The m_dwFPS variable can be changed by user at any time in the process of image looping with a drop-down list box embedded in a toolbar doakced on the top of the main GUI window.

Thank you for taking the time to read the long explanation on which I want to do. I do hope that it can help you in answering my following questions:

  1. In order to make m_dwFrom, m_dwTo, m_dwCurrent, and m_dwFPS thread safe, is it more efficient and performance gaining by using InterlockedExchange or InterlockedCompareExchange than the use of other locks such as CriticalSection, Mutex, and etc.?
  2. How to make std::map and std::vector thread safe? Use traditional locks only, or better coupled with compiler reordering barrier (for example, _ReadWriteBarrier forVisual C++) and/or CPU reordering barrier (for example, MemoryBarrier x86 and x64 CPU family)?

I'm looking forward to seeing your suggestions. Code or false code snippets are highly appreciated. Thank you in advance!

Golden Lee

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

看轻我的陪伴 2024-11-21 11:58:04

我可能是错的,但据我从你的描述中猜测,我会使用传统的锁和互斥体来使你的共享向量和映射以及其他共享变量线程安全。这只是最直接的方法,您的场景听起来并没有真正需要性能密集型来证明任何更复杂的事情是合理的。如果分析显示传统锁定成为性能问题,我只会接触任何更奇特的东西!

如何使 std::map 和 std::vector 线程安全?

常见的方法是简单地在需要访问的容器函数周围编写一个锁定包装器。例如:

class myAnimationManager{
private:
std::map<std::string, CBitmap*> m_imagesMap;
Mutex m_mutex;

public:
CBitmap * getImageByName(const std::string & _name)
{
ScopedLock l(m_mutex); //lock image map access
return m_imagesMaps[_name];
}
//...
};

使用标准锁定原语的好处不仅在于简单,而且在使用 boost::thread 时也具有可移植性。

I might be wrong but as far as I can guess from you description I'd go with traditional locks and mutexes to make your shared vector and map aswell as your other shared variables threadsafe. It simply is the most straightforward way and your scenario does not really sound that performance intensive to justify anything more complex. I'd only touch anything more fancy if profiling shows that traditional locking becomes a performance issue!

How to make std::map and std::vector thread safe?

The common way to do that is to simply write a locking wrapper around the container functions you need access to. For instance:

class myAnimationManager{
private:
std::map<std::string, CBitmap*> m_imagesMap;
Mutex m_mutex;

public:
CBitmap * getImageByName(const std::string & _name)
{
ScopedLock l(m_mutex); //lock image map access
return m_imagesMaps[_name];
}
//...
};

The good thing about staying with standard locking primitives is not only simplicity but also portability when using boost::thread for instance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文