Annotation of sbbs/src/sbbs3/ringbuf.c, revision 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.