summaryrefslogtreecommitdiffstats
path: root/include/iprt/handletable.h
blob: f5b74b4bb59e6a76daf58970d00f9f5028014492 (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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/** @file
 * IPRT - Handle Tables.
 */

/*
 * Copyright (C) 2008-2019 Oracle Corporation
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 *
 * The contents of this file may alternatively be used under the terms
 * of the Common Development and Distribution License Version 1.0
 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
 * VirtualBox OSE distribution, in which case the provisions of the
 * CDDL are applicable instead of those of the GPL.
 *
 * You may elect to license modified versions of this file under the
 * terms and conditions of either the GPL or the CDDL or both.
 */

#ifndef IPRT_INCLUDED_handletable_h
#define IPRT_INCLUDED_handletable_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif

#include <iprt/cdefs.h>
#include <iprt/types.h>

RT_C_DECLS_BEGIN

/** @defgroup grp_rt_handletable    RTHandleTable - Handle Tables
 * @ingroup grp_rt
 * @{
 */

/**
 * Callback for retaining an object during the lookup and free calls.
 *
 * This callback is executed when a handle is being looked up in one
 * way or another from behind the handle table lock. This allows you
 * to increase the reference (or some equivalent thing) during the
 * handle lookup and thereby eliminate any race with anyone trying
 * to free the handle.
 *
 * Note that there is no counterpart to this callback, so if you make
 * use of this you'll have to release the object manually of course.
 *
 * Another use of this callback is to do some extra access checking.
 * Use the return code to indicate whether the lookup should fail
 * or not (no object is returned on faliure, naturally).
 *
 * @returns IPRT status code for the lookup (the caller won't see this).
 *
 * @param   hHandleTable    The handle table handle.
 * @param   pvObj           The object which has been looked up.
 * @param   pvCtx           The context argument if the handle table was created with the
 *                          RTHANDLETABLE_FLAGS_CONTEXT set. Otherwise NULL.
 * @param   pvUser          The user context argument specified when creating the table.
 */
typedef DECLCALLBACK(int) FNRTHANDLETABLERETAIN(RTHANDLETABLE hHandleTable, void *pvObj, void *pvCtx, void *pvUser);
/** Pointer to a FNHANDLETABLERETAIN. */
typedef FNRTHANDLETABLERETAIN *PFNRTHANDLETABLERETAIN;

/**
 * Callback for deleting a left over object during RTHandleTableDestroy.
 *
 * @param   hHandleTable    The handle table handle.
 * @param   h               The handle.
 * @param   pvObj           The object.
 * @param   pvCtx           The context argument if the handle table was created with the
 *                          RTHANDLETABLE_FLAGS_CONTEXT set. Otherwise NULL.
 * @param   pvUser          The user context argument specified when creating the table.
 *
 */
typedef DECLCALLBACK(void) FNRTHANDLETABLEDELETE(RTHANDLETABLE hHandleTable, uint32_t h, void *pvObj, void *pvCtx, void *pvUser);
/** Pointer to a FNRTHANDLETABLEDELETE. */
typedef FNRTHANDLETABLEDELETE *PFNRTHANDLETABLEDELETE;


/** @name RTHandleTableCreateEx flags
 * @{ */
/** Whether the handle table entries takes a context or not.
 *
 * This can be useful for associating a handle with for instance a process or
 * similar in order to prevent anyone but the owner from using the handle.
 *
 * Setting this means you will have to use the WithCtx functions to do the
 * handle management. */
#define RTHANDLETABLE_FLAGS_CONTEXT         RT_BIT_32(0)
/** Whether the handle table should take care of the serialization (IRQ unsafe).
 * If not specified the caller will have to take care of that. */
#define RTHANDLETABLE_FLAGS_LOCKED          RT_BIT_32(1)
/** Like RTHANDLETABLE_FLAGS_LOCKED, except it's IRQ safe.
 * A side-effect is that callbacks may be called with IRQs disabled.  */
#define RTHANDLETABLE_FLAGS_LOCKED_IRQ_SAFE RT_BIT_32(2)
/** The mask of valid flags. */
#define RTHANDLETABLE_FLAGS_MASK            UINT32_C(0x00000007)
/** @} */


/**
 * Creates a handle table.
 *
 * The handle table translates a 32-bit handle into an object pointer,
 * optionally calling you back so you can retain the object without
 * racing RTHandleTableFree.
 *
 * @returns IPRT status code and on success a handle table handle will be stored at the
 *          location phHandleTable points at.
 *
 * @param   phHandleTable   Where to store the handle table handle on success.
 * @param   fFlags          Flags, see RTHANDLETABLE_FLAGS_*.
 * @param   uBase           The handle base value. This is the value of the
 *                          first handle to be returned.
 * @param   cMax            The max number of handles. When exceeded the RTHandleTableAlloc
 *                          or RTHandleTableAllocWithCtx calls will fail. Note that this
 *                          number will be rounded up to a multiple of the sub-table size,
 *                          or if it's too close to UINT32_MAX it will be rounded down.
 * @param   pfnRetain       Optional retain callback that will be called from behind the
 *                          lock (if any) during lookup.
 * @param   pvUser          The user argument to the retain callback.
 */
RTDECL(int)     RTHandleTableCreateEx(PRTHANDLETABLE phHandleTable, uint32_t fFlags, uint32_t uBase, uint32_t cMax,
                                      PFNRTHANDLETABLERETAIN pfnRetain, void *pvUser);

/**
 * A simplified version of the RTHandleTableCreateEx API.
 *
 * It assumes a max of about 64K handles with 1 being the base. The table
 * access will serialized (RTHANDLETABLE_FLAGS_LOCKED).
 *
 * @returns IPRT status code and *phHandleTable.
 *
 * @param   phHandleTable   Where to store the handle table handle on success.
 */
RTDECL(int)     RTHandleTableCreate(PRTHANDLETABLE phHandleTable);

/**
 * Destroys a handle table.
 *
 * If any entries are still in used the pfnDelete callback will be invoked
 * on each of them (if specfied) to allow to you clean things up.
 *
 * @returns IPRT status code
 *
 * @param   hHandleTable    The handle to the handle table.
 * @param   pfnDelete       Function to be called back on each handle still in use. Optional.
 * @param   pvUser          The user argument to pfnDelete.
 */
RTDECL(int)     RTHandleTableDestroy(RTHANDLETABLE hHandleTable, PFNRTHANDLETABLEDELETE pfnDelete, void *pvUser);

/**
 * Allocates a handle from the handle table.
 *
 * @returns IPRT status code, almost any.
 * @retval  VINF_SUCCESS on success.
 * @retval  VERR_NO_MEMORY if we failed to extend the handle table.
 * @retval  VERR_NO_MORE_HANDLES if we're out of handles.
 *
 * @param   hHandleTable    The handle to the handle table.
 * @param   pvObj           The object to associate with the new handle.
 *                          This must be aligned on a 4 byte boundary.
 * @param   ph              Where to return the handle on success.
 *
 * @remarks Do not call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation.
 */
RTDECL(int)     RTHandleTableAlloc(RTHANDLETABLE hHandleTable, void *pvObj, uint32_t *ph);

/**
 * Looks up a handle.
 *
 * @returns The object pointer on success. NULL on failure.
 *
 * @param   hHandleTable    The handle to the handle table.
 * @param   h               The handle to lookup.
 *
 * @remarks Do not call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation.
 */
RTDECL(void *)  RTHandleTableLookup(RTHANDLETABLE hHandleTable, uint32_t h);

/**
 * Looks up and frees a handle.
 *
 * @returns The object pointer on success. NULL on failure.
 *
 * @param   hHandleTable    The handle to the handle table.
 * @param   h               The handle to lookup.
 *
 * @remarks Do not call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation.
 */
RTDECL(void *)  RTHandleTableFree(RTHANDLETABLE hHandleTable, uint32_t h);

/**
 * Allocates a handle from the handle table.
 *
 * @returns IPRT status code, almost any.
 * @retval  VINF_SUCCESS on success.
 * @retval  VERR_NO_MEMORY if we failed to extend the handle table.
 * @retval  VERR_NO_MORE_HANDLES if we're out of handles.
 *
 * @param   hHandleTable    The handle to the handle table.
 * @param   pvObj           The object to associate with the new handle.
 *                          This must be aligned on a 4 byte boundary.
 * @param   pvCtx           The context to associate with the new handle.
 * @param   ph              Where to return the handle on success.
 *
 * @remarks Call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation.
 */
RTDECL(int)     RTHandleTableAllocWithCtx(RTHANDLETABLE hHandleTable, void *pvObj, void *pvCtx, uint32_t *ph);

/**
 * Looks up a handle.
 *
 * @returns The object pointer on success. NULL on failure.
 *
 * @param   hHandleTable    The handle to the handle table.
 * @param   h               The handle to lookup.
 * @param   pvCtx           The handle context, this must match what was given on allocation.
 *
 * @remarks Call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation.
 */
RTDECL(void *)  RTHandleTableLookupWithCtx(RTHANDLETABLE hHandleTable, uint32_t h, void *pvCtx);

/**
 * Looks up and frees a handle.
 *
 * @returns The object pointer on success. NULL on failure.
 *
 * @param   hHandleTable    The handle to the handle table.
 * @param   h               The handle to lookup.
 * @param   pvCtx           The handle context, this must match what was given on allocation.
 *
 * @remarks Call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation.
 */
RTDECL(void *)  RTHandleTableFreeWithCtx(RTHANDLETABLE hHandleTable, uint32_t h, void *pvCtx);

/** @} */

RT_C_DECLS_END


#endif /* !IPRT_INCLUDED_handletable_h */