--- 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 <QMutex>
+#include <QMutexLocker>
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: