1 /* Implementation of a ring buffer for reports
3 * Copyright 2015 CodeWeavers, Aric Stewart
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define NONAMELESSUNION
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(hid
);
29 #define BASE_BUFFER_SIZE 32
30 #define MIN_BUFFER_SIZE 2
31 #define MAX_BUFFER_SIZE 512
33 struct ReportRingBuffer
35 UINT start
, end
, size
;
41 CRITICAL_SECTION lock
;
46 struct ReportRingBuffer
* RingBuffer_Create(UINT buffer_size
)
48 struct ReportRingBuffer
*ring
;
49 TRACE("Create Ring Buffer with buffer size %i\n",buffer_size
);
50 ring
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ring
));
53 ring
->start
= ring
->end
= 0;
54 ring
->size
= BASE_BUFFER_SIZE
;
55 ring
->buffer_size
= buffer_size
;
56 ring
->pointer_alloc
= 2;
57 ring
->pointers
= HeapAlloc(GetProcessHeap(), 0, sizeof(int) * ring
->pointer_alloc
);
60 HeapFree(GetProcessHeap(), 0, ring
);
63 memset(ring
->pointers
, 0xff, sizeof(int) * ring
->pointer_alloc
);
64 ring
->buffer
= HeapAlloc(GetProcessHeap(), 0, buffer_size
* ring
->size
);
67 HeapFree(GetProcessHeap(), 0, ring
->pointers
);
68 HeapFree(GetProcessHeap(), 0, ring
);
71 InitializeCriticalSection(&ring
->lock
);
72 ring
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": RingBuffer.lock");
76 void RingBuffer_Destroy(struct ReportRingBuffer
*ring
)
78 HeapFree(GetProcessHeap(), 0, ring
->buffer
);
79 HeapFree(GetProcessHeap(), 0, ring
->pointers
);
80 ring
->lock
.DebugInfo
->Spare
[0] = 0;
81 DeleteCriticalSection(&ring
->lock
);
82 HeapFree(GetProcessHeap(), 0, ring
);
85 UINT
RingBuffer_GetBufferSize(struct ReportRingBuffer
*ring
)
87 return ring
->buffer_size
;
90 UINT
RingBuffer_GetSize(struct ReportRingBuffer
*ring
)
95 NTSTATUS
RingBuffer_SetSize(struct ReportRingBuffer
*ring
, UINT size
)
100 if (size
< MIN_BUFFER_SIZE
|| size
> MAX_BUFFER_SIZE
|| size
== ring
->size
)
101 return STATUS_INVALID_PARAMETER
;
103 EnterCriticalSection(&ring
->lock
);
104 ring
->start
= ring
->end
= 0;
105 for (i
= 0; i
< ring
->pointer_alloc
; i
++)
107 if (ring
->pointers
[i
] != 0xffffffff)
108 ring
->pointers
[i
] = 0;
110 new_buffer
= HeapAlloc(GetProcessHeap(), 0, ring
->buffer_size
* size
);
113 LeaveCriticalSection(&ring
->lock
);
114 return STATUS_NO_MEMORY
;
116 HeapFree(GetProcessHeap(), 0, ring
->buffer
);
117 ring
->buffer
= new_buffer
;
119 LeaveCriticalSection(&ring
->lock
);
120 return STATUS_SUCCESS
;
123 void RingBuffer_Read(struct ReportRingBuffer
*ring
, UINT index
, void *output
, UINT
*size
)
127 EnterCriticalSection(&ring
->lock
);
128 if (index
>= ring
->pointer_alloc
|| ring
->pointers
[index
] == 0xffffffff)
130 LeaveCriticalSection(&ring
->lock
);
134 if (ring
->pointers
[index
] == ring
->end
)
136 LeaveCriticalSection(&ring
->lock
);
141 ret
= &ring
->buffer
[ring
->pointers
[index
] * ring
->buffer_size
];
142 memcpy(output
, ret
, ring
->buffer_size
);
143 ring
->pointers
[index
]++;
144 if (ring
->pointers
[index
] == ring
->size
)
145 ring
->pointers
[index
] = 0;
146 LeaveCriticalSection(&ring
->lock
);
147 *size
= ring
->buffer_size
;
151 UINT
RingBuffer_AddPointer(struct ReportRingBuffer
*ring
)
154 EnterCriticalSection(&ring
->lock
);
155 for (idx
= 0; idx
< ring
->pointer_alloc
; idx
++)
156 if (ring
->pointers
[idx
] == -1)
158 if (idx
>= ring
->pointer_alloc
)
160 int count
= idx
= ring
->pointer_alloc
;
161 ring
->pointer_alloc
*= 2;
162 ring
->pointers
= HeapReAlloc(GetProcessHeap(), 0, ring
->pointers
, sizeof(int) * ring
->pointer_alloc
);
163 for( ;count
< ring
->pointer_alloc
; count
++)
164 ring
->pointers
[count
] = -1;
166 ring
->pointers
[idx
] = ring
->start
;
167 LeaveCriticalSection(&ring
->lock
);
171 void RingBuffer_RemovePointer(struct ReportRingBuffer
*ring
, UINT index
)
173 EnterCriticalSection(&ring
->lock
);
174 if (index
< ring
->pointer_alloc
)
175 ring
->pointers
[index
] = 0xffffffff;
176 LeaveCriticalSection(&ring
->lock
);
179 void RingBuffer_Write(struct ReportRingBuffer
*ring
, void *data
)
183 EnterCriticalSection(&ring
->lock
);
184 memcpy(&ring
->buffer
[ring
->end
* ring
->buffer_size
], data
, ring
->buffer_size
);
186 if (ring
->end
== ring
->size
)
188 if (ring
->start
== ring
->end
)
191 if (ring
->start
== ring
->size
)
194 for (i
= 0; i
< ring
->pointer_alloc
; i
++)
195 if (ring
->pointers
[i
] == ring
->end
)
196 ring
->pointers
[i
] = ring
->start
;
197 LeaveCriticalSection(&ring
->lock
);