/** * Looking Glass * Copyright © 2017-2022 The Looking Glass Authors * https://looking-glass.io * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., 59 * Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _H_LL_ #define _H_LL_ #include #include #include "common/locking.h" struct ll_item { void * data; struct ll_item * prev, * next; }; struct ll { struct ll_item * head; struct ll_item * tail; struct ll_item * pos; unsigned int count; LG_Lock lock; }; struct ll * ll_new(); void ll_free (struct ll * list); void ll_push (struct ll * list, void * data); bool ll_shift (struct ll * list, void ** data); bool ll_peek_head(struct ll * list, void ** data); bool ll_peek_tail(struct ll * list, void ** data); bool ll_walk (struct ll * list, void ** data); #define ll_lock(ll) LG_LOCK((ll)->lock) #define ll_unlock(ll) LG_UNLOCK((ll)->lock) #define ll_forEachNL(ll, item, v) \ for(struct ll_item * item = (ll)->head, * _ = (ll)->head->next; (item);) \ for((v) = (__typeof__(v))((item)->data); (item); (item) = _, \ _ = _ ? _->next : NULL, (v) = (__typeof__(v))((item)->data)) static inline unsigned int ll_count(struct ll * list) { return list->count; } static inline void ll_reset (struct ll * list) { LG_LOCK(list->lock); list->pos = NULL; LG_UNLOCK(list->lock); } static inline void ll_removeNL(struct ll * list, struct ll_item * item) { --list->count; if (list->head == item) list->head = item->next; if (list->tail == item) list->tail = item->prev; if (item->prev) item->prev->next = item->next; if (item->next) item->next->prev = item->prev; list->pos = NULL; } static inline bool ll_removeData(struct ll * list, void * match) { void * data; ll_lock(list); ll_forEachNL(list, item, data) if (data == match) { ll_removeNL(list, item); ll_unlock(list); free(item); return true; } ll_unlock(list); return false; } #endif