help-smalltalk
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Help-smalltalk] Re: Gtk event loop


From: Paolo Bonzini
Subject: [Help-smalltalk] Re: Gtk event loop
Date: Tue, 16 Feb 2010 19:20:06 +0100
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.7) Gecko/20100120 Fedora/3.0.1-1.fc12 Lightning/1.0b2pre Thunderbird/3.0.1

On 02/16/2010 05:00 PM, Paolo Bonzini wrote:
On 02/16/2010 03:32 PM, Gwenael Casaccio wrote:
we should extend the binding generator to generate thread safe gtk
functions
(with gdk_threads_enter the gtk_function gdk_threads_leave)

Please expand?

Uhm, from discussion on IRC I see what you're saying.

While nice, this approach is probably a kind of dead end. You'd have a huge nightmare stemming from executing C callbacks in a thread and Smalltalk callbacks in another.

Instead, we should keep the best of the two approaches we have.

From your code we get the fact that polling runs in another thread. From what exists we get the fact that only one thread runs GTK+ stuff.

Based on GLib's code, this is approximately the code that should run in the other thread:

gpointer
loop (gpointer data)
{
    static GPollFD *fds;
    static int allocated_nfds;
    GMainLoop *loop = data;
    GMainContext *context = g_main_loop_get_context (loop);

    if (!fds) {
        fds = g_new (GPollFD, 20);
        allocated_nfds = 20;
    }

    while (g_main_loop_is_running (loop)) {
        int nfds, maxprio, timeout;
        if (!g_main_context_acquire (context)) {
            if (!g_main_context_pending (context))
                continue;
        } else {
            g_main_context_prepare (context, &maxprio);
            while ((nfds = g_main_context_query (context, maxprio,
                               &timeout, fds, allocated_nfds)) >
                     allocated_nfds) {
                g_free (fds);
                fds = g_new (GPollFD, nfds);
                allocated_nfds = nfds;
            }

            // release the context so that the other thread can dispatch
            g_main_context_release (context);
            g_poll (timeout, fds, nfds);

            // If the other thread is now dispatching, calling
            // g_main_context_pending will wait until it releases the
            // context and then poll again---but without dispatching,
            // so we still have to signal the semaphore!
            if (!g_main_context_acquire (context)) {
                if (!g_main_context_pending (context))
                    continue;
            } else {
                g_main_context_check (context, maxprio, fds, nfds);
                g_main_context_release (context);
            }
        }

        // signal smalltalk semaphore and wake up other thread
        sched_yield ();
    }
}

static GMainLoop *loop;
static GThread *thread;

void
gstGtkMain ()
{
    loop = g_main_loop_new (NULL, TRUE);
    thread = // create thread
}

void
gstGtkMainQuit ()
{
    g_main_loop_quit (loop);
    g_thread_join (thread);
}

and the Smalltalk process will just call repeatedly (with an async C callout, contradicting what I said in the previous email):

void
gstGtkMainDispatch ()
{
    while (!g_main_context_acquire (context)) {
        g_main_context_pending (context);
    }
    g_main_context_dispatch (g_main_loop_get_context (loop));
    g_main_context_release (context);
}

after waiting on a Semaphore.

Paolo




reply via email to

[Prev in Thread] Current Thread [Next in Thread]