/*-------------------------------------------------------------------------
*
* proclist . h
* operations on doubly - linked lists of pgprocnos
*
* The interface is similar to dlist from ilist . h , but uses pgprocno instead
* of pointers . This allows proclist_head to be mapped at different addresses
* in different backends .
*
* See proclist_types . h for the structs that these functions operate on . They
* are separated to break a header dependency cycle with proc . h .
*
* Portions Copyright ( c ) 2016 - 2025 , PostgreSQL Global Development Group
*
* IDENTIFICATION
* src / include / storage / proclist . h
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
#ifndef PROCLIST_H
#define PROCLIST_H
#include "storage/proc.h"
#include "storage/proclist_types.h"
/*
* Initialize a proclist .
*/
static inline void
proclist_init(proclist_head *list)
{
list->head = list->tail = INVALID_PROC_NUMBER;
}
/*
* Is the list empty ?
*/
static inline bool
proclist_is_empty(const proclist_head *list)
{
return list->head == INVALID_PROC_NUMBER;
}
/*
* Get a pointer to a proclist_node inside a given PGPROC , given a procno and
* the proclist_node field ' s offset within struct PGPROC .
*/
static inline proclist_node *
proclist_node_get(int procno, size_t node_offset)
{
char *entry = (char *) GetPGProcByNumber(procno);
return (proclist_node *) (entry + node_offset);
}
/*
* Insert a process at the beginning of a list .
*/
static inline void
proclist_push_head_offset(proclist_head *list, int procno, size_t node_offset)
{
proclist_node *node = proclist_node_get(procno, node_offset);
Assert(node->next == 0 && node->prev == 0 );
if (list->head == INVALID_PROC_NUMBER)
{
Assert(list->tail == INVALID_PROC_NUMBER);
node->next = node->prev = INVALID_PROC_NUMBER;
list->head = list->tail = procno;
}
else
{
Assert(list->tail != INVALID_PROC_NUMBER);
Assert(list->head != procno);
Assert(list->tail != procno);
node->next = list->head;
proclist_node_get(node->next, node_offset)->prev = procno;
node->prev = INVALID_PROC_NUMBER;
list->head = procno;
}
}
/*
* Insert a process at the end of a list .
*/
static inline void
proclist_push_tail_offset(proclist_head *list, int procno, size_t node_offset)
{
proclist_node *node = proclist_node_get(procno, node_offset);
Assert(node->next == 0 && node->prev == 0 );
if (list->tail == INVALID_PROC_NUMBER)
{
Assert(list->head == INVALID_PROC_NUMBER);
node->next = node->prev = INVALID_PROC_NUMBER;
list->head = list->tail = procno;
}
else
{
Assert(list->head != INVALID_PROC_NUMBER);
Assert(list->head != procno);
Assert(list->tail != procno);
node->prev = list->tail;
proclist_node_get(node->prev, node_offset)->next = procno;
node->next = INVALID_PROC_NUMBER;
list->tail = procno;
}
}
/*
* Delete a process from a list - - - it must be in the list !
*/
static inline void
proclist_delete_offset(proclist_head *list, int procno, size_t node_offset)
{
proclist_node *node = proclist_node_get(procno, node_offset);
Assert(node->next != 0 || node->prev != 0 );
if (node->prev == INVALID_PROC_NUMBER)
{
Assert(list->head == procno);
list->head = node->next;
}
else
proclist_node_get(node->prev, node_offset)->next = node->next;
if (node->next == INVALID_PROC_NUMBER)
{
Assert(list->tail == procno);
list->tail = node->prev;
}
else
proclist_node_get(node->next, node_offset)->prev = node->prev;
node->next = node->prev = 0 ;
}
/*
* Check if a process is currently in a list . It must be known that the
* process is not in any _ other_ proclist that uses the same proclist_node ,
* so that the only possibilities are that it is in this list or none .
*/
static inline bool
proclist_contains_offset(const proclist_head *list, int procno,
size_t node_offset)
{
const proclist_node *node = proclist_node_get(procno, node_offset);
/* If it's not in any list, it's definitely not in this one. */
if (node->prev == 0 && node->next == 0 )
return false ;
/*
* It must , in fact , be in this list . Ideally , in assert - enabled builds ,
* we ' d verify that . But since this function is typically used while
* holding a spinlock , crawling the whole list is unacceptable . However ,
* we can verify matters in O ( 1 ) time when the node is a list head or
* tail , and that seems worth doing , since in practice that should often
* be enough to catch mistakes .
*/
Assert(node->prev != INVALID_PROC_NUMBER || list->head == procno);
Assert(node->next != INVALID_PROC_NUMBER || list->tail == procno);
return true ;
}
/*
* Remove and return the first process from a list ( there must be one ) .
*/
static inline PGPROC *
proclist_pop_head_node_offset(proclist_head *list, size_t node_offset)
{
PGPROC *proc;
Assert(!proclist_is_empty(list));
proc = GetPGProcByNumber(list->head);
proclist_delete_offset(list, list->head, node_offset);
return proc;
}
/*
* Helper macros to avoid repetition of offsetof ( PGPROC , < member > ) .
* ' link_member ' is the name of a proclist_node member in PGPROC .
*/
#define proclist_delete(list, procno, link_member) \
proclist_delete_offset((list), (procno), offsetof(PGPROC, link_member))
#define proclist_push_head(list, procno, link_member) \
proclist_push_head_offset((list), (procno), offsetof(PGPROC, link_member))
#define proclist_push_tail(list, procno, link_member) \
proclist_push_tail_offset((list), (procno), offsetof(PGPROC, link_member))
#define proclist_pop_head_node(list, link_member) \
proclist_pop_head_node_offset((list), offsetof(PGPROC, link_member))
#define proclist_contains(list, procno, link_member) \
proclist_contains_offset((list), (procno), offsetof(PGPROC, link_member))
/*
* Iterate through the list pointed at by ' lhead ' , storing the current
* position in ' iter ' . ' link_member ' is the name of a proclist_node member in
* PGPROC . Access the current position with iter . cur .
*
* The only list modification allowed while iterating is deleting the current
* node with proclist_delete ( list , iter . cur , node_offset ) .
*/
#define proclist_foreach_modify(iter, lhead, link_member) \
for (AssertVariableIsOfTypeMacro(iter, proclist_mutable_iter), \
AssertVariableIsOfTypeMacro(lhead, proclist_head *), \
(iter).cur = (lhead)->head, \
(iter).next = (iter).cur == INVALID_PROC_NUMBER ? INVALID_PROC_NUMBER : \
proclist_node_get((iter).cur, \
offsetof(PGPROC, link_member))->next; \
(iter).cur != INVALID_PROC_NUMBER; \
(iter).cur = (iter).next, \
(iter).next = (iter).cur == INVALID_PROC_NUMBER ? INVALID_PROC_NUMBER : \
proclist_node_get((iter).cur, \
offsetof(PGPROC, link_member))->next)
#endif /* PROCLIST_H */
Messung V0.5 in Prozent C=91 H=96 G=93
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-08-08)
¤
*© Formatika GbR, Deutschland