mirror of
https://github.com/transmission/transmission
synced 2025-03-03 18:25:35 +00:00
make list less error-prone by changing the API s.t. we're guaranteed to update the list's pointer correctly.
This commit is contained in:
parent
8f8100e4d8
commit
26dabf816e
6 changed files with 80 additions and 39 deletions
|
@ -29,44 +29,70 @@ node_free( tr_list_t* node )
|
|||
***/
|
||||
|
||||
void
|
||||
tr_list_free( tr_list_t* list )
|
||||
tr_list_free( tr_list_t** list )
|
||||
{
|
||||
while( list )
|
||||
while( *list )
|
||||
{
|
||||
tr_list_t * node = list;
|
||||
list = list->next;
|
||||
tr_list_t * node = *list;
|
||||
*list = (*list)->next;
|
||||
node_free( node );
|
||||
}
|
||||
}
|
||||
|
||||
tr_list_t*
|
||||
tr_list_prepend( tr_list_t * list, void * data )
|
||||
void
|
||||
tr_list_prepend( tr_list_t ** list, void * data )
|
||||
{
|
||||
tr_list_t * node = node_alloc ();
|
||||
node->data = data;
|
||||
node->next = list;
|
||||
if( list )
|
||||
list->prev = node;
|
||||
return node;
|
||||
node->next = *list;
|
||||
if( *list )
|
||||
(*list)->prev = node;
|
||||
*list = node;
|
||||
}
|
||||
|
||||
tr_list_t*
|
||||
tr_list_append( tr_list_t * list, void * data )
|
||||
void
|
||||
tr_list_append( tr_list_t ** list, void * data )
|
||||
{
|
||||
tr_list_t * node = node_alloc( );
|
||||
node->data = data;
|
||||
if( !list )
|
||||
return node;
|
||||
if( !*list )
|
||||
*list = node;
|
||||
else {
|
||||
tr_list_t * l = list;
|
||||
tr_list_t * l = *list;
|
||||
while( l->next )
|
||||
l = l->next;
|
||||
l->next = node;
|
||||
node->prev = l;
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tr_list_insert_sorted( tr_list_t ** list,
|
||||
void * data,
|
||||
int compare(const void*,const void*) )
|
||||
{
|
||||
/* find l, the node that we'll insert this data before */
|
||||
tr_list_t * l;
|
||||
for( l=*list; l!=NULL; l=l->next ) {
|
||||
const int c = (compare)( data, l->data );
|
||||
if( c <= 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
if( l == NULL)
|
||||
tr_list_append( list, data );
|
||||
else if( l == *list )
|
||||
tr_list_prepend( list, data );
|
||||
else {
|
||||
tr_list_t * node = node_alloc( );
|
||||
node->data = data;
|
||||
if( l->prev ) { node->prev = l->prev; node->prev->next = node; }
|
||||
node->next = l;
|
||||
l->prev = node;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tr_list_t*
|
||||
tr_list_find_data ( tr_list_t * list, const void * data )
|
||||
{
|
||||
|
@ -77,21 +103,20 @@ tr_list_find_data ( tr_list_t * list, const void * data )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
tr_list_t*
|
||||
tr_list_remove_data ( tr_list_t * list, const void * data )
|
||||
void
|
||||
tr_list_remove_data ( tr_list_t ** list, const void * data )
|
||||
{
|
||||
tr_list_t * node = tr_list_find_data( list, data );
|
||||
tr_list_t * node = tr_list_find_data( *list, data );
|
||||
tr_list_t * prev = node ? node->prev : NULL;
|
||||
tr_list_t * next = node ? node->next : NULL;
|
||||
if( prev ) prev->next = next;
|
||||
if( next ) next->prev = prev;
|
||||
if( list == node ) list = next;
|
||||
if( *list == node ) *list = next;
|
||||
node_free( node );
|
||||
return list;
|
||||
}
|
||||
|
||||
tr_list_t*
|
||||
tr_list_find ( tr_list_t * list , TrListCompareFunc func, const void * b )
|
||||
tr_list_find ( tr_list_t * list , const void * b, TrListCompareFunc func )
|
||||
{
|
||||
for( ; list; list=list->next )
|
||||
if( !func( list->data, b ) )
|
||||
|
|
|
@ -19,17 +19,33 @@ typedef struct tr_list_s
|
|||
}
|
||||
tr_list_t;
|
||||
|
||||
void tr_list_free ( tr_list_t* );
|
||||
tr_list_t* tr_list_append ( tr_list_t*, void * data );
|
||||
tr_list_t* tr_list_prepend ( tr_list_t*, void * data );
|
||||
tr_list_t* tr_list_remove_data ( tr_list_t*, const void * data );
|
||||
|
||||
typedef int (*TrListCompareFunc)(const void * a, const void * b);
|
||||
tr_list_t* tr_list_find ( tr_list_t*, TrListCompareFunc func, const void * b );
|
||||
tr_list_t* tr_list_find_data ( tr_list_t*, const void * data );
|
||||
|
||||
typedef void (*TrListForeachFunc)(void *);
|
||||
void tr_list_foreach ( tr_list_t*, TrListForeachFunc func );
|
||||
|
||||
void tr_list_free ( tr_list_t ** list );
|
||||
|
||||
void tr_list_append ( tr_list_t ** list,
|
||||
void * data );
|
||||
|
||||
void tr_list_prepend ( tr_list_t ** list,
|
||||
void * data );
|
||||
|
||||
void tr_list_remove_data ( tr_list_t ** list,
|
||||
const void * data );
|
||||
|
||||
void tr_list_insert_sorted ( tr_list_t ** list,
|
||||
void * data,
|
||||
TrListCompareFunc compare_func );
|
||||
|
||||
tr_list_t* tr_list_find ( tr_list_t * list,
|
||||
const void * b,
|
||||
TrListCompareFunc compare_func );
|
||||
|
||||
tr_list_t* tr_list_find_data ( tr_list_t * list,
|
||||
const void * data );
|
||||
|
||||
void tr_list_foreach ( tr_list_t * list,
|
||||
TrListForeachFunc foreach_func );
|
||||
|
||||
#endif /* TR_LIST_H */
|
||||
|
||||
|
|
|
@ -313,7 +313,7 @@ void tr_peerDestroy( tr_peer_t * peer )
|
|||
tr_bitfieldFree( peer->banfield );
|
||||
tr_bitfieldFree( peer->reqfield );
|
||||
tr_list_foreach( peer->outRequests, tr_free );
|
||||
tr_list_free( peer->outRequests );
|
||||
tr_list_free( &peer->outRequests );
|
||||
tr_free( peer->inRequests );
|
||||
tr_free( peer->buf );
|
||||
tr_free( peer->outMessages );
|
||||
|
|
|
@ -123,7 +123,7 @@ blockPending( tr_torrent_t * tor,
|
|||
|
||||
r = (tr_request_t*) peer->outRequests->data;
|
||||
assert( r != NULL );
|
||||
peer->outRequests = tr_list_remove_data( peer->outRequests, r );
|
||||
tr_list_remove_data( &peer->outRequests, r );
|
||||
|
||||
if( !tr_cpPieceIsComplete( tor->completion, r->index ) ) /* sanity clause */
|
||||
{
|
||||
|
@ -226,7 +226,7 @@ static void sendChoke( tr_peer_t * peer, int yes )
|
|||
{
|
||||
/* Drop older requests from the last time it was unchoked, if any */
|
||||
tr_list_foreach( peer->outRequests, tr_free );
|
||||
tr_list_free( peer->outRequests );
|
||||
tr_list_free( &peer->outRequests );
|
||||
peer->outRequests = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -244,7 +244,7 @@ static int parseRequest( tr_torrent_t * tor, tr_peer_t * peer,
|
|||
r->index = index;
|
||||
r->begin = begin;
|
||||
r->length = length;
|
||||
peer->outRequests = tr_list_append( peer->outRequests, r );
|
||||
tr_list_append( &peer->outRequests, r );
|
||||
|
||||
return TR_OK;
|
||||
}
|
||||
|
@ -418,9 +418,9 @@ static int parseCancel( tr_torrent_t * tor, tr_peer_t * peer,
|
|||
req.index = index;
|
||||
req.begin = begin;
|
||||
req.length = length;
|
||||
while(( l = tr_list_find( peer->outRequests, reqCompare, &req ) )) {
|
||||
while(( l = tr_list_find( peer->outRequests, &req, reqCompare ) )) {
|
||||
tr_request_t * r = (tr_request_t *) l->data;
|
||||
peer->outRequests = tr_list_remove_data( peer->outRequests, r );
|
||||
tr_list_remove_data( &peer->outRequests, r );
|
||||
tr_free( r );
|
||||
}
|
||||
|
||||
|
|
|
@ -270,7 +270,7 @@ tr_loadTorrents ( tr_handle_t * h,
|
|||
tr_buildPath( path, sizeof(path), torrentDir, d->d_name, NULL );
|
||||
tor = tr_torrentInit( h, path, destination, flags, NULL );
|
||||
if( tor != NULL ) {
|
||||
list = tr_list_append( list, tor );
|
||||
tr_list_append( &list, tor );
|
||||
//fprintf (stderr, "#%d - %s\n", n, tor->info.name );
|
||||
n++;
|
||||
}
|
||||
|
@ -284,7 +284,7 @@ tr_loadTorrents ( tr_handle_t * h,
|
|||
torrents[i++] = (tr_torrent_t*) l->data;
|
||||
assert( i==n );
|
||||
|
||||
tr_list_free( list );
|
||||
tr_list_free( &list );
|
||||
|
||||
*setmeCount = n;
|
||||
tr_inf( "Loaded %d torrents from disk", *setmeCount );
|
||||
|
|
Loading…
Reference in a new issue