Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

rewrite double linked list and hash table functions #111

Closed
wants to merge 1 commit into from

1 participant

@iHiroakiKawai

Double linked list now uses a sentinel as a handler.
If prev or next hits the sentinel, then those are the ends.
The reason of using sentinel is that sentinel has a mutex
internally, and could not be NULL.
One more merit of using sentinel is performance improvement
in scanning the elements from the last to first.

Hash table data structure became simple.

Memory usage was reduced.

@iHiroakiKawai iHiroakiKawai rewrite double linked list and hash table functions
Double linked list now uses a sentinel as a handler.
If prev or next hits the sentinel, then those are the ends.
The reason of using sentinel is that sentinel has a mutex
internally, and could not be NULL.
One more merit of using sentinel is performance improvement
in scanning the elements from the last to first.

Hash table data structure became simple.

Memory usage was reduced.
78c7876
@iHiroakiKawai

I'll drop this request, because there're many things before rewriting this specific class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 7, 2014
  1. @iHiroakiKawai

    rewrite double linked list and hash table functions

    iHiroakiKawai authored
    Double linked list now uses a sentinel as a handler.
    If prev or next hits the sentinel, then those are the ends.
    The reason of using sentinel is that sentinel has a mutex
    internally, and could not be NULL.
    One more merit of using sentinel is performance improvement
    in scanning the elements from the last to first.
    
    Hash table data structure became simple.
    
    Memory usage was reduced.
This page is out of date. Refresh to see the latest.
View
2  src/lib/buffer.c
@@ -133,7 +133,7 @@ buffer *
alloc_buffer_with_length( size_t length ) {
assert( length != 0 );
- private_buffer *new_buf = xcalloc( 1, sizeof( private_buffer ) );
+ private_buffer *new_buf = xmalloc( sizeof( private_buffer ) );
new_buf->public.data = xmalloc( length );
new_buf->public.length = 0;
new_buf->public.user_data = NULL;
View
161 src/lib/doubly_linked_list.c
@@ -24,41 +24,31 @@
#include "wrapper.h"
-typedef struct private_dlist_element {
+typedef struct dlist_element_sentinel {
dlist_element public;
pthread_mutex_t *mutex;
-} private_dlist_element;
-
-
-static dlist_element *
-create_dlist_with_mutex( pthread_mutex_t *mutex ) {
- private_dlist_element *element = xmalloc( sizeof( private_dlist_element ) );
-
- element->public.data = NULL;
- element->public.prev = NULL;
- element->public.next = NULL;
- element->mutex = mutex;
-
- return ( dlist_element * ) element;
-}
+} dlist_element_sentinel;
/**
* Allocates space for one dlist_element.
*
- * @return a pointer to the newly-allocated dlist_element.
+ * @return a pointer to the newly-allocated dlist_element, as a sentinel.
*/
dlist_element *
create_dlist() {
- private_dlist_element *element = ( private_dlist_element * ) create_dlist_with_mutex( NULL );
+ dlist_element_sentinel *sentinel = ( dlist_element_sentinel * ) xmalloc( sizeof( dlist_element_sentinel ) );
+ sentinel->public.data = NULL;
+ sentinel->public.prev = ( dlist_element * ) sentinel;
+ sentinel->public.next = ( dlist_element * ) sentinel;
pthread_mutexattr_t attr;
pthread_mutexattr_init( &attr );
pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE_NP );
- element->mutex = xmalloc( sizeof( pthread_mutex_t ) );
- pthread_mutex_init( element->mutex, &attr );
+ sentinel->mutex = xmalloc( sizeof( pthread_mutex_t ) );
+ pthread_mutex_init( sentinel->mutex, &attr );
- return ( dlist_element * ) element;
+ return ( dlist_element * ) sentinel;
}
@@ -70,15 +60,16 @@ create_dlist() {
* @return a pointer to newly inserted element.
*/
dlist_element *
-insert_before_dlist( dlist_element *element, void *data ) {
- if ( element == NULL ) {
- die( "element must not be NULL" );
+insert_before_dlist( dlist_element *sentinel, dlist_element *element, void *data ) {
+ if ( sentinel == NULL ) {
+ die( "sentinel element must not be NULL" );
}
+ assert( data != NULL ); // only sentinel can have NULL data
- pthread_mutex_lock( ( ( private_dlist_element * ) element )->mutex );
- pthread_mutex_t *mutex = ( ( private_dlist_element * ) element )->mutex;
+ pthread_mutex_t *mutex = ( ( dlist_element_sentinel * ) sentinel )->mutex;
+ pthread_mutex_lock( mutex );
- dlist_element *new_prev = create_dlist_with_mutex( mutex );
+ dlist_element *new_prev = ( dlist_element * ) xmalloc( sizeof( dlist_element ) );
if ( element->prev ) {
dlist_element *old_prev = element->prev;
@@ -104,15 +95,16 @@ insert_before_dlist( dlist_element *element, void *data ) {
* @return a pointer to newly inserted element.
*/
dlist_element *
-insert_after_dlist( dlist_element *element, void *data ) {
- if ( element == NULL ) {
- die( "element must not be NULL" );
+insert_after_dlist( dlist_element *sentinel, dlist_element *element, void *data ) {
+ if ( sentinel == NULL ) {
+ die( "sentinel element must not be NULL" );
}
+ assert( data != NULL ); // only sentinel can have NULL data
- pthread_mutex_lock( ( ( private_dlist_element * ) element )->mutex );
- pthread_mutex_t *mutex = ( ( private_dlist_element * ) element )->mutex;
+ pthread_mutex_t *mutex = ( ( dlist_element_sentinel * ) sentinel )->mutex;
+ pthread_mutex_lock( mutex );
- dlist_element *new_next = create_dlist_with_mutex( mutex );
+ dlist_element *new_next = ( dlist_element * ) xmalloc( sizeof( dlist_element ) );
if ( element->next ) {
dlist_element *old_next = element->next;
@@ -137,20 +129,11 @@ insert_after_dlist( dlist_element *element, void *data ) {
* @return the first element in the list.
*/
dlist_element *
-get_first_element( dlist_element *element ) {
- if ( element == NULL ) {
- die( "element must not be NULL" );
+get_first_element( dlist_element *sentinel ) {
+ if ( sentinel == NULL ) {
+ die( "sentinel element must not be NULL" );
}
-
- pthread_mutex_lock( ( ( private_dlist_element * ) element )->mutex );
-
- while ( element->prev != NULL ) {
- element = element->prev;
- }
-
- pthread_mutex_unlock( ( ( private_dlist_element * ) element )->mutex );
-
- return element;
+ return sentinel->next;
}
@@ -161,20 +144,11 @@ get_first_element( dlist_element *element ) {
* @return the last element in the list.
*/
dlist_element *
-get_last_element( dlist_element *element ) {
- if ( element == NULL ) {
- die( "element must not be NULL" );
- }
-
- pthread_mutex_lock( ( ( private_dlist_element * ) element )->mutex );
-
- while ( element->next != NULL ) {
- element = element->next;
+get_last_element( dlist_element *sentinel ) {
+ if ( sentinel == NULL ) {
+ die( "sentinel element must not be NULL" );
}
-
- pthread_mutex_unlock( ( ( private_dlist_element * ) element )->mutex );
-
- return element;
+ return sentinel->prev;
}
@@ -186,33 +160,34 @@ get_last_element( dlist_element *element ) {
* @return the found list element, or NULL if it is not found.
*/
dlist_element *
-find_element( dlist_element *element, const void *data ) {
- if ( element == NULL ) {
- die( "element must not be NULL" );
+find_element( dlist_element *sentinel, const void *data ) {
+ if ( sentinel == NULL ) {
+ die( "sentinel element must not be NULL" );
}
- pthread_mutex_lock( ( ( private_dlist_element * ) element )->mutex );
+ pthread_mutex_lock( ( ( dlist_element_sentinel * ) sentinel )->mutex );
dlist_element *e = NULL;
- for ( e = element; e; e = e->next ) {
- if ( e->data == data ) {
- pthread_mutex_unlock( ( ( private_dlist_element * ) element )->mutex );
- return e;
- }
- }
- for ( e = element->prev; e; e = e->prev ) {
+ for ( e = sentinel->next; e != sentinel; e = e->next ) {
if ( e->data == data ) {
- pthread_mutex_unlock( ( ( private_dlist_element * ) element )->mutex );
+ pthread_mutex_unlock( ( ( dlist_element_sentinel * ) sentinel )->mutex );
return e;
}
}
- pthread_mutex_unlock( ( ( private_dlist_element * ) element )->mutex );
+ pthread_mutex_unlock( ( ( dlist_element_sentinel * ) sentinel )->mutex );
return NULL;
}
+static void
+_delete_dlist_element( dlist_element *element ) {
+ element->prev->next = element->next;
+ element->next->prev = element->prev;
+ xfree( element );
+}
+
/**
* Removes an element from a list. If two elements contain the same
* data, only the first is removed. If none of the elements contain
@@ -222,21 +197,15 @@ find_element( dlist_element *element, const void *data ) {
* @return true on success; false otherwise.
*/
bool
-delete_dlist_element( dlist_element *element ) {
- if ( element == NULL ) {
+delete_dlist_element( dlist_element *sentinel, dlist_element *element ) {
+ if ( sentinel == NULL || element == NULL ) {
die( "element must not be NULL" );
}
- pthread_mutex_lock( ( ( private_dlist_element * ) element )->mutex );
- pthread_mutex_t *mutex = ( ( private_dlist_element * ) element )->mutex;
+ pthread_mutex_t *mutex = ( ( dlist_element_sentinel * ) sentinel )->mutex;
+ pthread_mutex_lock( mutex );
- if ( element->prev != NULL ) {
- element->prev->next = element->next;
- }
- if ( element->next != NULL ) {
- element->next->prev = element->prev;
- }
- xfree( ( private_dlist_element * ) element );
+ _delete_dlist_element( element );
pthread_mutex_unlock( mutex );
@@ -251,28 +220,24 @@ delete_dlist_element( dlist_element *element ) {
* @return true on success; false otherwise.
*/
bool
-delete_dlist( dlist_element *element ) {
- if ( element == NULL ) {
- die( "element must not be NULL" );
+delete_dlist( dlist_element *sentinel ) {
+ if ( sentinel == NULL ) {
+ die( "sentinel element must not be NULL" );
}
- pthread_mutex_lock( ( ( private_dlist_element * ) element )->mutex );
- pthread_mutex_t *mutex = ( ( private_dlist_element * ) element )->mutex;
-
- dlist_element *e = NULL;
-
- while ( element->prev != NULL ) {
- element = element->prev;
- }
+ pthread_mutex_t *mutex = ( ( dlist_element_sentinel * ) sentinel )->mutex;
+ pthread_mutex_lock( mutex );
- for ( e = element; e != NULL; ) {
- dlist_element *delete_me = e;
- e = e->next;
- xfree( ( private_dlist_element * ) delete_me );
+ dlist_element *e_next;
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e_next ) {
+ e_next = e->next;
+ _delete_dlist_element( e );
}
+ xfree( sentinel );
pthread_mutex_unlock( mutex );
- xfree( mutex );
+ pthread_mutex_destroy( mutex );
+ xfree(mutex);
return true;
}
View
25 src/lib/doubly_linked_list.h
@@ -32,19 +32,20 @@
*
* @code
* // Create a doubly linked list ("alpha" <=> "bravo" <=> "charlie")
- * dlist_element *alpha = create_dlist();
+ * dlist_element *sentinel = create_dlist();
+ * dlist_element *alpha = insert_after_dlist( sentinel, "alpha" );
* dlist_element *bravo = insert_after_dlist( alpha, "bravo" );
* dlist_element *charlie = insert_after_dlist( bravo, "charlie" );
*
* // Find element "charlie" from the list
- * find_element( alpha, "charlie" ); // => charlie
- * find_element( alpha, "delta" ); // => NULL
+ * find_element( sentinel, "charlie" ); // => charlie
+ * find_element( sentinel, "delta" ); // => NULL
*
* // Delete element "bravo" from the list
- * delete_dlist_element( bravo ); // => true
+ * delete_dlist_element( sentinel, bravo ); // => true
*
* // Delete entire list
- * delete_dlist( alpha );
+ * delete_dlist( sentinel );
* @endcode
*/
@@ -68,13 +69,13 @@ typedef struct dlist_element {
dlist_element *create_dlist( void );
-dlist_element *insert_before_dlist( dlist_element *element, void *data );
-dlist_element *insert_after_dlist( dlist_element *element, void *data );
-dlist_element *get_first_element( dlist_element *element );
-dlist_element *get_last_element( dlist_element *element );
-dlist_element *find_element( dlist_element *element, const void *data );
-bool delete_dlist_element( dlist_element *element );
-bool delete_dlist( dlist_element *element );
+dlist_element *insert_before_dlist( dlist_element *sentinel, dlist_element *element, void *data );
+dlist_element *insert_after_dlist( dlist_element *sentinel, dlist_element *element, void *data );
+dlist_element *get_first_element( dlist_element *sentinel );
+dlist_element *get_last_element( dlist_element *sentinel );
+dlist_element *find_element( dlist_element *sentinel, const void *data );
+bool delete_dlist_element( dlist_element *sentinel, dlist_element *element );
+bool delete_dlist( dlist_element *sentinel );
#endif // DOUBLY_LINKED_LIST_H
View
127 src/lib/hash_table.c
@@ -102,9 +102,8 @@ create_hash_with_size( const compare_function compare, const hash_function hash,
table->public.compare = compare ? compare : compare_atom;
table->public.hash = hash ? hash : hash_atom;
table->public.length = 0;
- table->public.buckets = xmalloc( sizeof( dlist_element * ) * table->public.number_of_buckets );
- memset( table->public.buckets, 0, sizeof( dlist_element * ) * table->public.number_of_buckets );
- table->public.nonempty_bucket_index = create_dlist();
+ table->public.buckets = xmalloc( sizeof( dlist_element * ) * size );
+ memset( table->public.buckets, 0, sizeof( dlist_element * ) * size );
pthread_mutexattr_t attr;
pthread_mutexattr_init( &attr );
@@ -128,7 +127,6 @@ get_bucket_index( const hash_table *table, const void *key ) {
static void
new_bucket( hash_table *table, unsigned int bucket_index ) {
table->buckets[ bucket_index ] = create_dlist();
- table->buckets[ bucket_index ]->data = insert_after_dlist( table->nonempty_bucket_index, ( void * ) ( unsigned long ) bucket_index );
}
@@ -157,9 +155,10 @@ insert_hash_entry( hash_table *table, void *key, void *value ) {
unsigned int i = get_bucket_index( table, key );
if ( table->buckets[ i ] != NULL ) {
- dlist_element *old_element = NULL;
- for ( old_element = table->buckets[ i ]->next; old_element; old_element = old_element->next ) {
- if ( ( *table->compare )( key, ( ( hash_entry * ) old_element->data )->key ) ) {
+ dlist_element *sentinel = table->buckets[ i ], *old_element = NULL;
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
+ if ( ( *table->compare )( key, ( ( hash_entry * ) e->data )->key ) == true ) {
+ old_element = e;
break;
}
}
@@ -176,7 +175,7 @@ insert_hash_entry( hash_table *table, void *key, void *value ) {
hash_entry *new_entry = xmalloc( sizeof( hash_entry ) );
new_entry->key = key;
new_entry->value = value;
- insert_after_dlist( table->buckets[ i ], new_entry );
+ insert_after_dlist( table->buckets[ i ], table->buckets[ i ], new_entry );
table->length++;
MUTEX_UNLOCK( table );
@@ -202,7 +201,8 @@ lookup_hash_entry( hash_table *table, const void *key ) {
void *value = NULL;
unsigned int i = get_bucket_index( table, key );
if ( table->buckets[ i ] != NULL ) {
- for ( dlist_element *e = table->buckets[ i ]->next; e; e = e->next ) {
+ dlist_element *sentinel = table->buckets[ i ];
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
if ( ( *table->compare )( key, ( ( hash_entry * ) e->data )->key ) ) {
value = ( ( hash_entry * ) e->data )->value;
break;
@@ -218,11 +218,15 @@ lookup_hash_entry( hash_table *table, const void *key ) {
static void
delete_bucket( hash_table *table, unsigned int bucket_index ) {
- if ( table->buckets[ bucket_index ]->data != NULL ) {
- delete_dlist_element( table->buckets[ bucket_index ]->data );
- table->buckets[ bucket_index ]->data = NULL;
- }
+ assert( table != NULL );
+ assert( bucket_index < table->number_of_buckets );
+ assert( table->buckets[ bucket_index ] != NULL );
+ dlist_element *sentinel = table->buckets[ bucket_index ];
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
+ xfree( e->data ); // hash_entry, note key and value won't be freed.
+ table->length--;
+ }
delete_dlist( table->buckets[ bucket_index ] );
table->buckets[ bucket_index ] = NULL;
}
@@ -250,19 +254,19 @@ delete_hash_entry( hash_table *table, const void *key ) {
}
void *deleted = NULL;
- dlist_element *e = NULL;
- for ( e = table->buckets[ i ]->next; e; e = e->next ) {
+ dlist_element *sentinel = table->buckets[ i ];
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
if ( ( *table->compare )( key, ( ( hash_entry * ) e->data )->key ) ) {
hash_entry *delete_me = e->data;
deleted = delete_me->value;
- delete_dlist_element( e );
+ delete_dlist_element( sentinel, e );
xfree( delete_me );
table->length--;
break;
}
}
- if ( table->buckets[ i ]->next == NULL ) {
+ if ( sentinel->next == sentinel ) {
delete_bucket( table, i );
}
@@ -284,20 +288,18 @@ delete_hash_entry( hash_table *table, const void *key ) {
void
foreach_hash( hash_table *table, void function( void *key, void *value, void *user_data ), void *user_data ) {
assert( table != NULL );
+ assert( function != NULL );
MUTEX_LOCK( table );
- for ( dlist_element *nonempty = table->nonempty_bucket_index->next; nonempty; ) {
- int i = ( int ) ( unsigned long ) nonempty->data;
- nonempty = nonempty->next;
-
+ for ( unsigned int i = 0; i < table->number_of_buckets; i++ ) {
if ( table->buckets[ i ] == NULL ) {
continue;
}
- for ( dlist_element *e = table->buckets[ i ]->next; e != NULL; ) {
+ dlist_element *sentinel = table->buckets[ i ];
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
hash_entry *h = e->data;
- e = e->next;
function( h->key, h->value, user_data );
}
}
@@ -319,16 +321,26 @@ init_hash_iterator( hash_table *table, hash_iterator *iterator ) {
assert( table != NULL );
assert( iterator != NULL );
- iterator->buckets = table->buckets;
- if ( table->nonempty_bucket_index->next ) {
- iterator->bucket_index = table->nonempty_bucket_index->next;
- iterator->next_bucket_index = iterator->bucket_index->next;
- assert( iterator->buckets[ ( int ) ( unsigned long ) iterator->bucket_index->data ] != NULL );
- iterator->element = iterator->buckets[ ( int ) ( unsigned long ) iterator->bucket_index->data ]->next;
+ iterator->pos = 0;
+ iterator->length = 0;
+ for ( unsigned int i = 0; i < table->number_of_buckets; i++ ) {
+ if ( table->buckets[ i ] != NULL ) {
+ dlist_element *sentinel = table->buckets[ i ];
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
+ iterator->length++;
+ }
+ }
}
- else {
- iterator->bucket_index = NULL;
- iterator->element = NULL;
+ iterator->hash_entries = ( void ** ) xmalloc( sizeof( hash_entry * ) * iterator->length );
+ unsigned int pos = 0;
+ for ( unsigned int i = 0; i < table->number_of_buckets; i++ ) {
+ if ( table->buckets[ i ] != NULL ) {
+ dlist_element *sentinel = table->buckets[ i ];
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
+ iterator->hash_entries[ pos ] = e->data;
+ pos++;
+ }
+ }
}
}
@@ -345,29 +357,12 @@ hash_entry *
iterate_hash_next( hash_iterator *iterator ) {
assert( iterator != NULL );
- for ( ;; ) {
- if ( iterator->bucket_index == NULL ) {
- return NULL;
- }
-
- dlist_element *e = iterator->element;
- if ( e == NULL ) {
- if ( iterator->next_bucket_index != NULL ) {
- iterator->bucket_index = iterator->next_bucket_index;
- iterator->next_bucket_index = iterator->next_bucket_index->next;
- int bucket_index = ( int ) ( unsigned long ) iterator->bucket_index->data;
- assert( iterator->buckets[ bucket_index ] != NULL );
- iterator->element = iterator->buckets[ bucket_index ]->next;
- }
- else {
- return NULL;
- }
- }
- else {
- iterator->element = e->next;
- return e->data;
- }
+ if ( iterator->pos < iterator->length ) {
+ return ( hash_entry * ) iterator->hash_entries[ iterator->pos++ ];
}
+ iterator->pos = 0;
+ iterator->length = 0;
+ xfree(iterator->hash_entries);
return NULL;
}
@@ -381,32 +376,20 @@ void
delete_hash( hash_table *table ) {
assert( table != NULL );
- pthread_mutex_lock( ( ( private_hash_table * ) table )->mutex );
pthread_mutex_t *mutex = ( ( private_hash_table * ) table )->mutex;
+ pthread_mutex_lock( mutex );
- for ( dlist_element *nonempty = table->nonempty_bucket_index->next; nonempty; ) {
- unsigned int i = ( unsigned int ) ( unsigned long ) nonempty->data;
- nonempty = nonempty->next;
- if ( table->buckets[ i ] == NULL ) {
- continue;
+ for ( unsigned int i = 0; i < table->number_of_buckets; i++ ) {
+ if ( table->buckets[ i ] != NULL ) {
+ delete_bucket( table, i );
}
-
- for ( dlist_element *e = table->buckets[ i ]->next; e != NULL; ) {
- dlist_element *delete_me = e;
- e = e->next;
- xfree( delete_me->data );
- }
-
- delete_bucket( table, i );
}
xfree( table->buckets );
-
- delete_dlist( table->nonempty_bucket_index );
-
xfree( table );
pthread_mutex_unlock( mutex );
- xfree( mutex );
+ pthread_mutex_destroy( mutex );
+ xfree(mutex);
}
View
10 src/lib/hash_table.h
@@ -90,12 +90,11 @@ typedef struct {
* hash_table. It should only be accessed via the following functions.
*/
typedef struct {
+ dlist_element **buckets;
unsigned int number_of_buckets;
compare_function compare;
hash_function hash;
unsigned int length;
- dlist_element **buckets;
- dlist_element *nonempty_bucket_index;
} hash_table;
@@ -106,10 +105,9 @@ typedef struct {
* initialized with init_hash_iterator().
*/
typedef struct {
- dlist_element **buckets;
- dlist_element *bucket_index;
- dlist_element *next_bucket_index;
- dlist_element *element;
+ void **hash_entries;
+ unsigned int pos;
+ unsigned int length;
} hash_iterator;
View
40 src/lib/messenger.c
@@ -423,18 +423,21 @@ delete_receive_queue( void *service_name, void *_rq, void *user_data ) {
receive_queue *rq = _rq;
messenger_socket *client_socket;
- dlist_element *element;
+ dlist_element *sentinel;
receive_queue_callback *cb;
assert( rq != NULL );
- for ( element = rq->message_callbacks->next; element; element = element->next ) {
+
+ sentinel = rq->message_callbacks;
+ for ( dlist_element *element = sentinel->next; element != sentinel; element = element->next ) {
cb = element->data;
debug( "Deleting a callback ( function = %p, message_type = %#x ).", cb->function, cb->message_type );
xfree( cb );
}
delete_dlist( rq->message_callbacks );
- for ( element = rq->client_sockets->next; element; element = element->next ) {
+ sentinel = rq->client_sockets;
+ for ( dlist_element *element = sentinel->next; element != sentinel; element = element->next ) {
client_socket = element->data;
debug( "Closing a client socket ( fd = %d ).", client_socket->fd );
@@ -622,7 +625,7 @@ add_message_callback( const char *service_name, uint8_t message_type, void *call
receive_queue_callback *cb = xmalloc( sizeof( receive_queue_callback ) );
cb->message_type = message_type;
cb->function = callback;
- insert_after_dlist( rq->message_callbacks, cb );
+ insert_after_dlist( rq->message_callbacks, rq->message_callbacks, cb );
return true;
}
@@ -685,13 +688,13 @@ delete_message_callback( const char *service_name, uint8_t message_type, void (
receive_queue_callback *cb;
if ( NULL != rq ) {
- dlist_element *e;
- for ( e = rq->message_callbacks->next; e; e = e->next ) {
+ dlist_element *sentinel = rq->message_callbacks;
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
cb = e->data;
if ( ( cb->function == callback ) && ( cb->message_type == message_type ) ) {
debug( "Deleting a callback ( message_type = %#x, callback = %p ).", message_type, callback );
xfree( cb );
- delete_dlist_element( e );
+ delete_dlist_element( sentinel, e );
if ( rq->message_callbacks->next == NULL ) {
debug( "No more callback for message_type = %#x.", message_type );
delete_receive_queue( rq->service_name, rq, NULL );
@@ -758,8 +761,6 @@ _rename_message_received_callback( const char *old_service_name, const char *new
receive_queue *old_rq = lookup_hash_entry( receive_queues, old_service_name );
receive_queue *new_rq = lookup_hash_entry( receive_queues, new_service_name );
- dlist_element *element;
- receive_queue_callback *cb;
if ( old_rq == NULL ) {
error( "No receive queue for old service name ( %s ) found.", old_service_name );
@@ -770,8 +771,9 @@ _rename_message_received_callback( const char *old_service_name, const char *new
return false;
}
- for ( element = old_rq->message_callbacks->next; element; element = element->next ) {
- cb = element->data;
+ dlist_element *sentinel = old_rq->message_callbacks;
+ for ( dlist_element *element = sentinel->next; element != sentinel; element = element->next ) {
+ receive_queue_callback *cb = element->data;
add_message_callback( new_service_name, cb->message_type, cb->function );
}
@@ -1250,7 +1252,7 @@ add_recv_queue_client_fd( receive_queue *rq, int fd ) {
socket = xmalloc( sizeof( messenger_socket ) );
socket->fd = fd;
- insert_after_dlist( rq->client_sockets, socket );
+ insert_after_dlist( rq->client_sockets, rq->client_sockets, socket );
set_fd_handler( fd, on_recv, rq, NULL, NULL );
set_readable( fd, true );
@@ -1300,18 +1302,18 @@ del_recv_queue_client_fd( receive_queue *rq, int fd ) {
assert( fd >= 0 );
messenger_socket *socket;
- dlist_element *element;
debug( "Deleting a client fd from receive queue ( fd = %d, service_name = %s ).", fd, rq->service_name );
- for ( element = rq->client_sockets->next; element; element = element->next ) {
+ dlist_element *sentinel = rq->client_sockets;
+ for ( dlist_element *element = sentinel->next; element != sentinel; element = element->next ) {
socket = element->data;
if ( socket->fd == fd ) {
set_readable( fd, false );
delete_fd_handler( fd );
debug( "Deleting fd ( %d ).", fd );
- delete_dlist_element( element );
+ delete_dlist_element( sentinel, element );
xfree( socket );
return 1;
}
@@ -1401,14 +1403,12 @@ static void
call_message_callbacks( receive_queue *rq, const uint8_t message_type, const uint16_t tag, void *data, size_t len ) {
assert( rq != NULL );
- dlist_element *element;
- receive_queue_callback *cb;
-
debug( "Calling message callbacks ( service_name = %s, message_type = %#x, tag = %#x, data = %p, len = %u ).",
rq->service_name, message_type, tag, data, len );
- for ( element = rq->message_callbacks->next; element; element = element->next ) {
- cb = element->data;
+ dlist_element *sentinel = rq->message_callbacks;
+ for ( dlist_element *element = sentinel->next; element != sentinel; element = element->next ) {
+ receive_queue_callback *cb = element->data;
if ( cb->message_type != message_type ) {
continue;
}
View
35 src/lib/safe_timer.c
@@ -68,7 +68,8 @@ _finalize_timer() {
debug( "Deleting timer callbacks ( timer_callbacks = %p ).", timer->timer_callbacks );
if ( timer->timer_callbacks != NULL ) {
- for ( dlist_element *e = timer->timer_callbacks->next; e; e = e->next ) {
+ dlist_element *sentinel = timer->timer_callbacks;
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
xfree( e->data );
}
delete_dlist( timer->timer_callbacks );
@@ -120,17 +121,19 @@ on_timer( timer_callback_info *callback, struct timespec *now ) {
static void
insert_timer_callback( struct timer_info *timer, timer_callback_info *new_cb ) {
+ assert( timer != NULL );
assert( timer->timer_callbacks != NULL );
- dlist_element *element, *last = timer->timer_callbacks;
- for ( element = timer->timer_callbacks->next; element != NULL; element = element->next ) {
+
+ // note: new_cb is likely to be the last element
+ dlist_element *sentinel = timer->timer_callbacks;
+ for ( dlist_element *element = sentinel->prev; element != sentinel; element = element->prev ) {
timer_callback_info *cb = element->data;
- if ( TIMESPEC_LESS_THEN( &new_cb->expires_at, &cb->expires_at ) ) {
- insert_before_dlist( element, new_cb );
+ if ( TIMESPEC_LESS_THEN( &cb->expires_at, &new_cb->expires_at ) ) {
+ insert_after_dlist( sentinel, element, new_cb );
return;
}
- last = element;
}
- insert_after_dlist( last, new_cb );
+ insert_after_dlist( sentinel, sentinel, new_cb );
}
@@ -149,33 +152,32 @@ _execute_timer_events( int *next_timeout_usec ) {
assert( clock_gettime( CLOCK_MONOTONIC, &now ) == 0 );
assert( timer->timer_callbacks != NULL );
- timer_callback_info *callback = NULL;
- dlist_element *element_next = NULL;
- for ( dlist_element *element = timer->timer_callbacks->next; element; element = element_next ) {
+ dlist_element *element_next, *sentinel = timer->timer_callbacks;
+ for ( dlist_element *element = sentinel->next; element != sentinel; element = element_next ) {
element_next = element->next;
- callback = element->data;
+ timer_callback_info *callback = element->data;
if ( callback->function != NULL ) {
if ( TIMESPEC_LESS_THEN( &now, &callback->expires_at ) ) {
break;
}
on_timer( callback, &now );
}
- delete_dlist_element( element );
+ delete_dlist_element( sentinel, element );
if ( callback->function == NULL ) {
xfree( callback );
}
- else {
+ else { // callback interval is set
insert_timer_callback( timer, callback );
}
}
struct timespec max_timeout = { ( INT_MAX / 1000000 ), 0 };
struct timespec min_timeout = { 0, 0 };
- if ( timer->timer_callbacks->next == NULL ) {
+ if ( timer->timer_callbacks->next == timer->timer_callbacks ) {
TIMESPEC_TO_MICROSECONDS( &max_timeout, next_timeout_usec );
}
else {
- callback = timer->timer_callbacks->next->data;
+ timer_callback_info *callback = timer->timer_callbacks->next->data;
if ( TIMESPEC_LESS_THEN( &callback->expires_at, &now ) ) {
TIMESPEC_TO_MICROSECONDS( &min_timeout, next_timeout_usec );
}
@@ -277,7 +279,8 @@ _delete_timer_event( timer_callback callback, void *user_data ) {
return false;
}
- for ( dlist_element *e = timer->timer_callbacks->next; e; e = e->next ) {
+ dlist_element *sentinel = timer->timer_callbacks;
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
timer_callback_info *cb = e->data;
if ( cb->function == callback && cb->user_data == user_data ) {
debug( "Deleting a callback ( callback = %p, user_data = %p ).", callback, user_data );
View
28 src/lib/timer.c
@@ -60,6 +60,7 @@ typedef struct timer_callback_info {
} timer_callback_info;
+// XXX: thread-safety issue; This is the major difference with safe_timer.c
static dlist_element *timer_callbacks = NULL;
@@ -80,12 +81,11 @@ bool ( *init_timer )( void ) = _init_timer;
bool
_finalize_timer() {
- dlist_element *e;
-
debug( "Deleting timer callbacks ( timer_callbacks = %p ).", timer_callbacks );
if ( timer_callbacks != NULL ) {
- for ( e = timer_callbacks->next; e; e = e->next ) {
+ dlist_element *sentinel = timer_callbacks;
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
xfree( e->data );
}
delete_dlist( timer_callbacks );
@@ -172,16 +172,16 @@ on_timer( timer_callback_info *callback, struct timespec *now ) {
static void
insert_timer_callback( timer_callback_info *new_cb ) {
assert( timer_callbacks != NULL );
- dlist_element *element, *last = timer_callbacks;
- for ( element = timer_callbacks->next; element != NULL; element = element->next ) {
- timer_callback_info *cb = element->data;
- if ( TIMESPEC_LESS_THEN( &new_cb->expires_at, &cb->expires_at ) ) {
- insert_before_dlist( element, new_cb );
+
+ dlist_element *sentinel = timer_callbacks;
+ for ( dlist_element *e = sentinel->prev; e != sentinel; e = e->prev ) {
+ timer_callback_info *cb = e->data;
+ if ( TIMESPEC_LESS_THEN( &cb->expires_at, &new_cb->expires_at ) ) {
+ insert_after_dlist( timer_callbacks, e, new_cb );
return;
}
- last = element;
}
- insert_after_dlist( last, new_cb );
+ insert_after_dlist( timer_callbacks, timer_callbacks, new_cb );
}
@@ -190,14 +190,14 @@ _execute_timer_events( int *next_timeout_usec ) {
assert( next_timeout_usec != NULL );
struct timespec now;
timer_callback_info *callback;
- dlist_element *element, *element_next;
debug( "Executing timer events ( timer_callbacks = %p ).", timer_callbacks );
assert( clock_gettime( CLOCK_MONOTONIC, &now ) == 0 );
assert( timer_callbacks != NULL );
- for ( element = timer_callbacks->next; element; element = element_next ) {
+ dlist_element *element_next, *sentinel = timer_callbacks;
+ for ( dlist_element *element = sentinel->next; element != sentinel; element = element_next ) {
element_next = element->next;
callback = element->data;
if ( callback->function != NULL ) {
@@ -206,7 +206,7 @@ _execute_timer_events( int *next_timeout_usec ) {
}
on_timer( callback, &now );
}
- delete_dlist_element( element );
+ delete_dlist_element( sentinel, element );
if ( callback->function == NULL ) {
xfree( callback );
}
@@ -319,7 +319,7 @@ _delete_timer_event( timer_callback callback, void *user_data ) {
return false;
}
- for ( e = timer_callbacks->next; e; e = e->next ) {
+ for ( e = timer_callbacks->next; e != timer_callbacks; e = e->next ) {
timer_callback_info *cb = e->data;
if ( cb->function == callback && cb->user_data == user_data ) {
debug( "Deleting a callback ( callback = %p, user_data = %p ).", callback, user_data );
View
27 src/switch/datapath/action.c
@@ -223,12 +223,14 @@ void
delete_action_list( action_list *list ) {
assert( list != NULL );
- for ( dlist_element *element = get_first_element( list ); element != NULL; element = element->next ) {
+ dlist_element *sentinel = list;
+ for ( dlist_element *element = sentinel->next; element != sentinel; element = element->next ) {
action *action = element->data;
if ( action != NULL ) {
delete_action( action );
}
}
+
delete_dlist( list );
}
@@ -261,7 +263,7 @@ append_action( action_list *list, action *action ) {
return ERROR_OFDPE_BAD_ACTION_BAD_TYPE;
}
- list = insert_before_dlist( list, ( void * ) action );
+ list = insert_before_dlist( list, list, ( void * ) action );
if ( list == NULL ) {
return ERROR_APPEND_TO_LIST;
}
@@ -274,13 +276,13 @@ OFDPE
remove_action( action_list *list, action *action ) {
assert( list != NULL );
assert( action != NULL );
-
+
dlist_element *element = find_element( get_first_element( list ), action );
if ( element == NULL ) {
return ERROR_NOT_FOUND;
}
delete_action( action );
- delete_dlist_element( element );
+ delete_dlist_element( list, element );
return OFDPE_SUCCESS;
}
@@ -307,11 +309,12 @@ duplicate_action_list( action_list *list ) {
}
dlist_element *dst = create_action_list();
- for ( dlist_element *element = get_first_element( list ); element != NULL; element = element->next ) {
+ dlist_element *sentinel = list;
+ for ( dlist_element *element = sentinel->next; element != sentinel; element = element->next ) {
action *src_action = element->data;
if ( src_action != NULL ) {
action *dst_action = duplicate_action( src_action );
- insert_before_dlist( dst, dst_action );
+ insert_before_dlist( dst, dst, dst_action );
}
}
@@ -336,7 +339,8 @@ validate_action_set( action_list *list ) {
bool output = false;
bool ret = true;
- for ( dlist_element *element = get_first_element( list ); element != NULL; element = element->next ) {
+ dlist_element *sentinel = list;
+ for ( dlist_element *element = sentinel->next; element != sentinel; element = element->next ) {
action *action = element->data;
if ( action == NULL ) {
continue;
@@ -474,7 +478,8 @@ validate_action_list( action_list *list ) {
}
OFDPE ret = OFDPE_SUCCESS;
- for ( dlist_element *element = get_first_element( list ); element != NULL; element = element->next ) {
+ dlist_element *sentinel = list;
+ for ( dlist_element *element = sentinel->next; element != sentinel; element = element->next ) {
if ( element->data == NULL ) {
continue;
}
@@ -536,7 +541,8 @@ write_action_set( action_list *list, action_set *set ) {
assert( set != NULL );
OFDPE ret = OFDPE_SUCCESS;
- for ( dlist_element *element = get_first_element( list ); element != NULL; element = element->next ) {
+ dlist_element *sentinel = list;
+ for ( dlist_element *element = sentinel->next; element != sentinel; element = element->next ) {
if ( element->data == NULL ) {
continue;
}
@@ -821,7 +827,8 @@ void
dump_action_list( action_list *list, void dump_function( const char *format, ... ) ) {
assert( dump_function != NULL );
- for ( dlist_element *e = get_first_element( list ); e != NULL; e = e->next ) {
+ dlist_element *sentinel = list;
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
if ( e->data == NULL ) {
continue;
}
View
27 src/switch/datapath/action_bucket.c
@@ -55,14 +55,14 @@ void
delete_action_bucket_list( bucket_list *list ) {
assert( list != NULL );
- dlist_element *element = get_first_element( list );
- while ( element != NULL ) {
+ dlist_element *sentinel = list;
+ for ( dlist_element *element = sentinel->next; element != sentinel; element = element->next ) {
bucket *b = element->data;
if ( b != NULL ) {
delete_action_bucket( b );
}
- element = element->next;
}
+
delete_dlist( list );
}
@@ -72,7 +72,7 @@ append_action_bucket( bucket_list *list, bucket *bucket ) {
assert( list != NULL );
assert( bucket != NULL );
- list = insert_before_dlist( list, ( void * ) bucket );
+ list = insert_before_dlist( list, list, ( void * ) bucket );
if ( list == NULL ) {
return ERROR_NO_MEMORY;
}
@@ -91,7 +91,7 @@ remove_action_bucket( bucket_list *list, bucket *bucket ) {
return ERROR_NOT_FOUND;
}
delete_action_bucket( bucket );
- delete_dlist_element( elemenet );
+ delete_dlist_element( list, elemenet );
return OFDPE_SUCCESS;
}
@@ -110,8 +110,9 @@ validate_action_bucket_list( bucket_list *buckets ) {
assert( buckets != NULL );
OFDPE ret = OFDPE_SUCCESS;
- dlist_element *element = get_first_element( buckets );
- while ( element != NULL ) {
+
+ dlist_element *sentinel = buckets;
+ for ( dlist_element *element = sentinel->next; element != sentinel; element = element->next ) {
bucket *b = element->data;
if ( b != NULL ) {
ret = validate_action_bucket( b );
@@ -119,7 +120,6 @@ validate_action_bucket_list( bucket_list *buckets ) {
break;
}
}
- element = element->next;
}
return ret;
@@ -132,12 +132,11 @@ get_bucket_count( bucket_list *list ) {
uint32_t count = 0;
- dlist_element *element = get_first_element ( list );
- while ( element != NULL ) {
+ dlist_element *sentinel = list;
+ for ( dlist_element *element = sentinel->next; element != sentinel; element = element->next ) {
if ( element->data != NULL ) {
count++;
}
- element = element->next;
}
return count;
@@ -165,7 +164,8 @@ duplicate_bucket_list( bucket_list *buckets ) {
}
bucket_list *duplicated = create_action_bucket_list();
- for ( dlist_element *e = get_first_element( buckets ); e != NULL; e = e->next ) {
+ dlist_element *sentinel = buckets;
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
if ( e->data == NULL ) {
continue;
}
@@ -198,7 +198,8 @@ dump_buckets( bucket_list *buckets, void dump_function( const char *format, ...
assert( buckets != NULL );
assert( dump_function != NULL );
- for ( dlist_element *element = get_first_element( buckets ); element != NULL; element = element->next ) {
+ dlist_element *sentinel = buckets;
+ for ( dlist_element *element = sentinel->next; element != sentinel; element = element->next ) {
if ( element->data == NULL ) {
continue;
}
View
18 src/switch/datapath/action_executor.c
@@ -2076,18 +2076,16 @@ execute_group_select( buffer *frame, bucket_list *buckets ) {
create_list( &candidates );
uint32_t candidates_weight_total = 0;
- dlist_element *bucket_element = get_first_element( buckets );
-
- while ( bucket_element != NULL ) {
- bucket *b = bucket_element->data;
+ dlist_element *sentinel = buckets;
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
+ bucket *b = e->data;
if ( b != NULL ) {
if ( !check_bucket( b->actions ) ) {
continue;
}
candidates_weight_total += b->weight;
- append_to_tail( &candidates, bucket_element );
+ append_to_tail( &candidates, b );
}
- bucket_element = bucket_element->next;
}
uint32_t length_of_candidates = list_length_of( candidates );
@@ -2104,20 +2102,18 @@ execute_group_select( buffer *frame, bucket_list *buckets ) {
uint32_t candidate_index = 0;
list_element *target = candidates;
- for ( uint32_t i = 0; target != NULL && i < length_of_candidates; i++ ) {
+ for ( ; target != NULL ; target = target->next ) {
bucket *b = target->data;
if ( candidate_weight < b->weight ) {
break;
}
candidate_index++;
candidate_weight -= b->weight;
- target = target->next;
}
debug( "execute group select. bucket=%u(/%u)", candidate_index, length_of_candidates );
if ( target != NULL ) {
- bucket_element = target->data;
- bucket *b = bucket_element->data;
+ bucket *b = target->data;
if ( b != NULL ) {
b->packet_count++;
b->byte_count += frame->length;
@@ -2298,7 +2294,7 @@ execute_action_list( action_list *list, buffer *frame ) {
debug( "Executing action list ( list = %p, frame = %p ).", list, frame );
- for ( action_list *element = get_first_element( list ); element != NULL; element = element->next ) {
+ for ( action_list *element = get_first_element( list ); element != list; element = element->next ) {
action *action = element->data;
if ( action == NULL ) {
continue;
View
6 src/switch/datapath/flow_entry.c
@@ -60,7 +60,8 @@ alloc_flow_entry( match *match, instruction_set *instructions,
if ( instructions->write_actions != NULL && instructions->write_actions->actions != NULL ) {
action_list *actions = instructions->write_actions->actions;
- for ( dlist_element *e = get_first_element( actions ); e != NULL; e = e->next ) {
+ dlist_element *sentinel = actions;
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
action *action = e->data;
if ( action != NULL ) {
action->entry = entry;
@@ -69,7 +70,8 @@ alloc_flow_entry( match *match, instruction_set *instructions,
}
if ( instructions->apply_actions != NULL && instructions->apply_actions->actions != NULL ) {
action_list *actions = instructions->apply_actions->actions;
- for ( dlist_element *e = get_first_element( actions ); e != NULL; e = e->next ) {
+ dlist_element *sentinel = actions;
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
action *action = e->data;
if ( action != NULL ) {
action->entry = entry;
View
7 src/switch/datapath/group_table.c
@@ -114,7 +114,8 @@ validate_buckets( uint8_t type, bucket_list *buckets ) {
assert( buckets != NULL );
OFDPE ret = OFDPE_SUCCESS;
- for ( dlist_element *element = get_first_element( buckets ); element != NULL; element = element->next ) {
+ dlist_element *sentinel = buckets;
+ for ( dlist_element *element = sentinel->next; element != sentinel; element = element->next ) {
if ( element->data == NULL ) {
continue;
}
@@ -337,7 +338,9 @@ get_group_stats( const uint32_t group_id, group_stats **stats, uint32_t *n_group
stat->duration_sec = ( uint32_t ) diff.tv_sec;
stat->duration_nsec = ( uint32_t ) diff.tv_nsec;
create_list( &stat->bucket_stats );
- for ( dlist_element *b = get_first_element( entry->buckets ); b != NULL; b = b->next ) {
+
+ dlist_element *sentinel = entry->buckets;
+ for ( dlist_element *b = sentinel->next; b != sentinel; b = b->next ) {
if ( b->data == NULL ) {
continue;
}
View
4 src/switch/datapath/instruction.c
@@ -104,6 +104,7 @@ free_instruction( instruction *instruction ) {
if ( instruction->actions != NULL ) {
delete_action_list( instruction->actions );
+ instruction->actions = NULL;
}
xfree( instruction );
@@ -525,7 +526,8 @@ update_reference_counters_in_instruction( instruction *instruction, counter_upda
return;
}
- for ( dlist_element *a = get_first_element( instruction->actions ); a != NULL; a = a->next ) {
+ dlist_element *sentinel = instruction->actions;
+ for ( dlist_element *a = sentinel->next; a != sentinel; a = a->next ) {
if ( a->data == NULL ) {
continue;
}
View
9 src/switch/datapath/openflow_helper.c
@@ -469,7 +469,8 @@ get_ofp_bucket_length( const bucket *bucket ) {
size_t length = offsetof( struct ofp_bucket, actions );
if ( bucket->actions != NULL ) {
- for ( dlist_element *e = get_first_element( bucket->actions ); e != NULL; e = e->next ) {
+ dlist_element *sentinel = bucket->actions;
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
if ( e->data == NULL ) {
continue;
}
@@ -487,7 +488,8 @@ get_ofp_buckets_length( bucket_list *buckets ) {
size_t length = 0;
- for ( dlist_element *e = get_first_element( buckets ); e != NULL; e = e->next ) {
+ dlist_element *sentinel = buckets;
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
if ( e->data == NULL ) {
continue;
}
@@ -628,7 +630,8 @@ get_ofp_bucket( const bucket *bucket, struct ofp_bucket **translated, size_t *le
bool ret = true;
struct ofp_action_header *actions = ( *translated )->actions;
- for ( dlist_element *e = get_first_element( bucket->actions ); e != NULL; e = e->next ) {
+ dlist_element *sentinel = bucket->actions;
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
if ( e->data == NULL ) {
continue;
}
View
17 src/switch/switch/action-helper.c
@@ -124,16 +124,15 @@ _action_pack( void *dest, action_list **list ) {
if ( *list == NULL ) {
return;
}
- dlist_element *item = get_first_element( *list );
- action *action;
struct ofp_action_header *ac_hdr = dest;
- while ( item != NULL ) {
- action = item->data;
+
+ dlist_element *sentinel = *list;
+ for ( dlist_element *item = sentinel->next; item != sentinel; item = item->next ) {
+ action *action = item->data;
if ( action != NULL ) {
action_tlv_pack( ac_hdr, action );
ac_hdr = ( struct ofp_action_header * ) ( ( char * ) ac_hdr + ac_hdr->len );
}
- item = item->next;
}
}
void ( *action_pack )( void *dest, action_list **list ) = _action_pack;
@@ -145,10 +144,9 @@ _action_list_length( action_list **list ) {
return 0;
}
uint16_t length = 0;
- dlist_element *item = get_first_element( *list );
- action *action;
- while ( item != NULL ) {
- action = item->data;
+ dlist_element *sentinel = *list;
+ for ( dlist_element *item = sentinel->next; item != sentinel; item = item->next ) {
+ action *action = item->data;
if ( action != NULL ) {
length = ( uint16_t ) ( length + action_tlv_length_by_type( action->type ) );
if ( action->type == OFPAT_SET_FIELD && action->match ) {
@@ -158,7 +156,6 @@ _action_list_length( action_list **list ) {
length = ( uint16_t ) ( length + PADLEN_TO_64( length ) );
}
}
- item = item->next;
}
return length;
}
View
34 unittests/lib/doubly_linked_list_test.c
@@ -68,8 +68,8 @@ test_create_dlist() {
assert_true( new_element != NULL );
assert_true( new_element->data == NULL );
- assert_true( new_element->next == NULL );
- assert_true( new_element->prev == NULL );
+ assert_true( new_element->next == new_element );
+ assert_true( new_element->prev == new_element );
delete_dlist( new_element );
}
@@ -194,61 +194,67 @@ test_get_last_element_aborts_with_NULL_dlist() {
// Remove "alpha" of "alpha" <-> "bravo" <-> "charlie"
static void
test_remove_first_element() {
+ char element_data1[] = "alpha";
char element_data2[] = "bravo";
char element_data3[] = "charlie";
- dlist_element *alpha = create_dlist();
+ dlist_element *sentinel = create_dlist();
+ dlist_element *alpha = insert_after_dlist( sentinel, element_data1 );
dlist_element *bravo = insert_after_dlist( alpha, element_data2 );
dlist_element *charlie = insert_after_dlist( bravo, element_data3 );
- assert_true( delete_dlist_element( alpha ) );
- assert_true( bravo->prev == NULL );
+ assert_true( delete_dlist_element( sentinel, alpha ) );
+ assert_true( bravo->prev == sentinel );
assert_true( bravo->next == charlie );
- delete_dlist( bravo );
+ delete_dlist( sentinel );
}
// Remove "bravo" of "alpha" <-> "bravo" <-> "charlie"
static void
test_remove_middle_element() {
+ char element_data1[] = "alpha";
char element_data2[] = "bravo";
char element_data3[] = "charlie";
- dlist_element *alpha = create_dlist();
+ dlist_element *sentinel = create_dlist();
+ dlist_element *alpha = insert_after_dlist( sentinel, element_data1 );
dlist_element *bravo = insert_after_dlist( alpha, element_data2 );
dlist_element *charlie = insert_after_dlist( bravo, element_data3 );
- assert_true( delete_dlist_element( bravo ) );
+ assert_true( delete_dlist_element( sentinel, bravo ) );
assert_true( alpha->next == charlie );
assert_true( charlie->prev == alpha );
- delete_dlist( alpha );
+ delete_dlist( sentinel );
}
// Remove "charlie" of "alpha" <-> "bravo" <-> "charlie"
static void
test_remove_last_element() {
+ char element_data1[] = "alpha";
char element_data2[] = "bravo";
char element_data3[] = "charlie";
- dlist_element *alpha = create_dlist();
+ dlist_element *sentinel = create_dlist();
+ dlist_element *alpha = insert_after_dlist( sentinel, element_data1 );
dlist_element *bravo = insert_after_dlist( alpha, element_data2 );
dlist_element *charlie = insert_after_dlist( bravo, element_data3 );
- assert_true( delete_dlist_element( charlie ) );
- assert_true( bravo->next == NULL );
+ assert_true( delete_dlist_element( sentinel, charlie ) );
+ assert_true( bravo->next == sentinel );
assert_true( bravo->prev == alpha );
- delete_dlist( alpha );
+ delete_dlist( sentinel );
}
static void
test_delete_dlist_element_aborts_with_NULL_dlist() {
expect_string( mock_die, output, "element must not be NULL" );
- expect_assert_failure( delete_dlist_element( NULL ) );
+ expect_assert_failure( delete_dlist_element( NULL, NULL ) );
}
View
9 unittests/lib/timer_test.c
@@ -80,12 +80,9 @@ mock_debug( const char *format, ... ) {
static timer_callback_info *
find_timer_callback( void ( *callback )( void *user_data ) ) {
- dlist_element *e;
- timer_callback_info *cb;
-
- cb = NULL;
- for ( e = timer_callbacks->next; e; e = e->next ) {
- cb = e->data;
+ dlist_element *sentinel = timer_callbacks;
+ for ( dlist_element *e = sentinel->next; e != sentinel; e = e->next ) {
+ timer_callback_info * cb = e->data;
if ( cb->function == callback ) {
return cb;
}
View
6 unittests/switch/switch/stats-helper-test.c
@@ -985,7 +985,7 @@ test_instructions( void **state ) {
if ( e->data == NULL ) {
e = ins_list->next;
}
- for (; e; e = e->next ) {
+ for (; e != ins_list; e = e->next ) {
if ( e->data != NULL ) {
instruction *ins = e->data;
printf( "ins type( %u )\n", ins->type );
@@ -999,7 +999,7 @@ test_instructions( void **state ) {
if ( e->data == NULL ) {
e = ins_list->next;
}
- for (; e; e = e->next ) {
+ for (; e != ins_list; e = e->next ) {
if ( e->data != NULL ) {
instruction *ins = e->data;
printf( "ad ins type( %u )\n", ins->type );
@@ -1011,7 +1011,7 @@ test_instructions( void **state ) {
if ( e->data == NULL ) {
e = new_ins_list->next;
}
- for (; e; e = e->next ) {
+ for (; e != new_ins_list; e = e->next ) {
if ( e->data != NULL ) {
instruction *ins = e->data;
printf( "ins type( %u )\n", ins->type );
Something went wrong with that request. Please try again.