|
|
1.1 ! root 1: /* msg_queue.c */ ! 2: ! 3: /* Uni or Bi-directional FIFO message queue */ ! 4: ! 5: /* $Id: msg_queue.c,v 1.10 2004/11/19 00:51:25 rswindell 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 2004 Rob Swindell - http://www.synchro.net/copyright.html * ! 12: * * ! 13: * This library is free software; you can redistribute it and/or * ! 14: * modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details: lgpl.txt or * ! 18: * http://www.fsf.org/copyleft/lesser.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: #include <stdlib.h> /* malloc */ ! 39: #include <string.h> /* memset */ ! 40: ! 41: #include "genwrap.h" /* msclock() */ ! 42: #include "threadwrap.h" /* pthread_self */ ! 43: #include "msg_queue.h" ! 44: ! 45: msg_queue_t* msgQueueInit(msg_queue_t* q, long flags) ! 46: { ! 47: if(q==NULL) { ! 48: if((q=(msg_queue_t*)malloc(sizeof(msg_queue_t)))==NULL) ! 49: return(NULL); ! 50: flags |= MSG_QUEUE_MALLOC; ! 51: } ! 52: ! 53: memset(q,0,sizeof(msg_queue_t)); ! 54: ! 55: q->flags = flags; ! 56: q->refs = 1; ! 57: q->owner_thread_id = pthread_self(); ! 58: ! 59: if(q->flags&MSG_QUEUE_BIDIR) ! 60: listInit(&q->in,LINK_LIST_SEMAPHORE); ! 61: listInit(&q->out,LINK_LIST_SEMAPHORE); ! 62: ! 63: return(q); ! 64: } ! 65: ! 66: BOOL msgQueueFree(msg_queue_t* q) ! 67: { ! 68: if(q==NULL) ! 69: return(FALSE); ! 70: ! 71: listFree(&q->in); ! 72: listFree(&q->out); ! 73: ! 74: if(q->flags&MSG_QUEUE_MALLOC) ! 75: free(q); ! 76: ! 77: return(TRUE); ! 78: } ! 79: ! 80: long msgQueueAttach(msg_queue_t* q) ! 81: { ! 82: if(q==NULL) ! 83: return(-1); ! 84: ! 85: q->refs++; ! 86: ! 87: return(q->refs); ! 88: } ! 89: ! 90: long msgQueueDetach(msg_queue_t* q) ! 91: { ! 92: int refs; ! 93: ! 94: if(q==NULL || q->refs<1) ! 95: return(-1); ! 96: ! 97: if((refs=--q->refs)==0) ! 98: msgQueueFree(q); ! 99: ! 100: return(refs); ! 101: } ! 102: ! 103: void* msgQueueSetPrivateData(msg_queue_t* q, void* p) ! 104: { ! 105: void* old; ! 106: ! 107: if(q==NULL) ! 108: return(NULL); ! 109: ! 110: old=q->private_data; ! 111: q->private_data=p; ! 112: return(old); ! 113: } ! 114: ! 115: void* msgQueueGetPrivateData(msg_queue_t* q) ! 116: { ! 117: if(q==NULL) ! 118: return(NULL); ! 119: return(q->private_data); ! 120: } ! 121: ! 122: static link_list_t* msgQueueReadList(msg_queue_t* q) ! 123: { ! 124: if(q==NULL) ! 125: return(NULL); ! 126: ! 127: if((q->flags&MSG_QUEUE_BIDIR) ! 128: && q->owner_thread_id == pthread_self()) ! 129: return(&q->in); ! 130: return(&q->out); ! 131: } ! 132: ! 133: static link_list_t* msgQueueWriteList(msg_queue_t* q) ! 134: { ! 135: if(q==NULL) ! 136: return(NULL); ! 137: ! 138: if(!(q->flags&MSG_QUEUE_BIDIR) ! 139: || q->owner_thread_id == pthread_self()) ! 140: return(&q->out); ! 141: return(&q->in); ! 142: } ! 143: ! 144: long msgQueueReadLevel(msg_queue_t* q) ! 145: { ! 146: return listCountNodes(msgQueueReadList(q)); ! 147: } ! 148: ! 149: static BOOL list_wait(link_list_t* list, long timeout) ! 150: { ! 151: #if defined(LINK_LIST_THREADSAFE) ! 152: if(timeout<0) /* infinite */ ! 153: return listSemWait(list); ! 154: if(timeout==0) /* poll */ ! 155: return listSemTryWait(list); ! 156: ! 157: return listSemTryWaitBlock(list,timeout); ! 158: #else ! 159: clock_t start; ! 160: long count; ! 161: ! 162: start=msclock(); ! 163: while((count=listCountNodes(list))==0) { ! 164: if(timeout==0) ! 165: break; ! 166: if(timeout>0 && msclock()-start > timeout) ! 167: break; ! 168: YIELD(); ! 169: } ! 170: return(INT_TO_BOOL(count)); ! 171: #endif ! 172: } ! 173: ! 174: BOOL msgQueueWait(msg_queue_t* q, long timeout) ! 175: { ! 176: return(list_wait(msgQueueReadList(q),timeout)); ! 177: } ! 178: ! 179: void* msgQueueRead(msg_queue_t* q, long timeout) ! 180: { ! 181: if(!list_wait(msgQueueReadList(q),timeout)) ! 182: return(NULL); ! 183: ! 184: return listShiftNode(msgQueueReadList(q)); ! 185: } ! 186: ! 187: void* msgQueuePeek(msg_queue_t* q, long timeout) ! 188: { ! 189: if(!list_wait(msgQueueReadList(q),timeout)) ! 190: return(NULL); ! 191: ! 192: return listNodeData(listFirstNode(msgQueueReadList(q))); ! 193: } ! 194: ! 195: void* msgQueueFind(msg_queue_t* q, const void* data, size_t length) ! 196: { ! 197: link_list_t* list = msgQueueReadList(q); ! 198: list_node_t* node; ! 199: ! 200: if((node=listFindNode(list,data,length))==NULL) ! 201: return(NULL); ! 202: return listRemoveNode(list,node,/* Free Data? */FALSE); ! 203: } ! 204: ! 205: list_node_t* msgQueueFirstNode(msg_queue_t* q) ! 206: { ! 207: return listFirstNode(msgQueueReadList(q)); ! 208: } ! 209: ! 210: list_node_t* msgQueueLastNode(msg_queue_t* q) ! 211: { ! 212: return listLastNode(msgQueueReadList(q)); ! 213: } ! 214: ! 215: long msgQueueWriteLevel(msg_queue_t* q) ! 216: { ! 217: return listCountNodes(msgQueueWriteList(q)); ! 218: } ! 219: ! 220: BOOL msgQueueWrite(msg_queue_t* q, const void* data, size_t length) ! 221: { ! 222: return listPushNodeData(msgQueueWriteList(q),data,length)!=NULL; ! 223: } ! 224:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.