[cairo-bugs] [Bug 74355] Line drawing not thread-safe
bugzilla-daemon at freedesktop.org
bugzilla-daemon at freedesktop.org
Thu Feb 6 10:41:24 PST 2014
https://bugs.freedesktop.org/show_bug.cgi?id=74355
--- Comment #3 from H. Guijt <hguijtra at xs4all.nl> ---
The following program should reproduce the problem but _doesn't_. I'm at a loss
why since it goes through the exact same steps the larger application does; the
only thing I can think of right now is that it might actually be a stack
problem for the worker threads - this might not occur if the whole thing runs
on a single thread. Not quite sure what to make of it right now, but I will
continue to investigate.
------
#include <array>
#include <cairo-win32.h>
#include <future>
#include <iostream>
const int Width = 2000;
const int Height = 1000;
const int NumThreads = 4;
double RandomValue (double Range)
{ return (Range * rand ()) / RAND_MAX;
}
void DrawCurve (cairo_t *Cairo)
{ ::cairo_set_source_rgba (Cairo, RandomValue (1.0), RandomValue (1.0),
RandomValue (1.0), RandomValue (1.0));
::cairo_set_line_width (Cairo, RandomValue (10.0));
const struct {
int Size;
double Pattern [6];
} Patterns [] = {
{ 0, { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } },
{ 2, { 0.0, 4.0, 0.0, 0.0, 0.0, 0.0 } },
{ 2, { 12.0, 4.0, 0.0, 0.0, 0.0, 0.0 } },
{ 4, { 12.0, 4.0, 0.0, 4.0, 0.0, 0.0 } },
{ 6, { 12.0, 4.0, 0.0, 4.0, 0.0, 4.0 } },
};
const int LinePattern = static_cast<int> (RandomValue (7.0));
if (LinePattern == 6)
::cairo_set_dash (Cairo, nullptr, 0, 0.0);
else
::cairo_set_dash (Cairo, Patterns [LinePattern].Pattern, Patterns
[LinePattern].Size, 0.0);
::cairo_move_to (Cairo, RandomValue (Width), RandomValue (Height));
const int NumLines = static_cast<int> (RandomValue (2000.0));
for (int x=0; x<NumLines; ++x)
::cairo_line_to (Cairo, RandomValue (Width), RandomValue (Height));
::cairo_stroke (Cairo);
}
int main (int argc, const char* argv [])
{
int It = 0;
for (;;) {
std::cout << "Iteration " << ++It << "\n";
struct THREADDATA {
std::future<void> Future;
cairo_surface_t *CairoSurface;
cairo_t *Cairo;
THREADDATA () {};
THREADDATA (const THREADDATA &Other) {};
};
std::array<THREADDATA, NumThreads> Threads;
// Set up the surfaces.
for (auto &Thread : Threads) {
Thread.CairoSurface = ::cairo_image_surface_create
(CAIRO_FORMAT_ARGB32, Width, Height);
Thread.Cairo = ::cairo_create (Thread.CairoSurface);
// Make the surface transparent.
::cairo_set_operator (Thread.Cairo, CAIRO_OPERATOR_SOURCE);
::cairo_set_source_rgba (Thread.Cairo, 0.0, 0.0, 0.0, 0.0);
::cairo_rectangle (Thread.Cairo, 0, 0, Width, Height);
::cairo_fill (Thread.Cairo);
::cairo_set_operator (Thread.Cairo, CAIRO_OPERATOR_OVER);
}
// Draw the curves on separate threads.
for (auto &Thread : Threads) {
Thread.Future = std::async (std::launch::async, [&Thread] {
for (int x=0; x<250; ++x)
DrawCurve (Thread.Cairo);
});
}
// Wait for completion.
for (auto &Thread : Threads)
Thread.Future.get ();
// Create the final graph.
cairo_surface_t *CairoSurface = ::cairo_image_surface_create
(CAIRO_FORMAT_ARGB32, Width, Height);
cairo_t *Cairo = ::cairo_create (CairoSurface);
for (auto &Thread : Threads) {
::cairo_set_source_surface (Cairo, Thread.CairoSurface, 0, 0);
::cairo_rectangle (Cairo, 0, 0, Width, Height);
::cairo_fill (Cairo);
::cairo_destroy (Thread.Cairo);
::cairo_surface_destroy (Thread.CairoSurface);
}
::cairo_surface_write_to_png (CairoSurface, "c:\\result.png");
::cairo_destroy (Cairo);
::cairo_surface_destroy (CairoSurface);
}
return 0;
}
--
You are receiving this mail because:
You are the QA Contact for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cairographics.org/archives/cairo-bugs/attachments/20140206/2e4c50a9/attachment.html>
More information about the cairo-bugs
mailing list