我有一个多线程应用程序,其中每个线程都创建自己的表面、渲染内容、保存并销毁所有内容。
但是,一段时间后(例如保存了 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
变量,用于保护某些初始化。由于它是静态的,我们可以确定没有其他代码接触到这个变量。
_cairo_atomic_init_once_enter
检查 once
是否已经初始化,然后返回 0/false
。既然你说你已经有 20 个成功的电话,那么初始化必须已经完成。否则,其他 20 个调用不应该起作用。
根据上述...这应该不可能发生,对吧?
除非有什么东西覆盖了一些它不应该接触的内存并且 once
的值被破坏,或者类似的东西。
或者,这是由于我不明白的原因而发生的某种错误编译。您是自己编译 cairo 还是从哪里得到的?
关于c++ - 开罗 - 多线程 - 在 cairo_image_surface_create 期间卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58120390/