Annotation of sbbs/src/sbbs3/ringbuf.c, revision 1.1.1.1

1.1       root        1: /* ringbuf.c */
                      2: 
                      3: /* Synchronet ring buffer routines */
                      4: 
                      5: /* $Id: ringbuf.c,v 1.27 2005/10/21 21:52:45 deuce Exp $ */
                      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:  *                                                                                                                                                     *
                     11:  * Copyright 2005 Rob Swindell - http://www.synchro.net/copyright.html         *
                     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: #include "genwrap.h"   /* SLEEP() */
                     50: 
                     51: #ifdef RINGBUF_USE_STD_RTL
                     52: 
                     53:        #ifndef VTOOLSD
                     54: 
                     55:        /* FreeBSD uses <stdlib.h> instead of <malloc.h> */
                     56:        #ifdef __unix__
                     57:                #include <stdlib.h>
                     58:        #else
                     59:                #include <malloc.h>             /* malloc prototype */
                     60:        #endif
                     61:        #include <string.h>                     /* memcpy prototype */
                     62:     #endif     /* !VTOOLSD */
                     63: 
                     64:        #define os_malloc       malloc
                     65:        #define rb_malloc       malloc
                     66:        #define os_free         free
                     67:        #define rb_free         free
                     68:        #define os_memcpy       memcpy
                     69:        #define rb_memcpy       memcpy
                     70: 
                     71: #else
                     72: 
                     73:        void (*rb_free)(void *);
                     74:        void *(*rb_memcpy)(void *, const void *, size_t);
                     75: 
                     76: #endif
                     77: /****************************************************************************/
                     78: /* Returns 0 on success, non-zero on failure                                                           */
                     79: /****************************************************************************/
                     80: int RINGBUFCALL RingBufInit( RingBuf* rb, DWORD size
                     81: #ifndef RINGBUF_USE_STD_RTL
                     82:        ,void *(os_malloc)(size_t)
                     83:        ,void (os_free)(void *)
                     84:        ,void *(os_memcpy)(void *, const void *, size_t)
                     85: #endif
                     86:        )
                     87: {
                     88:        memset(rb,0,sizeof(RingBuf));
                     89:        if((rb->pStart=(BYTE *)os_malloc(size+1))==NULL)
                     90:                return(-1);
                     91: #ifndef RINGBUF_USE_STD_RTL
                     92:        rb_free=os_free;
                     93:        rb_memcpy=os_memcpy;
                     94: #endif
                     95:        rb->pHead=rb->pTail=rb->pStart;
                     96:        rb->pEnd=rb->pStart+size;
                     97:     rb->size=size;
                     98: #ifdef RINGBUF_SEM
                     99:        sem_init(&rb->sem,0,0);
                    100:        sem_init(&rb->highwater_sem,0,0);
                    101: #endif
                    102: #ifdef RINGBUF_EVENT
                    103:        rb->empty_event=CreateEvent(NULL,TRUE,TRUE,NULL);
                    104: #endif
                    105: #ifdef RINGBUF_MUTEX
                    106:        pthread_mutex_init(&rb->mutex,NULL);
                    107: #endif
                    108:        return(0);
                    109: }
                    110: 
                    111: void RINGBUFCALL RingBufDispose( RingBuf* rb)
                    112: {
                    113:     if(rb->pStart!=NULL)
                    114:                os_free(rb->pStart);
                    115: #ifdef RINGBUF_SEM
                    116:        sem_post(&rb->sem);                     /* just incase someone's waiting */
                    117:        while(sem_destroy(&rb->sem)==-1 && errno==EBUSY) {
                    118:                SLEEP(1);
                    119:                sem_post(&rb->sem);
                    120:        }
                    121:        while(sem_destroy(&rb->highwater_sem)==-1 && errno==EBUSY) {
                    122:                SLEEP(1);
                    123:                sem_post(&rb->highwater_sem);
                    124:        }
                    125: #endif
                    126: #ifdef RINGBUF_EVENT
                    127:        if(rb->empty_event!=NULL)
                    128:                CloseEvent(rb->empty_event);
                    129: #endif
                    130: #ifdef RINGBUF_MUTEX
                    131:        while(pthread_mutex_destroy(&rb->mutex)==EBUSY)
                    132:                SLEEP(1);
                    133: #endif
                    134:        memset(rb,0,sizeof(RingBuf));
                    135: }
                    136: 
                    137: #define RINGBUF_FILL_LEVEL(rb) (rb->pHead >= rb->pTail ? (rb->pHead - rb->pTail) \
                    138:                                                                : (rb->size - (rb->pTail - (rb->pHead + 1))))
                    139: 
                    140: DWORD RINGBUFCALL RingBufFull( RingBuf* rb )
                    141: {
                    142:        DWORD   retval;
                    143: 
                    144: #ifdef RINGBUF_MUTEX
                    145:        pthread_mutex_lock(&rb->mutex);
                    146: #endif
                    147: 
                    148:        retval = RINGBUF_FILL_LEVEL(rb);
                    149: 
                    150: #ifdef RINGBUF_EVENT
                    151:        if(rb->empty_event!=NULL) {
                    152:                if(retval==0)
                    153:                        SetEvent(rb->empty_event);
                    154:                else
                    155:                        ResetEvent(rb->empty_event);
                    156:        }
                    157: #endif
                    158: 
                    159: #ifdef RINGBUF_MUTEX
                    160:        pthread_mutex_unlock(&rb->mutex);
                    161: #endif
                    162: 
                    163:        return(retval);
                    164: }
                    165: 
                    166: DWORD RINGBUFCALL RingBufFree( RingBuf* rb )
                    167: {
                    168:        DWORD retval;
                    169: 
                    170:        retval = (rb->size - RingBufFull( rb ));
                    171: 
                    172:        return(retval);
                    173: }
                    174: 
                    175: DWORD RINGBUFCALL RingBufWrite( RingBuf* rb, BYTE* src,  DWORD cnt )
                    176: {
                    177:        DWORD max, first, remain;
                    178: 
                    179:        if(rb->pStart==NULL)
                    180:                return(0);
                    181: 
                    182: #ifdef RINGBUF_MUTEX
                    183:        pthread_mutex_lock(&rb->mutex);
                    184: #endif
                    185: 
                    186:     /* allowed to write at pEnd */
                    187:        max = (((DWORD) rb->pEnd) - ((DWORD) rb->pHead)) + 1;
                    188: 
                    189:        /*
                    190:         * we assume the caller has checked that there is enough room. For this reason
                    191:         * we do not have to worry about head wrapping past the tail
                    192:         */
                    193: 
                    194:        if( max >= cnt ) {
                    195:                first = cnt;
                    196:                remain = 0;
                    197:        } else {
                    198:                first = max;
                    199:                remain = cnt - first;
                    200:        }
                    201: 
                    202:        rb_memcpy( rb->pHead, src, first );
                    203:        rb->pHead += first;
                    204:     src += first;
                    205: 
                    206:        if(remain) {
                    207: 
                    208:                rb->pHead = rb->pStart;
                    209:                rb_memcpy(rb->pHead, src, remain);
                    210:                rb->pHead += remain;
                    211:        }
                    212: 
                    213:     if(rb->pHead > rb->pEnd)
                    214:        rb->pHead = rb->pStart;
                    215: 
                    216: #ifdef RINGBUF_SEM
                    217:        sem_post(&rb->sem);
                    218:        if(rb->highwater_mark!=0 && RINGBUF_FILL_LEVEL(rb)>=rb->highwater_mark)
                    219:                sem_post(&rb->highwater_sem);
                    220: #endif
                    221: #ifdef RINGBUF_EVENT
                    222:        if(rb->empty_event!=NULL)
                    223:                ResetEvent(rb->empty_event);
                    224: #endif
                    225: 
                    226: #ifdef RINGBUF_MUTEX
                    227:        pthread_mutex_unlock(&rb->mutex);
                    228: #endif
                    229: 
                    230:        return(cnt);
                    231: }
                    232: 
                    233: /* Pass NULL dst to just foward pointer (after Peek) */
                    234: DWORD RINGBUFCALL RingBufRead( RingBuf* rb, BYTE* dst,  DWORD cnt )
                    235: {
                    236:        DWORD max, first, remain, len;
                    237: 
                    238: #ifdef RINGBUF_MUTEX
                    239:        pthread_mutex_lock(&rb->mutex);
                    240: #endif
                    241: 
                    242:        len = RINGBUF_FILL_LEVEL(rb);
                    243: 
                    244:        if( len < cnt )
                    245:         cnt = len;
                    246: 
                    247:        /* allowed to read at pEnd */
                    248:        max = (((DWORD) rb->pEnd) - ((DWORD) rb->pTail)) + 1;
                    249: 
                    250:        if( max >= cnt ) {
                    251:                first = cnt;
                    252:                remain = 0;
                    253:        } else {
                    254:                first = max;
                    255:                remain = cnt - first;
                    256:        }
                    257: 
                    258:     if(first && dst!=NULL) {
                    259:                rb_memcpy( dst, rb->pTail, first );
                    260:                dst += first;
                    261:     }
                    262:        rb->pTail += first;
                    263: 
                    264:        if( remain ){
                    265: 
                    266:                rb->pTail = rb->pStart;
                    267:         if(dst!=NULL)
                    268:                        rb_memcpy( dst, rb->pTail, remain );
                    269:                rb->pTail += remain;
                    270:        }
                    271: 
                    272:     if(rb->pTail > rb->pEnd)
                    273:                rb->pTail = rb->pStart;
                    274: 
                    275: #ifdef RINGBUF_SEM             /* clear/signal semaphores, if appropriate */
                    276:        if(RINGBUF_FILL_LEVEL(rb) == 0)         /* empty */
                    277:                sem_reset(&rb->sem);
                    278:        if(RINGBUF_FILL_LEVEL(rb) < rb->highwater_mark)
                    279:                sem_reset(&rb->highwater_sem);
                    280: #endif
                    281: 
                    282: #ifdef RINGBUF_EVENT
                    283:        if(rb->empty_event!=NULL && RINGBUF_FILL_LEVEL(rb)==0)
                    284:                SetEvent(rb->empty_event);
                    285: #endif
                    286: 
                    287: #ifdef RINGBUF_MUTEX
                    288:        pthread_mutex_unlock(&rb->mutex);
                    289: #endif
                    290: 
                    291:        return(cnt);
                    292: }
                    293: 
                    294: DWORD RINGBUFCALL RingBufPeek( RingBuf* rb, BYTE* dst,  DWORD cnt)
                    295: {
                    296:        DWORD max, first, remain, len;
                    297: 
                    298:        len = RingBufFull( rb );
                    299:        if( len == 0 )
                    300:                return(0);
                    301: 
                    302: #ifdef RINGBUF_MUTEX
                    303:        pthread_mutex_lock(&rb->mutex);
                    304: #endif
                    305: 
                    306:        if( len < cnt )
                    307:         cnt = len;
                    308: 
                    309:     /* allowed to read at pEnd */
                    310:        max = (((DWORD) rb->pEnd) - ((DWORD) rb->pTail)) + 1;
                    311: 
                    312:        if( max >= cnt ) {
                    313:                first = cnt;
                    314:                remain = 0;
                    315:        } else {
                    316:                first = max;
                    317:                remain = cnt - first;
                    318:        }
                    319: 
                    320:        rb_memcpy( dst, rb->pTail, first );
                    321:        dst += first;
                    322: 
                    323:        if(remain) {
                    324:                rb_memcpy( dst, rb->pStart, remain );
                    325:        }
                    326: 
                    327: #ifdef RINGBUF_MUTEX
                    328:        pthread_mutex_unlock(&rb->mutex);
                    329: #endif
                    330: 
                    331:        return(cnt);
                    332: }
                    333: 
                    334: /* Reset head and tail pointers */
                    335: void RINGBUFCALL RingBufReInit(RingBuf* rb)
                    336: {
                    337: #ifdef RINGBUF_MUTEX
                    338:        pthread_mutex_lock(&rb->mutex);
                    339: #endif
                    340:        rb->pHead = rb->pTail = rb->pStart;
                    341: #ifdef RINGBUF_SEM
                    342:        sem_reset(&rb->sem);
                    343:        sem_reset(&rb->highwater_sem);
                    344: #endif
                    345: #ifdef RINGBUF_MUTEX
                    346:        pthread_mutex_unlock(&rb->mutex);
                    347: #endif
                    348: }
                    349: 
                    350: /* 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.