|
|
1.1 root 1: /* ringbuf.c */
2:
3: /* Synchronet ring buffer routines */
4:
1.1.1.2 ! root 5: /* $Id: ringbuf.c,v 1.14 2003/05/08 21:06:05 rswindell Exp $ */
1.1 root 6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
1.1.1.2 ! root 11: * Copyright 2003 Rob Swindell - http://www.synchro.net/copyright.html *
1.1 root 12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: /* Pre-define RINGBUF_USE_STD_RTL to use standard C runtime library symbols
39: * for malloc, free, and memcpy
40: */
41:
42: #ifdef VTOOLSD
43: #include <vtoolsd.h>
44: #include LOCKED_CODE_SEGMENT
45: #include LOCKED_DATA_SEGMENT
46: #endif
47:
48: #include "ringbuf.h"
49:
50: #ifdef RINGBUF_USE_STD_RTL
51:
52: #ifndef VTOOLSD
1.1.1.2 ! root 53:
! 54: /* FreeBSD uses <stdlib.h> instead of <malloc.h> */
! 55: #ifdef __unix__
! 56: #include <stdlib.h>
! 57: #else
! 58: #include <malloc.h> /* malloc prototype */
! 59: #endif
! 60: #include <string.h> /* memcpy prototype */
! 61: #endif /* !VTOOLSD */
1.1 root 62:
63: #define os_malloc malloc
64: #define rb_malloc malloc
65: #define os_free free
66: #define rb_free free
67: #define os_memcpy memcpy
68: #define rb_memcpy memcpy
69:
70: #else
71:
72: void (*rb_free)(void *);
73: void *(*rb_memcpy)(void *, const void *, size_t);
74:
75: #endif
76: /****************************************************************************/
77: /* Returns 0 on success, non-zero on failure */
78: /****************************************************************************/
79: int RINGBUFCALL RingBufInit( RingBuf* rb, DWORD size
80: #ifndef RINGBUF_USE_STD_RTL
81: ,void *(os_malloc)(size_t)
82: ,void (os_free)(void *)
83: ,void *(os_memcpy)(void *, const void *, size_t)
84: #endif
85: )
86: {
1.1.1.2 ! root 87: memset(rb,0,sizeof(RingBuf));
! 88: if((rb->pStart=(BYTE *)os_malloc(size+1))==NULL)
1.1 root 89: return(-1);
90: #ifndef RINGBUF_USE_STD_RTL
91: rb_free=os_free;
92: rb_memcpy=os_memcpy;
93: #endif
94: rb->pHead=rb->pTail=rb->pStart;
1.1.1.2 ! root 95: rb->pEnd=rb->pStart+size;
1.1 root 96: rb->size=size;
1.1.1.2 ! root 97: #ifdef RINGBUF_SEM
! 98: sem_init(&rb->sem,0,0);
! 99: sem_init(&rb->highwater_sem,0,0);
! 100: #endif
! 101: #ifdef RINGBUF_MUTEX
! 102: pthread_mutex_init(&rb->mutex,NULL);
! 103: #endif
1.1 root 104: return(0);
105: }
106:
107: void RINGBUFCALL RingBufDispose( RingBuf* rb)
108: {
109: if(rb->pStart!=NULL)
110: os_free(rb->pStart);
1.1.1.2 ! root 111: #ifdef RINGBUF_SEM
! 112: sem_post(&rb->sem); /* just incase someone's waiting */
! 113: sem_destroy(&rb->sem);
! 114: sem_destroy(&rb->highwater_sem);
! 115: #endif
! 116: #ifdef RINGBUF_MUTEX
! 117: pthread_mutex_destroy(&rb->mutex);
! 118: #endif
1.1 root 119: memset(rb,0,sizeof(RingBuf));
120: }
121:
122: DWORD RINGBUFCALL RingBufFull( RingBuf* rb )
123: {
124: DWORD head,tail,retval;
125:
1.1.1.2 ! root 126: #ifdef RINGBUF_MUTEX
! 127: pthread_mutex_lock(&rb->mutex);
! 128: #endif
! 129:
1.1 root 130: head = (DWORD) rb->pHead;
131: tail = (DWORD) rb->pTail;
132:
133: if(head >= tail)
134: retval = head - tail;
135: else
136: retval = rb->size - (tail - head);
137:
1.1.1.2 ! root 138: #ifdef RINGBUF_MUTEX
! 139: pthread_mutex_unlock(&rb->mutex);
! 140: #endif
! 141:
1.1 root 142: return(retval);
143: }
144:
145: DWORD RINGBUFCALL RingBufFree( RingBuf* rb )
146: {
147: DWORD retval;
148:
1.1.1.2 ! root 149: retval = (rb->size - RingBufFull( rb ));
1.1 root 150:
151: return(retval);
152: }
153:
154: DWORD RINGBUFCALL RingBufWrite( RingBuf* rb, BYTE* src, DWORD cnt )
155: {
156: DWORD max, first, remain;
157:
158: if(rb->pStart==NULL)
159: return(0);
160:
1.1.1.2 ! root 161: #ifdef RINGBUF_MUTEX
! 162: pthread_mutex_lock(&rb->mutex);
! 163: #endif
! 164:
1.1 root 165: /* allowed to write at pEnd */
166: max = (((DWORD) rb->pEnd) - ((DWORD) rb->pHead)) + 1;
167:
168: /*
169: * we assume the caller has checked that there is enough room. For this reason
170: * we do not have to worry about head wrapping past the tail
171: */
172:
173: if( max >= cnt ) {
174: first = cnt;
175: remain = 0;
176: } else {
177: first = max;
178: remain = cnt - first;
179: }
180:
181: rb_memcpy( rb->pHead, src, first );
182: rb->pHead += first;
183: src += first;
184:
185: if(remain) {
186:
187: rb->pHead = rb->pStart;
188: rb_memcpy(rb->pHead, src, remain);
189: rb->pHead += remain;
190: }
191:
192: if(rb->pHead > rb->pEnd)
193: rb->pHead = rb->pStart;
194:
1.1.1.2 ! root 195: #ifdef RINGBUF_SEM
! 196: sem_post(&rb->sem);
! 197: if(rb->highwater_mark!=0 && RingBufFull(rb)>=rb->highwater_mark)
! 198: sem_post(&rb->highwater_sem);
! 199: #endif
! 200: #ifdef RINGBUF_MUTEX
! 201: pthread_mutex_unlock(&rb->mutex);
! 202: #endif
! 203:
1.1 root 204: return(cnt);
205: }
206:
207: /* Pass NULL dst to just foward pointer (after Peek) */
208: DWORD RINGBUFCALL RingBufRead( RingBuf* rb, BYTE* dst, DWORD cnt )
209: {
210: DWORD max, first, remain, len;
211:
212: len = RingBufFull( rb );
213: if( len == 0 )
214: return(0);
215:
1.1.1.2 ! root 216: #ifdef RINGBUF_MUTEX
! 217: pthread_mutex_lock(&rb->mutex);
! 218: #endif
! 219:
1.1 root 220: if( len < cnt )
221: cnt = len;
222:
223: /* allowed to read at pEnd */
224: max = (((DWORD) rb->pEnd) - ((DWORD) rb->pTail)) + 1;
225:
226: if( max >= cnt ) {
227: first = cnt;
228: remain = 0;
229: } else {
230: first = max;
231: remain = cnt - first;
232: }
233:
234: if(dst!=NULL) {
235: rb_memcpy( dst, rb->pTail, first );
236: dst += first;
237: }
238: rb->pTail += first;
239:
240: if( remain ){
241:
242: rb->pTail = rb->pStart;
243: if(dst!=NULL)
244: rb_memcpy( dst, rb->pTail, remain );
245: rb->pTail += remain;
246: }
247:
248: if(rb->pTail > rb->pEnd)
249: rb->pTail = rb->pStart;
250:
1.1.1.2 ! root 251: #ifdef RINGBUF_SEM /* clear semaphores, if appropriate */
! 252: if(len-cnt==0) /* empty */
! 253: sem_reset(&rb->sem);
! 254: if(len-cnt<rb->highwater_mark)
! 255: sem_reset(&rb->highwater_sem);
! 256: #endif
! 257:
! 258: #ifdef RINGBUF_MUTEX
! 259: pthread_mutex_unlock(&rb->mutex);
! 260: #endif
! 261:
1.1 root 262: return(cnt);
263: }
264:
265: DWORD RINGBUFCALL RingBufPeek( RingBuf* rb, BYTE* dst, DWORD cnt)
266: {
267: DWORD max, first, remain, len;
268:
269: len = RingBufFull( rb );
270: if( len == 0 )
271: return(0);
272:
1.1.1.2 ! root 273: #ifdef RINGBUF_MUTEX
! 274: pthread_mutex_lock(&rb->mutex);
! 275: #endif
! 276:
1.1 root 277: if( len < cnt )
278: cnt = len;
279:
280: /* allowed to read at pEnd */
281: max = (((DWORD) rb->pEnd) - ((DWORD) rb->pTail)) + 1;
282:
283: if( max >= cnt ) {
284: first = cnt;
285: remain = 0;
286: } else {
287: first = max;
288: remain = cnt - first;
289: }
290:
291: rb_memcpy( dst, rb->pTail, first );
292: dst += first;
293:
294: if(remain) {
295: rb_memcpy( dst, rb->pStart, remain );
296: }
297:
1.1.1.2 ! root 298: #ifdef RINGBUF_MUTEX
! 299: pthread_mutex_unlock(&rb->mutex);
! 300: #endif
! 301:
1.1 root 302: return(cnt);
303: }
304:
305: /* Reset head and tail pointers */
306: void RINGBUFCALL RingBufReInit(RingBuf* rb)
307: {
1.1.1.2 ! root 308: #ifdef RINGBUF_MUTEX
! 309: pthread_mutex_lock(&rb->mutex);
! 310: #endif
1.1 root 311: rb->pHead = rb->pTail = rb->pStart;
1.1.1.2 ! root 312: #ifdef RINGBUF_SEM
! 313: sem_reset(&rb->sem);
! 314: sem_reset(&rb->highwater_sem);
! 315: #endif
! 316: #ifdef RINGBUF_MUTEX
! 317: pthread_mutex_unlock(&rb->mutex);
! 318: #endif
1.1 root 319: }
320:
321: /* End of RINGBUF.C */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.