Exemplo n.º 1
0
int cf_queue_delete(cf_queue *q, void *buf, bool only_one) {
	if (NULL == q)
		return(CF_QUEUE_ERR);

	QUEUE_LOCK(q);
	
	bool found = false;
	
	if (CF_Q_SZ(q)) {

		for (uint32_t i = q->read_offset ;
			 i < q->write_offset ;
			 i++)
		{
			
			int rv = memcmp(CF_Q_ELEM_PTR(q,i), buf, q->elementsz);
			
			if (rv == 0) { // delete!
				cf_queue_delete_offset(q, i);
				found = true;
				if (only_one == true)	goto Done;
			}
		};
	}

Done:
	QUEUE_UNLOCK(q);

	if (found == false)
		return(CF_QUEUE_EMPTY);
	else
		return(CF_QUEUE_OK);
}
//
// This assumes the element we're looking for is unique! Returns
// CF_QUEUE_NOMATCH if the element is not found or not moved.
//
int cf_queue_priority_change(cf_queue_priority *priority_q, const void *ptr, int new_pri)
{
	cf_queue_priority_lock(priority_q);

	cf_queue *queues[3];

	queues[0] = priority_q->high_q;
	queues[1] = priority_q->medium_q;
	queues[2] = priority_q->low_q;

	int dest_q_itr = CF_QUEUE_PRIORITY_HIGH - new_pri;
	cf_queue *q;

	for (int q_itr = 0; q_itr < 3; q_itr++) {
		q = queues[q_itr];

		if (q_itr == dest_q_itr || CF_Q_SZ(q) == 0) {
			continue;
		}

		for (uint32_t i = q->read_offset; i < q->write_offset; i++) {
			if (memcmp(CF_Q_ELEM_PTR(q, i), ptr, q->element_sz) == 0) {
				// Move it to the queue with desired priority.
				cf_queue_delete_offset(q, i);
				cf_queue_push(queues[dest_q_itr], ptr);

				cf_queue_priority_unlock(priority_q);
				return CF_QUEUE_OK;
			}
		}
	}

	cf_queue_priority_unlock(priority_q);
	return CF_QUEUE_NOMATCH;
}
//
// Reduce the inner queues whose priorities are different to 'new_pri'. If the
// callback returns -1, move that element to the inner queue whose priority is
// 'new_pri' and return CF_QUEUE_OK. Returns CF_QUEUE_NOMATCH if callback never
// triggers a move.
//
int cf_queue_priority_reduce_change(cf_queue_priority *priority_q, int new_pri, cf_queue_reduce_fn cb, void *udata)
{
	cf_queue_priority_lock(priority_q);

	cf_queue *queues[3];

	queues[0] = priority_q->high_q;
	queues[1] = priority_q->medium_q;
	queues[2] = priority_q->low_q;

	int dest_q_itr = CF_QUEUE_PRIORITY_HIGH - new_pri;
	cf_queue *q;

	for (int q_itr = 0; q_itr < 3; q_itr++) {
		q = queues[q_itr];

		if (q_itr == dest_q_itr || CF_Q_SZ(q) == 0) {
			continue;
		}

		for (uint32_t i = q->read_offset; i < q->write_offset; i++) {
			int rv = cb(CF_Q_ELEM_PTR(q, i), udata);

			if (rv == 0) {
				continue;
			}

			if (rv == -1) {
				// Found it - move to desired queue and return.
				uint8_t* buf = alloca(q->element_sz);

				memcpy(buf, CF_Q_ELEM_PTR(q, i), q->element_sz);
				cf_queue_delete_offset(q, i);
				cf_queue_push(queues[dest_q_itr], buf);

				cf_queue_priority_unlock(priority_q);
				return CF_QUEUE_OK;
			}
		}
	}

	cf_queue_priority_unlock(priority_q);
	return CF_QUEUE_NOMATCH;
}
Exemplo n.º 4
0
int
cf_queue_reduce(cf_queue *q,  cf_queue_reduce_fn cb, void *udata)
{
    if (NULL == q)
        return(-1);

    /* FIXME error checking */
    if (q->threadsafe && (0 != pthread_mutex_lock(&q->LOCK)))
        return(-1);

    if (CF_Q_SZ(q)) {

        // it would be faster to have a local variable to hold the index,
        // and do it in bytes or something, but a delete
        // will change the read and write offset, so this is simpler for now
        // can optimize if necessary later....

        for (uint i = q->read_offset ;
                i < q->write_offset ;
                i++)
        {

            int rv = cb(CF_Q_ELEM_PTR(q, i), udata);

            // rv == 0 i snormal case, just increment to next point
            if (rv == -1) {
                break; // found what it was looking for
            }
            else if (rv == -2) { // delete!
                cf_queue_delete_offset(q, i);
                goto Found;
            }
        };
    }

Found:
    if (q->threadsafe && (0 != pthread_mutex_unlock(&q->LOCK))) {
        fprintf(stderr, "unlock failed\n");
        return(-1);
    }

    return(0);

}
/**
 * Use this function to find an element to pop from the queue using a reduce
 * callback function. Have the callback function return -1 when you want to pop
 * the element and stop reducing. If you have not popped an element,
 * CF_QUEUE_NOMATCH is returned.
 */
int cf_queue_priority_reduce_pop(cf_queue_priority *priority_q, void *buf, cf_queue_reduce_fn cb, void *udata)
{
	cf_queue_priority_lock(priority_q);

	cf_queue *queues[3];

	queues[0] = priority_q->high_q;
	queues[1] = priority_q->medium_q;
	queues[2] = priority_q->low_q;

	cf_queue *q;

	for (int q_itr = 0; q_itr < 3; q_itr++) {
		q = queues[q_itr];

		if (CF_Q_SZ(q) == 0) {
			continue;
		}

		for (uint32_t i = q->read_offset; i < q->write_offset; i++) {
			int rv = cb(CF_Q_ELEM_PTR(q, i), udata);

			if (rv == 0) {
				continue;
			}

			if (rv == -1) {
				// Found an element, so copy to 'buf', delete from q, and return.
				memcpy(buf, CF_Q_ELEM_PTR(q, i), q->element_sz);
				cf_queue_delete_offset(q, i);

				cf_queue_priority_unlock(priority_q);
				return CF_QUEUE_OK;
			}
		}
	}

	cf_queue_priority_unlock(priority_q);
	return CF_QUEUE_NOMATCH;
}
Exemplo n.º 6
0
int
cf_queue_delete(cf_queue *q, void *buf, bool only_one)
{
    if (NULL == q)
        return(CF_QUEUE_ERR);

    /* FIXME error checking */
    if (q->threadsafe && (0 != pthread_mutex_lock(&q->LOCK)))
        return(CF_QUEUE_ERR);

    bool found = false;

    if (CF_Q_SZ(q)) {

        for (uint i = q->read_offset ;
                i < q->write_offset ;
                i++)
        {

            int rv = memcmp(CF_Q_ELEM_PTR(q,i), buf, q->elementsz);

            if (rv == 0) { // delete!
                cf_queue_delete_offset(q, i);
                found = true;
                if (only_one == true)	goto Done;
            }
        };
    }

Done:
    if (q->threadsafe && (0 != pthread_mutex_unlock(&q->LOCK))) {
        fprintf(stderr, "unlock failed\n");
        return(-1);
    }

    if (found == false)
        return(CF_QUEUE_EMPTY);
    else
        return(CF_QUEUE_OK);
}
Exemplo n.º 7
0
int cf_queue_reduce(cf_queue *q,  cf_queue_reduce_fn cb, void *udata) {
	if (NULL == q)
		return(-1);

	QUEUE_LOCK(q);	

	if (CF_Q_SZ(q)) {
		
		// it would be faster to have a local variable to hold the index,
		// and do it in uint8_ts or something, but a delete
		// will change the read and write offset, so this is simpler for now
		// can optimize if necessary later....
		
		for (uint32_t i = q->read_offset ;
			 i < q->write_offset ;
			 i++)
		{
			
			int rv = cb(CF_Q_ELEM_PTR(q, i), udata);
			
			// rv == 0 i snormal case, just increment to next point
			if (rv == -1) {
				break; // found what it was looking for
			}
			else if (rv == -2) { // delete!
				cf_queue_delete_offset(q, i);
				goto Found;
			}
		};
	}
	
Found:	
	QUEUE_UNLOCK(q);

	return(0);
	
}
/**
 * Use this function to find an element to pop from the queue using a reduce
 * callback function. Have the callback function
 * return -1 when you know you want to pop the element immediately, returns -2
 * when the element is the best candidate for popping found so far but you want
 * to keep looking, and returns 0 when you are not interested in popping
 * the element. You then pop the best candidate you've found - either the
 * "-1 case" or the last "-2 case". If you have not found a suitable candidate,
 * CF_QUEUE_NOMATCH is returned.
 */
int cf_queue_priority_reduce_pop(cf_queue_priority *priority_q,  void *buf, cf_queue_reduce_fn cb, void *udata)
{
    if (NULL == priority_q)
        return(-1);
	
    if (priority_q->threadsafe && (0 != pthread_mutex_lock(&priority_q->LOCK)))
        return(-1);
	
    int rv = 0;
	
    cf_queue *queues[3];
    queues[0] = priority_q->high_q;
    queues[1] = priority_q->medium_q;
    queues[2] = priority_q->low_q;
	
    cf_queue *q;
    int found_index = -1;
	
    for (int q_itr = 0; q_itr < 3; q_itr++)
    {
        q = queues[q_itr];
		
        if (CF_Q_SZ(q)) {
			
            // it would be faster to have a local variable to hold the index,
            // and do it in bytes or something, but a delete
            // will change the read and write offset, so this is simpler for now
            // can optimize if necessary later....
			
            for (uint i = q->read_offset ;
				 i < q->write_offset ;
				 i++)
            {
				
                rv = cb(CF_Q_ELEM_PTR(q, i), udata);
				
                // rv == 0 is normal case, just increment to next point
                if (rv == -1) {
                    found_index = i;
                    break; // found what it was looking for, so break
                }
                else if (rv == -2) {
                    // found new candidate, but keep looking for one better
                    found_index = i;
                }
				
            };
			
            break; // only traverse the highest priority q
        }
    }
	
    if (found_index >= 0) {
        // found an element, so memcpy to buf, delete from q, and return
        memcpy(buf, CF_Q_ELEM_PTR(q, found_index), q->elementsz);
        cf_queue_delete_offset(q, found_index);
    }
	
    if (priority_q->threadsafe && (0 != pthread_mutex_unlock(&priority_q->LOCK))) {
        return(-1);
    }
	
    if (found_index == -1)
        return(CF_QUEUE_NOMATCH);
	
    return(0);
}