VirtualBox

source: vbox/trunk/include/iprt/once.h@ 40979

Last change on this file since 40979 was 37316, checked in by vboxsync, 14 years ago

IPRT: Inlined the already-done check in RTOnce().

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.2 KB
Line 
1/** @file
2 * IPRT - Execute Once.
3 */
4
5/*
6 * Copyright (C) 2006-2007 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26#ifndef ___iprt_once_h
27#define ___iprt_once_h
28
29#include <iprt/cdefs.h>
30#include <iprt/types.h>
31#include <iprt/asm.h>
32#include <iprt/err.h>
33
34RT_C_DECLS_BEGIN
35
36/** @defgroup grp_rt_once RTOnce - Execute Once
37 * @ingroup grp_rt
38 * @{
39 */
40
41/**
42 * Execute once structure.
43 *
44 * This is typically a global variable that is statically initialized
45 * by RTONCE_INITIALIZER.
46 */
47typedef struct RTONCE
48{
49 /** Event semaphore that the other guys are blocking on. */
50 RTSEMEVENTMULTI volatile hEventMulti;
51 /** Reference counter for hEventMulti. */
52 int32_t volatile cEventRefs;
53 /** -1 when uninitialized, 1 when initializing (busy) and 2 when done. */
54 int32_t volatile iState;
55 /** The return code of pfnOnce. */
56 int32_t volatile rc;
57} RTONCE;
58/** Pointer to a execute once struct. */
59typedef RTONCE *PRTONCE;
60
61/**
62 * The execute once statemachine.
63 */
64typedef enum RTONCESTATE
65{
66 /** RTOnce() has not been called.
67 * Next: NO_SEM */
68 RTONCESTATE_UNINITIALIZED = 1,
69 /** RTOnce() is busy, no race.
70 * Next: CREATING_SEM, DONE */
71 RTONCESTATE_BUSY_NO_SEM,
72 /** More than one RTOnce() caller is busy.
73 * Next: BUSY_HAVE_SEM, BUSY_SPIN, DONE_CREATING_SEM, DONE */
74 RTONCESTATE_BUSY_CREATING_SEM,
75 /** More than one RTOnce() caller, the first is busy, the others are
76 * waiting.
77 * Next: DONE */
78 RTONCESTATE_BUSY_HAVE_SEM,
79 /** More than one RTOnce() caller, the first is busy, the others failed to
80 * create a semaphore and are spinning.
81 * Next: DONE */
82 RTONCESTATE_BUSY_SPIN,
83 /** More than one RTOnce() caller, the first has completed, the others
84 * are busy creating the semaphore.
85 * Next: DONE_HAVE_SEM */
86 RTONCESTATE_DONE_CREATING_SEM,
87 /** More than one RTOnce() caller, the first is busy grabbing the
88 * semaphore, while the others are waiting.
89 * Next: DONE */
90 RTONCESTATE_DONE_HAVE_SEM,
91 /** The execute once stuff has completed. */
92 RTONCESTATE_DONE = 16
93} RTONCESTATE;
94
95/** Static initializer for RTONCE variables. */
96#define RTONCE_INITIALIZER { NIL_RTSEMEVENTMULTI, 0, RTONCESTATE_UNINITIALIZED, VERR_INTERNAL_ERROR }
97
98
99/**
100 * Callback that gets executed once.
101 *
102 * @returns IPRT style status code, RTOnce returns this.
103 *
104 * @param pvUser1 The first user parameter.
105 * @param pvUser2 The second user parameter.
106 */
107typedef DECLCALLBACK(int32_t) FNRTONCE(void *pvUser1, void *pvUser2);
108/** Pointer to a FNRTONCE. */
109typedef FNRTONCE *PFNRTONCE;
110
111/**
112 * Serializes execution of the pfnOnce function, making sure it's
113 * executed exactly once and that nobody returns from RTOnce before
114 * it has executed successfully.
115 *
116 * @returns IPRT like status code returned by pfnOnce.
117 *
118 * @param pOnce Pointer to the execute once variable.
119 * @param pfnOnce The function to executed once.
120 * @param pvUser1 The first user parameter for pfnOnce.
121 * @param pvUser2 The second user parameter for pfnOnce.
122 */
123RTDECL(int) RTOnceSlow(PRTONCE pOnce, PFNRTONCE pfnOnce, void *pvUser1, void *pvUser2);
124
125/**
126 * Serializes execution of the pfnOnce function, making sure it's
127 * executed exactly once and that nobody returns from RTOnce before
128 * it has executed successfully.
129 *
130 * @returns IPRT like status code returned by pfnOnce.
131 *
132 * @param pOnce Pointer to the execute once variable.
133 * @param pfnOnce The function to executed once.
134 * @param pvUser1 The first user parameter for pfnOnce.
135 * @param pvUser2 The second user parameter for pfnOnce.
136 */
137DECLINLINE(int) RTOnce(PRTONCE pOnce, PFNRTONCE pfnOnce, void *pvUser1, void *pvUser2)
138{
139 int32_t iState = ASMAtomicUoReadS32(&pOnce->iState);
140 if (RT_LIKELY( iState == RTONCESTATE_DONE
141 || iState == RTONCESTATE_DONE_CREATING_SEM
142 || iState == RTONCESTATE_DONE_HAVE_SEM ))
143 return ASMAtomicUoReadS32(&pOnce->rc);
144 return RTOnceSlow(pOnce, pfnOnce, pvUser1, pvUser2);
145}
146
147/**
148 * Resets an execute once variable.
149 *
150 * The caller is responsible for making sure there are no concurrent accesses to
151 * the execute once variable.
152 *
153 * @param pOnce Pointer to the execute once variable.
154 */
155RTDECL(void) RTOnceReset(PRTONCE pOnce);
156
157/** @} */
158
159RT_C_DECLS_END
160
161#endif
162
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette