|
|
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.