-1

私はこのコードでイベントを投稿しています:

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

QCoreApplication::postEvent についてはこちらで説明しています。ただし、postEvent で例外がスローされた場合に何をすべきかについての情報はまったくありません。

この関数は、次の 4 つのカテゴリのいずれかに分類されると思います。

  1. 例外をスローすることはありません (特に std::bad_alloc はありません)。
  2. スローされた場合、イベントは決して削除されません。
  3. スローすると、いつかイベントが削除されます。
  4. スローすると、常にイベントが削除されます。

最悪のシナリオは 3 番目です。

では、postEvent がスローされた場合、イベントを削除する必要がありますか?

4

1 に答える 1

2

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 ガードで例外が発生した場合、イベントを破棄するために細心の注意が必要です。

そして、私の質問に対する答えは 4 番目の選択肢だと思います。

スローすると、常に指定されたイベントが削除されます。

于 2014-05-15T10:48:37.693 に答える