mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-11 20:06:18 +01:00
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)
This commit is contained in:
parent
5791ec5b85
commit
e2fd4e2bd0
@ -28,6 +28,8 @@ stamp-h.in
|
||||
testgdate
|
||||
testgdateparser
|
||||
testglib
|
||||
timeloop
|
||||
timeloop-basic
|
||||
annotations
|
||||
logs
|
||||
glib.rc
|
||||
|
32
ChangeLog
32
ChangeLog
@ -1,3 +1,35 @@
|
||||
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.
|
||||
|
@ -1,3 +1,35 @@
|
||||
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.
|
||||
|
@ -1,3 +1,35 @@
|
||||
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.
|
||||
|
@ -1,3 +1,35 @@
|
||||
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.
|
||||
|
@ -1,3 +1,35 @@
|
||||
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.
|
||||
|
@ -1,3 +1,35 @@
|
||||
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.
|
||||
|
@ -1,3 +1,35 @@
|
||||
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.
|
||||
|
@ -1,3 +1,35 @@
|
||||
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
|
||||
|
24
docs/Changes-2.0.txt
Normal file
24
docs/Changes-2.0.txt
Normal file
@ -0,0 +1,24 @@
|
||||
* 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().
|
@ -27,6 +27,7 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
|
22
giochannel.c
22
giochannel.c
@ -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);
|
||||
}
|
||||
|
37
giochannel.h
37
giochannel.h
@ -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,
|
||||
|
131
giounix.c
131
giounix.c
@ -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 *
|
||||
|
122
giowin32.c
122
giowin32.c
@ -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,
|
||||
user_data);
|
||||
return (*callback) (watch->channel,
|
||||
watch->pollfd.revents & watch->condition,
|
||||
user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
g_io_win32_destroy (gpointer source_data)
|
||||
g_io_win32_destroy (GSource *source)
|
||||
{
|
||||
GIOWin32Watch *data = source_data;
|
||||
GIOWin32Watch *watch = (GIOWin32Watch *)source;
|
||||
|
||||
g_main_remove_poll (&data->pollfd);
|
||||
g_io_channel_unref (data->channel);
|
||||
g_free (data);
|
||||
g_io_channel_unref (watch->channel);
|
||||
}
|
||||
|
||||
static GSourceFuncs win32_watch_funcs = {
|
||||
@ -382,22 +376,21 @@ static GSourceFuncs win32_watch_funcs = {
|
||||
g_io_win32_destroy
|
||||
};
|
||||
|
||||
static guint
|
||||
g_io_win32_add_watch (GIOChannel *channel,
|
||||
gint priority,
|
||||
GIOCondition condition,
|
||||
GIOFunc func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify,
|
||||
int (*reader) (int, guchar *, int))
|
||||
static GSource *
|
||||
g_io_win32_create_watch (GIOChannel *channel,
|
||||
GIOCondition condition,
|
||||
int (*reader) (int, guchar *, int)))
|
||||
{
|
||||
GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
|
||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
||||
GIOWin32Watch *watch;
|
||||
GSource *source;
|
||||
|
||||
source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
|
||||
watch = (GIOWin32Watch *)source;
|
||||
|
||||
watch->channel = channel;
|
||||
g_io_channel_ref (channel);
|
||||
|
||||
watch->callback = func;
|
||||
watch->condition = condition;
|
||||
|
||||
if (win32_channel->data_avail_event == NULL)
|
||||
@ -407,16 +400,15 @@ g_io_win32_add_watch (GIOChannel *channel,
|
||||
watch->pollfd.events = condition;
|
||||
|
||||
if (win32_channel->debug)
|
||||
g_print ("g_io_win32_add_watch: fd:%d handle:%#x\n",
|
||||
g_print ("g_io_win32_create_watch: fd:%d handle:%#x\n",
|
||||
win32_channel->fd, watch->pollfd.fd);
|
||||
|
||||
if (win32_channel->thread_id == 0)
|
||||
create_reader_thread (win32_channel, reader);
|
||||
|
||||
g_main_add_poll (&watch->pollfd, priority);
|
||||
g_source_add_poll (source, &watch->pollfd);
|
||||
|
||||
return g_source_add (priority, TRUE, &win32_watch_funcs, watch,
|
||||
user_data, notify);
|
||||
return source;
|
||||
}
|
||||
|
||||
static GIOError
|
||||
@ -490,29 +482,27 @@ g_io_win32_free (GIOChannel *channel)
|
||||
g_free (win32_channel);
|
||||
}
|
||||
|
||||
static guint
|
||||
g_io_win32_msg_add_watch (GIOChannel *channel,
|
||||
gint priority,
|
||||
GIOCondition condition,
|
||||
GIOFunc func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify)
|
||||
static GSource *
|
||||
g_io_win32_msg_create_watch (GIOChannel *channel,
|
||||
GIOCondition condition)
|
||||
{
|
||||
GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
|
||||
GIOWin32Watch *watch;
|
||||
GSource *source;
|
||||
|
||||
source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
|
||||
watch = (GIOWin32Watch *)source;
|
||||
|
||||
watch->channel = channel;
|
||||
g_io_channel_ref (channel);
|
||||
|
||||
watch->callback = func;
|
||||
watch->condition = condition;
|
||||
|
||||
watch->pollfd.fd = G_WIN32_MSG_HANDLE;
|
||||
watch->pollfd.events = condition;
|
||||
|
||||
g_main_add_poll (&watch->pollfd, priority);
|
||||
g_source_add_poll (source, &watch->pollfd);
|
||||
|
||||
return g_source_add (priority, TRUE, &win32_watch_funcs,
|
||||
watch, user_data, notify);
|
||||
return source;
|
||||
}
|
||||
|
||||
static GIOError
|
||||
@ -653,16 +643,11 @@ fd_reader (int fd,
|
||||
return read (fd, buf, len);
|
||||
}
|
||||
|
||||
static guint
|
||||
g_io_win32_fd_add_watch (GIOChannel *channel,
|
||||
gint priority,
|
||||
GIOCondition condition,
|
||||
GIOFunc func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify)
|
||||
static GSource *
|
||||
g_io_win32_fd_create_watch (GIOChannel *channel,
|
||||
GIOCondition condition)
|
||||
{
|
||||
return g_io_win32_add_watch (channel, priority, condition,
|
||||
func, user_data, notify, fd_reader);
|
||||
return g_io_win32_create_watch (channel, condition, fd_reader);
|
||||
}
|
||||
|
||||
static GIOError
|
||||
@ -752,16 +737,11 @@ sock_reader (int fd,
|
||||
return recv (fd, buf, len, 0);
|
||||
}
|
||||
|
||||
static guint
|
||||
g_io_win32_sock_add_watch (GIOChannel *channel,
|
||||
gint priority,
|
||||
GIOCondition condition,
|
||||
GIOFunc func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify)
|
||||
static GSource *
|
||||
g_io_win32_sock_create_watch (GIOChannel *channel,
|
||||
GIOCondition condition)
|
||||
{
|
||||
return g_io_win32_add_watch (channel, priority, condition,
|
||||
func, user_data, notify, sock_reader);
|
||||
return g_io_win32_add_watch (channel, condition, sock_reader);
|
||||
}
|
||||
|
||||
static GIOFuncs win32_channel_msg_funcs = {
|
||||
@ -769,7 +749,7 @@ static GIOFuncs win32_channel_msg_funcs = {
|
||||
g_io_win32_msg_write,
|
||||
g_io_win32_no_seek,
|
||||
g_io_win32_msg_close,
|
||||
g_io_win32_msg_add_watch,
|
||||
g_io_win32_msg_create_watch,
|
||||
g_io_win32_free
|
||||
};
|
||||
|
||||
@ -778,7 +758,7 @@ static GIOFuncs win32_channel_fd_funcs = {
|
||||
g_io_win32_fd_write,
|
||||
g_io_win32_fd_seek,
|
||||
g_io_win32_fd_close,
|
||||
g_io_win32_fd_add_watch,
|
||||
g_io_win32_fd_create_watch,
|
||||
g_io_win32_free
|
||||
};
|
||||
|
||||
@ -787,7 +767,7 @@ static GIOFuncs win32_channel_sock_funcs = {
|
||||
g_io_win32_sock_write,
|
||||
g_io_win32_no_seek,
|
||||
g_io_win32_sock_close,
|
||||
g_io_win32_sock_add_watch,
|
||||
g_io_win32_sock_create_watch,
|
||||
g_io_win32_free
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
131
glib/giounix.c
131
glib/giounix.c
@ -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 *
|
||||
|
122
glib/giowin32.c
122
glib/giowin32.c
@ -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,
|
||||
user_data);
|
||||
return (*callback) (watch->channel,
|
||||
watch->pollfd.revents & watch->condition,
|
||||
user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
g_io_win32_destroy (gpointer source_data)
|
||||
g_io_win32_destroy (GSource *source)
|
||||
{
|
||||
GIOWin32Watch *data = source_data;
|
||||
GIOWin32Watch *watch = (GIOWin32Watch *)source;
|
||||
|
||||
g_main_remove_poll (&data->pollfd);
|
||||
g_io_channel_unref (data->channel);
|
||||
g_free (data);
|
||||
g_io_channel_unref (watch->channel);
|
||||
}
|
||||
|
||||
static GSourceFuncs win32_watch_funcs = {
|
||||
@ -382,22 +376,21 @@ static GSourceFuncs win32_watch_funcs = {
|
||||
g_io_win32_destroy
|
||||
};
|
||||
|
||||
static guint
|
||||
g_io_win32_add_watch (GIOChannel *channel,
|
||||
gint priority,
|
||||
GIOCondition condition,
|
||||
GIOFunc func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify,
|
||||
int (*reader) (int, guchar *, int))
|
||||
static GSource *
|
||||
g_io_win32_create_watch (GIOChannel *channel,
|
||||
GIOCondition condition,
|
||||
int (*reader) (int, guchar *, int)))
|
||||
{
|
||||
GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
|
||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
||||
GIOWin32Watch *watch;
|
||||
GSource *source;
|
||||
|
||||
source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
|
||||
watch = (GIOWin32Watch *)source;
|
||||
|
||||
watch->channel = channel;
|
||||
g_io_channel_ref (channel);
|
||||
|
||||
watch->callback = func;
|
||||
watch->condition = condition;
|
||||
|
||||
if (win32_channel->data_avail_event == NULL)
|
||||
@ -407,16 +400,15 @@ g_io_win32_add_watch (GIOChannel *channel,
|
||||
watch->pollfd.events = condition;
|
||||
|
||||
if (win32_channel->debug)
|
||||
g_print ("g_io_win32_add_watch: fd:%d handle:%#x\n",
|
||||
g_print ("g_io_win32_create_watch: fd:%d handle:%#x\n",
|
||||
win32_channel->fd, watch->pollfd.fd);
|
||||
|
||||
if (win32_channel->thread_id == 0)
|
||||
create_reader_thread (win32_channel, reader);
|
||||
|
||||
g_main_add_poll (&watch->pollfd, priority);
|
||||
g_source_add_poll (source, &watch->pollfd);
|
||||
|
||||
return g_source_add (priority, TRUE, &win32_watch_funcs, watch,
|
||||
user_data, notify);
|
||||
return source;
|
||||
}
|
||||
|
||||
static GIOError
|
||||
@ -490,29 +482,27 @@ g_io_win32_free (GIOChannel *channel)
|
||||
g_free (win32_channel);
|
||||
}
|
||||
|
||||
static guint
|
||||
g_io_win32_msg_add_watch (GIOChannel *channel,
|
||||
gint priority,
|
||||
GIOCondition condition,
|
||||
GIOFunc func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify)
|
||||
static GSource *
|
||||
g_io_win32_msg_create_watch (GIOChannel *channel,
|
||||
GIOCondition condition)
|
||||
{
|
||||
GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
|
||||
GIOWin32Watch *watch;
|
||||
GSource *source;
|
||||
|
||||
source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
|
||||
watch = (GIOWin32Watch *)source;
|
||||
|
||||
watch->channel = channel;
|
||||
g_io_channel_ref (channel);
|
||||
|
||||
watch->callback = func;
|
||||
watch->condition = condition;
|
||||
|
||||
watch->pollfd.fd = G_WIN32_MSG_HANDLE;
|
||||
watch->pollfd.events = condition;
|
||||
|
||||
g_main_add_poll (&watch->pollfd, priority);
|
||||
g_source_add_poll (source, &watch->pollfd);
|
||||
|
||||
return g_source_add (priority, TRUE, &win32_watch_funcs,
|
||||
watch, user_data, notify);
|
||||
return source;
|
||||
}
|
||||
|
||||
static GIOError
|
||||
@ -653,16 +643,11 @@ fd_reader (int fd,
|
||||
return read (fd, buf, len);
|
||||
}
|
||||
|
||||
static guint
|
||||
g_io_win32_fd_add_watch (GIOChannel *channel,
|
||||
gint priority,
|
||||
GIOCondition condition,
|
||||
GIOFunc func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify)
|
||||
static GSource *
|
||||
g_io_win32_fd_create_watch (GIOChannel *channel,
|
||||
GIOCondition condition)
|
||||
{
|
||||
return g_io_win32_add_watch (channel, priority, condition,
|
||||
func, user_data, notify, fd_reader);
|
||||
return g_io_win32_create_watch (channel, condition, fd_reader);
|
||||
}
|
||||
|
||||
static GIOError
|
||||
@ -752,16 +737,11 @@ sock_reader (int fd,
|
||||
return recv (fd, buf, len, 0);
|
||||
}
|
||||
|
||||
static guint
|
||||
g_io_win32_sock_add_watch (GIOChannel *channel,
|
||||
gint priority,
|
||||
GIOCondition condition,
|
||||
GIOFunc func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify)
|
||||
static GSource *
|
||||
g_io_win32_sock_create_watch (GIOChannel *channel,
|
||||
GIOCondition condition)
|
||||
{
|
||||
return g_io_win32_add_watch (channel, priority, condition,
|
||||
func, user_data, notify, sock_reader);
|
||||
return g_io_win32_add_watch (channel, condition, sock_reader);
|
||||
}
|
||||
|
||||
static GIOFuncs win32_channel_msg_funcs = {
|
||||
@ -769,7 +749,7 @@ static GIOFuncs win32_channel_msg_funcs = {
|
||||
g_io_win32_msg_write,
|
||||
g_io_win32_no_seek,
|
||||
g_io_win32_msg_close,
|
||||
g_io_win32_msg_add_watch,
|
||||
g_io_win32_msg_create_watch,
|
||||
g_io_win32_free
|
||||
};
|
||||
|
||||
@ -778,7 +758,7 @@ static GIOFuncs win32_channel_fd_funcs = {
|
||||
g_io_win32_fd_write,
|
||||
g_io_win32_fd_seek,
|
||||
g_io_win32_fd_close,
|
||||
g_io_win32_fd_add_watch,
|
||||
g_io_win32_fd_create_watch,
|
||||
g_io_win32_free
|
||||
};
|
||||
|
||||
@ -787,7 +767,7 @@ static GIOFuncs win32_channel_sock_funcs = {
|
||||
g_io_win32_sock_write,
|
||||
g_io_win32_no_seek,
|
||||
g_io_win32_sock_close,
|
||||
g_io_win32_sock_add_watch,
|
||||
g_io_win32_sock_create_watch,
|
||||
g_io_win32_free
|
||||
};
|
||||
|
||||
|
2746
glib/gmain.c
2746
glib/gmain.c
File diff suppressed because it is too large
Load Diff
334
glib/gmain.h
334
glib/gmain.h
@ -1,122 +1,87 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
/* gmain.h - the GLib Main loop
|
||||
* Copyright (C) 1998-2000 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#ifndef __G_MAIN_H__
|
||||
#define __G_MAIN_H__
|
||||
|
||||
#include <gtypes.h>
|
||||
#include <gslist.h>
|
||||
#include <gthread.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* Main loop
|
||||
*/
|
||||
typedef struct _GTimeVal GTimeVal;
|
||||
typedef struct _GSourceFuncs GSourceFuncs;
|
||||
typedef struct _GMainLoop GMainLoop; /* Opaque */
|
||||
typedef struct _GMainContext GMainContext; /* Opaque */
|
||||
typedef struct _GMainLoop GMainLoop; /* Opaque */
|
||||
typedef struct _GSource GSource;
|
||||
typedef struct _GSourceCallbackFuncs GSourceCallbackFuncs;
|
||||
typedef struct _GSourceFuncs GSourceFuncs;
|
||||
|
||||
struct _GTimeVal
|
||||
typedef gboolean (*GSourceFunc) (gpointer data);
|
||||
|
||||
struct _GSource
|
||||
{
|
||||
glong tv_sec;
|
||||
glong tv_usec;
|
||||
/*< private >*/
|
||||
gpointer callback_data;
|
||||
GSourceCallbackFuncs *callback_funcs;
|
||||
|
||||
GSourceFuncs *source_funcs;
|
||||
guint ref_count;
|
||||
|
||||
GMainContext *context;
|
||||
|
||||
gint priority;
|
||||
guint flags;
|
||||
guint id;
|
||||
|
||||
GSList *poll_fds;
|
||||
|
||||
GSource *prev;
|
||||
GSource *next;
|
||||
};
|
||||
|
||||
struct _GSourceCallbackFuncs
|
||||
{
|
||||
void (*ref) (gpointer cb_data);
|
||||
void (*unref) (gpointer cb_data);
|
||||
void (*get) (gpointer cb_data,
|
||||
GSourceFunc *func,
|
||||
gpointer *data);
|
||||
};
|
||||
|
||||
struct _GSourceFuncs
|
||||
{
|
||||
gboolean (*prepare) (gpointer source_data,
|
||||
GTimeVal *current_time,
|
||||
gint *timeout,
|
||||
gpointer user_data);
|
||||
gboolean (*check) (gpointer source_data,
|
||||
GTimeVal *current_time,
|
||||
gpointer user_data);
|
||||
gboolean (*dispatch) (gpointer source_data,
|
||||
GTimeVal *dispatch_time,
|
||||
gpointer user_data);
|
||||
GDestroyNotify destroy;
|
||||
gboolean (*prepare) (GSource *source,
|
||||
gint *timeout);
|
||||
gboolean (*check) (GSource *source);
|
||||
gboolean (*dispatch) (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data);
|
||||
void (*destroy) (GSource *source);
|
||||
};
|
||||
|
||||
/* Standard priorities */
|
||||
|
||||
#define G_PRIORITY_HIGH -100
|
||||
#define G_PRIORITY_DEFAULT 0
|
||||
#define G_PRIORITY_HIGH_IDLE 100
|
||||
#define G_PRIORITY_DEFAULT_IDLE 200
|
||||
#define G_PRIORITY_LOW 300
|
||||
|
||||
typedef gboolean (*GSourceFunc) (gpointer data);
|
||||
|
||||
/* Hooks for adding to the main loop */
|
||||
guint g_source_add (gint priority,
|
||||
gboolean can_recurse,
|
||||
GSourceFuncs *funcs,
|
||||
gpointer source_data,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify);
|
||||
gboolean g_source_remove (guint tag);
|
||||
gboolean g_source_remove_by_user_data (gpointer user_data);
|
||||
gboolean g_source_remove_by_source_data (gpointer source_data);
|
||||
gboolean g_source_remove_by_funcs_user_data (GSourceFuncs *funcs,
|
||||
gpointer user_data);
|
||||
|
||||
void g_get_current_time (GTimeVal *result);
|
||||
|
||||
/* Running the main loop */
|
||||
GMainLoop* g_main_new (gboolean is_running);
|
||||
void g_main_run (GMainLoop *loop);
|
||||
void g_main_quit (GMainLoop *loop);
|
||||
void g_main_destroy (GMainLoop *loop);
|
||||
gboolean g_main_is_running (GMainLoop *loop);
|
||||
|
||||
/* Run a single iteration of the mainloop. If block is FALSE,
|
||||
* will never block
|
||||
*/
|
||||
gboolean g_main_iteration (gboolean may_block);
|
||||
|
||||
/* See if any events are pending */
|
||||
gboolean g_main_pending (void);
|
||||
|
||||
/* Idles and timeouts */
|
||||
guint g_timeout_add_full (gint priority,
|
||||
guint interval,
|
||||
GSourceFunc function,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
guint g_timeout_add (guint interval,
|
||||
GSourceFunc function,
|
||||
gpointer data);
|
||||
guint g_idle_add (GSourceFunc function,
|
||||
gpointer data);
|
||||
guint g_idle_add_full (gint priority,
|
||||
GSourceFunc function,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy);
|
||||
gboolean g_idle_remove_by_data (gpointer data);
|
||||
|
||||
/* GPollFD
|
||||
/* Any definitions using GPollFD or GPollFunc are primarily
|
||||
* for Unix and not guaranteed to be the compatible on all
|
||||
* operating systems on which GLib runs. Right now, the
|
||||
* GLib does use these functions on Win32 as well, but interprets
|
||||
* them in a fairly different way than on Unix. If you use
|
||||
* these definitions, you are should be prepared to recode
|
||||
* for different operating systems.
|
||||
*
|
||||
* System-specific IO and main loop calls
|
||||
*
|
||||
* On Win32, the fd in a GPollFD should be Win32 HANDLE (*not* a file
|
||||
* descriptor as provided by the C runtime) that can be used by
|
||||
@ -137,32 +102,185 @@ gboolean g_idle_remove_by_data (gpointer data);
|
||||
* Win32. It's really only written for the GIMP's needs so
|
||||
* far.
|
||||
*/
|
||||
|
||||
typedef struct _GPollFD GPollFD;
|
||||
typedef gint (*GPollFunc) (GPollFD *ufds,
|
||||
guint nfsd,
|
||||
gint timeout);
|
||||
typedef gint (*GPollFunc) (GPollFD *ufds,
|
||||
guint nfsd,
|
||||
gint timeout);
|
||||
|
||||
struct _GPollFD
|
||||
{
|
||||
gint fd;
|
||||
gushort events;
|
||||
gushort revents;
|
||||
gint fd;
|
||||
gushort events;
|
||||
gushort revents;
|
||||
};
|
||||
|
||||
void g_main_add_poll (GPollFD *fd,
|
||||
gint priority);
|
||||
void g_main_remove_poll (GPollFD *fd);
|
||||
void g_main_set_poll_func (GPollFunc func);
|
||||
/* Standard priorities */
|
||||
|
||||
#define G_PRIORITY_HIGH -100
|
||||
#define G_PRIORITY_DEFAULT 0
|
||||
#define G_PRIORITY_HIGH_IDLE 100
|
||||
#define G_PRIORITY_DEFAULT_IDLE 200
|
||||
#define G_PRIORITY_LOW 300
|
||||
|
||||
/* GMainContext: */
|
||||
|
||||
GMainContext *g_main_context_get (GThread *thread);
|
||||
GMainContext *g_main_context_default (void);
|
||||
|
||||
gboolean g_main_context_iteration (GMainContext *context,
|
||||
gboolean may_block);
|
||||
gboolean g_main_context_pending (GMainContext *context);
|
||||
|
||||
/* For implementation of legacy interfaces
|
||||
*/
|
||||
GSource *g_main_context_find_source_by_id (GMainContext *context,
|
||||
guint id);
|
||||
GSource *g_main_context_find_source_by_user_data (GMainContext *context,
|
||||
gpointer user_data);
|
||||
GSource *g_main_context_find_source_by_funcs_user_data (GMainContext *context,
|
||||
GSourceFuncs *funcs,
|
||||
gpointer user_data);
|
||||
|
||||
/* Low level functions for implementing custom main loops.
|
||||
*/
|
||||
gboolean g_main_context_prepare (GMainContext *context,
|
||||
gint *priority);
|
||||
gint g_main_context_query (GMainContext *context,
|
||||
gint max_priority,
|
||||
gint *timeout,
|
||||
GPollFD *fds,
|
||||
gint n_fds);
|
||||
gint g_main_context_check (GMainContext *context,
|
||||
gint max_priority,
|
||||
GPollFD *fds,
|
||||
gint n_fds);
|
||||
void g_main_context_dispatch (GMainContext *context);
|
||||
|
||||
void g_main_context_set_poll_func (GMainContext *context,
|
||||
GPollFunc func);
|
||||
GPollFunc g_main_context_get_poll_func (GMainContext *context);
|
||||
|
||||
/* Low level functions for use by source implementations
|
||||
*/
|
||||
void g_main_context_add_poll (GMainContext *context,
|
||||
GPollFD *fd,
|
||||
gint priority);
|
||||
void g_main_context_remove_poll (GMainContext *context,
|
||||
GPollFD *fd);
|
||||
|
||||
/* GMainLoop: */
|
||||
|
||||
GMainLoop *g_main_loop_new (GMainContext *context,
|
||||
gboolean is_running);
|
||||
void g_main_loop_run (GMainLoop *loop);
|
||||
void g_main_loop_quit (GMainLoop *loop);
|
||||
void g_main_loop_destroy (GMainLoop *loop);
|
||||
gboolean g_main_loop_is_running (GMainLoop *loop);
|
||||
|
||||
/* GSource: */
|
||||
|
||||
GSource *g_source_new (GSourceFuncs *source_funcs,
|
||||
guint struct_size);
|
||||
GSource *g_source_ref (GSource *source);
|
||||
void g_source_unref (GSource *source);
|
||||
|
||||
guint g_source_attach (GSource *source,
|
||||
GMainContext *context);
|
||||
void g_source_destroy (GSource *source);
|
||||
|
||||
void g_source_set_priority (GSource *source,
|
||||
gint priority);
|
||||
gint g_source_get_priority (GSource *source);
|
||||
void g_source_set_can_recurse (GSource *source,
|
||||
gboolean can_recurse);
|
||||
gboolean g_source_get_can_recurse (GSource *source);
|
||||
guint g_source_get_id (GSource *source);
|
||||
|
||||
GMainContext *g_source_get_context (GSource *source);
|
||||
|
||||
void g_source_set_callback (GSource *source,
|
||||
GSourceFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
|
||||
|
||||
/* Used to implement g_source_connect_closure and internally*/
|
||||
void g_source_set_callback_indirect (GSource *source,
|
||||
gpointer callback_data,
|
||||
GSourceCallbackFuncs *callback_funcs);
|
||||
|
||||
void g_source_add_poll (GSource *source,
|
||||
GPollFD *fd);
|
||||
void g_source_remove_poll (GSource *source,
|
||||
GPollFD *fd);
|
||||
|
||||
void g_source_get_current_time (GSource *source,
|
||||
GTimeVal *timeval);
|
||||
|
||||
/* void g_source_connect_closure (GSource *source,
|
||||
GClosure *closure);
|
||||
*/
|
||||
|
||||
/* Specific source types
|
||||
*/
|
||||
GSource *g_idle_source_new (void);
|
||||
GSource *g_timeout_source_new (guint interval);
|
||||
|
||||
/* Miscellaneous functions
|
||||
*/
|
||||
void g_get_current_time (GTimeVal *result);
|
||||
|
||||
/* ============== Compat main loop stuff ================== */
|
||||
|
||||
/* Legacy names for GMainLoop functions
|
||||
*/
|
||||
#define g_main_new(is_running) g_main_loop_new (NULL, is_running);
|
||||
#define g_main_run(loop) g_main_loop_run(loop)
|
||||
#define g_main_quit(loop) g_main_loop_quit(loop)
|
||||
#define g_main_destroy(loop) g_main_loop_destroy(loop)
|
||||
#define g_main_is_running(loop) g_main_loop_is_running(loop)
|
||||
|
||||
/* Source manipulation by ID */
|
||||
gboolean g_source_remove (guint tag);
|
||||
gboolean g_source_remove_by_user_data (gpointer user_data);
|
||||
gboolean g_source_remove_by_funcs_user_data (GSourceFuncs *funcs,
|
||||
gpointer user_data);
|
||||
|
||||
/* Functions to manipulate the default main loop
|
||||
*/
|
||||
|
||||
#define g_main_iteration(may_block) g_main_context_iteration (NULL, may_block)
|
||||
#define g_main_pending() g_main_context_pending (NULL)
|
||||
|
||||
#define g_main_set_poll_func(func) g_main_context_set_poll_func (NULL, func)
|
||||
|
||||
/* Idles and timeouts */
|
||||
guint g_timeout_add_full (gint priority,
|
||||
guint interval,
|
||||
GSourceFunc function,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
guint g_timeout_add (guint interval,
|
||||
GSourceFunc function,
|
||||
gpointer data);
|
||||
guint g_idle_add (GSourceFunc function,
|
||||
gpointer data);
|
||||
guint g_idle_add_full (gint priority,
|
||||
GSourceFunc function,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
gboolean g_idle_remove_by_data (gpointer data);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
|
||||
/* Useful on other platforms, too? */
|
||||
|
||||
GPollFunc g_main_win32_get_poll_func (void);
|
||||
|
||||
#endif
|
||||
/* This is used to add polling for Windows messages. GDK (GTK+) programs
|
||||
* should *not* use this.
|
||||
*/
|
||||
void g_main_poll_win32_msg_add (gint priority,
|
||||
GPollFD *fd,
|
||||
guint hwnd);
|
||||
#endif G_OS_WIN32
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_MAIN_H__ */
|
||||
|
||||
|
@ -28,7 +28,6 @@
|
||||
#define __G_THREAD_H__
|
||||
|
||||
#include <gerror.h>
|
||||
#include <gmain.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -314,6 +314,14 @@ union _GDoubleIEEE754
|
||||
#error unknown ENDIAN type
|
||||
#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
|
||||
|
||||
typedef struct _GTimeVal GTimeVal;
|
||||
|
||||
struct _GTimeVal
|
||||
{
|
||||
glong tv_sec;
|
||||
glong tv_usec;
|
||||
};
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_TYPES_H__ */
|
||||
|
334
gmain.h
334
gmain.h
@ -1,122 +1,87 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
/* gmain.h - the GLib Main loop
|
||||
* Copyright (C) 1998-2000 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#ifndef __G_MAIN_H__
|
||||
#define __G_MAIN_H__
|
||||
|
||||
#include <gtypes.h>
|
||||
#include <gslist.h>
|
||||
#include <gthread.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* Main loop
|
||||
*/
|
||||
typedef struct _GTimeVal GTimeVal;
|
||||
typedef struct _GSourceFuncs GSourceFuncs;
|
||||
typedef struct _GMainLoop GMainLoop; /* Opaque */
|
||||
typedef struct _GMainContext GMainContext; /* Opaque */
|
||||
typedef struct _GMainLoop GMainLoop; /* Opaque */
|
||||
typedef struct _GSource GSource;
|
||||
typedef struct _GSourceCallbackFuncs GSourceCallbackFuncs;
|
||||
typedef struct _GSourceFuncs GSourceFuncs;
|
||||
|
||||
struct _GTimeVal
|
||||
typedef gboolean (*GSourceFunc) (gpointer data);
|
||||
|
||||
struct _GSource
|
||||
{
|
||||
glong tv_sec;
|
||||
glong tv_usec;
|
||||
/*< private >*/
|
||||
gpointer callback_data;
|
||||
GSourceCallbackFuncs *callback_funcs;
|
||||
|
||||
GSourceFuncs *source_funcs;
|
||||
guint ref_count;
|
||||
|
||||
GMainContext *context;
|
||||
|
||||
gint priority;
|
||||
guint flags;
|
||||
guint id;
|
||||
|
||||
GSList *poll_fds;
|
||||
|
||||
GSource *prev;
|
||||
GSource *next;
|
||||
};
|
||||
|
||||
struct _GSourceCallbackFuncs
|
||||
{
|
||||
void (*ref) (gpointer cb_data);
|
||||
void (*unref) (gpointer cb_data);
|
||||
void (*get) (gpointer cb_data,
|
||||
GSourceFunc *func,
|
||||
gpointer *data);
|
||||
};
|
||||
|
||||
struct _GSourceFuncs
|
||||
{
|
||||
gboolean (*prepare) (gpointer source_data,
|
||||
GTimeVal *current_time,
|
||||
gint *timeout,
|
||||
gpointer user_data);
|
||||
gboolean (*check) (gpointer source_data,
|
||||
GTimeVal *current_time,
|
||||
gpointer user_data);
|
||||
gboolean (*dispatch) (gpointer source_data,
|
||||
GTimeVal *dispatch_time,
|
||||
gpointer user_data);
|
||||
GDestroyNotify destroy;
|
||||
gboolean (*prepare) (GSource *source,
|
||||
gint *timeout);
|
||||
gboolean (*check) (GSource *source);
|
||||
gboolean (*dispatch) (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data);
|
||||
void (*destroy) (GSource *source);
|
||||
};
|
||||
|
||||
/* Standard priorities */
|
||||
|
||||
#define G_PRIORITY_HIGH -100
|
||||
#define G_PRIORITY_DEFAULT 0
|
||||
#define G_PRIORITY_HIGH_IDLE 100
|
||||
#define G_PRIORITY_DEFAULT_IDLE 200
|
||||
#define G_PRIORITY_LOW 300
|
||||
|
||||
typedef gboolean (*GSourceFunc) (gpointer data);
|
||||
|
||||
/* Hooks for adding to the main loop */
|
||||
guint g_source_add (gint priority,
|
||||
gboolean can_recurse,
|
||||
GSourceFuncs *funcs,
|
||||
gpointer source_data,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify);
|
||||
gboolean g_source_remove (guint tag);
|
||||
gboolean g_source_remove_by_user_data (gpointer user_data);
|
||||
gboolean g_source_remove_by_source_data (gpointer source_data);
|
||||
gboolean g_source_remove_by_funcs_user_data (GSourceFuncs *funcs,
|
||||
gpointer user_data);
|
||||
|
||||
void g_get_current_time (GTimeVal *result);
|
||||
|
||||
/* Running the main loop */
|
||||
GMainLoop* g_main_new (gboolean is_running);
|
||||
void g_main_run (GMainLoop *loop);
|
||||
void g_main_quit (GMainLoop *loop);
|
||||
void g_main_destroy (GMainLoop *loop);
|
||||
gboolean g_main_is_running (GMainLoop *loop);
|
||||
|
||||
/* Run a single iteration of the mainloop. If block is FALSE,
|
||||
* will never block
|
||||
*/
|
||||
gboolean g_main_iteration (gboolean may_block);
|
||||
|
||||
/* See if any events are pending */
|
||||
gboolean g_main_pending (void);
|
||||
|
||||
/* Idles and timeouts */
|
||||
guint g_timeout_add_full (gint priority,
|
||||
guint interval,
|
||||
GSourceFunc function,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
guint g_timeout_add (guint interval,
|
||||
GSourceFunc function,
|
||||
gpointer data);
|
||||
guint g_idle_add (GSourceFunc function,
|
||||
gpointer data);
|
||||
guint g_idle_add_full (gint priority,
|
||||
GSourceFunc function,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy);
|
||||
gboolean g_idle_remove_by_data (gpointer data);
|
||||
|
||||
/* GPollFD
|
||||
/* Any definitions using GPollFD or GPollFunc are primarily
|
||||
* for Unix and not guaranteed to be the compatible on all
|
||||
* operating systems on which GLib runs. Right now, the
|
||||
* GLib does use these functions on Win32 as well, but interprets
|
||||
* them in a fairly different way than on Unix. If you use
|
||||
* these definitions, you are should be prepared to recode
|
||||
* for different operating systems.
|
||||
*
|
||||
* System-specific IO and main loop calls
|
||||
*
|
||||
* On Win32, the fd in a GPollFD should be Win32 HANDLE (*not* a file
|
||||
* descriptor as provided by the C runtime) that can be used by
|
||||
@ -137,32 +102,185 @@ gboolean g_idle_remove_by_data (gpointer data);
|
||||
* Win32. It's really only written for the GIMP's needs so
|
||||
* far.
|
||||
*/
|
||||
|
||||
typedef struct _GPollFD GPollFD;
|
||||
typedef gint (*GPollFunc) (GPollFD *ufds,
|
||||
guint nfsd,
|
||||
gint timeout);
|
||||
typedef gint (*GPollFunc) (GPollFD *ufds,
|
||||
guint nfsd,
|
||||
gint timeout);
|
||||
|
||||
struct _GPollFD
|
||||
{
|
||||
gint fd;
|
||||
gushort events;
|
||||
gushort revents;
|
||||
gint fd;
|
||||
gushort events;
|
||||
gushort revents;
|
||||
};
|
||||
|
||||
void g_main_add_poll (GPollFD *fd,
|
||||
gint priority);
|
||||
void g_main_remove_poll (GPollFD *fd);
|
||||
void g_main_set_poll_func (GPollFunc func);
|
||||
/* Standard priorities */
|
||||
|
||||
#define G_PRIORITY_HIGH -100
|
||||
#define G_PRIORITY_DEFAULT 0
|
||||
#define G_PRIORITY_HIGH_IDLE 100
|
||||
#define G_PRIORITY_DEFAULT_IDLE 200
|
||||
#define G_PRIORITY_LOW 300
|
||||
|
||||
/* GMainContext: */
|
||||
|
||||
GMainContext *g_main_context_get (GThread *thread);
|
||||
GMainContext *g_main_context_default (void);
|
||||
|
||||
gboolean g_main_context_iteration (GMainContext *context,
|
||||
gboolean may_block);
|
||||
gboolean g_main_context_pending (GMainContext *context);
|
||||
|
||||
/* For implementation of legacy interfaces
|
||||
*/
|
||||
GSource *g_main_context_find_source_by_id (GMainContext *context,
|
||||
guint id);
|
||||
GSource *g_main_context_find_source_by_user_data (GMainContext *context,
|
||||
gpointer user_data);
|
||||
GSource *g_main_context_find_source_by_funcs_user_data (GMainContext *context,
|
||||
GSourceFuncs *funcs,
|
||||
gpointer user_data);
|
||||
|
||||
/* Low level functions for implementing custom main loops.
|
||||
*/
|
||||
gboolean g_main_context_prepare (GMainContext *context,
|
||||
gint *priority);
|
||||
gint g_main_context_query (GMainContext *context,
|
||||
gint max_priority,
|
||||
gint *timeout,
|
||||
GPollFD *fds,
|
||||
gint n_fds);
|
||||
gint g_main_context_check (GMainContext *context,
|
||||
gint max_priority,
|
||||
GPollFD *fds,
|
||||
gint n_fds);
|
||||
void g_main_context_dispatch (GMainContext *context);
|
||||
|
||||
void g_main_context_set_poll_func (GMainContext *context,
|
||||
GPollFunc func);
|
||||
GPollFunc g_main_context_get_poll_func (GMainContext *context);
|
||||
|
||||
/* Low level functions for use by source implementations
|
||||
*/
|
||||
void g_main_context_add_poll (GMainContext *context,
|
||||
GPollFD *fd,
|
||||
gint priority);
|
||||
void g_main_context_remove_poll (GMainContext *context,
|
||||
GPollFD *fd);
|
||||
|
||||
/* GMainLoop: */
|
||||
|
||||
GMainLoop *g_main_loop_new (GMainContext *context,
|
||||
gboolean is_running);
|
||||
void g_main_loop_run (GMainLoop *loop);
|
||||
void g_main_loop_quit (GMainLoop *loop);
|
||||
void g_main_loop_destroy (GMainLoop *loop);
|
||||
gboolean g_main_loop_is_running (GMainLoop *loop);
|
||||
|
||||
/* GSource: */
|
||||
|
||||
GSource *g_source_new (GSourceFuncs *source_funcs,
|
||||
guint struct_size);
|
||||
GSource *g_source_ref (GSource *source);
|
||||
void g_source_unref (GSource *source);
|
||||
|
||||
guint g_source_attach (GSource *source,
|
||||
GMainContext *context);
|
||||
void g_source_destroy (GSource *source);
|
||||
|
||||
void g_source_set_priority (GSource *source,
|
||||
gint priority);
|
||||
gint g_source_get_priority (GSource *source);
|
||||
void g_source_set_can_recurse (GSource *source,
|
||||
gboolean can_recurse);
|
||||
gboolean g_source_get_can_recurse (GSource *source);
|
||||
guint g_source_get_id (GSource *source);
|
||||
|
||||
GMainContext *g_source_get_context (GSource *source);
|
||||
|
||||
void g_source_set_callback (GSource *source,
|
||||
GSourceFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
|
||||
|
||||
/* Used to implement g_source_connect_closure and internally*/
|
||||
void g_source_set_callback_indirect (GSource *source,
|
||||
gpointer callback_data,
|
||||
GSourceCallbackFuncs *callback_funcs);
|
||||
|
||||
void g_source_add_poll (GSource *source,
|
||||
GPollFD *fd);
|
||||
void g_source_remove_poll (GSource *source,
|
||||
GPollFD *fd);
|
||||
|
||||
void g_source_get_current_time (GSource *source,
|
||||
GTimeVal *timeval);
|
||||
|
||||
/* void g_source_connect_closure (GSource *source,
|
||||
GClosure *closure);
|
||||
*/
|
||||
|
||||
/* Specific source types
|
||||
*/
|
||||
GSource *g_idle_source_new (void);
|
||||
GSource *g_timeout_source_new (guint interval);
|
||||
|
||||
/* Miscellaneous functions
|
||||
*/
|
||||
void g_get_current_time (GTimeVal *result);
|
||||
|
||||
/* ============== Compat main loop stuff ================== */
|
||||
|
||||
/* Legacy names for GMainLoop functions
|
||||
*/
|
||||
#define g_main_new(is_running) g_main_loop_new (NULL, is_running);
|
||||
#define g_main_run(loop) g_main_loop_run(loop)
|
||||
#define g_main_quit(loop) g_main_loop_quit(loop)
|
||||
#define g_main_destroy(loop) g_main_loop_destroy(loop)
|
||||
#define g_main_is_running(loop) g_main_loop_is_running(loop)
|
||||
|
||||
/* Source manipulation by ID */
|
||||
gboolean g_source_remove (guint tag);
|
||||
gboolean g_source_remove_by_user_data (gpointer user_data);
|
||||
gboolean g_source_remove_by_funcs_user_data (GSourceFuncs *funcs,
|
||||
gpointer user_data);
|
||||
|
||||
/* Functions to manipulate the default main loop
|
||||
*/
|
||||
|
||||
#define g_main_iteration(may_block) g_main_context_iteration (NULL, may_block)
|
||||
#define g_main_pending() g_main_context_pending (NULL)
|
||||
|
||||
#define g_main_set_poll_func(func) g_main_context_set_poll_func (NULL, func)
|
||||
|
||||
/* Idles and timeouts */
|
||||
guint g_timeout_add_full (gint priority,
|
||||
guint interval,
|
||||
GSourceFunc function,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
guint g_timeout_add (guint interval,
|
||||
GSourceFunc function,
|
||||
gpointer data);
|
||||
guint g_idle_add (GSourceFunc function,
|
||||
gpointer data);
|
||||
guint g_idle_add_full (gint priority,
|
||||
GSourceFunc function,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
gboolean g_idle_remove_by_data (gpointer data);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
|
||||
/* Useful on other platforms, too? */
|
||||
|
||||
GPollFunc g_main_win32_get_poll_func (void);
|
||||
|
||||
#endif
|
||||
/* This is used to add polling for Windows messages. GDK (GTK+) programs
|
||||
* should *not* use this.
|
||||
*/
|
||||
void g_main_poll_win32_msg_add (gint priority,
|
||||
GPollFD *fd,
|
||||
guint hwnd);
|
||||
#endif G_OS_WIN32
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_MAIN_H__ */
|
||||
|
||||
|
@ -28,7 +28,6 @@
|
||||
#define __G_THREAD_H__
|
||||
|
||||
#include <gerror.h>
|
||||
#include <gmain.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
8
gtypes.h
8
gtypes.h
@ -314,6 +314,14 @@ union _GDoubleIEEE754
|
||||
#error unknown ENDIAN type
|
||||
#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
|
||||
|
||||
typedef struct _GTimeVal GTimeVal;
|
||||
|
||||
struct _GTimeVal
|
||||
{
|
||||
glong tv_sec;
|
||||
glong tv_usec;
|
||||
};
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_TYPES_H__ */
|
||||
|
@ -11,6 +11,7 @@ date-test
|
||||
dirname-test
|
||||
hash-test
|
||||
list-test
|
||||
mainloop-test
|
||||
markup-test
|
||||
node-test
|
||||
queue-test
|
||||
|
@ -19,6 +19,7 @@ TESTS = \
|
||||
gio-test \
|
||||
hash-test \
|
||||
list-test \
|
||||
mainloop-test \
|
||||
markup-test \
|
||||
node-test \
|
||||
queue-test \
|
||||
@ -45,6 +46,7 @@ dirname_test_LDADD = $(progs_LDADD)
|
||||
gio_test_LDADD = $(progs_LDADD)
|
||||
hash_test_LDADD = $(progs_LDADD)
|
||||
list_test_LDADD = $(progs_LDADD)
|
||||
mainloop_test_LDADD = $(thread_LDADD)
|
||||
markup_test_LDADD = $(progs_LDADD)
|
||||
node_test_LDADD = $(progs_LDADD)
|
||||
queue_test_LDADD = $(progs_LDADD)
|
||||
|
396
tests/mainloop-test.c
Normal file
396
tests/mainloop-test.c
Normal file
@ -0,0 +1,396 @@
|
||||
#include <errno.h>
|
||||
#include <glib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ITERS 10000
|
||||
#define INCREMENT 10
|
||||
#define NTHREADS 4
|
||||
#define NCRAWLERS 4
|
||||
#define CRAWLER_TIMEOUT_RANGE 40
|
||||
#define RECURSER_TIMEOUT 50
|
||||
|
||||
G_LOCK_DEFINE_STATIC (context_array_lock);
|
||||
GPtrArray *context_array;
|
||||
GMainLoop *main_loop;
|
||||
|
||||
G_LOCK_DEFINE_STATIC (crawler_array_lock);
|
||||
GPtrArray *crawler_array;
|
||||
|
||||
typedef struct _AddrData AddrData;
|
||||
typedef struct _TestData TestData;
|
||||
|
||||
struct _AddrData
|
||||
{
|
||||
GMainLoop *loop;
|
||||
GIOChannel *dest;
|
||||
gint count;
|
||||
};
|
||||
|
||||
struct _TestData
|
||||
{
|
||||
gint current_val;
|
||||
gint iters;
|
||||
GIOChannel *in;
|
||||
};
|
||||
|
||||
static void cleanup_crawlers (GMainContext *context);
|
||||
|
||||
gboolean
|
||||
read_all (GIOChannel *channel, char *buf, int len)
|
||||
{
|
||||
int bytes_read = 0;
|
||||
int count;
|
||||
GIOError err;
|
||||
|
||||
while (bytes_read < len)
|
||||
{
|
||||
err = g_io_channel_read (channel, buf + bytes_read, len - bytes_read, &count);
|
||||
if (err)
|
||||
{
|
||||
if (err != G_IO_ERROR_AGAIN)
|
||||
return FALSE;
|
||||
}
|
||||
else if (count == 0)
|
||||
return FALSE;
|
||||
|
||||
bytes_read += count;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
write_all (GIOChannel *channel, char *buf, int len)
|
||||
{
|
||||
int bytes_written = 0;
|
||||
int count;
|
||||
GIOError err;
|
||||
|
||||
while (bytes_written < len)
|
||||
{
|
||||
err = g_io_channel_write (channel, buf + bytes_written, len - bytes_written, &count);
|
||||
if (err && err != G_IO_ERROR_AGAIN)
|
||||
return FALSE;
|
||||
|
||||
bytes_written += count;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
adder_callback (GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
gpointer data)
|
||||
{
|
||||
char buf1[32];
|
||||
char buf2[32];
|
||||
|
||||
char result[32];
|
||||
|
||||
AddrData *addr_data = data;
|
||||
|
||||
if (!read_all (source, buf1, 32) ||
|
||||
!read_all (source, buf2, 32))
|
||||
{
|
||||
g_main_loop_quit (addr_data->loop);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
sprintf (result, "%d", atoi(buf1) + atoi(buf2));
|
||||
write_all (addr_data->dest, result, 32);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
timeout_callback (gpointer data)
|
||||
{
|
||||
AddrData *addr_data = data;
|
||||
|
||||
addr_data->count++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
adder_thread (gpointer data)
|
||||
{
|
||||
GMainContext *context;
|
||||
GSource *adder_source;
|
||||
GSource *timeout_source;
|
||||
|
||||
GIOChannel **channels = data;
|
||||
AddrData addr_data;
|
||||
|
||||
context = g_main_context_get (g_thread_self());
|
||||
|
||||
G_LOCK (context_array_lock);
|
||||
g_ptr_array_add (context_array, context);
|
||||
G_UNLOCK (context_array_lock);
|
||||
|
||||
addr_data.dest = channels[1];
|
||||
addr_data.loop = g_main_loop_new (context, FALSE);
|
||||
addr_data.count = 0;
|
||||
|
||||
adder_source = g_io_create_watch (channels[0], G_IO_IN | G_IO_HUP);
|
||||
g_source_set_callback (adder_source, (GSourceFunc)adder_callback, &addr_data, NULL);
|
||||
g_source_attach (adder_source, context);
|
||||
|
||||
timeout_source = g_timeout_source_new (10);
|
||||
g_source_set_callback (timeout_source, (GSourceFunc)timeout_callback, &addr_data, NULL);
|
||||
g_source_set_priority (timeout_source, G_PRIORITY_HIGH);
|
||||
g_source_attach (timeout_source, context);
|
||||
|
||||
g_main_run (addr_data.loop);
|
||||
|
||||
g_io_channel_close (channels[0]);
|
||||
g_io_channel_close (channels[1]);
|
||||
g_io_channel_unref (channels[0]);
|
||||
g_io_channel_unref (channels[1]);
|
||||
|
||||
g_free (channels);
|
||||
|
||||
g_main_loop_destroy (addr_data.loop);
|
||||
|
||||
g_print ("Timeout run %d times\n", addr_data.count);
|
||||
|
||||
G_LOCK (context_array_lock);
|
||||
g_ptr_array_remove (context_array, context);
|
||||
if (context_array->len == 0)
|
||||
g_main_loop_quit (main_loop);
|
||||
G_UNLOCK (context_array_lock);
|
||||
|
||||
cleanup_crawlers (context);
|
||||
}
|
||||
|
||||
void
|
||||
io_pipe (GIOChannel **channels)
|
||||
{
|
||||
gint fds[2];
|
||||
|
||||
if (pipe(fds) < 0)
|
||||
{
|
||||
g_warning ("Cannot create pipe %s\n", g_strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
channels[0] = g_io_channel_unix_new (fds[0]);
|
||||
channels[1] = g_io_channel_unix_new (fds[1]);
|
||||
}
|
||||
|
||||
void
|
||||
do_add (GIOChannel *in, gint a, gint b)
|
||||
{
|
||||
char buf1[32];
|
||||
char buf2[32];
|
||||
|
||||
sprintf (buf1, "%d", a);
|
||||
sprintf (buf2, "%d", b);
|
||||
|
||||
write_all (in, buf1, 32);
|
||||
write_all (in, buf2, 32);
|
||||
}
|
||||
|
||||
gboolean
|
||||
adder_response (GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
gpointer data)
|
||||
{
|
||||
char result[32];
|
||||
TestData *test_data = data;
|
||||
|
||||
if (!read_all (source, result, 32))
|
||||
return FALSE;
|
||||
|
||||
test_data->current_val = atoi (result);
|
||||
test_data->iters--;
|
||||
|
||||
if (test_data->iters == 0)
|
||||
{
|
||||
if (test_data->current_val != ITERS * INCREMENT)
|
||||
{
|
||||
g_print ("Addition failed: %d != %d\n",
|
||||
test_data->current_val, ITERS * INCREMENT);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
g_io_channel_close (source);
|
||||
g_io_channel_close (test_data->in);
|
||||
|
||||
g_io_channel_unref (source);
|
||||
g_io_channel_unref (test_data->in);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
do_add (test_data->in, test_data->current_val, INCREMENT);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
create_adder_thread (void)
|
||||
{
|
||||
GError *err = NULL;
|
||||
TestData *test_data;
|
||||
|
||||
GIOChannel *in_channels[2];
|
||||
GIOChannel *out_channels[2];
|
||||
|
||||
GIOChannel **sub_channels;
|
||||
|
||||
sub_channels = g_new (GIOChannel *, 2);
|
||||
|
||||
io_pipe (in_channels);
|
||||
io_pipe (out_channels);
|
||||
|
||||
sub_channels[0] = in_channels[0];
|
||||
sub_channels[1] = out_channels[1];
|
||||
|
||||
g_thread_create (adder_thread, sub_channels, 0,
|
||||
FALSE, TRUE, G_THREAD_PRIORITY_NORMAL, &err);
|
||||
|
||||
if (err)
|
||||
{
|
||||
g_warning ("Cannot create thread: %s", err->message);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
test_data = g_new (TestData, 1);
|
||||
test_data->in = in_channels[1];
|
||||
test_data->current_val = 0;
|
||||
test_data->iters = ITERS;
|
||||
|
||||
g_io_add_watch (out_channels[0], G_IO_IN | G_IO_HUP,
|
||||
adder_response, test_data);
|
||||
|
||||
do_add (test_data->in, test_data->current_val, INCREMENT);
|
||||
}
|
||||
|
||||
static void create_crawler (void);
|
||||
|
||||
static void
|
||||
remove_crawler (void)
|
||||
{
|
||||
GSource *other_source;
|
||||
|
||||
if (crawler_array->len > 0)
|
||||
{
|
||||
other_source = crawler_array->pdata[g_random_int_range (0, crawler_array->len)];
|
||||
g_source_destroy (other_source);
|
||||
g_assert (g_ptr_array_remove_fast (crawler_array, other_source));
|
||||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
crawler_callback (gpointer data)
|
||||
{
|
||||
GSource *source = data;
|
||||
|
||||
G_LOCK (crawler_array_lock);
|
||||
|
||||
if (!g_ptr_array_remove_fast (crawler_array, source))
|
||||
remove_crawler();
|
||||
|
||||
remove_crawler();
|
||||
G_UNLOCK (crawler_array_lock);
|
||||
|
||||
create_crawler();
|
||||
create_crawler();
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
create_crawler (void)
|
||||
{
|
||||
GSource *source = g_timeout_source_new (g_random_int_range (0, CRAWLER_TIMEOUT_RANGE));
|
||||
g_source_set_callback (source, (GSourceFunc)crawler_callback, source, NULL);
|
||||
|
||||
G_LOCK (context_array_lock);
|
||||
g_source_attach (source, context_array->pdata[g_random_int_range (0, context_array->len)]);
|
||||
G_UNLOCK (context_array_lock);
|
||||
|
||||
G_LOCK (crawler_array_lock);
|
||||
g_ptr_array_add (crawler_array, source);
|
||||
G_UNLOCK (crawler_array_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup_crawlers (GMainContext *context)
|
||||
{
|
||||
gint i;
|
||||
|
||||
G_LOCK (crawler_array_lock);
|
||||
for (i=0; i < crawler_array->len; i++)
|
||||
{
|
||||
if (g_source_get_context (crawler_array->pdata[i]) == context)
|
||||
{
|
||||
g_source_destroy (g_ptr_array_remove_index (crawler_array, i));
|
||||
i--;
|
||||
}
|
||||
}
|
||||
G_UNLOCK (crawler_array_lock);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
recurser_idle (gpointer data)
|
||||
{
|
||||
GMainContext *context = data;
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
g_main_context_iteration (context, TRUE);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
recurser_start (gpointer data)
|
||||
{
|
||||
GMainContext *context;
|
||||
GSource *source;
|
||||
|
||||
G_LOCK (context_array_lock);
|
||||
context = context_array->pdata[g_random_int_range (0, context_array->len)];
|
||||
source = g_idle_source_new ();
|
||||
g_source_set_callback (source, recurser_idle, context, NULL);
|
||||
g_source_attach (source, context);
|
||||
G_UNLOCK (context_array_lock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
/* Only run the test, if threads are enabled and a default thread
|
||||
implementation is available */
|
||||
#if defined(G_THREADS_ENABLED) && ! defined(G_THREADS_IMPL_NONE)
|
||||
gint i;
|
||||
|
||||
g_thread_init (NULL);
|
||||
|
||||
context_array = g_ptr_array_new ();
|
||||
crawler_array = g_ptr_array_new ();
|
||||
|
||||
main_loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
for (i = 0; i < NTHREADS; i++)
|
||||
create_adder_thread ();
|
||||
|
||||
for (i = 0; i < NCRAWLERS; i++)
|
||||
create_crawler ();
|
||||
|
||||
g_timeout_add (RECURSER_TIMEOUT, recurser_start, NULL);
|
||||
|
||||
g_main_loop_run (main_loop);
|
||||
g_main_loop_destroy (main_loop);
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
}
|
232
tests/timeloop-basic.c
Normal file
232
tests/timeloop-basic.c
Normal file
@ -0,0 +1,232 @@
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/poll.h>
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
static int n_children = 3;
|
||||
static int n_active_children;
|
||||
static int n_iters = 10000;
|
||||
|
||||
static int write_fds[1024];
|
||||
static struct pollfd poll_fds[1024];
|
||||
|
||||
void
|
||||
my_pipe (int *fds)
|
||||
{
|
||||
if (pipe(fds) < 0)
|
||||
{
|
||||
fprintf (stderr, "Cannot create pipe %s\n", strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
read_all (int fd, char *buf, int len)
|
||||
{
|
||||
int bytes_read = 0;
|
||||
int count;
|
||||
|
||||
while (bytes_read < len)
|
||||
{
|
||||
count = read (fd, buf + bytes_read, len - bytes_read);
|
||||
if (count < 0)
|
||||
{
|
||||
if (errno != EAGAIN)
|
||||
return FALSE;
|
||||
}
|
||||
else if (count == 0)
|
||||
return FALSE;
|
||||
|
||||
bytes_read += count;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
write_all (int fd, char *buf, int len)
|
||||
{
|
||||
int bytes_written = 0;
|
||||
int count;
|
||||
|
||||
while (bytes_written < len)
|
||||
{
|
||||
count = write (fd, buf + bytes_written, len - bytes_written);
|
||||
if (count < 0)
|
||||
{
|
||||
if (errno != EAGAIN)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bytes_written += count;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
run_child (int in_fd, int out_fd)
|
||||
{
|
||||
int i;
|
||||
int val = 1;
|
||||
|
||||
for (i = 0; i < n_iters; i++)
|
||||
{
|
||||
write_all (out_fd, (char *)&val, sizeof (val));
|
||||
read_all (in_fd, (char *)&val, sizeof (val));
|
||||
}
|
||||
|
||||
val = 0;
|
||||
write_all (out_fd, (char *)&val, sizeof (val));
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
int
|
||||
input_callback (int source, int dest)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (!read_all (source, (char *)&val, sizeof(val)))
|
||||
{
|
||||
fprintf (stderr,"Unexpected EOF\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (val)
|
||||
{
|
||||
write_all (dest, (char *)&val, sizeof(val));
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
close (source);
|
||||
close (dest);
|
||||
|
||||
n_active_children--;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
create_child (int pos)
|
||||
{
|
||||
int pid;
|
||||
int in_fds[2];
|
||||
int out_fds[2];
|
||||
|
||||
my_pipe (in_fds);
|
||||
my_pipe (out_fds);
|
||||
|
||||
pid = fork ();
|
||||
|
||||
if (pid > 0) /* Parent */
|
||||
{
|
||||
close (in_fds[0]);
|
||||
close (out_fds[1]);
|
||||
|
||||
write_fds[pos] = in_fds[1];
|
||||
poll_fds[pos].fd = out_fds[0];
|
||||
poll_fds[pos].events = POLLIN;
|
||||
}
|
||||
else if (pid == 0) /* Child */
|
||||
{
|
||||
close (in_fds[1]);
|
||||
close (out_fds[0]);
|
||||
|
||||
setsid ();
|
||||
|
||||
run_child (in_fds[0], out_fds[1]);
|
||||
}
|
||||
else /* Error */
|
||||
{
|
||||
fprintf (stderr,"Cannot fork: %s\n", strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
static double
|
||||
difftimeval (struct timeval *old, struct timeval *new)
|
||||
{
|
||||
return
|
||||
(new->tv_sec - old->tv_sec) * 1000. + (new->tv_usec - old->tv_usec) / 1000;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int i, j;
|
||||
struct rusage old_usage;
|
||||
struct rusage new_usage;
|
||||
|
||||
if (argc > 1)
|
||||
n_children = atoi(argv[1]);
|
||||
|
||||
if (argc > 2)
|
||||
n_iters = atoi(argv[2]);
|
||||
|
||||
printf ("Children: %d Iters: %d\n", n_children, n_iters);
|
||||
|
||||
n_active_children = n_children;
|
||||
for (i = 0; i < n_children; i++)
|
||||
create_child (i);
|
||||
|
||||
getrusage (RUSAGE_SELF, &old_usage);
|
||||
|
||||
while (n_active_children > 0)
|
||||
{
|
||||
int old_n_active_children = n_active_children;
|
||||
|
||||
poll (poll_fds, n_active_children, -1);
|
||||
|
||||
for (i=0; i<n_active_children; i++)
|
||||
{
|
||||
if (poll_fds[i].events & (POLLIN | POLLHUP))
|
||||
{
|
||||
if (!input_callback (poll_fds[i].fd, write_fds[i]))
|
||||
write_fds[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (old_n_active_children > n_active_children)
|
||||
{
|
||||
j = 0;
|
||||
for (i=0; i<old_n_active_children; i++)
|
||||
{
|
||||
if (write_fds[i] != -1)
|
||||
{
|
||||
if (j < i)
|
||||
{
|
||||
poll_fds[j] = poll_fds[i];
|
||||
write_fds[j] = write_fds[i];
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getrusage (RUSAGE_SELF, &new_usage);
|
||||
|
||||
printf ("Elapsed user: %g\n",
|
||||
difftimeval (&old_usage.ru_utime, &new_usage.ru_utime));
|
||||
printf ("Elapsed system: %g\n",
|
||||
difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
|
||||
printf ("Elapsed total: %g\n",
|
||||
difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +
|
||||
difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
|
||||
printf ("total / iteration: %g\n",
|
||||
(difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +
|
||||
difftimeval (&old_usage.ru_stime, &new_usage.ru_stime)) /
|
||||
(n_iters * n_children));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
213
tests/timeloop.c
Normal file
213
tests/timeloop.c
Normal file
@ -0,0 +1,213 @@
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
static int n_children = 3;
|
||||
static int n_active_children;
|
||||
static int n_iters = 10000;
|
||||
static GMainLoop *loop;
|
||||
|
||||
void
|
||||
io_pipe (GIOChannel **channels)
|
||||
{
|
||||
int fds[2];
|
||||
|
||||
if (pipe(fds) < 0)
|
||||
{
|
||||
fprintf (stderr, "Cannot create pipe %s\n", g_strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
channels[0] = g_io_channel_unix_new (fds[0]);
|
||||
channels[1] = g_io_channel_unix_new (fds[1]);
|
||||
}
|
||||
|
||||
gboolean
|
||||
read_all (GIOChannel *channel, char *buf, int len)
|
||||
{
|
||||
int bytes_read = 0;
|
||||
int count;
|
||||
GIOError err;
|
||||
|
||||
while (bytes_read < len)
|
||||
{
|
||||
err = g_io_channel_read (channel, buf + bytes_read, len - bytes_read, &count);
|
||||
if (err)
|
||||
{
|
||||
if (err != G_IO_ERROR_AGAIN)
|
||||
return FALSE;
|
||||
}
|
||||
else if (count == 0)
|
||||
return FALSE;
|
||||
|
||||
bytes_read += count;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
write_all (GIOChannel *channel, char *buf, int len)
|
||||
{
|
||||
int bytes_written = 0;
|
||||
int count;
|
||||
GIOError err;
|
||||
|
||||
while (bytes_written < len)
|
||||
{
|
||||
err = g_io_channel_write (channel, buf + bytes_written, len - bytes_written, &count);
|
||||
if (err && err != G_IO_ERROR_AGAIN)
|
||||
return FALSE;
|
||||
|
||||
bytes_written += count;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
run_child (GIOChannel *in_channel, GIOChannel *out_channel)
|
||||
{
|
||||
int i;
|
||||
int val = 1;
|
||||
GTimer *timer = g_timer_new();
|
||||
|
||||
for (i = 0; i < n_iters; i++)
|
||||
{
|
||||
write_all (out_channel, (char *)&val, sizeof (val));
|
||||
read_all (in_channel, (char *)&val, sizeof (val));
|
||||
}
|
||||
|
||||
val = 0;
|
||||
write_all (out_channel, (char *)&val, sizeof (val));
|
||||
|
||||
val = g_timer_elapsed (timer, NULL) * 1000;
|
||||
|
||||
write_all (out_channel, (char *)&val, sizeof (val));
|
||||
g_timer_destroy (timer);
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
gboolean
|
||||
input_callback (GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
gpointer data)
|
||||
{
|
||||
int val;
|
||||
GIOChannel *dest = (GIOChannel *)data;
|
||||
|
||||
if (!read_all (source, (char *)&val, sizeof(val)))
|
||||
{
|
||||
fprintf (stderr, "Unexpected EOF\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (val)
|
||||
{
|
||||
write_all (dest, (char *)&val, sizeof(val));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_io_channel_close (source);
|
||||
g_io_channel_close (dest);
|
||||
|
||||
g_io_channel_unref (source);
|
||||
g_io_channel_unref (dest);
|
||||
|
||||
n_active_children--;
|
||||
if (n_active_children == 0)
|
||||
g_main_quit (loop);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
create_child ()
|
||||
{
|
||||
int pid;
|
||||
GIOChannel *in_channels[2];
|
||||
GIOChannel *out_channels[2];
|
||||
|
||||
io_pipe (in_channels);
|
||||
io_pipe (out_channels);
|
||||
|
||||
pid = fork ();
|
||||
|
||||
if (pid > 0) /* Parent */
|
||||
{
|
||||
g_io_channel_close (in_channels[0]);
|
||||
g_io_channel_close (out_channels[1]);
|
||||
|
||||
g_io_add_watch (out_channels[0], G_IO_IN | G_IO_HUP,
|
||||
input_callback, in_channels[1]);
|
||||
}
|
||||
else if (pid == 0) /* Child */
|
||||
{
|
||||
g_io_channel_close (in_channels[1]);
|
||||
g_io_channel_close (out_channels[0]);
|
||||
|
||||
setsid ();
|
||||
|
||||
run_child (in_channels[0], out_channels[1]);
|
||||
}
|
||||
else /* Error */
|
||||
{
|
||||
fprintf (stderr, "Cannot fork: %s\n", g_strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
static double
|
||||
difftimeval (struct timeval *old, struct timeval *new)
|
||||
{
|
||||
return
|
||||
(new->tv_sec - old->tv_sec) * 1000. + (new->tv_usec - old->tv_usec) / 1000;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
struct rusage old_usage;
|
||||
struct rusage new_usage;
|
||||
|
||||
if (argc > 1)
|
||||
n_children = atoi(argv[1]);
|
||||
|
||||
if (argc > 2)
|
||||
n_iters = atoi(argv[2]);
|
||||
|
||||
printf ("Children: %d Iters: %d\n", n_children, n_iters);
|
||||
|
||||
n_active_children = n_children;
|
||||
for (i = 0; i < n_children; i++)
|
||||
create_child ();
|
||||
|
||||
getrusage (RUSAGE_SELF, &old_usage);
|
||||
loop = g_main_new (FALSE);
|
||||
g_main_run (loop);
|
||||
getrusage (RUSAGE_SELF, &new_usage);
|
||||
|
||||
printf ("Elapsed user: %g\n",
|
||||
difftimeval (&old_usage.ru_utime, &new_usage.ru_utime));
|
||||
printf ("Elapsed system: %g\n",
|
||||
difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
|
||||
printf ("Elapsed total: %g\n",
|
||||
difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +
|
||||
difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
|
||||
printf ("total / iteration: %g\n",
|
||||
(difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +
|
||||
difftimeval (&old_usage.ru_stime, &new_usage.ru_stime)) /
|
||||
(n_iters * n_children));
|
||||
|
||||
return 0;
|
||||
}
|
232
timeloop-basic.c
Normal file
232
timeloop-basic.c
Normal file
@ -0,0 +1,232 @@
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/poll.h>
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
static int n_children = 3;
|
||||
static int n_active_children;
|
||||
static int n_iters = 10000;
|
||||
|
||||
static int write_fds[1024];
|
||||
static struct pollfd poll_fds[1024];
|
||||
|
||||
void
|
||||
my_pipe (int *fds)
|
||||
{
|
||||
if (pipe(fds) < 0)
|
||||
{
|
||||
fprintf (stderr, "Cannot create pipe %s\n", strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
read_all (int fd, char *buf, int len)
|
||||
{
|
||||
int bytes_read = 0;
|
||||
int count;
|
||||
|
||||
while (bytes_read < len)
|
||||
{
|
||||
count = read (fd, buf + bytes_read, len - bytes_read);
|
||||
if (count < 0)
|
||||
{
|
||||
if (errno != EAGAIN)
|
||||
return FALSE;
|
||||
}
|
||||
else if (count == 0)
|
||||
return FALSE;
|
||||
|
||||
bytes_read += count;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
write_all (int fd, char *buf, int len)
|
||||
{
|
||||
int bytes_written = 0;
|
||||
int count;
|
||||
|
||||
while (bytes_written < len)
|
||||
{
|
||||
count = write (fd, buf + bytes_written, len - bytes_written);
|
||||
if (count < 0)
|
||||
{
|
||||
if (errno != EAGAIN)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bytes_written += count;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
run_child (int in_fd, int out_fd)
|
||||
{
|
||||
int i;
|
||||
int val = 1;
|
||||
|
||||
for (i = 0; i < n_iters; i++)
|
||||
{
|
||||
write_all (out_fd, (char *)&val, sizeof (val));
|
||||
read_all (in_fd, (char *)&val, sizeof (val));
|
||||
}
|
||||
|
||||
val = 0;
|
||||
write_all (out_fd, (char *)&val, sizeof (val));
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
int
|
||||
input_callback (int source, int dest)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (!read_all (source, (char *)&val, sizeof(val)))
|
||||
{
|
||||
fprintf (stderr,"Unexpected EOF\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (val)
|
||||
{
|
||||
write_all (dest, (char *)&val, sizeof(val));
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
close (source);
|
||||
close (dest);
|
||||
|
||||
n_active_children--;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
create_child (int pos)
|
||||
{
|
||||
int pid;
|
||||
int in_fds[2];
|
||||
int out_fds[2];
|
||||
|
||||
my_pipe (in_fds);
|
||||
my_pipe (out_fds);
|
||||
|
||||
pid = fork ();
|
||||
|
||||
if (pid > 0) /* Parent */
|
||||
{
|
||||
close (in_fds[0]);
|
||||
close (out_fds[1]);
|
||||
|
||||
write_fds[pos] = in_fds[1];
|
||||
poll_fds[pos].fd = out_fds[0];
|
||||
poll_fds[pos].events = POLLIN;
|
||||
}
|
||||
else if (pid == 0) /* Child */
|
||||
{
|
||||
close (in_fds[1]);
|
||||
close (out_fds[0]);
|
||||
|
||||
setsid ();
|
||||
|
||||
run_child (in_fds[0], out_fds[1]);
|
||||
}
|
||||
else /* Error */
|
||||
{
|
||||
fprintf (stderr,"Cannot fork: %s\n", strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
static double
|
||||
difftimeval (struct timeval *old, struct timeval *new)
|
||||
{
|
||||
return
|
||||
(new->tv_sec - old->tv_sec) * 1000. + (new->tv_usec - old->tv_usec) / 1000;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int i, j;
|
||||
struct rusage old_usage;
|
||||
struct rusage new_usage;
|
||||
|
||||
if (argc > 1)
|
||||
n_children = atoi(argv[1]);
|
||||
|
||||
if (argc > 2)
|
||||
n_iters = atoi(argv[2]);
|
||||
|
||||
printf ("Children: %d Iters: %d\n", n_children, n_iters);
|
||||
|
||||
n_active_children = n_children;
|
||||
for (i = 0; i < n_children; i++)
|
||||
create_child (i);
|
||||
|
||||
getrusage (RUSAGE_SELF, &old_usage);
|
||||
|
||||
while (n_active_children > 0)
|
||||
{
|
||||
int old_n_active_children = n_active_children;
|
||||
|
||||
poll (poll_fds, n_active_children, -1);
|
||||
|
||||
for (i=0; i<n_active_children; i++)
|
||||
{
|
||||
if (poll_fds[i].events & (POLLIN | POLLHUP))
|
||||
{
|
||||
if (!input_callback (poll_fds[i].fd, write_fds[i]))
|
||||
write_fds[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (old_n_active_children > n_active_children)
|
||||
{
|
||||
j = 0;
|
||||
for (i=0; i<old_n_active_children; i++)
|
||||
{
|
||||
if (write_fds[i] != -1)
|
||||
{
|
||||
if (j < i)
|
||||
{
|
||||
poll_fds[j] = poll_fds[i];
|
||||
write_fds[j] = write_fds[i];
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getrusage (RUSAGE_SELF, &new_usage);
|
||||
|
||||
printf ("Elapsed user: %g\n",
|
||||
difftimeval (&old_usage.ru_utime, &new_usage.ru_utime));
|
||||
printf ("Elapsed system: %g\n",
|
||||
difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
|
||||
printf ("Elapsed total: %g\n",
|
||||
difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +
|
||||
difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
|
||||
printf ("total / iteration: %g\n",
|
||||
(difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +
|
||||
difftimeval (&old_usage.ru_stime, &new_usage.ru_stime)) /
|
||||
(n_iters * n_children));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
213
timeloop.c
Normal file
213
timeloop.c
Normal file
@ -0,0 +1,213 @@
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
static int n_children = 3;
|
||||
static int n_active_children;
|
||||
static int n_iters = 10000;
|
||||
static GMainLoop *loop;
|
||||
|
||||
void
|
||||
io_pipe (GIOChannel **channels)
|
||||
{
|
||||
int fds[2];
|
||||
|
||||
if (pipe(fds) < 0)
|
||||
{
|
||||
fprintf (stderr, "Cannot create pipe %s\n", g_strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
channels[0] = g_io_channel_unix_new (fds[0]);
|
||||
channels[1] = g_io_channel_unix_new (fds[1]);
|
||||
}
|
||||
|
||||
gboolean
|
||||
read_all (GIOChannel *channel, char *buf, int len)
|
||||
{
|
||||
int bytes_read = 0;
|
||||
int count;
|
||||
GIOError err;
|
||||
|
||||
while (bytes_read < len)
|
||||
{
|
||||
err = g_io_channel_read (channel, buf + bytes_read, len - bytes_read, &count);
|
||||
if (err)
|
||||
{
|
||||
if (err != G_IO_ERROR_AGAIN)
|
||||
return FALSE;
|
||||
}
|
||||
else if (count == 0)
|
||||
return FALSE;
|
||||
|
||||
bytes_read += count;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
write_all (GIOChannel *channel, char *buf, int len)
|
||||
{
|
||||
int bytes_written = 0;
|
||||
int count;
|
||||
GIOError err;
|
||||
|
||||
while (bytes_written < len)
|
||||
{
|
||||
err = g_io_channel_write (channel, buf + bytes_written, len - bytes_written, &count);
|
||||
if (err && err != G_IO_ERROR_AGAIN)
|
||||
return FALSE;
|
||||
|
||||
bytes_written += count;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
run_child (GIOChannel *in_channel, GIOChannel *out_channel)
|
||||
{
|
||||
int i;
|
||||
int val = 1;
|
||||
GTimer *timer = g_timer_new();
|
||||
|
||||
for (i = 0; i < n_iters; i++)
|
||||
{
|
||||
write_all (out_channel, (char *)&val, sizeof (val));
|
||||
read_all (in_channel, (char *)&val, sizeof (val));
|
||||
}
|
||||
|
||||
val = 0;
|
||||
write_all (out_channel, (char *)&val, sizeof (val));
|
||||
|
||||
val = g_timer_elapsed (timer, NULL) * 1000;
|
||||
|
||||
write_all (out_channel, (char *)&val, sizeof (val));
|
||||
g_timer_destroy (timer);
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
gboolean
|
||||
input_callback (GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
gpointer data)
|
||||
{
|
||||
int val;
|
||||
GIOChannel *dest = (GIOChannel *)data;
|
||||
|
||||
if (!read_all (source, (char *)&val, sizeof(val)))
|
||||
{
|
||||
fprintf (stderr, "Unexpected EOF\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (val)
|
||||
{
|
||||
write_all (dest, (char *)&val, sizeof(val));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_io_channel_close (source);
|
||||
g_io_channel_close (dest);
|
||||
|
||||
g_io_channel_unref (source);
|
||||
g_io_channel_unref (dest);
|
||||
|
||||
n_active_children--;
|
||||
if (n_active_children == 0)
|
||||
g_main_quit (loop);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
create_child ()
|
||||
{
|
||||
int pid;
|
||||
GIOChannel *in_channels[2];
|
||||
GIOChannel *out_channels[2];
|
||||
|
||||
io_pipe (in_channels);
|
||||
io_pipe (out_channels);
|
||||
|
||||
pid = fork ();
|
||||
|
||||
if (pid > 0) /* Parent */
|
||||
{
|
||||
g_io_channel_close (in_channels[0]);
|
||||
g_io_channel_close (out_channels[1]);
|
||||
|
||||
g_io_add_watch (out_channels[0], G_IO_IN | G_IO_HUP,
|
||||
input_callback, in_channels[1]);
|
||||
}
|
||||
else if (pid == 0) /* Child */
|
||||
{
|
||||
g_io_channel_close (in_channels[1]);
|
||||
g_io_channel_close (out_channels[0]);
|
||||
|
||||
setsid ();
|
||||
|
||||
run_child (in_channels[0], out_channels[1]);
|
||||
}
|
||||
else /* Error */
|
||||
{
|
||||
fprintf (stderr, "Cannot fork: %s\n", g_strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
static double
|
||||
difftimeval (struct timeval *old, struct timeval *new)
|
||||
{
|
||||
return
|
||||
(new->tv_sec - old->tv_sec) * 1000. + (new->tv_usec - old->tv_usec) / 1000;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
struct rusage old_usage;
|
||||
struct rusage new_usage;
|
||||
|
||||
if (argc > 1)
|
||||
n_children = atoi(argv[1]);
|
||||
|
||||
if (argc > 2)
|
||||
n_iters = atoi(argv[2]);
|
||||
|
||||
printf ("Children: %d Iters: %d\n", n_children, n_iters);
|
||||
|
||||
n_active_children = n_children;
|
||||
for (i = 0; i < n_children; i++)
|
||||
create_child ();
|
||||
|
||||
getrusage (RUSAGE_SELF, &old_usage);
|
||||
loop = g_main_new (FALSE);
|
||||
g_main_run (loop);
|
||||
getrusage (RUSAGE_SELF, &new_usage);
|
||||
|
||||
printf ("Elapsed user: %g\n",
|
||||
difftimeval (&old_usage.ru_utime, &new_usage.ru_utime));
|
||||
printf ("Elapsed system: %g\n",
|
||||
difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
|
||||
printf ("Elapsed total: %g\n",
|
||||
difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +
|
||||
difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
|
||||
printf ("total / iteration: %g\n",
|
||||
(difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +
|
||||
difftimeval (&old_usage.ru_stime, &new_usage.ru_stime)) /
|
||||
(n_iters * n_children));
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user