| /* cxx_linuxlist.h |
| * |
| * Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH |
| * Author: Jacob Erlbeck <jerlbeck@sysmocom.de> |
| * |
| * 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. |
| */ |
| |
| #pragma once |
| |
| extern "C" { |
| #include <osmocom/core/linuxlist.h> |
| } |
| |
| template <typename T> |
| struct LListHead { |
| typedef T entry_t; |
| |
| /* This must match the declaration of struct llist_head */ |
| LListHead<T> *next; |
| LListHead<T> *prev; |
| |
| LListHead() : m_back(0) { INIT_LLIST_HEAD(this); } |
| LListHead(T* entry) : m_back(entry) { |
| next = (LListHead<T> *)LLIST_POISON1; |
| prev = (LListHead<T> *)LLIST_POISON2; |
| } |
| |
| T *entry() {return m_back;} |
| const T *entry() const {return m_back;} |
| |
| llist_head &llist() { |
| return *static_cast<llist_head *>(static_cast<void *>(this)); |
| } |
| const llist_head &llist() const { |
| return *static_cast<const llist_head *>(static_cast<const void *>(this)); |
| } |
| |
| private: |
| T *const m_back; |
| }; |
| |
| /* Define a family of casting functions */ |
| template <typename T> |
| llist_head &llist(LListHead<T> &l) |
| { |
| return l->llist(); |
| } |
| |
| template <typename T> |
| const llist_head &llist(const LListHead<T> &l) |
| { |
| return l->llist(); |
| } |
| |
| template <typename T> |
| llist_head *llptr(LListHead<T> *l) |
| { |
| return &(l->llist()); |
| } |
| |
| template <typename T> |
| const llist_head *llptr(const LListHead<T> *l) |
| { |
| return &(l->llist()); |
| } |
| |
| /* Define type-safe wrapper for the existing linux_list.h functions */ |
| template <typename T> |
| inline void llist_add(LListHead<T> *new_, LListHead<T> *head) |
| { |
| llist_add(llptr(new_), llptr(head)); |
| } |
| |
| template <typename T> |
| inline void llist_add_tail(LListHead<T> *new_, LListHead<T> *head) |
| { |
| llist_add_tail(llptr(new_), llptr(head)); |
| } |
| |
| template <typename T> |
| inline void llist_del(LListHead<T> *entry) |
| { |
| llist_del(llptr(entry)); |
| } |
| |
| template <typename T> |
| inline void llist_del_init(LListHead<T> *entry) |
| { |
| llist_del_init(llptr(entry)); |
| } |
| |
| template <typename T> |
| inline void llist_move(LListHead<T> *list, LListHead<T> *head) |
| { |
| llist_move(llptr(list), llptr(head)); |
| } |
| |
| template <typename T> |
| inline void llist_move_tail(LListHead<T> *list, LListHead<T> *head) |
| { |
| llist_move_tail(llptr(list), llptr(head)); |
| } |
| |
| template <typename T> |
| inline int llist_empty(const LListHead<T> *head) |
| { |
| return llist_empty(llptr(head)); |
| } |
| |
| template <typename T> |
| inline void llist_splice(LListHead<T> *list, LListHead<T> *head) |
| { |
| llist_splice(llptr(list), llptr(head)); |
| } |
| |
| template <typename T> |
| inline void llist_splice_init(LListHead<T> *list, LListHead<T> *head) |
| { |
| llist_splice_init(llptr(list), llptr(head)); |
| } |