aboutsummaryrefslogtreecommitdiffstats
path: root/src/cxx_linuxlist.h
blob: 1562bfe1ebfc76e00b6f085c9d3c6ce75008bfc1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* 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));
}