[libvirt] [PATCH libvirt-glib 2/5] Add support for creating watches on streams
Daniel P. Berrange
berrange at redhat.com
Mon Nov 28 18:27:26 UTC 2011
On Mon, Nov 28, 2011 at 06:52:43PM +0100, Christophe Fergeau wrote:
> On Mon, Nov 28, 2011 at 01:13:45PM +0000, Daniel P. Berrange wrote:
> > From: "Daniel P. Berrange" <berrange at redhat.com>
> >
> > The GIO GInputStream/GOutputStream async model for I/O does not
> > work for working with non-blocking bi-directional streams. To
> > allow that to be done more effectively, add an API to allow
> > main loop watches to be registered against streams.
> >
> > Since the libvirt level virStreamEventAddCallback API only allows
> > a single callback to be registered to a stream at any time, the
> > GVirStream object needs to be multiplexing of multiple watches into
> > a single libvirt level callback.
> >
> > Watches can be removed in the normal way with g_source_remove
> >
> > * libvirt-gobject/libvirt-gobject-stream.c,
> > libvirt-gobject/libvirt-gobject-stream.h,
> > libvirt-gobject/libvirt-gobject.sym: Add gvir_stream_add_watch
> > ---
> > libvirt-gobject/libvirt-gobject-stream.c | 180 ++++++++++++++++++++++++++++++
> > libvirt-gobject/libvirt-gobject-stream.h | 17 +++
> > libvirt-gobject/libvirt-gobject.sym | 1 +
> > 3 files changed, 198 insertions(+), 0 deletions(-)
> > @@ -199,6 +212,14 @@ static void gvir_stream_finalize(GObject *object)
> > virStreamFree(priv->handle);
> > }
> >
> > + tmp = priv->sources;
> > + while (tmp) {
> > + GVirStreamSource *source = tmp->data;
> > + g_source_remove(g_source_get_id((GSource*)source));
>
> I think g_source_destroy can be used here
Yes, I believe so.
> > +static void gvir_stream_source_finalize(GSource *source)
> > +{
> > + GVirStreamSource *gsource = (GVirStreamSource*)source;
> > + GVirStreamPrivate *priv = gsource->stream->priv;
> > + GList *tmp, *prev = NULL;
> > +
> > + tmp = priv->sources;
> > + while (tmp) {
> > + if (tmp->data == source) {
> > + if (prev) {
> > + prev->next = tmp->next;
> > + } else {
> > + priv->sources = tmp->next;
> > + }
> > + tmp->next = NULL;
> > + g_list_free(tmp);
> > + break;
> > + }
> > +
> > + prev = tmp;
> > + tmp = tmp->next;
> > + }
>
> isn't it doing the same as g_list_remove?
Yes, indeed it is. I will simplify that.
>
> > +
> > + gvir_stream_update_events(gsource->stream);
> > +}
> > +
> > +GSourceFuncs gvir_stream_source_funcs = {
> > + .prepare = gvir_stream_source_prepare,
> > + .check = gvir_stream_source_check,
> > + .dispatch = gvir_stream_source_dispatch,
> > + .finalize = gvir_stream_source_finalize,
> > +};
> > +
> > +gint gvir_stream_add_watch(GVirStream *stream,
> > + GVirStreamIOCondition cond,
> > + GVirStreamIOFunc func,
> > + gpointer opaque,
> > + GDestroyNotify notify)
>
> Dunno if it's worth having both gvir_stream_add_watch and
> gvir_stream_add_watch_full to be consistent with most glib source functions
> (g_timeout_add, g_idle_add, g_io_add_watch, ...). The notify argument would
> only be in the _full variant.
Consistency is always nice, so I'll add a _full variant.
> > +{
> > + GVirStreamPrivate *priv = stream->priv;
> > + gint id;
> > + GVirStreamSource *source = (GVirStreamSource*)g_source_new(&gvir_stream_source_funcs,
> > + sizeof(GVirStreamSource));
> > +
> > + source->stream = stream;
> > + source->cond = cond;
> > +
> > + priv->sources = g_list_append(priv->sources, source);
> > +
> > + gvir_stream_update_events(source->stream);
> > +
> > + g_source_set_callback((GSource*)source, (GSourceFunc)func, opaque, notify);
> > + g_source_attach((GSource*)source, g_main_context_default());
> > +
> > + id = g_source_get_id((GSource*)source);
>
> g_source_attach returns this id which is of type guint.
Ahh, didn't notice that.
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
More information about the libvir-list
mailing list