This further eases porting existing hmap code to use cmap instead.
The iterator variants taking an explicit cursor are retained (renamed)
as they are needed when iteration is to be continued from the last
iterated node.
Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
* executing at postponed time, when it is known that the RCU grace period
* has already expired.
*/
-#define CMAP_FOR_EACH(NODE, MEMBER, CURSOR, CMAP) \
+
+#define CMAP_CURSOR_FOR_EACH(NODE, MEMBER, CURSOR, CMAP) \
for ((cmap_cursor_init(CURSOR, CMAP), \
ASSIGN_CONTAINER(NODE, cmap_cursor_next(CURSOR, NULL), MEMBER)); \
NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER); \
ASSIGN_CONTAINER(NODE, cmap_cursor_next(CURSOR, &(NODE)->MEMBER), \
MEMBER))
-#define CMAP_FOR_EACH_SAFE(NODE, NEXT, MEMBER, CURSOR, CMAP) \
+#define CMAP_CURSOR_FOR_EACH_SAFE(NODE, NEXT, MEMBER, CURSOR, CMAP) \
for ((cmap_cursor_init(CURSOR, CMAP), \
ASSIGN_CONTAINER(NODE, cmap_cursor_next(CURSOR, NULL), MEMBER)); \
(NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER) \
? ASSIGN_CONTAINER(NEXT, cmap_cursor_next(CURSOR, &(NODE)->MEMBER), \
- MEMBER), 1 \
- : 0); \
+ MEMBER), true \
+ : false); \
(NODE) = (NEXT))
-#define CMAP_FOR_EACH_CONTINUE(NODE, MEMBER, CURSOR, CMAP) \
+#define CMAP_CURSOR_FOR_EACH_CONTINUE(NODE, MEMBER, CURSOR) \
for (ASSIGN_CONTAINER(NODE, cmap_cursor_next(CURSOR, &(NODE)->MEMBER), \
MEMBER); \
NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER); \
struct cmap_node *cmap_cursor_next(struct cmap_cursor *,
const struct cmap_node *);
+
+static inline struct cmap_cursor cmap_cursor_start(const struct cmap *cmap,
+ void **pnode,
+ const void *offset)
+{
+ struct cmap_cursor cursor;
+
+ cmap_cursor_init(&cursor, cmap);
+ *pnode = (char *)cmap_cursor_next(&cursor, NULL) + (ptrdiff_t)offset;
+
+ return cursor;
+}
+
+#define CMAP_CURSOR_START(NODE, MEMBER, CMAP) \
+ cmap_cursor_start(CMAP, (void **)&(NODE), \
+ OBJECT_CONTAINING(NULL, NODE, MEMBER))
+
+#define CMAP_FOR_EACH(NODE, MEMBER, CMAP) \
+ for (struct cmap_cursor cursor__ = CMAP_CURSOR_START(NODE, MEMBER, CMAP); \
+ NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER); \
+ ASSIGN_CONTAINER(NODE, cmap_cursor_next(&cursor__, &(NODE)->MEMBER), \
+ MEMBER))
+
+#define CMAP_FOR_EACH_SAFE(NODE, NEXT, MEMBER, CMAP) \
+ for (struct cmap_cursor cursor__ = CMAP_CURSOR_START(NODE, MEMBER, CMAP); \
+ (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER) \
+ ? ASSIGN_CONTAINER(NEXT, \
+ cmap_cursor_next(&cursor__, &(NODE)->MEMBER), \
+ MEMBER), true \
+ : false); \
+ (NODE) = (NEXT))
+
static inline struct cmap_node *cmap_first(const struct cmap *);
/* Another, less preferred, form of iteration, for use in situations where it
{
struct dp_netdev_port *port;
struct dp_netdev_stats *bucket;
- struct cmap_cursor cursor;
int i;
shash_find_and_delete(&dp_netdevs, dp->name);
dp_netdev_flow_flush(dp);
ovs_mutex_lock(&dp->port_mutex);
- CMAP_FOR_EACH (port, node, &cursor, &dp->ports) {
+ CMAP_FOR_EACH (port, node, &dp->ports) {
do_del_port(dp, port);
}
ovs_mutex_unlock(&dp->port_mutex);
OVS_REQUIRES(dp->port_mutex)
{
struct dp_netdev_port *port;
- struct cmap_cursor cursor;
- CMAP_FOR_EACH (port, node, &cursor, &dp->ports) {
+ CMAP_FOR_EACH (port, node, &dp->ports) {
if (!strcmp(netdev_get_name(port->netdev), devname)) {
*portp = port;
return 0;
{
struct dp_netdev_port *port;
struct dp_netdev *dp = get_dp_netdev(dpif);
- struct cmap_cursor cursor;
- CMAP_FOR_EACH (port, node, &cursor, &dp->ports) {
+ CMAP_FOR_EACH (port, node, &dp->ports) {
if (!netdev_is_pmd(port->netdev)) {
int i;
{
struct dp_netdev_port *port;
struct dp_netdev *dp = get_dp_netdev(dpif);
- struct cmap_cursor cursor;
ovs_mutex_lock(&dp_netdev_mutex);
- CMAP_FOR_EACH (port, node, &cursor, &dp->ports) {
+ CMAP_FOR_EACH (port, node, &dp->ports) {
if (!netdev_is_pmd(port->netdev)) {
int i;
struct dp_netdev *dp = f->dp;
struct rxq_poll *poll_list = *ppoll_list;
struct dp_netdev_port *port;
- struct cmap_cursor cursor;
int id = f->id;
int index;
int i;
poll_cnt = 0;
index = 0;
- CMAP_FOR_EACH (port, node, &cursor, &f->dp->ports) {
+ CMAP_FOR_EACH (port, node, &f->dp->ports) {
if (netdev_is_pmd(port->netdev)) {
int i;
hash_func *hash)
{
int *sort_values, *cmap_values;
- struct cmap_cursor cursor;
- struct element *e;
+ const struct element *e;
size_t i;
/* Check that all the values are there in iteration. */
cmap_values = xmalloc(sizeof *sort_values * n);
i = 0;
- CMAP_FOR_EACH (e, node, &cursor, cmap) {
+ CMAP_FOR_EACH (e, node, cmap) {
assert(i < n);
cmap_values[i++] = e->value;
}
struct element *e;
printf("%s:", name);
- CMAP_FOR_EACH (e, node, &cursor, cmap) {
+ CMAP_CURSOR_FOR_EACH (e, node, &cursor, cmap) {
printf(" %d", e->value);
}
printf("\n");
struct element *elements;
struct cmap cmap;
struct element *e;
- struct cmap_cursor cursor;
struct timeval start;
pthread_t *threads;
struct cmap_aux aux;
/* Iteration. */
xgettimeofday(&start);
- CMAP_FOR_EACH (e, node, &cursor, &cmap) {
+ CMAP_FOR_EACH (e, node, &cmap) {
ignore(e);
}
printf("cmap iterate: %5d ms\n", elapsed(&start));
/* Destruction. */
xgettimeofday(&start);
- CMAP_FOR_EACH (e, node, &cursor, &cmap) {
+ CMAP_FOR_EACH (e, node, &cmap) {
cmap_remove(&cmap, &e->node, hash_int(e->value, 0));
}
cmap_destroy(&cmap);