/*------------------------------------------------------------------------- * *ilist.h *integrated/inlinedoubly-andsingly-linkedlists * *Theselisttypesareusefulwhenthereareonlyapredeterminedsetof *liststhatanobjectcouldbein.Listlinksareembeddeddirectlyinto *theobjects,andthusnoextramemorymanagementoverheadisrequired. *(Ofcourse,ifonlyasmallproportionofexistingobjectsareinalist, *thelinkfieldsintheremainderwouldbewastedspace.Butusually, *itsavesspacetonothaveseparately-allocatedlistnodes.) * *Thedoubly-linkedlistcomesin2forms.dlist_headdefinesaheadofa *doubly-linkedlistofdlist_nodes,whereasdclist_headdefinestheheadof *adoubly-linkedlistofdlist_nodeswithanadditional'count'fieldto *keeptrackofhowmanyitemsarecontainedwithinthegivenlist.For *simplicity,dlist_headanddclist_headsharethesamenodeanditerator *types.Thefunctionstomanipulateadlist_headalwayshaveaname *startingwith"dlist",whereasfunctionstomanipulateadclist_headhavea *namestartingwith"dclist".dclist_headcomeswithanadditionalfunction *(dclist_count)toreturnthenumberofentriesinthelist.dclistsare *abletostoreamaximumofPG_UINT32_MAXelements.Itisuptothecaller *toensurenomorethanthismanyitemsareaddedtoadclist. * *Noneofthefunctionshereallocateanymemory;theyjustmanipulate *externallymanagedmemory.Withtheexceptiondoubly-linkedcountlists *providingtheabilitytoobtainthenumberofitemsinthelist,theAPIs *forsinglyandbothdoublylinkedlistsareidenticalasfaras *capabilitiesofbothallow. * *Eachlisthasalistheader,whichexistsevenwhenthelistisempty. *Anemptysingly-linkedlisthasaNULLpointerinitsheader. * *Forbothdoubly-linkedlisttypes,therearetwovalidwaystorepresentan *emptylist.Thehead's'next'pointercaneitherbeNULLorthehead's *'next'and'prev'linkscanbothpointbacktothelisthead(circular). *(Ifadlistismodifiedandthenallitselementsaredeleted,itwillbe *inthecircularstate.).Weprefercirculardlistsbecausetherearesome *operationsthatcanbedonewithoutbranches(andthusfaster)onlists *thatusecircularrepresentation.However,itisoftenconvenientto *initializelistheaderstozeroesratherthansettingthemupwithan *explicitinitializationfunction,sowealsoallowtheNULLinitialization. * *EXAMPLES * *Here'sasimpleexampledemonstratinghowthiscanbeused.Let'sassume *wewanttostoreinformationaboutthetablescontainedinadatabase. * *#include"lib/ilist.h" * *// Define struct for the databases including a list header that will be *// used to access the nodes in the table list later on. *typedefstructmy_database *{ *char*datname; *dlist_headtables; *// ... *}my_database; * *// Define struct for the tables. Note the list_node element which stores *// prev/next list links. The list_node element need not be first. *typedefstructmy_table *{ *char*tablename; *dlist_nodelist_node; *perm_tpermissions; *// ... *}my_table; * *// create a database *my_database*db=create_database(); * *// and add a few tables to its table list *dlist_push_head(&db->tables,&create_table(db,"a")->list_node); *... *dlist_push_head(&db->tables,&create_table(db,"b")->list_node); * * *Toiterateoverthetablelist,weallocateaniteratorvariableanduse *aspecializedloopingconstruct.Insideadlist_foreach,theiterator's *'cur'fieldcanbeusedtoaccessthecurrentelement.iter.curpointsto *a'dlist_node',butmostofthetimewhatwewantistheactualtable *information;dlist_container()givesusthat,likeso: * *dlist_iteriter; *dlist_foreach(iter,&db->tables) *{ *my_table*tbl=dlist_container(my_table,list_node,iter.cur); *printf("wehaveatable:%sindatabase%s\n", *tbl->tablename,db->datname); *} * * *Whileasimpleiterationisuseful,wesometimesalsowanttomanipulate *thelistwhileiterating.Thereisadifferentiteratorelementandlooping *constructforthat.Supposewewanttodeletetablesthatmeetacertain *criterion: * *dlist_mutable_itermiter; *dlist_foreach_modify(miter,&db->tables) *{ *my_table*tbl=dlist_container(my_table,list_node,miter.cur); * *if(!tbl->to_be_deleted) *continue;// don't touch this one * *// unlink the current table from the linked list *dlist_delete(miter.cur); *// as these lists never manage memory, we can still access the table *// after it's been unlinked *drop_table(db,tbl); *} * * *PortionsCopyright(c)1996-2025,PostgreSQLGlobalDevelopmentGroup *PortionsCopyright(c)1994,RegentsoftheUniversityofCalifornia * *IDENTIFICATION *src/include/lib/ilist.h *-------------------------------------------------------------------------
*/ #ifndef ILIST_H #define ILIST_H
/* *Doublylinkedlistiteratortypefordlist_headanddclist_headtypes. * *Usedasstateindlist_foreach()anddlist_reverse_foreach()(andthe *dclistvariantthereof). * *Togetthecurrentelementoftheiterationusethe'cur'member. * *Iterationsusingthisare*not*allowedtochangethelistwhileiterating! * *NB:Weuseanextra"end"fieldheretoavoidmultipleevaluationsof *argumentsinthedlist_foreach()anddclist_foreach()macros.
*/ typedefstruct dlist_iter
{
dlist_node *cur; /* current element */
dlist_node *end; /* last node we'll iterate to */
} dlist_iter;
/* *Doublylinkedlistiteratorforbothdlist_headanddclist_headtypes. *Thisiteratortypeallowssomemodificationswhileiterating. * *Usedasstateindlist_foreach_modify()anddclist_foreach_modify(). * *Togetthecurrentelementoftheiterationusethe'cur'member. * *Iterationsusingthisareonlyallowedtochangethelistatthecurrent *pointofiteration.Itisfinetodeletethecurrentnode,butitis*not* *finetoinsertordeleteadjacentnodes. * *NB:Weneedaseparatetypeformutableiterationssothatwecanstore *the'next'nodeofthecurrentnodeincaseitgetsdeletedormodified.
*/ typedefstruct dlist_mutable_iter
{
dlist_node *cur; /* current element */
dlist_node *next; /* next node we'll iterate to */
dlist_node *end; /* last node we'll iterate to */
} dlist_mutable_iter;
/* *Headofadoublylinkedlistwithacountofthenumberofitems * *Thisinternallymakesuseofadlisttoimplementtheactuallist.When *itemsareaddedorremovedfromthelistthecountisupdatedtoreflect *thecurrentnumberofitemsinthelist.
*/ typedefstruct dclist_head
{
dlist_head dlist; /* the actual list header */
uint32 count; /* the number of items in the list */
} dclist_head;
/* *Moveelementfromitscurrentpositioninthelisttotheheadpositionin *thesamelist. * *Undefinedbehaviourif'node'isnotalreadypartofthelist.
*/ staticinlinevoid
dlist_move_head(dlist_head *head, dlist_node *node)
{ /* fast path if it's already at the head */ if (head->head.next == node) return;
dlist_delete(node);
dlist_push_head(head, node);
dlist_check(head);
}
/* *Moveelementfromitscurrentpositioninthelisttothetailpositionin *thesamelist. * *Undefinedbehaviourif'node'isnotalreadypartofthelist.
*/ staticinlinevoid
dlist_move_tail(dlist_head *head, dlist_node *node)
{ /* fast path if it's already at the tail */ if (head->head.prev == node) return;
/* internal support function to get address of head element's struct */ staticinlinevoid *
dlist_head_element_off(dlist_head *head, size_t off)
{
Assert(!dlist_is_empty(head)); return (char *) head->head.next - off;
}
/* internal support function to get address of head element's struct */ staticinlinevoid *
dclist_head_element_off(dclist_head *head, size_t off)
{
Assert(!dclist_is_empty(head));
/* internal support function to get address of tail element's struct */ staticinlinevoid *
dclist_tail_element_off(dclist_head *head, size_t off)
{
Assert(!dclist_is_empty(head));
/* internal support function to get address of head element's struct */ staticinlinevoid *
slist_head_element_off(slist_head *head, size_t off)
{
Assert(!slist_is_empty(head)); return (char *) head->head.next - off;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.90Bemerkung:
(vorverarbeitet am 2026-08-06)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.