[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kfm-devel
Subject:    using qcom interfaces wit parts (was Re: Plugins for non-major Parts)
From:       Simon Hausmann <hausmann () kde ! org>
Date:       2001-09-13 11:08:13
[Download RAW message or body]

Hi,

I keep on thinking and thinking about it but I can't seem to find an obvious solution to
the ownership problem...

What I have in mind is a virtual QUnknownInterface *qcomInterface() method in KParts::Part,
with a default implementation returning 0.

A real implementation could look like this:

QUnknownInterface *MyPart::qcomInterface()
{
    Q_CREATE_INSTANCE( MyInterfaceImplementation )
}

Or in expanded form

QUnknownInterface *MyPart::qcomInterface()
{
    MyInterfaceImplementation *impl = new MyInterfaceImplementation;
    QUnknownInterface *result = 0;
    impl->queryInterface( IID_QUnknown, &result );
    return result;
}

The problem with this is that it's a bit wrong :) We don't really want to
instantiate an interface implementation each time nor do we want to 
return an already ref'ed object (and we can't just return new MyInterfaceImpl
because it requires casting in case of multiple inheritance and that's
already implemented in MyInterfaceImpl's queryInterface, so we should re-use
that)

So what we could do is to add a level of indirection:

(non-virtual!)
QUnknownInterface *Part::qcomInterface()
{
    if ( !d->m_qcomInterface )
        d->m_qcomInterface = createQComInterface();
    return d->m_qcomInterface;
}

With d->m_qcomInterface being a QUnknownInterface * and with
createQComInterface() being a virtual factory method which does 
the above Q_CREATE_INSTANCE. Also we would have to do

Part::~Part()
{
    ...
    if ( d->m_qcomInterface )
        d->m_qcomInterface->release();
    ...
}

for proper refcounting (the factory returns an initial object with
refcount == 1, due to the queryInterface call, so we have to
deref)

The main problem I have with that is that it means that this looks
nice from a kparts point of view, but it means there's an ugly
side-effect from the component implementation point of view:
The component destructor (the one implementation the QUI based interfaces)
is likely to be called from the KParts::Part::~Part() destructor.
I would quite often expect a component implementation to either

 a) depend on the part component, by having a pointer to it and
    calling methods on it 

 or

 b) be the part itself, using multiple inheritance. 

The problem with a) is that it means that the component destructor
has to be _very_ careful about not calling anything on the part,
because it's too late (we're called from the ~Part dtor already) .

The problem with b) is that it means that we will never get
deleted because the Part baseclass holds a reference to itself.
 

So I for one am a bit lost how to solve this in a clean way. I think it
is definitely desirable to have support for pure abstract interfaces
to allow writing plugins without a binary library dependency. And for
that it would just make sense to re-use QUI (re-inventing that wheel
would be stupid IMHO) . Also it would make sense IMHO if we would have
a method to discover/retrieve an initial QUI object in our base
classes/interfaces, KParts::Part so to say (well, in PartBase in fact,
to automatically have it in MainWindow and KoView, too, but that's
unrelated to the actual above described ownership problem) . 

(in addition we have the problem of library unloading, described in
the previous mail, which doesn't seem easy to me either, but I might
be missing something)

Does anybody have ideas/suggestions?


Simon

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic