gpointer asyncpriorityqueue_pop(AsyncPriorityQueue *q) {
	g_assert(q);
	g_mutex_lock(&(q->lock));
	gpointer returnData = priorityqueue_pop(q->pq);
	g_mutex_unlock(&(q->lock));
	return returnData;
}
static Event* _schedulerpolicyhoststeal_popFromThread(SchedulerPolicy* policy, HostStealThreadData* tdata, GQueue* assignedHosts, SimulationTime barrier) {
    /* if there is no tdata, that means this thread didn't get any hosts assigned to it */
    if(!tdata) {
        return NULL;
    }

    HostStealPolicyData* data = policy->data;

    while(!g_queue_is_empty(assignedHosts) || tdata->runningHost) {
        /* if there's no running host, we completed the last assignment and need a new one */
        if(!tdata->runningHost) {
            tdata->runningHost = g_queue_pop_head(assignedHosts);
        }
        Host* host = tdata->runningHost;
        g_rw_lock_reader_lock(&data->lock);
        HostStealQueueData* qdata = g_hash_table_lookup(data->hostToQueueDataMap, host);
        g_rw_lock_reader_unlock(&data->lock);
        utility_assert(qdata);

        g_mutex_lock(&(qdata->lock));
        Event* nextEvent = priorityqueue_peek(qdata->pq);
        SimulationTime eventTime = (nextEvent != NULL) ? event_getTime(nextEvent) : SIMTIME_INVALID;

        if(nextEvent != NULL && eventTime < barrier) {
            utility_assert(eventTime >= qdata->lastEventTime);
            qdata->lastEventTime = eventTime;
            nextEvent = priorityqueue_pop(qdata->pq);
            qdata->nPopped++;
            /* migrate iff a migration is needed */
            _schedulerpolicyhoststeal_migrateHost(policy, host, pthread_self());
        } else {
            nextEvent = NULL;
        }

        if(nextEvent == NULL) {
            /* no more events on the runningHost, mark it as NULL so we get a new one */
            g_queue_push_tail(tdata->processedHosts, host);
            tdata->runningHost = NULL;
        }

        g_mutex_unlock(&(qdata->lock));

        if(nextEvent != NULL) {
            return nextEvent;
        }
    }

    /* if we make it here, all hosts for this thread have no more events before barrier */
    return NULL;
}
/* first-in-first-out queuing discipline ($ man tc)*/
static Packet* _networkinterface_selectFirstInFirstOut(NetworkInterface* interface, gint* socketHandle) {
	/* use packet priority field to select based on application ordering.
	 * this is really a simplification of prioritizing on timestamps. */
	Packet* packet = NULL;

	while(!packet && !priorityqueue_isEmpty(interface->fifoQueue)) {
		/* do fifo to get the next packet from the next socket */
		Socket* socket = priorityqueue_pop(interface->fifoQueue);
		packet = socket_pullOutPacket(socket);
		*socketHandle = *descriptor_getHandleReference((Descriptor*)socket);

		if(socket_peekNextPacket(socket)) {
			/* socket has more packets, and is still reffed from before */
			priorityqueue_push(interface->fifoQueue, socket);
		} else {
			/* socket has no more packets, unref it from the sendable queue */
			descriptor_unref((Descriptor*) socket);
		}
	}

	return packet;
}