/* * Copyright (c) 2003, 2004 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: ringhd.h,v 1.7 2006/12/26 23:43:36 ca Exp $ */ #ifndef SM_RINGHD_H #define SM_RINGHD_H 1 #include "sm/generic.h" #include "sm/types.h" #include "sm/assert.h" #include "sm/ring.h" /* ** Define a ring with a head (see sm/ring.h about rings). ** The head points to one element in a ring. ** Special precautions must be taken: ** - for append/prepend if the ring is empty (hd == NULL) ** - for delete if the ring has only one element ** ** hd: head of ring: pointer to a structure that has a ring embedded ** entry: pointer to a structure that has a ring embedded ** entry_ring: pointer to ring ** ring_member: name of field that is the ring in structure ** ** append(hd, entry) makes entry the last element in the list, ** i.e., it prepend entry to the element that hd points to. ** prepend(hd, entry) makes entry the first element in the list, ** i.e., it prepend entry to the element that hd points to and ** hd points afterwards to entry. ** ** Note: it is possible to perform operations on the ring itself, ** especially walking through the entries, and even adding entries. ** However, deleting entries will cause problems if: ** - the ring becomes empty ** - the entry to which the head points is removed. ** Be careful! ** ** example: struct entry_S { some e_types; sm_ring_T e_ring; }; struct head_S { some hd_types; entry_P hd_entry; }; entry_P entry; head_P hd; SM_RINGHD_INIT(hd->hd_entry); SM_RINGHD_APPEND(hd, entry, e_ring); SM_RINGHD_DELETE(hd, &(entry->e_ring)); */ #ifndef SM_RINGHD_INLINE # define SM_RINGHD_INLINE 0 #endif #define SM_RINGHD_INIT(hd_entry) (hd_entry) = NULLPTR #define SM_RINGHD_APPEND(hd, entry, ring_member) \ do { \ if ((hd) == NULLPTR) { \ (hd) = (entry); \ SM_RING_INIT(&((entry)->ring_member)); \ } \ else { \ SM_RING_PREPEND(&((hd)->ring_member), \ &((entry)->ring_member)); \ } \ } while (0) #define SM_RINGHD_PREPEND(hd, entry, ring_member) \ do { \ if ((hd) == NULLPTR) { \ SM_RING_INIT(&((entry)->ring_member)); \ } \ else { \ SM_RING_PREPEND(&((hd)->ring_member), \ &((entry)->ring_member)); \ } \ (hd) = (entry); \ } while (0) #define SM_RINGHD_DELENTRY(hd, entry_ring) \ do { \ sm_ring_P succ, pred; \ \ SM_REQUIRE((hd) != NULLPTR); \ succ = (entry_ring)->sm_rg_succ; \ pred = (entry_ring)->sm_rg_pred; \ if ((succ == NULL && pred == NULL) \ || (succ == (entry_ring) && pred == (entry_ring))) \ (hd) = NULLPTR; \ else { \ pred->sm_rg_succ = succ; \ succ->sm_rg_pred = pred; \ (entry_ring)->sm_rg_succ = \ (entry_ring)->sm_rg_pred = NULL; \ } \ } while (0) #endif /* SM_RINGHD_H */