A number of design decisions went into the GPK library. This page explains how the library is designed and some of the rationale for it.

Prerequisites

GPK needs two supporting libraries:
  1. GTK version 0.99.2 or later and
  2. An implementation of POSIX threads

Many versions of Pthreads exist on many platforms. Any standard implementation of 1003.1c threads should work fine.

On Linux, I have tested two Pthread implementations for use with GPK: PMPthreads and LinuxThreads.
  1. PMPthreads works for any version of Linux and has recently been updated to support Red Hat Linux 5.0. RH 5.0 includes glibc, the new version of the libc, and GPK works great with this library. It requires no special thread-safe versions of the X libraries or libc and requires no special compiler options other than the use of the pgcc script for the compiler.
  2. LinuxThreads are available for Linux 2.0 and beyond, but its use is a bit more difficult:
    • LinuxThreads requires use of X libraries compiled to be thread-safe. These are available as precompilied binaries on the Internet. Red Hat Linux 5.0 has these as part of its standard issue now.
    • You must install the LinuxThreads library and compile all your code using the -D_REENTRANT compiler flag.
    • If you use Red Hat Linux 5.0, LinuxThreads and glibc are built in, and GPK and PerfMon compile just fine. Unfortunately, a bug in LinuxThreads thread-specific data cleanup causes PerfMon (and any other programs that cancel threads) to crash.
    • RH 5.0 also contains an old version of GTK that is incompatible with new releases and will not work with GPK. Install the latest GTK (will go in /usr/local/bin) and uncomment the line in the Makefile that forces a static link.

The Classic Example

Below is the classic "Hello World" example for GPK. main() initializes itself to use GTK with gtk_init() as usual. The gpk_init() call then prepares this thread to act as a proxy for any threads using gpk_ calls. After firing up the hello() thread, it enters the GTK event loop.

The hello() thread illustrates the use of gpk_ calls. Nearly all parameters to a gpk_ functions are a pointers. In general, GPK functions try to encapsulate GTK idioms or commonly used sequences of GTK function calls. In other words, each GPK call is usually comprised of multiple GTK calls when it arrives at the GTK thread.

        
#include <gtk/gtk.h>
#include "gpk/gpk.h"

void
say_hello ()
{
  printf ("hello world\n");
}

void 
destroy (GtkWidget * widget, gpointer * data)
{
  gtk_main_quit ();
}

void
hello ()
{
  GskApplicationWindow *window;
  GtkWidget *hbox;
  BoxAttributes box_attr = { NONHOMOGENOUS,        /* homogenous  */
                             BOX_SHRINK_TO_OBJS,   /* expand      */
                             FILL_BETWEEN_WIDGETS, /* fill        */
                             0,                    /* spacing     */
                             0,                    /* padding     */
                             10 };                 /* borderwidth */

  WidgetAttributes button_attr = { BOX_SHRINK_TO_OBJS,    /* expand  */
                                   FILL_BETWEEN_WIDGETS,  /* fill    */
                                   0 };                   /* padding */
                 

  window = gpk_application_window_new ("Hello World", 
                                       GTK_SIGNAL_FUNC (destroy));

  hbox = gpk_hbox_new (window->widget, &box_attr);
  gpk_pushbutton_new ("Hello World", hbox, &button_attr, 
                      GTK_SIGNAL_FUNC (say_hello), NULL);

  gpk_widget_show (window->widget);
                               
}
  
int 
main (int argc, char *argv[])
{
  pthread_t tid;

  gtk_init (&argc, &argv);
  gpk_init ();

  pthread_create (&tid, NULL, (void *)hello, NULL);
  gtk_main ();

  return 0;
}


You may notice the lack of "show" functions. GPK maintains a show state for each thread automatically. By default, show is turned on, so all widget creation calls (except gpk_application_window_new) automagically show their respective widgets. To change the state, use gpk_show_set(value), where value is "TRUE" or "FALSE".

For a more complete example, check out the PerfMon page.


If you have comments or suggestions, email me at sdybiec@humanfactor.com