qtmobility/src/contacts/qcontactabstractrequest.cpp
changeset 14 6fbed849b4f4
parent 11 06b8e2af4411
child 15 1f895d8a5b2b
equal deleted inserted replaced
11:06b8e2af4411 14:6fbed849b4f4
    43 #include "qcontactabstractrequest_p.h"
    43 #include "qcontactabstractrequest_p.h"
    44 #include "qcontactmanager.h"
    44 #include "qcontactmanager.h"
    45 #include "qcontactmanager_p.h"
    45 #include "qcontactmanager_p.h"
    46 #include "qcontactmanagerengine.h"
    46 #include "qcontactmanagerengine.h"
    47 
    47 
       
    48 #include <QMutex>
       
    49 #include <QMutexLocker>
    48 
    50 
    49 QTM_BEGIN_NAMESPACE
    51 QTM_BEGIN_NAMESPACE
    50 /*!
    52 /*!
    51   \class QContactAbstractRequest
    53   \class QContactAbstractRequest
    52 
    54 
    62 
    64 
    63   Clients should not attempt to create instances of this class directly,
    65   Clients should not attempt to create instances of this class directly,
    64   but should instead use the use-case-specific classes derived from this
    66   but should instead use the use-case-specific classes derived from this
    65   class.
    67   class.
    66 
    68 
    67   After creating any sort of request, the client retains ownership and
    69   All such request classes have a similar interface: clients set the
    68   must delete the request to avoid leaking memory.  The client may either
    70   parameters of the asynchronous call, including which manager the
    69   do this directly (if not within a slot connected to a signal emitted
    71   request will be made of, and then call the start() slot of the request.
    70   by the request) or by using the deleteLater() slot to schedule the
    72   The manager will then enqueue or begin to process the request, at which
    71   request for deletion when control returns to the event loop.
    73   point the request's state will transition from \c InactiveState to
       
    74   \c ActiveState.  After any state transition, the request will emit the
       
    75   stateChanged() signal.  The manager may periodically update the request
       
    76   with results, at which point the request will emit the resultsAvailable()
       
    77   signal.  These results are not guaranteed to have a stable ordering.
       
    78   Error information is considered a result, so some requests will emit the
       
    79   resultsAvailable() signal even if no results are possible from the request
       
    80   (for example, a contact remove request) when the manager updates the request
       
    81   with information about any errors which may have occurred.
       
    82 
       
    83   Please see the class documentation of each of the use-case-specific
       
    84   classes derived from this class for information about how to retrieve
       
    85   the results of a request (including error information).  In all cases,
       
    86   those functions are synchronous, and will return the cached result set with
       
    87   which the manager has updated the request instance if the resultsAvailable()
       
    88   signal has been emitted.
       
    89 
       
    90   Clients can choose which signals they wish to handle from a request.
       
    91   If the client is not interested in interim results, they can choose to
       
    92   handle only the stateChanged() signal, and in the slot to which that
       
    93   signal is connected, check whether the state has changed to either
       
    94   \c FinishedState or \c CanceledState (both of which signify that the
       
    95   manager has finished handling the request, and that the request will not
       
    96   be updated with any more results).  If the client is not interested in
       
    97   any results (including error information), they may choose to delete
       
    98   the request after calling \l start(), or simply not connect the
       
    99   request's signals to any slots.
       
   100 
       
   101   If the request is allocated via operator new, the client must
       
   102   delete the request when they are no longer using it in order to avoid
       
   103   leaking memory.  That is, the client retains ownership of the request.
       
   104 
       
   105   The client may delete a heap-allocated request in various ways:
       
   106   by deleting it directly (but not within a slot connected to a signal
       
   107   emitted by the request), or by using the deleteLater() slot to schedule
       
   108   the request for deletion when control returns to the event loop (from
       
   109   within a slot connected to a signal emitted by the request, for example
       
   110   \l stateChanged()).
       
   111 
       
   112   An active request may be deleted by the client, but the client will not
       
   113   receive any notifications about whether the request succeeded or not,
       
   114   nor any results of the request.
       
   115 
       
   116   Because clients retain ownership of any request object, and may delete
       
   117   a request object at any time, manager engine implementors must be careful
       
   118   to ensure that they do not assume that a request has not been deleted
       
   119   at some point during processing of a request, particularly if the engine
       
   120   has a multithreaded implementation.  It is suggested that engine
       
   121   implementors read the \l{Qt Contacts Manager Engines} documentation for
       
   122   more information on this topic.
    72  */
   123  */
    73 
   124 
    74 /*!
   125 /*!
    75   \fn QContactAbstractRequest::stateChanged(QContactAbstractRequest::State newState)
   126   \fn QContactAbstractRequest::stateChanged(QContactAbstractRequest::State newState)
    76   This signal is emitted when the state of the request is changed.  The new state of
   127   This signal is emitted when the state of the request is changed.  The new state of
   129 
   180 
   130 /*! Cleans up the memory used by this request */
   181 /*! Cleans up the memory used by this request */
   131 QContactAbstractRequest::~QContactAbstractRequest()
   182 QContactAbstractRequest::~QContactAbstractRequest()
   132 {
   183 {
   133     if (d_ptr) {
   184     if (d_ptr) {
       
   185         QMutexLocker ml(&d_ptr->m_mutex);
   134         QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
   186         QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
       
   187         ml.unlock();
   135         if (engine) {
   188         if (engine) {
   136             engine->requestDestroyed(this);
   189             engine->requestDestroyed(this);
   137         }
   190         }
   138 
   191 
   139         delete d_ptr;
   192         delete d_ptr;
   145 
   198 
   146   \sa state()
   199   \sa state()
   147  */
   200  */
   148 bool QContactAbstractRequest::isInactive() const
   201 bool QContactAbstractRequest::isInactive() const
   149 {
   202 {
       
   203     QMutexLocker ml(&d_ptr->m_mutex);
   150     return (d_ptr->m_state == QContactAbstractRequest::InactiveState);
   204     return (d_ptr->m_state == QContactAbstractRequest::InactiveState);
   151 }
   205 }
   152 
   206 
   153 /*!
   207 /*!
   154   Returns true if the request is in the \c QContactAbstractRequest::ActiveState state; otherwise, returns false
   208   Returns true if the request is in the \c QContactAbstractRequest::ActiveState state; otherwise, returns false
   155 
   209 
   156   \sa state()
   210   \sa state()
   157  */
   211  */
   158 bool QContactAbstractRequest::isActive() const
   212 bool QContactAbstractRequest::isActive() const
   159 {
   213 {
       
   214     QMutexLocker ml(&d_ptr->m_mutex);
   160     return (d_ptr->m_state == QContactAbstractRequest::ActiveState);
   215     return (d_ptr->m_state == QContactAbstractRequest::ActiveState);
   161 }
   216 }
   162 
   217 
   163 /*!
   218 /*!
   164   Returns true if the request is in the \c QContactAbstractRequest::FinishedState; otherwise, returns false
   219   Returns true if the request is in the \c QContactAbstractRequest::FinishedState; otherwise, returns false
   165 
   220 
   166   \sa state()
   221   \sa state()
   167  */
   222  */
   168 bool QContactAbstractRequest::isFinished() const
   223 bool QContactAbstractRequest::isFinished() const
   169 {
   224 {
       
   225     QMutexLocker ml(&d_ptr->m_mutex);
   170     return (d_ptr->m_state == QContactAbstractRequest::FinishedState);
   226     return (d_ptr->m_state == QContactAbstractRequest::FinishedState);
   171 }
   227 }
   172 
   228 
   173 /*!
   229 /*!
   174   Returns true if the request is in the \c QContactAbstractRequest::CanceledState; otherwise, returns false
   230   Returns true if the request is in the \c QContactAbstractRequest::CanceledState; otherwise, returns false
   175 
   231 
   176   \sa state()
   232   \sa state()
   177  */
   233  */
   178 bool QContactAbstractRequest::isCanceled() const
   234 bool QContactAbstractRequest::isCanceled() const
   179 {
   235 {
       
   236     QMutexLocker ml(&d_ptr->m_mutex);
   180     return (d_ptr->m_state == QContactAbstractRequest::CanceledState);
   237     return (d_ptr->m_state == QContactAbstractRequest::CanceledState);
   181 }
   238 }
   182 
   239 
   183 /*! Returns the overall error of the most recent asynchronous operation */
   240 /*! Returns the overall error of the most recent asynchronous operation */
   184 QContactManager::Error QContactAbstractRequest::error() const
   241 QContactManager::Error QContactAbstractRequest::error() const
   185 {
   242 {
       
   243     QMutexLocker ml(&d_ptr->m_mutex);
   186     return d_ptr->m_error;
   244     return d_ptr->m_error;
   187 }
   245 }
   188 
   246 
   189 /*!
   247 /*!
   190   Returns the type of this asynchronous request
   248   Returns the type of this asynchronous request
   191  */
   249  */
   192 QContactAbstractRequest::RequestType QContactAbstractRequest::type() const
   250 QContactAbstractRequest::RequestType QContactAbstractRequest::type() const
   193 {
   251 {
       
   252     QMutexLocker ml(&d_ptr->m_mutex);
   194     return d_ptr->type();
   253     return d_ptr->type();
   195 }
   254 }
   196 
   255 
   197 /*!
   256 /*!
   198   Returns the current state of the request.
   257   Returns the current state of the request.
   199  */
   258  */
   200 QContactAbstractRequest::State QContactAbstractRequest::state() const
   259 QContactAbstractRequest::State QContactAbstractRequest::state() const
   201 {
   260 {
       
   261     QMutexLocker ml(&d_ptr->m_mutex);
   202     return d_ptr->m_state;
   262     return d_ptr->m_state;
   203 }
   263 }
   204 
   264 
   205 /*! Returns a pointer to the manager of which this request instance requests operations */
   265 /*! Returns a pointer to the manager of which this request instance requests operations */
   206 QContactManager* QContactAbstractRequest::manager() const
   266 QContactManager* QContactAbstractRequest::manager() const
   207 {
   267 {
       
   268     QMutexLocker ml(&d_ptr->m_mutex);
   208     return d_ptr->m_manager;
   269     return d_ptr->m_manager;
   209 }
   270 }
   210 
   271 
   211 /*! Sets the manager of which this request instance requests operations to \a manager */
   272 /*!
       
   273     Sets the manager of which this request instance requests operations to \a manager
       
   274 
       
   275     If the request is currently active, this function will return without updating the \a manager object.
       
   276 */
   212 void QContactAbstractRequest::setManager(QContactManager* manager)
   277 void QContactAbstractRequest::setManager(QContactManager* manager)
   213 {
   278 {
       
   279     QMutexLocker ml(&d_ptr->m_mutex);
       
   280     // In theory we might have been active and the manager didn't cancel/finish us
       
   281     if (d_ptr->m_state == QContactAbstractRequest::ActiveState && d_ptr->m_manager)
       
   282         return;
   214     d_ptr->m_manager = manager;
   283     d_ptr->m_manager = manager;
   215 }
   284 }
   216 
   285 
   217 /*! Attempts to start the request.  Returns false if the request is not in the \c QContactAbstractRequest::Inactive, \c QContactAbstractRequest::Finished or \c QContactAbstractRequest::Cancelled states,
   286 /*! Attempts to start the request.  Returns false if the request is not in the \c QContactAbstractRequest::Inactive, \c QContactAbstractRequest::Finished or \c QContactAbstractRequest::Cancelled states,
   218     or if the request was unable to be performed by the manager engine; otherwise returns true. */
   287     or if the request was unable to be performed by the manager engine; otherwise returns true. */
   219 bool QContactAbstractRequest::start()
   288 bool QContactAbstractRequest::start()
   220 {
   289 {
       
   290     QMutexLocker ml(&d_ptr->m_mutex);
   221     QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
   291     QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
   222     if (engine && (d_ptr->m_state == QContactAbstractRequest::CanceledState
   292     if (engine && (d_ptr->m_state == QContactAbstractRequest::CanceledState
   223                    || d_ptr->m_state == QContactAbstractRequest::FinishedState
   293                    || d_ptr->m_state == QContactAbstractRequest::FinishedState
   224                    || d_ptr->m_state == QContactAbstractRequest::InactiveState)) {
   294                    || d_ptr->m_state == QContactAbstractRequest::InactiveState)) {
       
   295         ml.unlock();
   225         return engine->startRequest(this);
   296         return engine->startRequest(this);
   226     }
   297     }
   227 
   298 
   228     return false; // unable to start operation; another operation already in progress or no engine.
   299     return false; // unable to start operation; another operation already in progress or no engine.
   229 }
   300 }
   230 
   301 
   231 /*! Attempts to cancel the request.  Returns false if the request is not in the \c QContactAbstractRequest::Active state,
   302 /*! Attempts to cancel the request.  Returns false if the request is not in the \c QContactAbstractRequest::Active state,
   232     or if the request is unable to be cancelled by the manager engine; otherwise returns true. */
   303     or if the request is unable to be cancelled by the manager engine; otherwise returns true. */
   233 bool QContactAbstractRequest::cancel()
   304 bool QContactAbstractRequest::cancel()
   234 {
   305 {
       
   306     QMutexLocker ml(&d_ptr->m_mutex);
   235     QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
   307     QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
   236     if (engine && state() == QContactAbstractRequest::ActiveState) {
   308     if (engine && d_ptr->m_state == QContactAbstractRequest::ActiveState) {
       
   309         ml.unlock();
   237         return engine->cancelRequest(this);
   310         return engine->cancelRequest(this);
   238     }
   311     }
   239 
   312 
   240     return false; // unable to cancel operation; not in progress or no engine.
   313     return false; // unable to cancel operation; not in progress or no engine.
   241 }
   314 }
   245     Returns true if the request was cancelled or completed successfully within the given period, otherwise false.
   318     Returns true if the request was cancelled or completed successfully within the given period, otherwise false.
   246     Some backends are unable to support this operation safely, and will return false immediately.
   319     Some backends are unable to support this operation safely, and will return false immediately.
   247  */
   320  */
   248 bool QContactAbstractRequest::waitForFinished(int msecs)
   321 bool QContactAbstractRequest::waitForFinished(int msecs)
   249 {
   322 {
       
   323     QMutexLocker ml(&d_ptr->m_mutex);
   250     QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
   324     QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
   251     if (engine) {
   325     if (engine) {
   252         switch (d_ptr->m_state) {
   326         switch (d_ptr->m_state) {
   253         case QContactAbstractRequest::ActiveState:
   327         case QContactAbstractRequest::ActiveState:
       
   328             ml.unlock();
   254             return engine->waitForRequestFinished(this, msecs);
   329             return engine->waitForRequestFinished(this, msecs);
   255         case QContactAbstractRequest::CanceledState:
   330         case QContactAbstractRequest::CanceledState:
   256         case QContactAbstractRequest::FinishedState:
   331         case QContactAbstractRequest::FinishedState:
   257             return true;
   332             return true;
   258         default:
   333         default: