int Ts2::Network::RouteManager::CancelDataPackets(u32 srcVtId)
{
    int err = 0;

    {
        MutexAutoLock lock(&mutex);
        state.clients++;
        if (state.stop == STOP_STATE_STOPPING) {
            LOG_WARN("RouteManager[%p]: Method called after Stop", this);
        }

        // Removing an element from the middle of a queue maybe expensive.
        // Thus, instead of removing it, we will simply replace the pointer to a Packet obj with a NULL pointer.
        // Dequeue code (in packetThreadMain()) will check the pointer value and ignore if NULL.
        std::deque<std::pair<Packet*, VPLTime_t> >::iterator it;
        for (it = packetQueue.begin(); it != packetQueue.end(); it++) {
            Packet *packet = it->first;
            if (packet && (packet->GetPktType() == TS_PKT_DATA) && (packet->GetSrcVtId() == srcVtId)) {
                delete packet;     // destroy Packet obj
                it->first = NULL;  // replace pointer with NULL pointer
            }
        }
    }

    {
        // If the worker thread is trying to send, wait until it is done.
        // This is necessary, since it may be currently processing a packet that
        // would have been cancelled by the loop above.
        MutexAutoLock lock(&mutex_packetThreadSending);
        while (packetThreadSending) {
            err = VPLCond_TimedWait(&cond_packetThreadSending, &mutex_packetThreadSending, VPL_TIMEOUT_NONE);
            if (err) {
                LOG_ERROR("RouteManager[%p]: CondVar failed: err %d", this, err);
                err = 0;  // Reset error and exit.
                break;
            }
        }
    }

    {
        MutexAutoLock lock(&mutex);
        state.clients--;
        if (state.clients == 0) {
            VPLCond_Broadcast(&cond_state_noClients);
        }
    }

    return err;
}