예제 #1
0
QThreadData *QThreadData::current()
{
    pthread_once(&current_thread_data_once, create_current_thread_data_key);

    QThreadData *data = reinterpret_cast<QThreadData *>(pthread_getspecific(current_thread_data_key));
    if (!data) {
        void *a;
        if (QInternal::activateCallbacks(QInternal::AdoptCurrentThread, &a)) {
            QThread *adopted = static_cast<QThread*>(a);
            Q_ASSERT(adopted);
            data = QThreadData::get2(adopted);
            pthread_setspecific(current_thread_data_key, data);
            adopted->d_func()->running = true;
            adopted->d_func()->finished = false;
            static_cast<QAdoptedThread *>(adopted)->init();
        } else {
            data = new QThreadData;
            pthread_setspecific(current_thread_data_key, data);
            QT_TRY {
                data->thread = new QAdoptedThread(data);
            } QT_CATCH(...) {
                pthread_setspecific(current_thread_data_key, 0);
                data->deref();
                data = 0;
                QT_RETHROW;
            }
            data->deref();
        }
예제 #2
0
QThreadData *QThreadData::current()
{
    QThreadData *data = get_thread_data();
    if (!data) {
        void *a;
        if (QInternal::activateCallbacks(QInternal::AdoptCurrentThread, &a)) {
            QThread *adopted = static_cast<QThread*>(a);
            Q_ASSERT(adopted);
            data = QThreadData::get2(adopted);
            set_thread_data(data);
            adopted->d_func()->running = true;
            adopted->d_func()->finished = false;
            static_cast<QAdoptedThread *>(adopted)->init();
        } else {
            data = new QThreadData;
            QT_TRY {
                set_thread_data(data);
                data->thread = new QAdoptedThread(data);
            } QT_CATCH(...) {
                clear_thread_data();
                data->deref();
                data = 0;
                QT_RETHROW;
            }
            data->deref();
        }
예제 #3
0
/*
    QThreadData
*/
QThreadData *QThreadData::current()
{
    qt_create_tls();
    QThreadData *threadData = reinterpret_cast<QThreadData *>(TlsGetValue(qt_current_thread_data_tls_index));
    if (!threadData) {
        QThread *adopted = 0;
        if (QInternal::activateCallbacks(QInternal::AdoptCurrentThread, (void **) &adopted)) {
            Q_ASSERT(adopted);
            threadData = QThreadData::get2(adopted);
            TlsSetValue(qt_current_thread_data_tls_index, threadData);
            adopted->d_func()->running = true;
            adopted->d_func()->finished = false;
            static_cast<QAdoptedThread *>(adopted)->init();
        } else {
            threadData = new QThreadData;
            // This needs to be called prior to new AdoptedThread() to
            // avoid recursion.
            TlsSetValue(qt_current_thread_data_tls_index, threadData);
            QT_TRY {
                threadData->thread = new QAdoptedThread(threadData);
            } QT_CATCH(...) {
                TlsSetValue(qt_current_thread_data_tls_index, 0);
                threadData->deref();
                threadData = 0;
                QT_RETHROW;
            }
            threadData->deref();
        }
예제 #4
0
QThreadData *QThreadData::current()
{
    pthread_once(&current_thread_data_once, create_current_thread_data_key);

    QThreadData *data = reinterpret_cast<QThreadData *>(pthread_getspecific(current_thread_data_key));
    if (!data) {
        void *a;
        if (QInternal::activateCallbacks(QInternal::AdoptCurrentThread, &a)) {
            QThread *adopted = static_cast<QThread*>(a);
            Q_ASSERT(adopted);
            data = QThreadData::get2(adopted);
            pthread_setspecific(current_thread_data_key, data);
            adopted->d_func()->running = true;
            adopted->d_func()->finished = false;
            static_cast<QAdoptedThread *>(adopted)->init();
        } else {
            data = new QThreadData;
            pthread_setspecific(current_thread_data_key, data);
            data->thread = new QAdoptedThread(data);
            data->deref();
        }
        (void) q_atomic_test_and_set_ptr(&QCoreApplicationPrivate::theMainThread, 0, data->thread);
    }
    return data;
}
예제 #5
0
static void destroy_current_thread_data(void *p)
{
#if defined(Q_OS_VXWORKS)
    // Calling setspecific(..., 0) sets the value to 0 for ALL threads.
    // The 'set to 1' workaround adds a bit of an overhead though,
    // since this function is called twice now.
    if (p == (void *)1)
        return;
#endif
    // POSIX says the value in our key is set to zero before calling
    // this destructor function, so we need to set it back to the
    // right value...
    pthread_setspecific(current_thread_data_key, p);
    QThreadData *data = static_cast<QThreadData *>(p);
    if (data->isAdopted) {
        QThread *thread = data->thread;
        Q_ASSERT(thread);
        QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
        Q_ASSERT(!thread_p->finished);
        thread_p->finish(thread);
    }
    data->deref();

    // ... but we must reset it to zero before returning so we aren't
    // called again (POSIX allows implementations to call destructor
    // functions repeatedly until all values are zero)
    pthread_setspecific(current_thread_data_key,
#if defined(Q_OS_VXWORKS)
                                                 (void *)1);
#else
                                                 0);
#endif
}
예제 #6
0
/*
    QThreadData
*/
QThreadData *QThreadData::current()
{
    qt_create_tls();
    QThreadData *threadData = *qt_tls;
    if (!threadData) {
        QThread *adopted = 0;
        if (QInternal::activateCallbacks(QInternal::AdoptCurrentThread, (void **) &adopted)) {
            Q_ASSERT(adopted);
            threadData = QThreadData::get2(adopted);
            *qt_tls = threadData;
            adopted->d_func()->running = true;
            adopted->d_func()->finished = false;
            static_cast<QAdoptedThread *>(adopted)->init();
        } else {
            threadData = new QThreadData;
            // This needs to be called prior to new AdoptedThread() to
            // avoid recursion.
            *qt_tls = threadData;
            threadData->thread = new QAdoptedThread(threadData);
            threadData->deref();
        }

        if (!QCoreApplicationPrivate::theMainThread) {
            QCoreApplicationPrivate::theMainThread = threadData->thread;
        } else {
            PTIB ptib;
            DosGetInfoBlocks(&ptib, NULL);
            qt_watch_adopted_thread(ptib->tib_ptib2->tib2_ultid, threadData->thread);
        }
    }
    return threadData;
}
예제 #7
0
void QObject::moveToThread(QThread *targetThread)
{
   if (m_threadData.load()->thread == targetThread) {
      // object is already in this thread
      return;
   }

   if (m_parent != 0) {
      qWarning("QObject::moveToThread() Can not move an object with a parent");
      return;
   }

   if (isWidgetType()) {
      qWarning("QObject::moveToThread() Widgets can not be moved to a new thread");
      return;
   }

   QThreadData *currentData = QThreadData::current();
   QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : new QThreadData(0);

   QThreadData *threadData = m_threadData.load();

   if (threadData->thread == 0 && currentData == targetData) {
      // exception: allow moving objects with no thread affinity to the current thread
      currentData = threadData;

   } else if (threadData != currentData) {

      qWarning("QObject::moveToThread() Current thread (%p) is not the current object's thread (%p).\n"
               "Can not move to target thread (%p)\n", currentData->thread, threadData->thread, targetData->thread);

#ifdef Q_WS_MAC

      qWarning("Multiple libraries might be loaded in the same process. Verify all plugins are "
               "linked with the correct binaries. Export DYLD_PRINT_LIBRARIES=1 and verify only one set of "
               "binaries are being loaded.");
#endif

      return;
   }

   // prepare to move
   this->moveToThread_helper();

   QOrderedMutexLocker locker(&currentData->postEventList.mutex, &targetData->postEventList.mutex);

   // keep currentData alive
   currentData->ref();

   // move the object
   this->setThreadData_helper(currentData, targetData);

   locker.unlock();
   currentData->deref();
}
예제 #8
0
QThreadData *QThreadData::current()
{
    QThreadData *data = get_thread_data();
    if (!data) {
        data = new QThreadData;
        QT_TRY {
            set_thread_data(data);
            data->thread = new QAdoptedThread(data);
        } QT_CATCH(...) {
            clear_thread_data();
            data->deref();
            data = 0;
            QT_RETHROW;
        }
예제 #9
0
QThreadData *QThreadData::current(bool createIfNecessary)
{
    qt_create_tls();
    QThreadData *threadData = reinterpret_cast<QThreadData *>(TlsGetValue(qt_current_thread_data_tls_index));
    if (!threadData && createIfNecessary) {
        threadData = new QThreadData;
        // This needs to be called prior to new AdoptedThread() to
        // avoid recursion.
        TlsSetValue(qt_current_thread_data_tls_index, threadData);
        QT_TRY {
            threadData->thread = new QAdoptedThread(threadData);
        } QT_CATCH(...) {
            TlsSetValue(qt_current_thread_data_tls_index, 0);
            threadData->deref();
            threadData = 0;
            QT_RETHROW;
        }
예제 #10
0
QThreadData *QThreadData::current(bool createIfNecessary)
{
    static bool winmainThread = true;
    QThreadData *threadData = qt_current_thread_data;
    if (!threadData && createIfNecessary) {
        threadData = new QThreadData;
        // This needs to be called prior to new AdoptedThread() to
        // avoid recursion.
        qt_current_thread_data = threadData;
        QT_TRY {
            threadData->thread = new QAdoptedThread(threadData);
        } QT_CATCH(...) {
            qt_current_thread_data = 0;
            threadData->deref();
            threadData = 0;
            QT_RETHROW;
        }
예제 #11
0
void QObject::setThreadData_helper(QThreadData *currentData, QThreadData *targetData)
{
   // move posted events
   int eventsMoved = 0;

   for (int i = 0; i < currentData->postEventList.size(); ++i) {
      const QPostEvent &postedEvent = currentData->postEventList.at(i);

      if (! postedEvent.event) {
         continue;
      }

      if (postedEvent.receiver == this) {
         // move this post event to the targetList
         targetData->postEventList.addEvent(postedEvent);
         const_cast<QPostEvent &>(postedEvent).event = 0;
         ++eventsMoved;
      }
   }

   if (eventsMoved > 0 && targetData->eventDispatcher) {
      targetData->canWait = false;
      targetData->eventDispatcher->wakeUp();
   }

   // the current emitting thread shouldn't restore currentSender after calling moveToThread()
   if (m_currentSender)  {
      m_currentSender->ref = 0;
   }

   m_currentSender = 0;

   // set new thread data
   targetData->ref();

	QThreadData *threadData = m_threadData.exchange(targetData);
   threadData->deref();
   
   for (int k = 0; k < m_children.size(); ++k) {
      QObject *child = m_children.at(k);
      child->setThreadData_helper(currentData, targetData);
   }
}
예제 #12
0
파일: qthread_win.cpp 프로젝트: Fale/qtmoko
/*
    QThreadData
*/
QThreadData *QThreadData::current()
{
    qt_create_tls();
    QThreadData *threadData = reinterpret_cast<QThreadData *>(TlsGetValue(qt_current_thread_data_tls_index));
    if (!threadData) {
        QThread *adopted = 0;
        if (QInternal::activateCallbacks(QInternal::AdoptCurrentThread, (void **) &adopted)) {
            Q_ASSERT(adopted);
            threadData = QThreadData::get2(adopted);
            TlsSetValue(qt_current_thread_data_tls_index, threadData);
            adopted->d_func()->running = true;
            adopted->d_func()->finished = false;
            static_cast<QAdoptedThread *>(adopted)->init();
        } else {
            threadData = new QThreadData;
            // This needs to be called prior to new AdoptedThread() to
            // avoid recursion.
            TlsSetValue(qt_current_thread_data_tls_index, threadData);
            threadData->thread = new QAdoptedThread(threadData);
            threadData->deref();
        }

        if (!QCoreApplicationPrivate::theMainThread) {
            QCoreApplicationPrivate::theMainThread = threadData->thread;
        } else {
            HANDLE realHandle = INVALID_HANDLE_VALUE;
#if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600))
            DuplicateHandle(GetCurrentProcess(),
                    GetCurrentThread(),
                    GetCurrentProcess(),
                    &realHandle,
                    0,
                    FALSE,
                    DUPLICATE_SAME_ACCESS);
#else
                        realHandle = (HANDLE)GetCurrentThreadId();
#endif
            qt_watch_adopted_thread(realHandle, threadData->thread);
        }
    }
    return threadData;
}
예제 #13
0
/*
    QThreadData
*/
QThreadData *QThreadData::current()
{
    qt_create_tls();
    QThreadData *threadData = reinterpret_cast<QThreadData *>(TlsGetValue(qt_current_thread_data_tls_index));
    if (!threadData) {
        QThread *adopted = 0;
        if (QInternal::activateCallbacks(QInternal::AdoptCurrentThread, (void **) &adopted)) {
            Q_ASSERT(adopted);
            threadData = QThreadData::get2(adopted);
            TlsSetValue(qt_current_thread_data_tls_index, threadData);
            adopted->d_func()->running = true;
            adopted->d_func()->finished = false;
            static_cast<QAdoptedThread *>(adopted)->init();
        } else {
            threadData = new QThreadData;
            // This needs to be called prior to new AdoptedThread() to
            // avoid recursion.
            TlsSetValue(qt_current_thread_data_tls_index, threadData);
            threadData->thread = new QAdoptedThread(threadData);
            threadData->deref();
        }

        const bool isMainThread = q_atomic_test_and_set_ptr(&QCoreApplicationPrivate::theMainThread, 0, threadData->thread);
        if (!isMainThread) {
            HANDLE realHandle;
            DuplicateHandle(GetCurrentProcess(),
                    GetCurrentThread(),
                    GetCurrentProcess(),
                    &realHandle,
                    0,
                    FALSE,
                    DUPLICATE_SAME_ACCESS);
            qt_watch_adopted_thread(realHandle, threadData->thread);
        }
    }
    return threadData;
}
예제 #14
0
QObject::~QObject()
{  
   this->m_blockSig   = false;    // unblock signals so we always emit destroyed()

   // this code comes before anything else since a signal can not be emited from a dead object
   try {
      emit destroyed(this);

   } catch(...) {
      // all signal/slots connections are still in place
      // quit now, as the app will crash soon

      qWarning("QObject:~QObject() Detected an unexpected exception while emitting destroyed()");
      throw;
   }

   // this line needs to be located after the emit destroyed 
   this->m_wasDeleted = true;

   QtSharedPointer::ExternalRefCountData *sharedRefCount = m_sharedRefCount.exchange(0);

   if (sharedRefCount) {

      if (sharedRefCount->strongref.load() > 0) {
         // continue deleting, unclear what else to do
         qWarning("QObject:~QObject()  Shared QObject was deleted directly, application may crash.");
      }

      // indicate to all QWeakPointers QObject has now been deleted
      sharedRefCount->strongref.store(0);

      if (! sharedRefCount->weakref.deref()) {
         delete sharedRefCount;
      }
   }
 
   //
   if (this->m_declarativeData) {
      CSAbstractDeclarativeData::destroyed(this->m_declarativeData, this);
   }

   // set ref to zero, indicates this object has been deleted
   if (this->m_currentSender != 0) {
      this->m_currentSender->ref = 0;
   }

   this->m_currentSender = 0;

   std::unique_lock<std::mutex> senderLock{this->m_mutex_ToReceiver};
   std::unique_lock<std::mutex> receiverLock{this->m_mutex_FromSender};

   // disconnect all receivers from sender
   for(auto index = this->m_connectList_ToReceiver.begin(); index != this->m_connectList_ToReceiver.end(); ++index) {
      const ConnectStruct &temp = *index;

      if (temp.sender == 0) {
         // connection is marked for deletion
         continue;
      }

      if (! temp.receiver) {
         continue;
      }
      
      std::unique_lock<std::mutex> tempReceiverLock{temp.receiver->m_mutex_FromSender, std::defer_lock};
      if (this != temp.receiver) {
         tempReceiverLock.lock();         
      }

      for (int x = 0; x < temp.receiver->m_connectList_FromSender.count(); ++x)  {

         if (this == temp.receiver->m_connectList_FromSender[x].sender) {
            temp.receiver->m_connectList_FromSender.removeAt(x);

            // yes, this is required
            x = x - 1;
         }
      }      
   }

   // disconnect all senders from receiver
   bool isDone = false;

   for(auto index = this->m_connectList_FromSender.begin(); index != this->m_connectList_FromSender.end(); ++index) {
      ConnectStruct &temp = *index;

      std::unique_lock<std::mutex> tempSenderLock{temp.sender->m_mutex_ToReceiver, std::defer_lock};
      if (this != temp.sender) {
         tempSenderLock.lock();         
      }

      for (int x = 0; x < temp.sender->m_connectList_ToReceiver.count(); ++x)  {
         // connection is in another object to one of our slots
         ConnectStruct &connection = temp.sender->m_connectList_ToReceiver[x];

         if (connection.sender == 0) {
            // connection is marked for deletion
            continue;
         }

         if (this == connection.receiver) {

            if (temp.sender->m_activateBusy) {

               if (! isDone) {
                  // warns activate the connectList has changed
                  temp.sender->m_raceCount++;
                  isDone = true;
               }

               // mark connection for deletion, activate() will finish
               connection.sender = 0;

            } else {
               temp.sender->m_connectList_ToReceiver.removeAt(x);

               // yes, this is required
               x = x - 1;
            }
         }
      }     
   }

   if (! this->m_children.isEmpty()) {
      this->deleteChildren();
   }

   this->removeObject();

   if (this->m_parent)  {
      // remove 'this' from parent object
      this->setParent(0);
   }

	QThreadData *threadData = m_threadData.load();

   if (m_pendTimer) {
      // unregister pending timers	

      if (threadData && threadData->eventDispatcher) {
         threadData->eventDispatcher->unregisterTimers(this);
      }
   }

   if (m_postedEvents) {
      QCoreApplication::removePostedEvents(this, 0);
   }

   if (threadData)  {
      threadData->deref();
   }
}