Re: Multi-threaded GUI



Ok, round 30 or so....

Bellow is the entire code for my callbacks that I cant seem to get working. I am trying to have a thread update the main window for the program. After much much hacking, trial, and error the code finaly compiles, however the program segfaults with no errors when I try to connect the Glib::signal_idle() (the highlighted line below).

I really have no idea whats going on... Thanks to all you guys who have been helping me so far.

Sincerely
Melvin Newman

// generated 2006/9/27 0:19:56 EDT by root Titan (none)
// using glademm V2.6.0
//
// newer (non customized) versions of this file go to window1.cc_new

// This file is for your program, I won't touch it again!

/*
    Define Statements for default config
**************************************************************/
#define SERVER_IP "192.168.0.142"
#define SERVER_PORT 18000

#include "config.h"
#include "window1.hh"

#include <stdlib.h>
#include < glib.h>
#include <gtkmm.h>
#include <pthread.h>

// Networking headers
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>

/* Structures
**************************************************************/
struct arguments{
    Glib::RefPtr<Gtk::TextBuffer> out_put_buffer;
    int socket_id;
    struct sockaddr_in address;
}pthread_arg;

/* I am tired of playing by the rules... So these thread
   classes are now being declared global to make my life
   easier
**************************************************************/
pthread_t thread1;

/* Custom functions
**************************************************************/
bool updater(void)
{
    /* Variables
    ******************************************/
        Glib::RefPtr<window1> main_window;
        Glib::RefPtr<Gdk::Window>win = main_window->get_window();
    /*****************************************/
   
    if(win)
    {
        Gdk::Rectangle r(0, 0, main_window->get_allocation().get_width(),main_window->get_allocation().get_height());
        win->invalidate_rect(r, false);
    }
    return(FALSE);
}

void *server_connect(void *ptr)
{
    /* Variables
    ******************************************/
        int tmp=0;
        int socket_id;
        struct sockaddr_in address;
        Glib::RefPtr<Gtk::TextBuffer> buffer;
        sigc::connection pipe1;
    /*****************************************/
   
    socket_id = pthread_arg.socket_id;
    address = pthread_arg.address;
    buffer = pthread_arg.out_put_buffer;
   
   ==============> Glib::signal_idle().connect(sigc::ptr_fun(&updater));  < ============== Program Segfaults here
       
    do
    {
        tmp = connect (socket_id,(struct sockaddr *) &address, sizeof(struct sockaddr));
        if (tmp <0)
        {
            buffer->insert_at_cursor("@");
            Glib::usleep(400000);
        }
       
    }while(tmp<0);
   
    buffer->insert_at_cursor("\n\n----------=========== Connected To Server ===========----------\n");

}
   
/*
    Call Backs for widgets
**************************************************************/

void window1::on_Menu_exit()
{
    Gtk::Main::quit();

}

void window1::on_Connect_pressed()
{
   
    /* Variables
    ******************************************/
    Glib::RefPtr<Gtk::TextBuffer> buffer; // buffer for text output (its a pointer)
    /* Network Specific Variables
    **********************************/
    struct sockaddr_in server_address;
    int socket_id; // File descripter for networking
    /*********************************/
   
    // Set up the text buffer for the text output section
    buffer=textview1->get_buffer();
   
    // Set up connection to server
    socket_id = socket(AF_INET, SOCK_STREAM,0);
    if (socket_id < 0)
    {
        buffer->insert_at_cursor("Unable to create socket\n");
    }

   
    server_address.sin_family = AF_INET;            // network protocol
    server_address.sin_port = htons(SERVER_PORT);        // destination port#, in this case 18000
    server_address.sin_addr.s_addr = inet_addr (SERVER_IP); // destination server ip... will be changeable later
    memset(&(server_address.sin_zero), '\0', 8);        // zero the rest of the structure
   
    pthread_arg.out_put_buffer=buffer;
    pthread_arg.socket_id=socket_id;
    pthread_arg.address=server_address;
   
    // Here we break off the
    pthread_create(&thread1,NULL,server_connect,0);
   
}


On 10/5/06, Chris Vine < chris cvine freeserve co uk> wrote:
On Thursday 05 October 2006 04:34, Melvin Newman wrote:
> My saga towards updating the GUI continues... the following are two code
> snippets:
>
> 1) My window update function. It is built into the window1 class and is
> supposed to update the main GUI window:
>
> gboolean window1::updater(gpointer data)
> {
>     /* Variables
>     ******************************************/
>         Glib::RefPtr<Gdk::Window>win = get_window();
>     /*****************************************/
>
>     if(win)
>     {
>         Gdk::Rectangle r(0, 0,
> get_allocation().get_width(),get_allocation().get_height());
>         win->invalidate_rect(r, false);
>     }
>     return(true);
> }
>
>
> 2) The following is my thread that calls this function through the
> g_idle_add() function... Unfortunately it does not compile at this line and
> being new to OO/C++ I have no idea why, or how to fix the problem:
>
> void *server_connect(void *ptr)
> {
>     /* Variables
>     ******************************************/
>         int tmp=0;
>         int socket_id;
>         struct sockaddr_in address;
>         gpointer data;
>         Glib::RefPtr<Gtk::TextBuffer> buffer;
>         sigc::connection pipe1;
>     /*****************************************/
>
>     socket_id = pthread_arg.socket_id;
>     address = pthread_arg.address;
>     buffer = pthread_arg.out_put_buffer;
>
>     do
>     {
>         tmp = connect (socket_id,(struct sockaddr *) &address,
> sizeof(struct sockaddr));
>         if (tmp <0)
>         {
>             buffer->insert_at_cursor("@");
>
>             g_idle_add(window1::updater,false);
>                ^-- Compiling stops here with: error: invalid use of
> non-static member function `gboolean window1::updater(void*)'
>
>             Glib::usleep(400000);
>         }
>
>     }while(tmp<0);
>
> }
>
> Unfortunately I cant seem to integrate the server_connect function into the
> class, because pthread then complains that it can not call it (miss mach
> type).
>
> Any help would be greatly appreciated.

If you are using (as it appears) the glibmm and gtkmm wrappers, then you ought
to use Glib::SignalIdle class (and the convenience function
Glib::signal_idle().connect()) rather than g_signal_idle().  Make sure your
idle handler returns false.  See
http://gtkmm.sourceforge.net/docs/glibmm-2.4/docs/reference/html/classGlib_1_1SignalIdle.html

You appear from your code snippet to be holding Gtkmm widgets in
Glib::RefPtr<>s.  That is a no-no - they are only intended to hold objects
which are GObjects, but not derived from GtkObject or GInitiallyUnowned
(Gtk::Object or Glib::InitiallyUnowned in gtkmm-speak).  The reference
counting will go awry if you put them into Glib::RefPtr<>s.

Alternatively it is quite straightforward to use unwrapped glib in C++
programs.  You can pass the this pointer of the class you are interested in
as the data argument in g_signal_idle() (and any other glib/gtk+ event/signal
handlers).  Make sure you declare your handler functions as extern "C"
though, so that they have the correct linkage.  (gcc allows you to use static
member functions in callbacks with C linkage, but not all compilers do.)

This has a few convenience things in it which I use, if you want to use
unwrapped glib/GTK+/pthreads:

http://efax-gtk.cvs.sourceforge.net/efax-gtk/efax-gtk/src/utils/

Chris




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