【问题标题】:Exception safety guarantee of QCoreApplication::postEventQCoreApplication::postEvent的异常安全保证
【发布时间】:2014-05-15 10:03:44
【问题描述】:

我正在使用此代码发布活动:

QEvent*event=new QEvent(QEvent::User);
QCoreApplication::postEvent(pointerToSomeQObject,event);

QCoreApplication::postEvent 描述为here。但是,如果在 postEvent 中引发异常,绝对没有关于我应该做什么的信息。

我认为该功能属于以下四类之一:

  1. 它从不抛出异常(特别是没有 std::bad_alloc)
  2. 如果它抛出它永远不会删除事件。
  3. 如果它抛出它有时会删除事件。
  4. 如果它抛出它总是会删除事件。

最坏的情况是第三种情况。

所以:如果 postEvent 抛出,我需要删除事件吗?

【问题讨论】:

    标签: c++ qt qt5 exception-safety


    【解决方案1】:

    我找到了 QApplication::postEvent 的代码:

    void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
    {
        if (receiver == 0) {
            qWarning("QCoreApplication::postEvent: Unexpected null receiver");
            delete event;
            return;
        }
    
        QThreadData * volatile * pdata = &receiver->d_func()->threadData;
        QThreadData *data = *pdata;
        if (!data) {
            // posting during destruction? just delete the event to prevent a leak
            delete event;
            return;
        }
    
        // lock the post event mutex
        data->postEventList.mutex.lock();
    
        // if object has moved to another thread, follow it
        while (data != *pdata) {
            data->postEventList.mutex.unlock();
    
            data = *pdata;
            if (!data) {
                // posting during destruction? just delete the event to prevent a leak
                delete event;
                return;
            }
    
            data->postEventList.mutex.lock();
        }
    
        QMutexUnlocker locker(&data->postEventList.mutex);
    
        // if this is one of the compressible events, do compression
        if (receiver->d_func()->postedEvents
            && self && self->compressEvent(event, receiver, &data->postEventList)) {
            return;
        }
    
        if (event->type() == QEvent::DeferredDelete && data == QThreadData::current()) {
            // remember the current running eventloop for DeferredDelete
            // events posted in the receiver's thread
            static_cast<QDeferredDeleteEvent *>(event)->level = data->loopLevel;
        }
    
        // delete the event on exceptions to protect against memory leaks till the event is
        // properly owned in the postEventList
        QScopedPointer<QEvent> eventDeleter(event);
        data->postEventList.addEvent(QPostEvent(receiver, event, priority));
        eventDeleter.take();
        event->posted = true;
        ++receiver->d_func()->postedEvents;
        data->canWait = false;
        locker.unlock();
    
        QAbstractEventDispatcher* dispatcher = data->eventDispatcher.loadAcquire();
        if (dispatcher)
            dispatcher->wakeUp();
    }
    

    在异常情况下使用 RAII QScopedPointer 守卫销毁事件是非常小心的。

    我猜我的问题的答案是第四个选择:

    如果它抛出它总是会删除给定的事件。

    【讨论】:

      猜你喜欢
      • 2017-07-24
      • 1970-01-01
      • 2021-03-24
      • 1970-01-01
      • 2013-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-16
      相关资源
      最近更新 更多