Makes popping each member of the list a bit easier.
Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
Acked-by: Russell Bryant <rbryant@redhat.com>
Acked-by: Ben Pfaff <blp@nicira.com>
void
dp_packet_list_delete(struct ovs_list *list)
{
- struct dp_packet *b, *next;
+ struct dp_packet *b;
- LIST_FOR_EACH_SAFE (b, next, list_node, list) {
- list_remove(&b->list_node);
+ LIST_FOR_EACH_POP (b, list_node, list) {
dp_packet_delete(b);
}
}
? INIT_CONTAINER(NEXT, (ITER)->MEMBER.next, MEMBER), 1 \
: 0); \
(ITER) = (NEXT))
+#define LIST_FOR_EACH_POP(ITER, MEMBER, LIST) \
+ while (!list_is_empty(LIST) \
+ && (INIT_CONTAINER(ITER, list_pop_front(LIST), MEMBER), 1))
\f
/* Inline implementations. */
void
lldpd_chassis_mgmt_cleanup(struct lldpd_chassis *chassis)
{
- struct lldpd_mgmt *mgmt, *mgmt_next;
+ struct lldpd_mgmt *mgmt;
VLOG_DBG("cleanup management addresses for chassis %s",
chassis->c_name ? chassis->c_name : "(unknown)");
- LIST_FOR_EACH_SAFE (mgmt, mgmt_next, m_entries, &chassis->c_mgmt) {
- list_remove(&mgmt->m_entries);
+ LIST_FOR_EACH_POP (mgmt, m_entries, &chassis->c_mgmt) {
free(mgmt);
}
lldpd_move_chassis(struct lldpd_chassis *ochassis,
struct lldpd_chassis *chassis)
{
- struct lldpd_mgmt *mgmt, *mgmt_next;
+ struct lldpd_mgmt *mgmt;
int refcount = ochassis->c_refcount;
int index = ochassis->c_index;
struct ovs_list listcopy;
list_init(&ochassis->c_mgmt);
/* Copy of management addresses */
- LIST_FOR_EACH_SAFE (mgmt, mgmt_next, m_entries, &chassis->c_mgmt) {
- list_remove(&mgmt->m_entries);
+ LIST_FOR_EACH_POP (mgmt, m_entries, &chassis->c_mgmt) {
list_insert(&ochassis->c_mgmt, &mgmt->m_entries);
}
mcast_snooping_flush_group(struct mcast_snooping *ms, struct mcast_group *grp)
OVS_REQ_WRLOCK(ms->rwlock)
{
- struct mcast_group_bundle *b, *next_b;
+ struct mcast_group_bundle *b;
- LIST_FOR_EACH_SAFE (b, next_b, bundle_node, &grp->bundle_lru) {
- list_remove(&b->bundle_node);
+ LIST_FOR_EACH_POP (b, bundle_node, &grp->bundle_lru) {
free(b);
}
mcast_snooping_flush_group__(ms, grp);
void
ofputil_bucket_list_destroy(struct ovs_list *buckets)
{
- struct ofputil_bucket *bucket, *next_bucket;
+ struct ofputil_bucket *bucket;
- LIST_FOR_EACH_SAFE (bucket, next_bucket, list_node, buckets) {
- list_remove(&bucket->list_node);
+ LIST_FOR_EACH_POP (bucket, list_node, buckets) {
free(bucket->ofpacts);
free(bucket);
}
void
ofpbuf_list_delete(struct ovs_list *list)
{
- struct ofpbuf *b, *next;
+ struct ofpbuf *b;
- LIST_FOR_EACH_SAFE (b, next, list_node, list) {
- list_remove(&b->list_node);
+ LIST_FOR_EACH_POP (b, list_node, list) {
ofpbuf_delete(b);
}
}
ovs_mutex_lock(&mutex);
HMAP_FOR_EACH (lldp, hmap_node, all_lldps) {
- struct bridge_aa_vlan *node, *node_next;
+ struct bridge_aa_vlan *node;
- LIST_FOR_EACH_SAFE (node,
- node_next,
- list_node,
- &lldp->active_mapping_queue) {
+ LIST_FOR_EACH_POP (node, list_node, &lldp->active_mapping_queue) {
struct bridge_aa_vlan *copy;
copy = xmalloc(sizeof *copy);
list_push_back(list, ©->list_node);
/* Cleanup */
- list_remove(&node->list_node);
free(node->port_name);
free(node);
}
void
ovs_numa_dump_destroy(struct ovs_numa_dump *dump)
{
- struct ovs_numa_info *iter, *next;
+ struct ovs_numa_info *iter;
- LIST_FOR_EACH_SAFE (iter, next, list_node, &dump->dump) {
- list_remove(&iter->list_node);
+ LIST_FOR_EACH_POP (iter, list_node, &dump->dump) {
free(iter);
}
static bool
ovsrcu_call_postponed(void)
{
- struct ovsrcu_cbset *cbset, *next_cbset;
+ struct ovsrcu_cbset *cbset;
struct ovs_list cbsets;
guarded_list_pop_all(&flushed_cbsets, &cbsets);
ovsrcu_synchronize();
- LIST_FOR_EACH_SAFE (cbset, next_cbset, list_node, &cbsets) {
+ LIST_FOR_EACH_POP (cbset, list_node, &cbsets) {
struct ovsrcu_cb *cb;
for (cb = cbset->cbs; cb < &cbset->cbs[cbset->n_cbs]; cb++) {
cb->function(cb->aux);
}
- list_remove(&cbset->list_node);
free(cbset);
}
vconn_transact_multiple_noreply(struct vconn *vconn, struct ovs_list *requests,
struct ofpbuf **replyp)
{
- struct ofpbuf *request, *next;
+ struct ofpbuf *request;
- LIST_FOR_EACH_SAFE (request, next, list_node, requests) {
+ LIST_FOR_EACH_POP (request, list_node, requests) {
int error;
- list_remove(&request->list_node);
-
error = vconn_transact_noreply(vconn, request, replyp);
if (error || *replyp) {
ofpbuf_list_delete(requests);
static void
ofp_bundle_remove(struct ofconn *ofconn, struct ofp_bundle *item)
{
- struct bundle_message *msg, *next;
+ struct bundle_message *msg;
struct hmap *bundles;
- LIST_FOR_EACH_SAFE (msg, next, node, &item->msg_list) {
- list_remove(&msg->node);
+ LIST_FOR_EACH_POP (msg, node, &item->msg_list) {
free(msg->msg);
free(msg);
}
void
ofconn_send_replies(const struct ofconn *ofconn, struct ovs_list *replies)
{
- struct ofpbuf *reply, *next;
+ struct ofpbuf *reply;
- LIST_FOR_EACH_SAFE (reply, next, list_node, replies) {
- list_remove(&reply->list_node);
+ LIST_FOR_EACH_POP (reply, list_node, replies) {
ofconn_send_reply(ofconn, reply);
}
}
static void
do_send_packet_ins(struct ofconn *ofconn, struct ovs_list *txq)
{
- struct ofpbuf *pin, *next_pin;
-
- LIST_FOR_EACH_SAFE (pin, next_pin, list_node, txq) {
- list_remove(&pin->list_node);
+ struct ofpbuf *pin;
+ LIST_FOR_EACH_POP (pin, list_node, txq) {
if (rconn_send_with_limit(ofconn->rconn, pin,
ofconn->packet_in_counter, 100) == EAGAIN) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
struct ofconn *ofconn;
LIST_FOR_EACH (ofconn, node, &mgr->all_conns) {
- struct ofpbuf *msg, *next;
+ struct ofpbuf *msg;
- LIST_FOR_EACH_SAFE (msg, next, list_node, &ofconn->updates) {
+ LIST_FOR_EACH_POP (msg, list_node, &ofconn->updates) {
unsigned int n_bytes;
- list_remove(&msg->list_node);
ofconn_send(ofconn, msg, ofconn->monitor_counter);
n_bytes = rconn_packet_counter_n_bytes(ofconn->monitor_counter);
if (!ofconn->monitor_paused && n_bytes > 128 * 1024) {
/* Do maintenance at most 4 times / sec. */
ovs_mutex_lock(&mutex);
if (now - last > 250) {
- struct recirc_id_node *node, *next;
+ struct recirc_id_node *node;
last = now;
/* Delete the expired. These have been lingering for at least 250 ms,
* which should be enough for any ongoing recirculations to be
* finished. */
- LIST_FOR_EACH_SAFE (node, next, exp_node, &expired) {
- list_remove(&node->exp_node);
+ LIST_FOR_EACH_POP (node, exp_node, &expired) {
cmap_remove(&id_map, &node->id_node, node->id);
ovsrcu_postpone(free, node);
}
static void
xlate_xbundle_remove(struct xlate_cfg *xcfg, struct xbundle *xbundle)
{
- struct xport *xport, *next;
+ struct xport *xport;
if (!xbundle) {
return;
}
- LIST_FOR_EACH_SAFE (xport, next, bundle_node, &xbundle->xports) {
- list_remove(&xport->bundle_node);
+ LIST_FOR_EACH_POP (xport, bundle_node, &xbundle->xports) {
xport->xbundle = NULL;
}
struct dpif_port port;
struct shash_node *node;
struct ovs_list garbage_list;
- struct odp_garbage *garbage, *next;
+ struct odp_garbage *garbage;
struct sset names;
char *backer_name;
}
dpif_port_dump_done(&port_dump);
- LIST_FOR_EACH_SAFE (garbage, next, list_node, &garbage_list) {
+ LIST_FOR_EACH_POP (garbage, list_node, &garbage_list) {
dpif_port_del(backer->dpif, garbage->odp_port);
- list_remove(&garbage->list_node);
free(garbage);
}
destruct(struct ofproto *ofproto_)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
- struct ofproto_packet_in *pin, *next_pin;
+ struct ofproto_packet_in *pin;
struct rule_dpif *rule;
struct oftable *table;
struct ovs_list pins;
}
guarded_list_pop_all(&ofproto->pins, &pins);
- LIST_FOR_EACH_SAFE (pin, next_pin, list_node, &pins) {
- list_remove(&pin->list_node);
+ LIST_FOR_EACH_POP (pin, list_node, &pins) {
free(CONST_CAST(void *, pin->up.packet));
free(pin);
}
/* Do not perform any periodic activity required by 'ofproto' while
* waiting for flow restore to complete. */
if (!ofproto_get_flow_restore_wait()) {
- struct ofproto_packet_in *pin, *next_pin;
+ struct ofproto_packet_in *pin;
struct ovs_list pins;
guarded_list_pop_all(&ofproto->pins, &pins);
- LIST_FOR_EACH_SAFE (pin, next_pin, list_node, &pins) {
+ LIST_FOR_EACH_POP (pin, list_node, &pins) {
connmgr_send_packet_in(ofproto->up.connmgr, pin);
- list_remove(&pin->list_node);
free(CONST_CAST(void *, pin->up.packet));
free(pin);
}
learned_cookies_flush(struct ofproto *ofproto, struct ovs_list *dead_cookies)
OVS_REQUIRES(ofproto_mutex)
{
- struct learned_cookie *c, *next;
+ struct learned_cookie *c;
- LIST_FOR_EACH_SAFE (c, next, u.list_node, dead_cookies) {
+ LIST_FOR_EACH_POP (c, u.list_node, dead_cookies) {
struct rule_criteria criteria;
struct rule_collection rules;
struct match match;
rule_criteria_destroy(&criteria);
rule_collection_destroy(&rules);
- list_remove(&c->u.list_node);
free(c);
}
}
AT_CLEANUP
AT_SETUP([test linked lists])
-AT_CHECK([ovstest test-list], [0], [..
+AT_CHECK([ovstest test-list], [0], [...
])
AT_CLEANUP
}
}
+/* Tests that LIST_FOR_EACH_POP removes the elements of a list. */
+static void
+test_list_for_each_pop(void)
+{
+ enum { MAX_ELEMS = 10 };
+ size_t n;
+
+ for (n = 0; n <= MAX_ELEMS; n++) {
+ struct element elements[MAX_ELEMS];
+ int values[MAX_ELEMS];
+ struct ovs_list list;
+ struct element *e;
+ size_t n_remaining;
+
+ make_list(&list, elements, values, n);
+
+ n_remaining = n;
+ LIST_FOR_EACH_POP (e, node, &list) {
+ n_remaining--;
+ memmove(values, values + 1, sizeof *values * n_remaining);
+ check_list(&list, values, n_remaining);
+ }
+ }
+}
+
static void
run_test(void (*function)(void))
{
{
run_test(test_list_construction);
run_test(test_list_for_each_safe);
+ run_test(test_list_for_each_pop);
printf("\n");
}