]>
Commit | Line | Data |
---|---|---|
1bf9f027 DL |
1 | /* |
2 | * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc. | |
3 | * | |
db2d8df6 DL |
4 | * Permission to use, copy, modify, and distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | |
6 | * copyright notice and this permission notice appear in all copies. | |
1bf9f027 | 7 | * |
db2d8df6 DL |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
1bf9f027 DL |
15 | */ |
16 | ||
17 | #ifndef _QOBJ_H | |
18 | #define _QOBJ_H | |
19 | ||
20 | #include <stdint.h> | |
21 | #include <stdlib.h> | |
22 | #include <stddef.h> | |
23 | ||
679b1649 DL |
24 | #include "typesafe.h" |
25 | ||
5e244469 RW |
26 | #ifdef __cplusplus |
27 | extern "C" { | |
28 | #endif | |
29 | ||
1bf9f027 DL |
30 | /* reserve a specific amount of bytes for a struct, which can grow up to |
31 | * that size (or be dummy'd out if not needed) | |
32 | * | |
33 | * note the padding's array size will be an error if it gets negative or zero; | |
34 | * this is intentional to prevent the struct from growing beyond the allocated | |
35 | * space. | |
36 | */ | |
f8cd615b | 37 | #ifndef __cplusplus |
d62a17ae | 38 | #define RESERVED_SPACE_STRUCT(name, fieldname, size) \ |
39 | struct { \ | |
40 | struct name fieldname; \ | |
41 | char padding##fieldname[size - sizeof(struct name)]; \ | |
1bf9f027 | 42 | }; |
f8cd615b DL |
43 | #else |
44 | #define RESERVED_SPACE_STRUCT(name, fieldname, size) \ | |
45 | struct name fieldname; \ | |
46 | char padding##fieldname[size - sizeof(struct name)]; | |
47 | #endif | |
1bf9f027 DL |
48 | |
49 | /* don't need struct definitions for these here. code actually using | |
50 | * these needs to define the struct *before* including this header. | |
51 | * HAVE_QOBJ_xxx should be defined to +1 in that case, like this: | |
52 | * | |
53 | * #if defined(HAVE_QOBJ_NODETYPE_CLI) && HAVE_QOBJ_NODETYPE_CLI < 0 | |
54 | * #error include files are in wrong order | |
55 | * #else | |
56 | * #define HAVE_QOBJ_NODETYPE_CLI 1 | |
57 | * struct qobj_nodetype_cli { ... } | |
58 | * #endif | |
59 | */ | |
60 | #ifndef HAVE_QOBJ_NODETYPE_CLI | |
61 | #define HAVE_QOBJ_NODETYPE_CLI -1 | |
d62a17ae | 62 | struct qobj_nodetype_cli { |
63 | int dummy; | |
64 | }; | |
1bf9f027 DL |
65 | #endif |
66 | ||
67 | #ifndef HAVE_QOBJ_NODETYPE_CAPNP | |
68 | #define HAVE_QOBJ_NODETYPE_CAPNP -1 | |
d62a17ae | 69 | struct qobj_nodetype_capnp { |
70 | int dummy; | |
71 | }; | |
1bf9f027 DL |
72 | #endif |
73 | ||
679b1649 DL |
74 | #include "typesafe.h" |
75 | ||
1bf9f027 DL |
76 | /* each different kind of object will have a global variable of this type, |
77 | * which can be used by various other pieces to store type-related bits. | |
78 | * type equality can be tested as pointer equality. (cf. QOBJ_GET_TYPESAFE) | |
79 | */ | |
80 | struct qobj_nodetype { | |
81 | ptrdiff_t node_member_offset; | |
82 | RESERVED_SPACE_STRUCT(qobj_nodetype_cli, cli, 256) | |
83 | RESERVED_SPACE_STRUCT(qobj_nodetype_capnp, capnp, 256) | |
84 | }; | |
85 | ||
679b1649 DL |
86 | PREDECL_HASH(qobj_nodes) |
87 | ||
1bf9f027 DL |
88 | /* anchor to be embedded somewhere in the object's struct */ |
89 | struct qobj_node { | |
90 | uint64_t nid; | |
679b1649 | 91 | struct qobj_nodes_item nodehash; |
154e9ca1 | 92 | const struct qobj_nodetype *type; |
1bf9f027 DL |
93 | }; |
94 | ||
d62a17ae | 95 | #define QOBJ_FIELDS struct qobj_node qobj_node; |
1bf9f027 DL |
96 | |
97 | /* call these at the end of any _create function (QOBJ_REG) | |
98 | * and beginning of any _destroy function (QOBJ_UNREG) */ | |
d62a17ae | 99 | #define QOBJ_REG(n, structname) qobj_reg(&n->qobj_node, &qobj_t_##structname) |
100 | #define QOBJ_UNREG(n) qobj_unreg(&n->qobj_node) | |
1bf9f027 | 101 | |
297c8f6a DL |
102 | /* internals - should not be directly used without a good reason |
103 | * | |
104 | * note: qobj_get is essentially never safe to use in MT context because | |
105 | * the object could be deleted by another thread -- and worse, it could be | |
106 | * of the "wrong" type and deleted. | |
107 | * | |
108 | * with qobj_get_typed, the type check is done under lock, which means that | |
109 | * it can be used as long as another lock prevents the deletion of objects | |
110 | * of the expected type. | |
111 | * | |
112 | * in the long this may need another touch, e.g. built-in per-object locking. | |
113 | */ | |
154e9ca1 | 114 | void qobj_reg(struct qobj_node *node, const struct qobj_nodetype *type); |
1bf9f027 DL |
115 | void qobj_unreg(struct qobj_node *node); |
116 | struct qobj_node *qobj_get(uint64_t id); | |
154e9ca1 | 117 | void *qobj_get_typed(uint64_t id, const struct qobj_nodetype *type); |
1bf9f027 DL |
118 | |
119 | /* type declarations */ | |
d62a17ae | 120 | #define DECLARE_QOBJ_TYPE(structname) \ |
154e9ca1 | 121 | extern const struct qobj_nodetype qobj_t_##structname; |
d62a17ae | 122 | #define DEFINE_QOBJ_TYPE(structname) \ |
154e9ca1 | 123 | const struct qobj_nodetype qobj_t_##structname = { \ |
d62a17ae | 124 | .node_member_offset = \ |
125 | (ptrdiff_t)offsetof(struct structname, qobj_node)}; | |
126 | #define DEFINE_QOBJ_TYPE_INIT(structname, ...) \ | |
154e9ca1 | 127 | const struct qobj_nodetype qobj_t_##structname = { \ |
d62a17ae | 128 | .node_member_offset = \ |
129 | (ptrdiff_t)offsetof(struct structname, qobj_node), \ | |
130 | __VA_ARGS__}; | |
1bf9f027 DL |
131 | |
132 | /* ID dereference with typecheck. | |
133 | * will return NULL if id not found or wrong type. */ | |
d62a17ae | 134 | #define QOBJ_GET_TYPESAFE(id, structname) \ |
135 | ((struct structname *)qobj_get_typed((id), &qobj_t_##structname)) | |
1bf9f027 | 136 | |
d62a17ae | 137 | #define QOBJ_ID(ptr) ((ptr)->qobj_node.nid) |
138 | #define QOBJ_ID_0SAFE(ptr) \ | |
139 | ({ \ | |
140 | typeof(ptr) _ptr = (ptr); \ | |
141 | _ptr ? _ptr->qobj_node.nid : 0ULL; \ | |
142 | }) | |
1bf9f027 DL |
143 | |
144 | void qobj_init(void); | |
145 | void qobj_finish(void); | |
146 | ||
5e244469 RW |
147 | #ifdef __cplusplus |
148 | } | |
149 | #endif | |
150 | ||
1bf9f027 | 151 | #endif /* _QOBJ_H */ |