diff -r 06b8e2af4411 -r 6fbed849b4f4 qtmobility/src/contacts/qcontactabstractrequest.cpp --- a/qtmobility/src/contacts/qcontactabstractrequest.cpp Fri Jun 11 14:26:25 2010 +0300 +++ b/qtmobility/src/contacts/qcontactabstractrequest.cpp Wed Jun 23 19:08:38 2010 +0300 @@ -45,6 +45,8 @@ #include "qcontactmanager_p.h" #include "qcontactmanagerengine.h" +#include +#include QTM_BEGIN_NAMESPACE /*! @@ -64,11 +66,60 @@ but should instead use the use-case-specific classes derived from this class. - After creating any sort of request, the client retains ownership and - must delete the request to avoid leaking memory. The client may either - do this directly (if not within a slot connected to a signal emitted - by the request) or by using the deleteLater() slot to schedule the - request for deletion when control returns to the event loop. + All such request classes have a similar interface: clients set the + parameters of the asynchronous call, including which manager the + request will be made of, and then call the start() slot of the request. + The manager will then enqueue or begin to process the request, at which + point the request's state will transition from \c InactiveState to + \c ActiveState. After any state transition, the request will emit the + stateChanged() signal. The manager may periodically update the request + with results, at which point the request will emit the resultsAvailable() + signal. These results are not guaranteed to have a stable ordering. + Error information is considered a result, so some requests will emit the + resultsAvailable() signal even if no results are possible from the request + (for example, a contact remove request) when the manager updates the request + with information about any errors which may have occurred. + + Please see the class documentation of each of the use-case-specific + classes derived from this class for information about how to retrieve + the results of a request (including error information). In all cases, + those functions are synchronous, and will return the cached result set with + which the manager has updated the request instance if the resultsAvailable() + signal has been emitted. + + Clients can choose which signals they wish to handle from a request. + If the client is not interested in interim results, they can choose to + handle only the stateChanged() signal, and in the slot to which that + signal is connected, check whether the state has changed to either + \c FinishedState or \c CanceledState (both of which signify that the + manager has finished handling the request, and that the request will not + be updated with any more results). If the client is not interested in + any results (including error information), they may choose to delete + the request after calling \l start(), or simply not connect the + request's signals to any slots. + + If the request is allocated via operator new, the client must + delete the request when they are no longer using it in order to avoid + leaking memory. That is, the client retains ownership of the request. + + The client may delete a heap-allocated request in various ways: + by deleting it directly (but not within a slot connected to a signal + emitted by the request), or by using the deleteLater() slot to schedule + the request for deletion when control returns to the event loop (from + within a slot connected to a signal emitted by the request, for example + \l stateChanged()). + + An active request may be deleted by the client, but the client will not + receive any notifications about whether the request succeeded or not, + nor any results of the request. + + Because clients retain ownership of any request object, and may delete + a request object at any time, manager engine implementors must be careful + to ensure that they do not assume that a request has not been deleted + at some point during processing of a request, particularly if the engine + has a multithreaded implementation. It is suggested that engine + implementors read the \l{Qt Contacts Manager Engines} documentation for + more information on this topic. */ /*! @@ -131,7 +182,9 @@ QContactAbstractRequest::~QContactAbstractRequest() { if (d_ptr) { + QMutexLocker ml(&d_ptr->m_mutex); QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager); + ml.unlock(); if (engine) { engine->requestDestroyed(this); } @@ -147,6 +200,7 @@ */ bool QContactAbstractRequest::isInactive() const { + QMutexLocker ml(&d_ptr->m_mutex); return (d_ptr->m_state == QContactAbstractRequest::InactiveState); } @@ -157,6 +211,7 @@ */ bool QContactAbstractRequest::isActive() const { + QMutexLocker ml(&d_ptr->m_mutex); return (d_ptr->m_state == QContactAbstractRequest::ActiveState); } @@ -167,6 +222,7 @@ */ bool QContactAbstractRequest::isFinished() const { + QMutexLocker ml(&d_ptr->m_mutex); return (d_ptr->m_state == QContactAbstractRequest::FinishedState); } @@ -177,12 +233,14 @@ */ bool QContactAbstractRequest::isCanceled() const { + QMutexLocker ml(&d_ptr->m_mutex); return (d_ptr->m_state == QContactAbstractRequest::CanceledState); } /*! Returns the overall error of the most recent asynchronous operation */ QContactManager::Error QContactAbstractRequest::error() const { + QMutexLocker ml(&d_ptr->m_mutex); return d_ptr->m_error; } @@ -191,6 +249,7 @@ */ QContactAbstractRequest::RequestType QContactAbstractRequest::type() const { + QMutexLocker ml(&d_ptr->m_mutex); return d_ptr->type(); } @@ -199,18 +258,28 @@ */ QContactAbstractRequest::State QContactAbstractRequest::state() const { + QMutexLocker ml(&d_ptr->m_mutex); return d_ptr->m_state; } /*! Returns a pointer to the manager of which this request instance requests operations */ QContactManager* QContactAbstractRequest::manager() const { + QMutexLocker ml(&d_ptr->m_mutex); return d_ptr->m_manager; } -/*! Sets the manager of which this request instance requests operations to \a manager */ +/*! + Sets the manager of which this request instance requests operations to \a manager + + If the request is currently active, this function will return without updating the \a manager object. +*/ void QContactAbstractRequest::setManager(QContactManager* manager) { + QMutexLocker ml(&d_ptr->m_mutex); + // In theory we might have been active and the manager didn't cancel/finish us + if (d_ptr->m_state == QContactAbstractRequest::ActiveState && d_ptr->m_manager) + return; d_ptr->m_manager = manager; } @@ -218,10 +287,12 @@ or if the request was unable to be performed by the manager engine; otherwise returns true. */ bool QContactAbstractRequest::start() { + QMutexLocker ml(&d_ptr->m_mutex); QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager); if (engine && (d_ptr->m_state == QContactAbstractRequest::CanceledState || d_ptr->m_state == QContactAbstractRequest::FinishedState || d_ptr->m_state == QContactAbstractRequest::InactiveState)) { + ml.unlock(); return engine->startRequest(this); } @@ -232,8 +303,10 @@ or if the request is unable to be cancelled by the manager engine; otherwise returns true. */ bool QContactAbstractRequest::cancel() { + QMutexLocker ml(&d_ptr->m_mutex); QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager); - if (engine && state() == QContactAbstractRequest::ActiveState) { + if (engine && d_ptr->m_state == QContactAbstractRequest::ActiveState) { + ml.unlock(); return engine->cancelRequest(this); } @@ -247,10 +320,12 @@ */ bool QContactAbstractRequest::waitForFinished(int msecs) { + QMutexLocker ml(&d_ptr->m_mutex); QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager); if (engine) { switch (d_ptr->m_state) { case QContactAbstractRequest::ActiveState: + ml.unlock(); return engine->waitForRequestFinished(this, msecs); case QContactAbstractRequest::CanceledState: case QContactAbstractRequest::FinishedState: