VirtualBox

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

Last change on this file since 78052 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.9 KB
Line 
1/* $Id: circbuf.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * IPRT - Lock Free Circular Buffer
4 */
5
6/*
7 * Copyright (C) 2011-2019 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/errcore.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(size_t) RTCircBufOffsetRead(PRTCIRCBUF pBuf)
151{
152 /* Validate input. */
153 AssertPtrReturn(pBuf, 0);
154
155 return ASMAtomicReadZ(&pBuf->offRead);
156}
157
158RTDECL(size_t) RTCircBufOffsetWrite(PRTCIRCBUF pBuf)
159{
160 /* Validate input. */
161 AssertPtrReturn(pBuf, 0);
162
163 return ASMAtomicReadZ(&pBuf->offWrite);
164}
165
166RTDECL(void) RTCircBufAcquireReadBlock(PRTCIRCBUF pBuf, size_t cbReqSize, void **ppvStart, size_t *pcbSize)
167{
168 /* Validate input. */
169 AssertPtr(pBuf);
170 Assert(cbReqSize > 0);
171 AssertPtr(ppvStart);
172 AssertPtr(pcbSize);
173
174 *ppvStart = 0;
175 *pcbSize = 0;
176
177 /* How much is in use? */
178 size_t cbUsed = ASMAtomicReadZ(&pBuf->cbUsed);
179 if (cbUsed > 0)
180 {
181 /* Get the size out of the requested size, the read block till the end
182 * of the buffer & the currently used size. */
183 size_t cbSize = RT_MIN(cbReqSize, RT_MIN(pBuf->cbBuf - pBuf->offRead, cbUsed));
184 if (cbSize > 0)
185 {
186 /* Return the pointer address which point to the current read
187 * position. */
188 *ppvStart = (char *)pBuf->pvBuf + pBuf->offRead;
189 *pcbSize = cbSize;
190
191 ASMAtomicWriteBool(&pBuf->fReading, true);
192 }
193 }
194}
195
196
197RTDECL(void) RTCircBufReleaseReadBlock(PRTCIRCBUF pBuf, size_t cbSize)
198{
199 /* Validate input. */
200 AssertPtr(pBuf);
201
202 /* Split at the end of the buffer. */
203 pBuf->offRead = (pBuf->offRead + cbSize) % pBuf->cbBuf;
204
205 ASMAtomicSubZ(&pBuf->cbUsed, cbSize);
206 ASMAtomicWriteBool(&pBuf->fReading, false);
207}
208
209
210RTDECL(void) RTCircBufAcquireWriteBlock(PRTCIRCBUF pBuf, size_t cbReqSize, void **ppvStart, size_t *pcbSize)
211{
212 /* Validate input. */
213 AssertPtr(pBuf);
214 Assert(cbReqSize > 0);
215 AssertPtr(ppvStart);
216 AssertPtr(pcbSize);
217
218 *ppvStart = 0;
219 *pcbSize = 0;
220
221 /* How much is free? */
222 size_t cbFree = pBuf->cbBuf - ASMAtomicReadZ(&pBuf->cbUsed);
223 if (cbFree > 0)
224 {
225 /* Get the size out of the requested size, then write block till the end
226 * of the buffer & the currently free size. */
227 size_t cbSize = RT_MIN(cbReqSize, RT_MIN(pBuf->cbBuf - pBuf->offWrite, cbFree));
228 if (cbSize > 0)
229 {
230 /* Return the pointer address which point to the current write
231 * position. */
232 *ppvStart = (char*)pBuf->pvBuf + pBuf->offWrite;
233 *pcbSize = cbSize;
234
235 ASMAtomicWriteBool(&pBuf->fWriting, true);
236 }
237 }
238}
239
240
241RTDECL(void) RTCircBufReleaseWriteBlock(PRTCIRCBUF pBuf, size_t cbSize)
242{
243 /* Validate input. */
244 AssertPtr(pBuf);
245
246 /* Split at the end of the buffer. */
247 pBuf->offWrite = (pBuf->offWrite + cbSize) % pBuf->cbBuf;
248
249 ASMAtomicAddZ(&pBuf->cbUsed, cbSize);
250 ASMAtomicWriteBool(&pBuf->fWriting, false);
251}
252
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