From 5d1c109fc4f44a82c059ccf1f5133928d22df335 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 22 Dec 2008 19:16:06 +0000 Subject: [PATCH] (trunk libT) speed improvments from wereHamster --- libtransmission/list.c | 60 +++++++++++++++++++++++++++++++ libtransmission/list.h | 75 +++++++++++++++++++++++++++++++++++++++ libtransmission/peer-io.c | 30 ++++++++++++---- 3 files changed, 159 insertions(+), 6 deletions(-) diff --git a/libtransmission/list.c b/libtransmission/list.c index 5e959480f..c6de04f1b 100644 --- a/libtransmission/list.c +++ b/libtransmission/list.c @@ -158,3 +158,63 @@ tr_list_size( const tr_list * list ) return size; } + + +/* + * Double-linked list with easy memory management and fast + * insert/remove operations + */ + +void +__tr_list_init( struct __tr_list * head ) +{ + head->next = head; + head->prev = head; +} + +void +__tr_list_insert( struct __tr_list * list, + struct __tr_list * prev, + struct __tr_list * next) +{ + next->prev = list; + list->next = next; + list->prev = prev; + prev->next = list; +} + +void +__tr_list_splice( struct __tr_list * prev, + struct __tr_list * next) +{ + next->prev = prev; + prev->next = next; +} + + +void +__tr_list_append( struct __tr_list * head, + struct __tr_list * list) +{ + __tr_list_insert( list, head->prev, head ); +} + +void +__tr_list_remove( struct __tr_list * head ) +{ + __tr_list_splice( head->prev, head->next ); + head->next = head->prev = NULL; +} + +void +__tr_list_destroy( struct __tr_list * head, + __tr_list_free_t func) +{ + while ( head->next != head ) + { + struct __tr_list * list = head->next; + __tr_list_splice( list->prev, list->next ); + + func( list ); + } +} diff --git a/libtransmission/list.h b/libtransmission/list.h index 4a87c5444..7e80996c5 100644 --- a/libtransmission/list.h +++ b/libtransmission/list.h @@ -52,5 +52,80 @@ tr_list* tr_list_find( tr_list * list, const void * b, TrListCompareFunc compare_func ); + +/* + * Double-linked list with easy memory management and fast + * insert/remove operations + */ + +struct __tr_list +{ + struct __tr_list * next, * prev; +}; + +#define __tr_list_entry(ptr, type, member) ({ \ + const struct __tr_list *__mptr = (ptr); \ + (void *)( (char *)__mptr - offsetof(type,member) ); \ +}) + +typedef int ( *__tr_list_cmp_t ) ( const void * a, const void * b ); +typedef void ( *__tr_list_free_t )( void * ); + + +/** + * __tr_list_init() + * + * Init @head as an empty list. + */ +void +__tr_list_init( struct __tr_list * head ); + + +/** + * __tr_list_insert() + * + * Insert @list between @prev and @next. + */ +void +__tr_list_insert( struct __tr_list * list, + struct __tr_list * prev, + struct __tr_list * next); + +/** + * __tr_list_splice() + * + * Connect @prev with @next, removing any nodes that were + * in between. + */ +void +__tr_list_splice( struct __tr_list * prev, + struct __tr_list * next); + +/** + * __tr_list_append() + * + * Append @list to the end of @head. + */ +void +__tr_list_append( struct __tr_list * head, + struct __tr_list * list); + +/** + * __tr_list_remove() + * + * Remove @head from the list it is in. + */ +void +__tr_list_remove( struct __tr_list * head ); + +/** + * __tr_list_destroy() + * + * Destroy the list and free all nodes + */ +void +__tr_list_destroy( struct __tr_list * head, + __tr_list_free_t func); + #endif /* TR_LIST_H */ diff --git a/libtransmission/peer-io.c b/libtransmission/peer-io.c index f199ac3d0..971928367 100644 --- a/libtransmission/peer-io.c +++ b/libtransmission/peer-io.c @@ -73,6 +73,7 @@ struct tr_datatype { tr_bool isPieceData; size_t length; + struct __tr_list head; }; struct tr_peerIo @@ -106,7 +107,7 @@ struct tr_peerIo struct evbuffer * inbuf; struct evbuffer * outbuf; - tr_list * outbuf_datatypes; /* struct tr_datatype */ + struct __tr_list outbuf_datatypes; /* struct tr_datatype */ struct event event_read; struct event event_write; @@ -121,7 +122,8 @@ didWriteWrapper( tr_peerIo * io, size_t bytes_transferred ) { while( bytes_transferred ) { - struct tr_datatype * next = io->outbuf_datatypes->data; + struct tr_datatype * next = __tr_list_entry( io->outbuf_datatypes.next, + struct tr_datatype, head ); const size_t payload = MIN( next->length, bytes_transferred ); const size_t overhead = getPacketOverhead( payload ); @@ -135,8 +137,10 @@ didWriteWrapper( tr_peerIo * io, size_t bytes_transferred ) bytes_transferred -= payload; next->length -= payload; - if( !next->length ) - tr_free( tr_list_pop_front( &io->outbuf_datatypes ) ); + if( !next->length ) { + __tr_list_remove( io->outbuf_datatypes.next ); + tr_free( next ); + } } } @@ -360,9 +364,14 @@ tr_peerIoNew( tr_session * session, io->timeCreated = time( NULL ); io->inbuf = evbuffer_new( ); io->outbuf = evbuffer_new( ); + event_set( &io->event_read, io->socket, EV_READ, event_read_cb, io ); event_set( &io->event_write, io->socket, EV_WRITE, event_write_cb, io ); + + __tr_list_init( &io->outbuf_datatypes ); + tr_peerIoSetBandwidth( io, session->bandwidth ); + return io; } @@ -398,6 +407,13 @@ tr_peerIoNewOutgoing( tr_session * session, : tr_peerIoNew( session, addr, port, torrentHash, 0, socket ); } +static void +trDatatypeFree( void * data ) +{ + struct tr_datatype * dt = __tr_list_entry( data, struct tr_datatype, head ); + tr_free(dt); +} + static void io_dtor( void * vio ) { @@ -410,7 +426,7 @@ io_dtor( void * vio ) evbuffer_free( io->inbuf ); tr_netClose( io->socket ); tr_cryptoFree( io->crypto ); - tr_list_free( &io->outbuf_datatypes, tr_free ); + __tr_list_destroy( &io->outbuf_datatypes, trDatatypeFree ); io->magicNumber = 0xDEAD; tr_free( io ); @@ -701,7 +717,9 @@ tr_peerIoWrite( tr_peerIo * io, datatype = tr_new( struct tr_datatype, 1 ); datatype->isPieceData = isPieceData != 0; datatype->length = writemeLen; - tr_list_append( &io->outbuf_datatypes, datatype ); + + __tr_list_init( &datatype->head ); + __tr_list_append( &io->outbuf_datatypes, &datatype->head ); evbuffer_add( io->outbuf, writeme, writemeLen ); } -- 2.40.0