Factories in telepathy-qt4

Olli Salli ollisal at gmail.com
Mon Nov 22 17:41:39 CET 2010


Hi,

I've been intending to write this mail for a long time already, sorry
for the delay. Now that we have tp-qt4-0.5.0 released and the new API
in this field finally set to stone, I guess it's about time.

The "factories" work targets three distinct problems:

1) Multiple proxies being built for the same actual D-Bus objects
  - because we had no way to share them e.g. between Client invocations,
and AccountManager
  - actually, even a single Client invocation used to have multiple
proxies for the same remote D-Bus objects!
  - severe performance issue due to redundantly introspecting proxies
even if some other proxy for that D-Bus object already has all the data
retrieved
  - Contacts and ReferencedHandles from e.g. Client invocations not
compatible with the ones from AccountManager->Account, and vice versa ->
need to do manual link-up

2) Calling becomeReady manually everywhere is error-prone and
inconvenient in a public API

3) No possibility to specify subclasses for proxies which tp-qt4
returns/signals to the application
  - led to maintaining wrapper objects for tp-qt4 proxies in
applications to keep track of auxiliary data and extra functionality ->
increased complexity

So, factories:
 - Allows tp-qt4 to safely share proxy instances between various parts
of the library internals and the public API, taking invalidation and
proxy refcounting / resource management into account
 - Allow applications to specify which features they want automatically
prepared in any given Account/Connection/Channel (without calling
becomeReady at all)
 - Allow applications to specify which subclass they want to be used
instead of Tp::Account, Tp::Connection and the stock Tp::Channel
subclasses themselves

To take full advantage of the first point, you only have to use tp-qt4
> >= 0.3.10 AND if your app has both an AccountManager and a ClientRegistrar,

***********************************************************************
 USE THE ClientRegistrar create() method overload which takes a pointer
to the AccountManager as a parameter, passing your AccountManager
instance to it!
***********************************************************************

Otherwise you'll still get separate Accounts/Connections from
AccountManager and passed to your AbstractClient* implementation, and
lose some of the performance benefit, and fully lose the benefit of
being able to cross-use Contacts etc. If your app only has a
ClientRegistrar, or only an AccountManager, everything is optimal already!

Other than having a much easier to use public development API, you
probably can't take full advantage of 2) and 3) given that the code that
does similar work is there already in your applications - but any new
code can get away not doing becomeReady calls if it does the following
wherever they're currently creating an AccountManager or a
ClientRegistrar (if they don't have an AM):

 - Use tp-qt4 >= 0.3.14

 - AccountFactory::create() an account factory instance
    - or subclass AccountFactory, overriding construct() with one
constructing the desired Tp::Account subclass

 - accFact->addFeatures(Account::FeatureCore |
Account::FeatureCapabilities) // or whatever you want. No features
passed here means "don't make them ready at all, I don't want extra
slowdown from making them ready as I'm not going to use them" which
could be applicable to e.g. account editing UIs, which probably don't
care about what happens in any Connections for the accounts

 - ditto for Connection, and Channel
   - except that for Channel you specify the features and subclasses
per-channel-type in the same way as you specify Client channel filters
(ChannelClassSpec in tp-qt4 >= 0.3.14, e.g.
chanFact->addFeaturesForTextChatrooms(TextChannel::FeatureMessageQueue)
 - pass those factories to AccountManager::create(), or
ClientRegistrar::create() if you don't have an AccountManager.
 - if you have both, still pass a pointer to the AM to
ClientRegistrar::create() to reuse the same factories and prevent 1)

The end result will be that any Account/Connection/Channel or subclass
thereof signaled/returned in the public API will be of the desired
subclass, with the desired features ready without calling becomeReady
manually.

Note that you should still apply common sense when deciding which
features to have ready. If you only need a given feature for a very
specific use case not used often (or don't need it at all!), you should
lazily activate it using becomeReady rather than unconditionally
enabling it for all proxies of a given kind using the factories.


-- 

Br,
Olli Salli


More information about the KDE-Telepathy mailing list