<html>
    <head>
      <base href="https://bugs.freedesktop.org/" />
    </head>
    <body>
      <p>
        <div>
            <b><a class="bz_bug_link 
          bz_status_NEEDINFO "
   title="NEEDINFO --- - Line drawing not thread-safe"
   href="https://bugs.freedesktop.org/show_bug.cgi?id=74355#c3">Comment # 3</a>
              on <a class="bz_bug_link 
          bz_status_NEEDINFO "
   title="NEEDINFO --- - Line drawing not thread-safe"
   href="https://bugs.freedesktop.org/show_bug.cgi?id=74355">bug 74355</a>
              from <span class="vcard"><a class="email" href="mailto:hguijtra@xs4all.nl" title="H. Guijt <hguijtra@xs4all.nl>"> <span class="fn">H. Guijt</span></a>
</span></b>
        <pre>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;
}</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are the QA Contact for the bug.</li>
      </ul>
    </body>
</html>