VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/misc/circbuf.cpp@ 44940

Last change on this file since 44940 was 39350, checked in by vboxsync, 13 years ago

Runtime: add methods for checking if something is in use in a circular buffer

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.3 KB
Line 
1/* $Id: circbuf.cpp 39350 2011-11-17 15:07:24Z vboxsync $ */
2/** @file
3 * IPRT - Lock Free Circular Buffer
4 */
5
6/*
7 * Copyright (C) 2011 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include <iprt/circbuf.h>
32#include <iprt/mem.h>
33#include <iprt/assert.h>
34#include <iprt/asm.h>
35#include <iprt/err.h>
36
37
38/*******************************************************************************
39* Structures and Typedefs *
40*******************************************************************************/
41/** @todo r=bird: this is missing docs and magic. */
42typedef struct RTCIRCBUF
43{
44 /** The current read position in the buffer. */
45 size_t offRead;
46 /** Is a read block acquired currently? */
47 bool fReading;
48 /** Is a write block acquired currently? */
49 bool fWriting;
50 /** The current write position in the buffer. */
51 size_t offWrite;
52 /** How much space of the buffer is currently in use. */
53 volatile size_t cbUsed;
54 /** How big is the buffer. */
55 size_t cbBuf;
56 /** The buffer itself. */
57 void *pvBuf;
58} RTCIRCBUF, *PRTCIRCBUF;
59
60
61RTDECL(int) RTCircBufCreate(PRTCIRCBUF *ppBuf, size_t cbSize)
62{
63 /* Validate input. */
64 AssertPtrReturn(ppBuf, VERR_INVALID_POINTER);
65 AssertReturn(cbSize > 0, VERR_INVALID_PARAMETER);
66
67 PRTCIRCBUF pTmpBuf;
68 pTmpBuf = (PRTCIRCBUF)RTMemAllocZ(sizeof(RTCIRCBUF));
69 if (!pTmpBuf)
70 return VERR_NO_MEMORY;
71
72 pTmpBuf->pvBuf = RTMemAlloc(cbSize);
73 if (pTmpBuf->pvBuf)
74 {
75 pTmpBuf->cbBuf = cbSize;
76 *ppBuf = pTmpBuf;
77 return VINF_SUCCESS;
78 }
79
80 RTMemFree(pTmpBuf);
81 return VERR_NO_MEMORY;
82}
83
84
85RTDECL(void) RTCircBufDestroy(PRTCIRCBUF pBuf)
86{
87 /* Validate input. */
88 if (!pBuf)
89 return;
90 AssertPtr(pBuf);
91 RTMemFree(pBuf->pvBuf);
92 RTMemFree(pBuf);
93}
94
95
96RTDECL(void) RTCircBufReset(PRTCIRCBUF pBuf)
97{
98 /* Validate input. */
99 AssertPtr(pBuf);
100
101 pBuf->offRead = 0;
102 pBuf->offWrite = 0;
103 pBuf->cbUsed = 0;
104 pBuf->fReading = false;
105 pBuf->fWriting = false;
106}
107
108
109RTDECL(size_t) RTCircBufFree(PRTCIRCBUF pBuf)
110{
111 /* Validate input. */
112 AssertPtrReturn(pBuf, 0);
113
114 return pBuf->cbBuf - ASMAtomicReadZ(&pBuf->cbUsed);
115}
116
117
118RTDECL(size_t) RTCircBufUsed(PRTCIRCBUF pBuf)
119{
120 /* Validate input. */
121 AssertPtrReturn(pBuf, 0);
122
123 return ASMAtomicReadZ(&pBuf->cbUsed);
124}
125
126RTDECL(size_t) RTCircBufSize(PRTCIRCBUF pBuf)
127{
128 /* Validate input. */
129 AssertPtrReturn(pBuf, 0);
130
131 return pBuf->cbBuf;
132}
133
134RTDECL(bool) RTCircBufIsReading(PRTCIRCBUF pBuf)
135{
136 /* Validate input. */
137 AssertPtrReturn(pBuf, 0);
138
139 return ASMAtomicReadBool(&pBuf->fReading);
140}
141
142RTDECL(bool) RTCircBufIsWriting(PRTCIRCBUF pBuf)
143{
144 /* Validate input. */
145 AssertPtrReturn(pBuf, 0);
146
147 return ASMAtomicReadBool(&pBuf->fWriting);
148}
149
150RTDECL(void) RTCircBufAcquireReadBlock(PRTCIRCBUF pBuf, size_t cbReqSize, void **ppvStart, size_t *pcbSize)
151{
152 /* Validate input. */
153 AssertPtr(pBuf);
154 Assert(cbReqSize > 0);
155 AssertPtr(ppvStart);
156 AssertPtr(pcbSize);
157
158 *ppvStart = 0;
159 *pcbSize = 0;
160
161 /* How much is in use? */
162 size_t cbUsed = ASMAtomicReadZ(&pBuf->cbUsed);
163 if (cbUsed > 0)
164 {
165 /* Get the size out of the requested size, the read block till the end
166 * of the buffer & the currently used size. */
167 size_t cbSize = RT_MIN(cbReqSize, RT_MIN(pBuf->cbBuf - pBuf->offRead, cbUsed));
168 if (cbSize > 0)
169 {
170 /* Return the pointer address which point to the current read
171 * position. */
172 *ppvStart = (char *)pBuf->pvBuf + pBuf->offRead;
173 *pcbSize = cbSize;
174
175 ASMAtomicWriteBool(&pBuf->fReading, true);
176 }
177 }
178}
179
180
181RTDECL(void) RTCircBufReleaseReadBlock(PRTCIRCBUF pBuf, size_t cbSize)
182{
183 /* Validate input. */
184 AssertPtr(pBuf);
185
186 /* Split at the end of the buffer. */
187 pBuf->offRead = (pBuf->offRead + cbSize) % pBuf->cbBuf;
188
189 ASMAtomicSubZ(&pBuf->cbUsed, cbSize);
190 ASMAtomicWriteBool(&pBuf->fReading, false);
191}
192
193
194RTDECL(void) RTCircBufAcquireWriteBlock(PRTCIRCBUF pBuf, size_t cbReqSize, void **ppvStart, size_t *pcbSize)
195{
196 /* Validate input. */
197 AssertPtr(pBuf);
198 Assert(cbReqSize > 0);
199 AssertPtr(ppvStart);
200 AssertPtr(pcbSize);
201
202 *ppvStart = 0;
203 *pcbSize = 0;
204
205 /* How much is free? */
206 size_t cbFree = pBuf->cbBuf - ASMAtomicReadZ(&pBuf->cbUsed);
207 if (cbFree > 0)
208 {
209 /* Get the size out of the requested size, then write block till the end
210 * of the buffer & the currently free size. */
211 size_t cbSize = RT_MIN(cbReqSize, RT_MIN(pBuf->cbBuf - pBuf->offWrite, cbFree));
212 if (cbSize > 0)
213 {
214 /* Return the pointer address which point to the current write
215 * position. */
216 *ppvStart = (char*)pBuf->pvBuf + pBuf->offWrite;
217 *pcbSize = cbSize;
218
219 ASMAtomicWriteBool(&pBuf->fWriting, true);
220 }
221 }
222}
223
224
225RTDECL(void) RTCircBufReleaseWriteBlock(PRTCIRCBUF pBuf, size_t cbSize)
226{
227 /* Validate input. */
228 AssertPtr(pBuf);
229
230 /* Split at the end of the buffer. */
231 pBuf->offWrite = (pBuf->offWrite + cbSize) % pBuf->cbBuf;
232
233 ASMAtomicAddZ(&pBuf->cbUsed, cbSize);
234 ASMAtomicWriteBool(&pBuf->fWriting, false);
235}
236
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