eventq.cc revision 9983
12SN/A/*
21762SN/A * Copyright (c) 2000-2005 The Regents of The University of Michigan
35502Snate@binkert.org * Copyright (c) 2008 The Hewlett-Packard Development Company
49983Sstever@gmail.com * Copyright (c) 2013 Advanced Micro Devices, Inc.
52SN/A * All rights reserved.
62SN/A *
72SN/A * Redistribution and use in source and binary forms, with or without
82SN/A * modification, are permitted provided that the following conditions are
92SN/A * met: redistributions of source code must retain the above copyright
102SN/A * notice, this list of conditions and the following disclaimer;
112SN/A * redistributions in binary form must reproduce the above copyright
122SN/A * notice, this list of conditions and the following disclaimer in the
132SN/A * documentation and/or other materials provided with the distribution;
142SN/A * neither the name of the copyright holders nor the names of its
152SN/A * contributors may be used to endorse or promote products derived from
162SN/A * this software without specific prior written permission.
172SN/A *
182SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
192SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
202SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
212SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
222SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
232SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
242SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
252SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
262SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
272SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
282SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
292665Ssaidi@eecs.umich.edu *
302665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt
312665Ssaidi@eecs.umich.edu *          Nathan Binkert
322665Ssaidi@eecs.umich.edu *          Steve Raasch
332SN/A */
342SN/A
355501Snate@binkert.org#include <cassert>
362SN/A#include <iostream>
372SN/A#include <string>
382SN/A#include <vector>
392SN/A
405502Snate@binkert.org#include "base/hashmap.hh"
415501Snate@binkert.org#include "base/misc.hh"
425501Snate@binkert.org#include "base/trace.hh"
431717SN/A#include "cpu/smt.hh"
448232Snate@binkert.org#include "debug/Config.hh"
455501Snate@binkert.org#include "sim/core.hh"
469356Snilay@cs.wisc.edu#include "sim/eventq_impl.hh"
472SN/A
482SN/Ausing namespace std;
492SN/A
509983Sstever@gmail.comTick simQuantum = 0;
519983Sstever@gmail.com
522SN/A//
539983Sstever@gmail.com// Main Event Queues
542SN/A//
559983Sstever@gmail.com// Events on these queues are processed at the *beginning* of each
562SN/A// cycle, before the pipeline simulation is performed.
572SN/A//
589983Sstever@gmail.comuint32_t numMainEventQueues = 0;
599983Sstever@gmail.comvector<EventQueue *> mainEventQueue;
609983Sstever@gmail.com__thread EventQueue *_curEventQueue = NULL;
619983Sstever@gmail.combool inParallelMode = false;
629983Sstever@gmail.com
639983Sstever@gmail.comEventQueue *
649983Sstever@gmail.comgetEventQueue(uint32_t index)
659983Sstever@gmail.com{
669983Sstever@gmail.com    while (numMainEventQueues <= index) {
679983Sstever@gmail.com        numMainEventQueues++;
689983Sstever@gmail.com        mainEventQueue.push_back(
699983Sstever@gmail.com            new EventQueue(csprintf("MainEventQueue-%d", index)));
709983Sstever@gmail.com    }
719983Sstever@gmail.com
729983Sstever@gmail.com    return mainEventQueue[index];
739983Sstever@gmail.com}
742SN/A
754017Sstever@eecs.umich.edu#ifndef NDEBUG
764016Sstever@eecs.umich.eduCounter Event::instanceCounter = 0;
774017Sstever@eecs.umich.edu#endif
784016Sstever@eecs.umich.edu
795768Snate@binkert.orgEvent::~Event()
805768Snate@binkert.org{
815774Snate@binkert.org    assert(!scheduled());
827059Snate@binkert.org    flags = 0;
835768Snate@binkert.org}
845768Snate@binkert.org
855768Snate@binkert.orgconst std::string
865768Snate@binkert.orgEvent::name() const
875768Snate@binkert.org{
885768Snate@binkert.org#ifndef NDEBUG
895768Snate@binkert.org    return csprintf("Event_%d", instance);
905768Snate@binkert.org#else
915768Snate@binkert.org    return csprintf("Event_%x", (uintptr_t)this);
925768Snate@binkert.org#endif
935768Snate@binkert.org}
945768Snate@binkert.org
955768Snate@binkert.org
965602Snate@binkert.orgEvent *
975602Snate@binkert.orgEvent::insertBefore(Event *event, Event *curr)
985502Snate@binkert.org{
995503Snate@binkert.org    // Either way, event will be the top element in the 'in bin' list
1005502Snate@binkert.org    // which is the pointer we need in order to look into the list, so
1015502Snate@binkert.org    // we need to insert that into the bin list.
1025502Snate@binkert.org    if (!curr || *event < *curr) {
1035502Snate@binkert.org        // Insert the event before the current list since it is in the future.
1045502Snate@binkert.org        event->nextBin = curr;
1055503Snate@binkert.org        event->nextInBin = NULL;
1065502Snate@binkert.org    } else {
1075502Snate@binkert.org        // Since we're on the correct list, we need to point to the next list
1085502Snate@binkert.org        event->nextBin = curr->nextBin;  // curr->nextBin can now become stale
1095502Snate@binkert.org
1105503Snate@binkert.org        // Insert event at the top of the stack
1115503Snate@binkert.org        event->nextInBin = curr;
1125503Snate@binkert.org    }
1135502Snate@binkert.org
1145503Snate@binkert.org    return event;
1155502Snate@binkert.org}
1165502Snate@binkert.org
1172SN/Avoid
1182SN/AEventQueue::insert(Event *event)
1192SN/A{
1205502Snate@binkert.org    // Deal with the head case
1215502Snate@binkert.org    if (!head || *event <= *head) {
1225602Snate@binkert.org        head = Event::insertBefore(event, head);
1235502Snate@binkert.org        return;
1245502Snate@binkert.org    }
1252SN/A
1265502Snate@binkert.org    // Figure out either which 'in bin' list we are on, or where a new list
1275502Snate@binkert.org    // needs to be inserted
1285503Snate@binkert.org    Event *prev = head;
1295503Snate@binkert.org    Event *curr = head->nextBin;
1305503Snate@binkert.org    while (curr && *curr < *event) {
1315503Snate@binkert.org        prev = curr;
1325503Snate@binkert.org        curr = curr->nextBin;
1335502Snate@binkert.org    }
1342SN/A
1355503Snate@binkert.org    // Note: this operation may render all nextBin pointers on the
1365503Snate@binkert.org    // prev 'in bin' list stale (except for the top one)
1375602Snate@binkert.org    prev->nextBin = Event::insertBefore(event, curr);
1385502Snate@binkert.org}
1392SN/A
1405602Snate@binkert.orgEvent *
1415602Snate@binkert.orgEvent::removeItem(Event *event, Event *top)
1425502Snate@binkert.org{
1435503Snate@binkert.org    Event *curr = top;
1445503Snate@binkert.org    Event *next = top->nextInBin;
1455502Snate@binkert.org
1465503Snate@binkert.org    // if we removed the top item, we need to handle things specially
1475503Snate@binkert.org    // and just remove the top item, fixing up the next bin pointer of
1485503Snate@binkert.org    // the new top item
1495503Snate@binkert.org    if (event == top) {
1505503Snate@binkert.org        if (!next)
1515503Snate@binkert.org            return top->nextBin;
1525503Snate@binkert.org        next->nextBin = top->nextBin;
1535503Snate@binkert.org        return next;
1545503Snate@binkert.org    }
1555503Snate@binkert.org
1565503Snate@binkert.org    // Since we already checked the current element, we're going to
1575503Snate@binkert.org    // keep checking event against the next element.
1585503Snate@binkert.org    while (event != next) {
1595503Snate@binkert.org        if (!next)
1605502Snate@binkert.org            panic("event not found!");
1615502Snate@binkert.org
1625503Snate@binkert.org        curr = next;
1635503Snate@binkert.org        next = next->nextInBin;
1642SN/A    }
1655502Snate@binkert.org
1665503Snate@binkert.org    // remove next from the 'in bin' list since it's what we're looking for
1675503Snate@binkert.org    curr->nextInBin = next->nextInBin;
1685503Snate@binkert.org    return top;
1692SN/A}
1702SN/A
1712SN/Avoid
1722SN/AEventQueue::remove(Event *event)
1732SN/A{
1742SN/A    if (head == NULL)
1755502Snate@binkert.org        panic("event not found!");
1762SN/A
1779983Sstever@gmail.com    assert(event->queue == this);
1789983Sstever@gmail.com
1795502Snate@binkert.org    // deal with an event on the head's 'in bin' list (event has the same
1805502Snate@binkert.org    // time as the head)
1815502Snate@binkert.org    if (*head == *event) {
1825602Snate@binkert.org        head = Event::removeItem(event, head);
1832SN/A        return;
1842SN/A    }
1852SN/A
1865502Snate@binkert.org    // Find the 'in bin' list that this event belongs on
1872SN/A    Event *prev = head;
1885502Snate@binkert.org    Event *curr = head->nextBin;
1895502Snate@binkert.org    while (curr && *curr < *event) {
1902SN/A        prev = curr;
1915502Snate@binkert.org        curr = curr->nextBin;
1922SN/A    }
1932SN/A
1945502Snate@binkert.org    if (!curr || *curr != *event)
1955502Snate@binkert.org        panic("event not found!");
1965502Snate@binkert.org
1975503Snate@binkert.org    // curr points to the top item of the the correct 'in bin' list, when
1985503Snate@binkert.org    // we remove an item, it returns the new top item (which may be
1995502Snate@binkert.org    // unchanged)
2005602Snate@binkert.org    prev->nextBin = Event::removeItem(event, curr);
2012SN/A}
2022SN/A
2032667Sstever@eecs.umich.eduEvent *
2042SN/AEventQueue::serviceOne()
2052SN/A{
2065503Snate@binkert.org    Event *event = head;
2075503Snate@binkert.org    Event *next = head->nextInBin;
2085769Snate@binkert.org    event->flags.clear(Event::Scheduled);
2095502Snate@binkert.org
2105503Snate@binkert.org    if (next) {
2115503Snate@binkert.org        // update the next bin pointer since it could be stale
2125503Snate@binkert.org        next->nextBin = head->nextBin;
2135503Snate@binkert.org
2145503Snate@binkert.org        // pop the stack
2155503Snate@binkert.org        head = next;
2165503Snate@binkert.org    } else {
2175502Snate@binkert.org        // this was the only element on the 'in bin' list, so get rid of
2185502Snate@binkert.org        // the 'in bin' list and point to the next bin list
2195503Snate@binkert.org        head = head->nextBin;
2205502Snate@binkert.org    }
2212SN/A
2222SN/A    // handle action
2232667Sstever@eecs.umich.edu    if (!event->squashed()) {
2249356Snilay@cs.wisc.edu        // forward current cycle to the time when this event occurs.
2259356Snilay@cs.wisc.edu        setCurTick(event->when());
2269356Snilay@cs.wisc.edu
2272SN/A        event->process();
2282667Sstever@eecs.umich.edu        if (event->isExitEvent()) {
2299328SAli.Saidi@ARM.com            assert(!event->flags.isSet(Event::AutoDelete) ||
2309328SAli.Saidi@ARM.com                   !event->flags.isSet(Event::IsMainQueue)); // would be silly
2312667Sstever@eecs.umich.edu            return event;
2322667Sstever@eecs.umich.edu        }
2332667Sstever@eecs.umich.edu    } else {
2345769Snate@binkert.org        event->flags.clear(Event::Squashed);
2352667Sstever@eecs.umich.edu    }
2362SN/A
2375769Snate@binkert.org    if (event->flags.isSet(Event::AutoDelete) && !event->scheduled())
2382SN/A        delete event;
2392667Sstever@eecs.umich.edu
2402667Sstever@eecs.umich.edu    return NULL;
2412SN/A}
2422SN/A
243224SN/Avoid
244224SN/AEvent::serialize(std::ostream &os)
245224SN/A{
246224SN/A    SERIALIZE_SCALAR(_when);
247224SN/A    SERIALIZE_SCALAR(_priority);
2485769Snate@binkert.org    short _flags = flags;
2495769Snate@binkert.org    SERIALIZE_SCALAR(_flags);
250224SN/A}
251224SN/A
252224SN/Avoid
253237SN/AEvent::unserialize(Checkpoint *cp, const string &section)
254224SN/A{
2559983Sstever@gmail.com}
2569983Sstever@gmail.com
2579983Sstever@gmail.comvoid
2589983Sstever@gmail.comEvent::unserialize(Checkpoint *cp, const string &section, EventQueue *eventq)
2599983Sstever@gmail.com{
2605695Snate@binkert.org    if (scheduled())
2619983Sstever@gmail.com        eventq->deschedule(this);
262224SN/A
263224SN/A    UNSERIALIZE_SCALAR(_when);
264224SN/A    UNSERIALIZE_SCALAR(_priority);
265224SN/A
2665769Snate@binkert.org    short _flags;
2675769Snate@binkert.org    UNSERIALIZE_SCALAR(_flags);
2687452SLisa.Hsu@amd.com
2697452SLisa.Hsu@amd.com    // Old checkpoints had no concept of the Initialized flag
2707452SLisa.Hsu@amd.com    // so restoring from old checkpoints always fail.
2717452SLisa.Hsu@amd.com    // Events are initialized on construction but original code
2727452SLisa.Hsu@amd.com    // "flags = _flags" would just overwrite the initialization.
2737452SLisa.Hsu@amd.com    // So, read in the checkpoint flags, but then set the Initialized
2747452SLisa.Hsu@amd.com    // flag on top of it in order to avoid failures.
2757451SLisa.Hsu@amd.com    assert(initialized());
2765769Snate@binkert.org    flags = _flags;
2777451SLisa.Hsu@amd.com    flags.set(Initialized);
2785769Snate@binkert.org
2797452SLisa.Hsu@amd.com    // need to see if original event was in a scheduled, unsquashed
2807452SLisa.Hsu@amd.com    // state, but don't want to restore those flags in the current
2817452SLisa.Hsu@amd.com    // object itself (since they aren't immediately true)
2825769Snate@binkert.org    bool wasScheduled = flags.isSet(Scheduled) && !flags.isSet(Squashed);
2835769Snate@binkert.org    flags.clear(Squashed | Scheduled);
284224SN/A
285224SN/A    if (wasScheduled) {
286224SN/A        DPRINTF(Config, "rescheduling at %d\n", _when);
2879983Sstever@gmail.com        eventq->schedule(this, _when);
288224SN/A    }
289224SN/A}
290224SN/A
2912SN/Avoid
292217SN/AEventQueue::serialize(ostream &os)
2932SN/A{
294265SN/A    std::list<Event *> eventPtrs;
295237SN/A
296237SN/A    int numEvents = 0;
2975502Snate@binkert.org    Event *nextBin = head;
2985502Snate@binkert.org    while (nextBin) {
2995503Snate@binkert.org        Event *nextInBin = nextBin;
3005502Snate@binkert.org
3015503Snate@binkert.org        while (nextInBin) {
3025769Snate@binkert.org            if (nextInBin->flags.isSet(Event::AutoSerialize)) {
3035502Snate@binkert.org                eventPtrs.push_back(nextInBin);
3045502Snate@binkert.org                paramOut(os, csprintf("event%d", numEvents++),
3055502Snate@binkert.org                         nextInBin->name());
3065502Snate@binkert.org            }
3075502Snate@binkert.org            nextInBin = nextInBin->nextInBin;
3085503Snate@binkert.org        }
3095502Snate@binkert.org
3105502Snate@binkert.org        nextBin = nextBin->nextBin;
3112SN/A    }
312237SN/A
313265SN/A    SERIALIZE_SCALAR(numEvents);
314265SN/A
3155502Snate@binkert.org    for (std::list<Event *>::iterator it = eventPtrs.begin();
316265SN/A         it != eventPtrs.end(); ++it) {
317265SN/A        (*it)->nameOut(os);
318265SN/A        (*it)->serialize(os);
319265SN/A    }
3202SN/A}
3212SN/A
322237SN/Avoid
323237SN/AEventQueue::unserialize(Checkpoint *cp, const std::string &section)
324237SN/A{
325265SN/A    int numEvents;
326265SN/A    UNSERIALIZE_SCALAR(numEvents);
327265SN/A
328270SN/A    std::string eventName;
329265SN/A    for (int i = 0; i < numEvents; i++) {
330265SN/A        // get the pointer value associated with the event
331270SN/A        paramIn(cp, section, csprintf("event%d", i), eventName);
332265SN/A
333265SN/A        // create the event based on its pointer value
334395SN/A        Serializable::create(cp, eventName);
335237SN/A    }
336237SN/A}
337237SN/A
3382SN/Avoid
3395501Snate@binkert.orgEventQueue::dump() const
3402SN/A{
3412SN/A    cprintf("============================================================\n");
3427823Ssteve.reinhardt@amd.com    cprintf("EventQueue Dump  (cycle %d)\n", curTick());
3432SN/A    cprintf("------------------------------------------------------------\n");
3442SN/A
3452SN/A    if (empty())
3462SN/A        cprintf("<No Events>\n");
3472SN/A    else {
3485502Snate@binkert.org        Event *nextBin = head;
3495502Snate@binkert.org        while (nextBin) {
3505502Snate@binkert.org            Event *nextInBin = nextBin;
3515503Snate@binkert.org            while (nextInBin) {
3525503Snate@binkert.org                nextInBin->dump();
3535502Snate@binkert.org                nextInBin = nextInBin->nextInBin;
3545503Snate@binkert.org            }
3555502Snate@binkert.org
3565502Snate@binkert.org            nextBin = nextBin->nextBin;
3572SN/A        }
3582SN/A    }
3592SN/A
3602SN/A    cprintf("============================================================\n");
3612SN/A}
3622SN/A
3635502Snate@binkert.orgbool
3645502Snate@binkert.orgEventQueue::debugVerify() const
3655502Snate@binkert.org{
3665502Snate@binkert.org    m5::hash_map<long, bool> map;
3675502Snate@binkert.org
3685502Snate@binkert.org    Tick time = 0;
3695502Snate@binkert.org    short priority = 0;
3705502Snate@binkert.org
3715502Snate@binkert.org    Event *nextBin = head;
3725502Snate@binkert.org    while (nextBin) {
3735503Snate@binkert.org        Event *nextInBin = nextBin;
3745503Snate@binkert.org        while (nextInBin) {
3755502Snate@binkert.org            if (nextInBin->when() < time) {
3765502Snate@binkert.org                cprintf("time goes backwards!");
3775502Snate@binkert.org                nextInBin->dump();
3785502Snate@binkert.org                return false;
3795502Snate@binkert.org            } else if (nextInBin->when() == time &&
3805502Snate@binkert.org                       nextInBin->priority() < priority) {
3815502Snate@binkert.org                cprintf("priority inverted!");
3825502Snate@binkert.org                nextInBin->dump();
3835502Snate@binkert.org                return false;
3845502Snate@binkert.org            }
3855502Snate@binkert.org
3865502Snate@binkert.org            if (map[reinterpret_cast<long>(nextInBin)]) {
3875502Snate@binkert.org                cprintf("Node already seen");
3885502Snate@binkert.org                nextInBin->dump();
3895502Snate@binkert.org                return false;
3905502Snate@binkert.org            }
3915502Snate@binkert.org            map[reinterpret_cast<long>(nextInBin)] = true;
3925502Snate@binkert.org
3935502Snate@binkert.org            time = nextInBin->when();
3945502Snate@binkert.org            priority = nextInBin->priority();
3955502Snate@binkert.org
3965502Snate@binkert.org            nextInBin = nextInBin->nextInBin;
3975503Snate@binkert.org        }
3985502Snate@binkert.org
3995502Snate@binkert.org        nextBin = nextBin->nextBin;
4005502Snate@binkert.org    }
4015502Snate@binkert.org
4025502Snate@binkert.org    return true;
4035502Snate@binkert.org}
4045502Snate@binkert.org
4058648Snilay@cs.wisc.eduEvent*
4068648Snilay@cs.wisc.eduEventQueue::replaceHead(Event* s)
4078648Snilay@cs.wisc.edu{
4088648Snilay@cs.wisc.edu    Event* t = head;
4098648Snilay@cs.wisc.edu    head = s;
4108648Snilay@cs.wisc.edu    return t;
4118648Snilay@cs.wisc.edu}
4128648Snilay@cs.wisc.edu
4131019SN/Avoid
4141019SN/AdumpMainQueue()
4151019SN/A{
4169983Sstever@gmail.com    for (uint32_t i = 0; i < numMainEventQueues; ++i) {
4179983Sstever@gmail.com        mainEventQueue[i]->dump();
4189983Sstever@gmail.com    }
4191019SN/A}
4201019SN/A
4212SN/A
4222SN/Aconst char *
4235336Shines@cs.fsu.eduEvent::description() const
4242SN/A{
4252SN/A    return "generic";
4262SN/A}
4272SN/A
4282SN/Avoid
4292SN/AEvent::trace(const char *action)
4302SN/A{
4312SN/A    // This DPRINTF is unconditional because calls to this function
4322SN/A    // are protected by an 'if (DTRACE(Event))' in the inlined Event
4332SN/A    // methods.
4342SN/A    //
4352SN/A    // This is just a default implementation for derived classes where
4362SN/A    // it's not worth doing anything special.  If you want to put a
4372SN/A    // more informative message in the trace, override this method on
4382SN/A    // the particular subclass where you have the information that
4392SN/A    // needs to be printed.
4402SN/A    DPRINTFN("%s event %s @ %d\n", description(), action, when());
4412SN/A}
4422SN/A
4432SN/Avoid
4445501Snate@binkert.orgEvent::dump() const
4452SN/A{
4465501Snate@binkert.org    cprintf("Event %s (%s)\n", name(), description());
4475769Snate@binkert.org    cprintf("Flags: %#x\n", flags);
4485501Snate@binkert.org#ifdef EVENTQ_DEBUG
4495501Snate@binkert.org    cprintf("Created: %d\n", whenCreated);
4502SN/A#endif
4512SN/A    if (scheduled()) {
4525501Snate@binkert.org#ifdef EVENTQ_DEBUG
4535501Snate@binkert.org        cprintf("Scheduled at  %d\n", whenScheduled);
4542SN/A#endif
4551019SN/A        cprintf("Scheduled for %d, priority %d\n", when(), _priority);
4565501Snate@binkert.org    } else {
4571019SN/A        cprintf("Not Scheduled\n");
4582SN/A    }
4592SN/A}
4607063Snate@binkert.org
4617063Snate@binkert.orgEventQueue::EventQueue(const string &n)
4629983Sstever@gmail.com    : objName(n), head(NULL), _curTick(0),
4639983Sstever@gmail.com    async_queue_mutex(new std::mutex())
4649983Sstever@gmail.com{
4659983Sstever@gmail.com}
4669983Sstever@gmail.com
4679983Sstever@gmail.comvoid
4689983Sstever@gmail.comEventQueue::asyncInsert(Event *event)
4699983Sstever@gmail.com{
4709983Sstever@gmail.com    async_queue_mutex->lock();
4719983Sstever@gmail.com    async_queue.push_back(event);
4729983Sstever@gmail.com    async_queue_mutex->unlock();
4739983Sstever@gmail.com}
4749983Sstever@gmail.com
4759983Sstever@gmail.comvoid
4769983Sstever@gmail.comEventQueue::handleAsyncInsertions()
4779983Sstever@gmail.com{
4789983Sstever@gmail.com    assert(this == curEventQueue());
4799983Sstever@gmail.com    async_queue_mutex->lock();
4809983Sstever@gmail.com
4819983Sstever@gmail.com    while (!async_queue.empty()) {
4829983Sstever@gmail.com        insert(async_queue.front());
4839983Sstever@gmail.com        async_queue.pop_front();
4849983Sstever@gmail.com    }
4859983Sstever@gmail.com
4869983Sstever@gmail.com    async_queue_mutex->unlock();
4879983Sstever@gmail.com}
488