[Telepathy] telepathy-glib: *_run_* methods.
simon.mcvittie at collabora.co.uk
Tue Nov 18 07:01:42 PST 2008
For the record:
On Tue, 18 Nov 2008 at 11:43:02 +0100, Xavier Claessens wrote:
> 1) If used inside a dbus signal callback, your mainloop get blocked and
> you'll never receive your reply.
This is a dbus-glib bug (the dbus-glib GSource is not reentrant - I filed
the bug when I discovered this during telepathy-glib development). I can't
remember whether I've worked around it in telepathy-glib yet or not.
> 2) If used inside a dbus method implementation you get the same as in 1.
This is the same dbus-glib bug. I haven't worked around it in telepathy-glib,
but I could probably put in a transparent workaround if we really needed this.
> 3) It looks like sync call but it is really not, so you have to be
> really careful.
> 4) If you make too much run calls you'll get a really big call stack.
> This is not efficient and makes crash debug more difficult.
> 5) gtk_quit() won't work while waiting for a reply, you'll have to wait
> for all calls to return before your program exit. If new calls are made
> after gtk_quit(), you'll have to wait for them to return too. If you are
> in the case 1 or 2, your program will even *never* quit.
True. All the _run_ functions can theoretically be cancelled, either by
stopping their main loop (which they will write through a pointer so you
can do this) or by calling tp_proxy_pending_call_cancel() on the
pending call, but doing so is probably impractical (you'd have to push
them onto a global stack or something).
> IMO run API should be avoided. It only makes easier to write quick test
> code, but real sync (blocking calls) is even easier and safer in that
libdbus pseudo-blocking is dangerous for the reasons I outlined in my
previous mail, so non-trivial code should use an
asynchronous/callback-based model. The _run_ methods can be useful for
(Empathy is far from trivial.)
One approach I've been using in telepathy-glib to reduce "twisty maze of
callbacks" syndrome is to set up a cache of an object's state (by making
D-Bus method calls), signal "this object is now ready", and keep the cache
up to date via D-Bus signals. This means that a library user can make
synchronous method calls to get the object's state, because they're just
retrievals from the cache. TpContact, TpChannel and TpConnection all use
this approach, to a lesser or greater extent.
Another is to encapsulate chains of method calls behind a single
request/callback pair, as in the slow-path versions of TpContact and
TpChannel. TpContact can either use the Contacts interface (which
fetches the avatars, aliases, presence etc. for a batch of contacts in
one go), or older method calls on the individual interfaces, but to a
library user it always looks like a single asynchronous call. Similarly,
TpChannel transparently falls back from a fast-path to a slow-path
implementation without altering the user-visible API.
(The fast paths actually only exist on a branch - I'm waiting for wjt to
review it, and until then TpContact and TpChannel only have the slow
paths - but you can't tell that from the API :-)
More information about the Telepathy