On Tue, 2008-12-23 at 10:53 +0100, Murray Cumming wrote: > On Mon, 2008-12-22 at 11:01 -0500, David Zeuthen wrote: > > > you'll have to use the supplied QUERY_INTERFACE macro for each of the > > generated interfaces to get an interface proxy. For example > > > > DevkitDevice *device; > > > > device = DEVKIT_QUERY_INTERFACE_DEVICE (object_proxy); > [snip] > > Ah, so you hard-code the expected interfaces at build time. And > DEVKIT_QUERY_INTERFACE_DEVICE() won't check that the interface is really > provided by that object, though you could get an error when then trying > to call a function of that interface. > > That's unfortunately not very helpful for Telepathy, for which various > "connection managers" (providers of IM functionality for particular IM > protocols) may or may not implement various additional interfaces, so > you have to check if those interfaces are available and fall back to > alternatives when possible. > > Not that I think that's a good situation (I like non-dynamic static > typing), but I guess there's no established way of doing > parallel-installs of D-Bus APIs, so they tend to evolve by adding > interfaces to stable versions, with some lag before those interfaces are > actually provided by everything that should implement them. > > Anyway, this is not very relevant to you.
Yeah, I think Telepathy does this in a reasonable way; I've been doing the same things with some of the D-Bus services that I've maintained; occasionally a new D-Bus interface is added to an object. Typically, clients just rev the version they depend on; obviously with Telepathy this is harder as you communicate with software on another system (I *think* this is the way it works). Anyway, with EggDBus you'd just introspect the object before you start consuming interfaces (see below). It's possibly that QUERY_INTERFACE() isn't a good name (inspired by COM); perhaps it could be GET_INTERFACE() and then we'd do a QUERY_INTERFACE() version that can return NULL if the remote object doesn't implement said interface. But I'm not happy to change that because it's a nice property that the current QUERY_INTERFACE() does no IO... and 99% of all D-Bus services guarantee that one interface or another is always available. So I think it's OK to require a bit more work there. (FWIW, there's really no good section yet in the D-Bus spec that says what it means to break ABI for D-Bus services (or more interesting, how to extend an interface while preserving ABI) so most people just go with what they think is right and usually this is correct.) > > Interface proxies are created on demand; e.g. only when used. There's no > > automatic discovery happening.. there is however an easy to use > > introspection facility > > > > http://people.freedesktop.org/~david/eggdbus-0.1-docs/EggDBusObjectProxy.html#egg-dbus-object-proxy-introspect > > > > that you can use to discover the available interfaces of a remote > > object. > [snip] > > From that documentation I couldn't tell where to actually get the > introspected information once that call has finished. You get a C structure like this one (by calling introspect_finish() back: http://people.freedesktop.org/~david/eggdbus-0.1-docs/eggdbus-eggdbusinterface.html#EggDBusInterfaceNodeInfo that is built from parsing the XML and then you can walk the childs. Incidentally, it's the same data structures we use to store introspection data for generated code; see http://people.freedesktop.org/~david/eggdbusproperties.c.txt for an example. Btw, is it a problem for non C (and probably non-C++) these are raw C structures? It's done this way so it can be stored in the read-only data segments. > [snip] > > > Isn't D-Bus property getting and setting asynchronous? How can this > > work > > > with the non-async g_object_get() function? > > > > Right now the first property_get() call on an interface proxy will > > synchronously invoke (blocking in libdbus on the dbus fd, not blocking > > in the main loop because that would cause reentrancy issues) the > > GetAll() method on the org.fd.DBus.Properties interface. > [snip] > > As you say, this does mean that it's particularly important for property > getting to be fast in the D-Bus service, meaning, for instance, that a > Telepathy object shouldn't get the information from a remote server. Yeah. I *think* D-Bus properties are designed to be fast; I mean, I think they are designed to mirror GObject and Qt properties and at least these are designed to be fast. If properties are not fast in Telepathy D-Bus services that might be a problem not only for EggDBus, also for things like d-feet and possibly for other D-Bus bindings that map to native properties, I don't know. Either way, for such services there's always the raw EggBusProperties interface. > [snip] > > Setting a property currently involves doing a sync call from > > property_set() that blocks until the server acknowledges the write with > > a reply. > > The Telepathy coders seem to have a strong dislike for blocking sync > D-Bus calls even when the call can be expected to complete quickly, > though I think that's partly due to problems with their version of sync > calls, and how they use the mainloop, as well as some D-Bus bugs: > http://lists.freedesktop.org/archives/telepathy/2008-November/002520.html > and > http://lists.freedesktop.org/archives/telepathy/2008-November/002521.html > > Again, that's not particularly relevant to you. I'm just mentioning it > because I have my head in all this stuff at the moment. Yeah, I think this is largely the same set of problems that Bonobo suffered from (reentrancy) and the main reason libdbus doesn't block in the mainloop. FWIW, with EggDBus you have the option to do either kind of blocking http://people.freedesktop.org/~david/eggdbus-0.1-docs/EggDBusConnection.html#EggDBusCallFlags depending on what behavior you want (by default we don't block in the mainloop which I think is the right behavior). FWIW, I've toyed around with the idea of guarding sync methods behind a EGG_DBUS_I_KNOW_SYNC_METHODS_ARE_UHM_SYNC_AND_THAT_THEY_BLOCK preprocessor symbol or something but I don't think it would help. Also, I don't think it would help by not generating sync methods (even though some people think that sync methods shouldn't be exposed at all, not even in things like GIO) either. > > I have a TODO item to make this async but it's hard (though not > > impossible) to implement correctly because of coherency issues. Note > > that there's very few services in the wild with writable properties. > > > > For changes, there's unfortunately no Changed() signal on the official > > org.fd.DBus.Properties interface. For now I'm using a signal called > > EggDBusChanged()) on said interface (embrace and extend!); FWIW, I'm > > going to propose the Changed() signal on the D-Bus list. > [snip] > > > [1] : I'd argue that if property get/set can fail, then the provider of > > the D-Bus service is doing something wrong and it shouldn't be a > > property in the first place. But, hey, things like this can happen. > [snip] > > I agree that D-Bus APIs should document restrictions on the behaviour of > implementations, such as whether they can fail and how long they may > take, allowing application code to be simpler by avoiding async calls. > That's something else that Telepathy doesn't seem happy to do. Well, sync calls are useful for a couple of reasons - For writing (simple) command-line clients (where the user can escape via Ctrl+C etc.) - It should be perfectly fine to use sync calls from a thread [1] David [1] : Note that EggDBus isn't yet thread-safe/aware; it's on the TODO list to figure out what guarantees / behavior we want to provide and then implement it. This task also includes taking a look at libdbus-1 sources to check that a sync call from one thread won't stall the D-Bus queue in another thread. _______________________________________________ gtk-devel-list mailing list [email protected] http://mail.gnome.org/mailman/listinfo/gtk-devel-list
