c++ - 开罗 - 多线程 - 在 cairo_image_surface_create 期间卡住

标签 c++ multithreading cairo

我有一个多线程应用程序,其中每个线程都创建自己的表面、渲染内容、保存并销毁所有内容。

但是,一段时间后(例如保存了 20 张图像),应用程序卡在 cairo-atomic-private.h_cairo_atomic_init_once_enter 中。

这是来自 Visual Studio 的堆栈跟踪:

[Inline Frame] app.exe!_cairo_atomic_init_once_enter(unsigned int *) Line 409   C
app.exe!_cairo_image_spans_compositor_get() Line 3135   C
[Inline Frame] app.exe!_cairo_image_surface_init(_cairo_image_surface *) Line 176   C
app.exe!_cairo_image_surface_create_for_pixman_image(pixman_image * pixman_image=0x0000023c1d1f31f0, pixman_format_code_t pixman_format=PIXMAN_a8r8g8b8) Line 197   C
app.exe!_cairo_image_surface_create_with_pixman_format(unsigned char * data=0x0000000000000000, pixman_format_code_t pixman_format=PIXMAN_a8r8g8b8, int width, int height, int stride=-1) Line 355  C
app.exe!cairo_image_surface_create(_cairo_format format, int width, int height) Line 403    C

我正在打电话:

surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, int(w), int(h));

我的并行循环是通过:

std::vector<int> xSeq(countX); 
std::iota(std::begin(xSeq), std::end(xSeq), 0); // Fill with 0, 1, ..., countX.
std::for_each(std::execution::par, std::begin(xSeq), std::end(xSeq), [&](auto x)
{
    //create cairo surface, write to it, store it and release it
}

如果我运行串行版本,一切正常。

编辑: 为了将表面存储到图像,我不使用内部 PNG 保护程序。我有自己的实现,它基于:

cairo_surface_flush(surface);
data = cairo_image_surface_get_data(surface);

data 包含来自 cairo 的原始数据,我手动处理它们并使用我自己的压缩系统存储它们。

在某些情况下,我还使用相同的系统将数据“注入(inject)”到 cairo 表面。我获得 data 指针,手动重写一些像素并调用 cairo_surface_mark_dirty(surface) 通知 Cairo 有关更改。

最佳答案

这并不是真正的答案,但您看到的行为应该是不可能的。

_cairo_image_traps_compositor_get 有一个 cairo_atomic_once_t 变量,用于保护某些初始化。由于它是静态的,我们可以确定没有其他代码接触到这个变量。

https://github.com/freedesktop/cairo/blob/52a7c79fd4ff96bb5fac175f0199819b0f8c18fc/src/cairo-image-compositor.c#L1270-L1304

_cairo_atomic_init_once_enter 检查 once 是否已经初始化,然后返回 0/false。既然你说你已经有 20 个成功的电话,那么初始化必须已经完成。否则,其他 20 个调用不应该起作用。

https://github.com/freedesktop/cairo/blob/52a7c79fd4ff96bb5fac175f0199819b0f8c18fc/src/cairo-atomic-private.h#L398-L411

根据上述...这应该不可能发生,对吧? 除非有什么东西覆盖了一些它不应该接触的内存并且 once 的值被破坏,或者类似的东西。 或者,这是由于我不明白的原因而发生的某种错误编译。您是自己编译 cairo 还是从哪里得到的?

关于c++ - 开罗 - 多线程 - 在 cairo_image_surface_create 期间卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58120390/

相关文章:

c++ - 卡在 api getdrivetype

gtk - 在 GtkDrawingArea draw_callback 之外访问 Cairo 上下文

java - Actor 与线程的定义有何不同?

c - 如何使用 GTK/Cairo 将多个 PNG 合成为单个 PNG

python - 重新粉刷开罗 window ?

c++ - 如何将用 linux 编写的 std::wstring 读入 windows

c++ - MongoDB C++ 段错误

c++ - 模板模板参数和转发引用

c# - 使用任务工厂存储每个任务的任务完成时间

c - Linux 内核互斥量