Annotation of sbbs/sbbs3/ringbuf.c, revision 1.1.1.2

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.