Commit e2fd4e2b authored by Owen Taylor's avatar Owen Taylor Committed by Owen Taylor

Major change in API for creating sources to handle multiple main loops

Tue Dec  5 12:23:04 2000  Owen Taylor  <otaylor@redhat.com>

        * gmain.[hc]: Major change in API for creating sources
	to handle multiple main loops (GMainContext *).

	GSources are now exposed as GSource * and implemented
	with structure derivation.

	* giochannel.[ch]: Changed vtable for GIOChannel to correspond
	to the new mainloop API, add g_io_channel_create_watch().

	* gtypes.h: Move GTimeVal here.

	* gthread.h: Remove gmain.h include to avoid circularity.

        * giounix.c: Update for new GMain API.

	* giowin32.c: Update for new GMain API. (No check for
	proper compilation or working.)

	* timeloop.c timeloop-basic.c: A benchmarking program for
	the main loop comparing the main loop against a
	hand-written (timeloop-basic.c) variant.

	* tests/mainloop-test.c: New torture test of mainloop.

	* docs/Changes-2.0.txt: Started. Added text about
	changes to GMain.

	* gmain.c (g_main_add_poll_unlocked): Initial fd->revents
	to zero. (#8482, Benjamin Kahn)
parent 5791ec5b
......@@ -28,6 +28,8 @@ stamp-h.in
testgdate
testgdateparser
testglib
timeloop
timeloop-basic
annotations
logs
glib.rc
......
Tue Dec 5 12:23:04 2000 Owen Taylor <otaylor@redhat.com>
* gmain.[hc]: Major change in API for creating sources
to handle multiple main loops (GMainContext *).
GSources are now exposed as GSource * and implemented
with structure derivation.
* giochannel.[ch]: Changed vtable for GIOChannel to correspond
to the new mainloop API, add g_io_channel_create_watch().
* gtypes.h: Move GTimeVal here.
* gthread.h: Remove gmain.h include to avoid circularity.
* giounix.c: Update for new GMain API.
* giowin32.c: Update for new GMain API. (No check for
proper compilation or working.)
* timeloop.c timeloop-basic.c: A benchmarking program for
the main loop comparing the main loop against a
hand-written (timeloop-basic.c) variant.
* tests/mainloop-test.c: New torture test of mainloop.
* docs/Changes-2.0.txt: Started. Added text about
changes to GMain.
* gmain.c (g_main_add_poll_unlocked): Initial fd->revents
to zero. (#8482, Benjamin Kahn)
2000-12-01 Tor Lillqvist <tml@iki.fi>
* {.,*}/makefile.msc.in: Include make.msc from GLib's build subdir.
......
Tue Dec 5 12:23:04 2000 Owen Taylor <otaylor@redhat.com>
* gmain.[hc]: Major change in API for creating sources
to handle multiple main loops (GMainContext *).
GSources are now exposed as GSource * and implemented
with structure derivation.
* giochannel.[ch]: Changed vtable for GIOChannel to correspond
to the new mainloop API, add g_io_channel_create_watch().
* gtypes.h: Move GTimeVal here.
* gthread.h: Remove gmain.h include to avoid circularity.
* giounix.c: Update for new GMain API.
* giowin32.c: Update for new GMain API. (No check for
proper compilation or working.)
* timeloop.c timeloop-basic.c: A benchmarking program for
the main loop comparing the main loop against a
hand-written (timeloop-basic.c) variant.
* tests/mainloop-test.c: New torture test of mainloop.
* docs/Changes-2.0.txt: Started. Added text about
changes to GMain.
* gmain.c (g_main_add_poll_unlocked): Initial fd->revents
to zero. (#8482, Benjamin Kahn)
2000-12-01 Tor Lillqvist <tml@iki.fi>
* {.,*}/makefile.msc.in: Include make.msc from GLib's build subdir.
......
Tue Dec 5 12:23:04 2000 Owen Taylor <otaylor@redhat.com>
* gmain.[hc]: Major change in API for creating sources
to handle multiple main loops (GMainContext *).
GSources are now exposed as GSource * and implemented
with structure derivation.
* giochannel.[ch]: Changed vtable for GIOChannel to correspond
to the new mainloop API, add g_io_channel_create_watch().
* gtypes.h: Move GTimeVal here.
* gthread.h: Remove gmain.h include to avoid circularity.
* giounix.c: Update for new GMain API.
* giowin32.c: Update for new GMain API. (No check for
proper compilation or working.)
* timeloop.c timeloop-basic.c: A benchmarking program for
the main loop comparing the main loop against a
hand-written (timeloop-basic.c) variant.
* tests/mainloop-test.c: New torture test of mainloop.
* docs/Changes-2.0.txt: Started. Added text about
changes to GMain.
* gmain.c (g_main_add_poll_unlocked): Initial fd->revents
to zero. (#8482, Benjamin Kahn)
2000-12-01 Tor Lillqvist <tml@iki.fi>
* {.,*}/makefile.msc.in: Include make.msc from GLib's build subdir.
......
Tue Dec 5 12:23:04 2000 Owen Taylor <otaylor@redhat.com>
* gmain.[hc]: Major change in API for creating sources
to handle multiple main loops (GMainContext *).
GSources are now exposed as GSource * and implemented
with structure derivation.
* giochannel.[ch]: Changed vtable for GIOChannel to correspond
to the new mainloop API, add g_io_channel_create_watch().
* gtypes.h: Move GTimeVal here.
* gthread.h: Remove gmain.h include to avoid circularity.
* giounix.c: Update for new GMain API.
* giowin32.c: Update for new GMain API. (No check for
proper compilation or working.)
* timeloop.c timeloop-basic.c: A benchmarking program for
the main loop comparing the main loop against a
hand-written (timeloop-basic.c) variant.
* tests/mainloop-test.c: New torture test of mainloop.
* docs/Changes-2.0.txt: Started. Added text about
changes to GMain.
* gmain.c (g_main_add_poll_unlocked): Initial fd->revents
to zero. (#8482, Benjamin Kahn)
2000-12-01 Tor Lillqvist <tml@iki.fi>
* {.,*}/makefile.msc.in: Include make.msc from GLib's build subdir.
......
Tue Dec 5 12:23:04 2000 Owen Taylor <otaylor@redhat.com>
* gmain.[hc]: Major change in API for creating sources
to handle multiple main loops (GMainContext *).
GSources are now exposed as GSource * and implemented
with structure derivation.
* giochannel.[ch]: Changed vtable for GIOChannel to correspond
to the new mainloop API, add g_io_channel_create_watch().
* gtypes.h: Move GTimeVal here.
* gthread.h: Remove gmain.h include to avoid circularity.
* giounix.c: Update for new GMain API.
* giowin32.c: Update for new GMain API. (No check for
proper compilation or working.)
* timeloop.c timeloop-basic.c: A benchmarking program for
the main loop comparing the main loop against a
hand-written (timeloop-basic.c) variant.
* tests/mainloop-test.c: New torture test of mainloop.
* docs/Changes-2.0.txt: Started. Added text about
changes to GMain.
* gmain.c (g_main_add_poll_unlocked): Initial fd->revents
to zero. (#8482, Benjamin Kahn)
2000-12-01 Tor Lillqvist <tml@iki.fi>
* {.,*}/makefile.msc.in: Include make.msc from GLib's build subdir.
......
Tue Dec 5 12:23:04 2000 Owen Taylor <otaylor@redhat.com>
* gmain.[hc]: Major change in API for creating sources
to handle multiple main loops (GMainContext *).
GSources are now exposed as GSource * and implemented
with structure derivation.
* giochannel.[ch]: Changed vtable for GIOChannel to correspond
to the new mainloop API, add g_io_channel_create_watch().
* gtypes.h: Move GTimeVal here.
* gthread.h: Remove gmain.h include to avoid circularity.
* giounix.c: Update for new GMain API.
* giowin32.c: Update for new GMain API. (No check for
proper compilation or working.)
* timeloop.c timeloop-basic.c: A benchmarking program for
the main loop comparing the main loop against a
hand-written (timeloop-basic.c) variant.
* tests/mainloop-test.c: New torture test of mainloop.
* docs/Changes-2.0.txt: Started. Added text about
changes to GMain.
* gmain.c (g_main_add_poll_unlocked): Initial fd->revents
to zero. (#8482, Benjamin Kahn)
2000-12-01 Tor Lillqvist <tml@iki.fi>
* {.,*}/makefile.msc.in: Include make.msc from GLib's build subdir.
......
Tue Dec 5 12:23:04 2000 Owen Taylor <otaylor@redhat.com>
* gmain.[hc]: Major change in API for creating sources
to handle multiple main loops (GMainContext *).
GSources are now exposed as GSource * and implemented
with structure derivation.
* giochannel.[ch]: Changed vtable for GIOChannel to correspond
to the new mainloop API, add g_io_channel_create_watch().
* gtypes.h: Move GTimeVal here.
* gthread.h: Remove gmain.h include to avoid circularity.
* giounix.c: Update for new GMain API.
* giowin32.c: Update for new GMain API. (No check for
proper compilation or working.)
* timeloop.c timeloop-basic.c: A benchmarking program for
the main loop comparing the main loop against a
hand-written (timeloop-basic.c) variant.
* tests/mainloop-test.c: New torture test of mainloop.
* docs/Changes-2.0.txt: Started. Added text about
changes to GMain.
* gmain.c (g_main_add_poll_unlocked): Initial fd->revents
to zero. (#8482, Benjamin Kahn)
2000-12-01 Tor Lillqvist <tml@iki.fi>
* {.,*}/makefile.msc.in: Include make.msc from GLib's build subdir.
......
Tue Dec 5 12:23:04 2000 Owen Taylor <otaylor@redhat.com>
* gmain.[hc]: Major change in API for creating sources
to handle multiple main loops (GMainContext *).
GSources are now exposed as GSource * and implemented
with structure derivation.
* giochannel.[ch]: Changed vtable for GIOChannel to correspond
to the new mainloop API, add g_io_channel_create_watch().
* gtypes.h: Move GTimeVal here.
* gthread.h: Remove gmain.h include to avoid circularity.
* giounix.c: Update for new GMain API.
* giowin32.c: Update for new GMain API. (No check for
proper compilation or working.)
* timeloop.c timeloop-basic.c: A benchmarking program for
the main loop comparing the main loop against a
hand-written (timeloop-basic.c) variant.
* tests/mainloop-test.c: New torture test of mainloop.
* docs/Changes-2.0.txt: Started. Added text about
changes to GMain.
* gmain.c (g_main_add_poll_unlocked): Initial fd->revents
to zero. (#8482, Benjamin Kahn)
2000-12-01 Tor Lillqvist <tml@iki.fi>
* {.,*}/makefile.msc.in: Include make.msc from GLib's build subdir.
......
......@@ -165,10 +165,11 @@ libglib_1_3_la_LDFLAGS = \
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
-export-dynamic
noinst_PROGRAMS = testglib testgdate testgdateparser
noinst_PROGRAMS = testglib testgdate testgdateparser timeloop
testglib_LDADD = libglib-1.3.la
testgdate_LDADD = libglib-1.3.la
testgdateparser_LDADD = libglib-1.3.la
timeloop_LDADD = libglib-1.3.la
m4datadir = $(datadir)/aclocal
m4data_DATA = glib-2.0.m4
......
* The event loop functionality GMain has extensively been revised to
support multiple separate main loops in separate threads. All sources
(timeouts, idle functions, etc.) are associated with a GMainContext.
Compatibility functions exist so that most application code dealing with
the main loop will continue to work. However, code that creates
new custom types of sources will require modification.
The main changes here are:
- Sources are now exposed as GSource *, rather than simply as numeric
IDS.
- New types of sources are created by structure "derivation" from GSource,
so the source_data parameter to the GSource vfuncs has been
replaced with a GSource *.
- Sources are first created, then later added to a specific GMainContext
- Dispatching has been modified so both the callback and data are passed
in to the ->dispatch() vfunc.
To go along with this change, the vtable for GIOChannel has changed and
add_watch() has been replaced by create_watch().
\ No newline at end of file
......@@ -27,6 +27,7 @@
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
......
......@@ -104,6 +104,15 @@ g_io_channel_close (GIOChannel *channel)
channel->funcs->io_close (channel);
}
GSource *
g_io_create_watch (GIOChannel *channel,
GIOCondition condition)
{
g_return_val_if_fail (channel != NULL, NULL);
return channel->funcs->io_create_watch (channel, condition);
}
guint
g_io_add_watch_full (GIOChannel *channel,
gint priority,
......@@ -112,10 +121,17 @@ g_io_add_watch_full (GIOChannel *channel,
gpointer user_data,
GDestroyNotify notify)
{
GSource *source;
g_return_val_if_fail (channel != NULL, 0);
return channel->funcs->io_add_watch (channel, priority, condition,
func, user_data, notify);
source = g_io_create_watch (channel, condition);
if (priority != G_PRIORITY_DEFAULT)
g_source_set_priority (source, priority);
g_source_set_callback (source, (GSourceFunc)func, user_data, notify);
return g_source_attach (source, NULL);
}
guint
......@@ -124,5 +140,5 @@ g_io_add_watch (GIOChannel *channel,
GIOFunc func,
gpointer user_data)
{
return g_io_add_watch_full (channel, 0, condition, func, user_data, NULL);
return g_io_add_watch_full (channel, G_PRIORITY_DEFAULT, condition, func, user_data, NULL);
}
......@@ -27,6 +27,7 @@
#ifndef __G_IOCHANNEL_H__
#define __G_IOCHANNEL_H__
#include <gmain.h>
#include <gtypes.h>
G_BEGIN_DECLS
......@@ -71,25 +72,21 @@ typedef gboolean (*GIOFunc) (GIOChannel *source,
gpointer data);
struct _GIOFuncs
{
GIOError (*io_read) (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_read);
GIOError (*io_write) (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_written);
GIOError (*io_seek) (GIOChannel *channel,
gint offset,
GSeekType type);
void (*io_close) (GIOChannel *channel);
guint (*io_add_watch) (GIOChannel *channel,
gint priority,
GIOCondition condition,
GIOFunc func,
gpointer user_data,
GDestroyNotify notify);
void (*io_free) (GIOChannel *channel);
GIOError (*io_read) (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_read);
GIOError (*io_write) (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_written);
GIOError (*io_seek) (GIOChannel *channel,
gint offset,
GSeekType type);
void (*io_close) (GIOChannel *channel);
GSource * (*io_create_watch) (GIOChannel *channel,
GIOCondition condition);
void (*io_free) (GIOChannel *channel);
};
void g_io_channel_init (GIOChannel *channel);
......@@ -113,6 +110,8 @@ guint g_io_add_watch_full (GIOChannel *channel,
GIOFunc func,
gpointer user_data,
GDestroyNotify notify);
GSource *g_io_create_watch (GIOChannel *channel,
GIOCondition condition);
guint g_io_add_watch (GIOChannel *channel,
GIOCondition condition,
GIOFunc func,
......
......@@ -43,12 +43,15 @@
typedef struct _GIOUnixChannel GIOUnixChannel;
typedef struct _GIOUnixWatch GIOUnixWatch;
struct _GIOUnixChannel {
struct _GIOUnixChannel
{
GIOChannel channel;
gint fd;
};
struct _GIOUnixWatch {
struct _GIOUnixWatch
{
GSource source;
GPollFD pollfd;
GIOChannel *channel;
GIOCondition condition;
......@@ -56,37 +59,29 @@ struct _GIOUnixWatch {
};
static GIOError g_io_unix_read (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_written);
static GIOError g_io_unix_write(GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_written);
static GIOError g_io_unix_seek (GIOChannel *channel,
gint offset,
GSeekType type);
static void g_io_unix_close (GIOChannel *channel);
static void g_io_unix_free (GIOChannel *channel);
static guint g_io_unix_add_watch (GIOChannel *channel,
gint priority,
GIOCondition condition,
GIOFunc func,
gpointer user_data,
GDestroyNotify notify);
static gboolean g_io_unix_prepare (gpointer source_data,
GTimeVal *current_time,
gint *timeout,
gpointer user_data);
static gboolean g_io_unix_check (gpointer source_data,
GTimeVal *current_time,
gpointer user_data);
static gboolean g_io_unix_dispatch (gpointer source_data,
GTimeVal *current_time,
gpointer user_data);
static void g_io_unix_destroy (gpointer source_data);
static GIOError g_io_unix_read (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_written);
static GIOError g_io_unix_write (GIOChannel *channel,
gchar *buf,
guint count,
guint *bytes_written);
static GIOError g_io_unix_seek (GIOChannel *channel,
gint offset,
GSeekType type);
static void g_io_unix_close (GIOChannel *channel);
static void g_io_unix_free (GIOChannel *channel);
static GSource *g_io_unix_create_watch (GIOChannel *channel,
GIOCondition condition);
static gboolean g_io_unix_prepare (GSource *source,
gint *timeout);
static gboolean g_io_unix_check (GSource *source);
static gboolean g_io_unix_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data);
static void g_io_unix_destroy (GSource *source);
GSourceFuncs unix_watch_funcs = {
g_io_unix_prepare,
......@@ -100,51 +95,53 @@ GIOFuncs unix_channel_funcs = {
g_io_unix_write,
g_io_unix_seek,
g_io_unix_close,
g_io_unix_add_watch,
g_io_unix_create_watch,
g_io_unix_free,
};
static gboolean
g_io_unix_prepare (gpointer source_data,
GTimeVal *current_time,
gint *timeout,
gpointer user_data)
g_io_unix_prepare (GSource *source,
gint *timeout)
{
*timeout = -1;
return FALSE;
}
static gboolean
g_io_unix_check (gpointer source_data,
GTimeVal *current_time,
gpointer user_data)
g_io_unix_check (GSource *source)
{
GIOUnixWatch *data = source_data;
GIOUnixWatch *watch = (GIOUnixWatch *)source;
return (data->pollfd.revents & data->condition);
return (watch->pollfd.revents & watch->condition);
}
static gboolean
g_io_unix_dispatch (gpointer source_data,
GTimeVal *current_time,
gpointer user_data)
g_io_unix_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
GIOUnixWatch *data = source_data;
GIOFunc func = (GIOFunc)callback;
GIOUnixWatch *watch = (GIOUnixWatch *)source;
return (*data->callback)(data->channel,
data->pollfd.revents & data->condition,
user_data);
if (!func)
{
g_warning ("IO watch dispatched without callback\n"
"You must call g_source_connect().");
return FALSE;
}
return (*func) (watch->channel,
watch->pollfd.revents & watch->condition,
user_data);
}
static void
g_io_unix_destroy (gpointer source_data)
g_io_unix_destroy (GSource *source)
{
GIOUnixWatch *data = source_data;
GIOUnixWatch *watch = (GIOUnixWatch *)source;
g_main_remove_poll (&data->pollfd);
g_io_channel_unref (data->channel);
g_free (data);
g_io_channel_unref (watch->channel);
}
static GIOError
......@@ -269,29 +266,29 @@ g_io_unix_free (GIOChannel *channel)
g_free (unix_channel);
}
static guint
g_io_unix_add_watch (GIOChannel *channel,
gint priority,
GIOCondition condition,
GIOFunc func,
gpointer user_data,
GDestroyNotify notify)
static GSource *
g_io_unix_create_watch (GIOChannel *channel,
GIOCondition condition)
{
GIOUnixWatch *watch = g_new (GIOUnixWatch, 1);
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
GSource *source;
GIOUnixWatch *watch;
source = g_source_new (&unix_watch_funcs, sizeof (GIOUnixWatch));
watch = (GIOUnixWatch *)source;
watch->channel = channel;
g_io_channel_ref (channel);
watch->callback = func;
watch->condition = condition;
watch->pollfd.fd = unix_channel->fd;
watch->pollfd.events = condition;
g_main_add_poll (&watch->pollfd, priority);
g_source_add_poll (source, &watch->pollfd);
return g_source_add (priority, TRUE, &unix_watch_funcs, watch, user_data, notify);
return source;
}
GIOChannel *
......
......@@ -102,6 +102,7 @@ struct _GIOWin32Channel {
#define UNLOCK(mutex) LeaveCriticalSection (&mutex)
struct _GIOWin32Watch {
GSource source;
GPollFD pollfd;
GIOChannel *channel;
GIOCondition condition;
......@@ -319,10 +320,8 @@ buffer_read (GIOWin32Channel *channel,
}
static gboolean
g_io_win32_prepare (gpointer source_data,
GTimeVal *current_time,
gint *timeout,
gpointer user_data)
g_io_win32_prepare (GSource *source,
gint *timeout)
{
*timeout = -1;
......@@ -330,12 +329,10 @@ g_io_win32_prepare (gpointer source_data,
}
static gboolean
g_io_win32_check (gpointer source_data,
GTimeVal *current_time,
gpointer user_data)
g_io_win32_check (GSource *source)
{
GIOWin32Watch *data = source_data;
GIOWin32Channel *channel = (GIOWin32Channel *) data->channel;
GIOWin32Watch *watch = (GIOWin32Watch *)source;
GIOWin32Channel *channel = (GIOWin32Channel *) watch->channel;
/* If the thread has died, we have encountered EOF. If the buffer
* also is emtpty set the HUP bit.
......@@ -345,34 +342,31 @@ g_io_win32_check (gpointer source_data,
if (channel->debug)
g_print ("g_io_win32_check: setting G_IO_HUP thread %#x rdp=%d wrp=%d\n",
channel->thread_id, channel->rdp, channel->wrp);
data->pollfd.revents |= G_IO_HUP;
watch->pollfd.revents |= G_IO_HUP;
return TRUE;
}
return (data->pollfd.revents & data->condition);
return (watch->pollfd.revents & watch->condition);
}
static gboolean
g_io_win32_dispatch (gpointer source_data,
GTimeVal *current_time,
gpointer user_data)
g_io_win32_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
GIOWin32Watch *data = source_data;
GIOWin32Watch *watch = (GIOWin32Watch *)source;
return (*data->callback) (data->channel,
data->pollfd.revents & data->condition,