]> rtime.felk.cvut.cz Git - ulut.git/blob - ulut/ul_dqfifo.h
0dd8f4dab5dc84b245e0a0d1a996d29aa8a5dc50
[ulut.git] / ulut / ul_dqfifo.h
1 /*******************************************************************
2   uLan Utilities Library - C library of basic reusable constructions
3
4   ul_dqfifo.h   - data queue FIFO for filters and other computations
5
6   (C) Copyright 2006 by Pavel Pisa - Originator
7
8   The uLan utilities library can be used, copied and modified under
9   next licenses
10     - GPL - GNU General Public License
11     - LGPL - GNU Lesser General Public License
12     - MPL - Mozilla Public License
13     - and other licenses added by project originators
14   Code can be modified and re-distributed under any combination
15   of the above listed licenses. If contributor does not agree with
16   some of the licenses, he/she can delete appropriate line.
17   Warning, if you delete all lines, you are not allowed to
18   distribute source code and/or binaries utilizing code.
19
20   See files COPYING and README for details.
21
22  *******************************************************************/
23
24 #ifndef _UL_DQFIFO_H
25 #define _UL_DQFIFO_H
26
27 typedef unsigned int ul_dqfifo_loc_t;
28
29 /**
30  * struct ul_dqfifo_base_t - basic structure for data queues locations counting
31  * @locin:      continuously increased location counter for data input position
32  * @locout:     continuously increased location counter for data output position
33  * @locmask:    number of allocated slots to hold actual data minus 1
34  */
35 typedef struct ul_dqfifo_base_t {
36   ul_dqfifo_loc_t locin;
37   ul_dqfifo_loc_t locout;
38   ul_dqfifo_loc_t locmask;
39 } ul_dqfifo_base_t;
40
41
42 static inline unsigned int
43 ul_dqfifo_base_loc2idx(ul_dqfifo_base_t *dqf, ul_dqfifo_loc_t loc)
44 {
45   return loc & dqf->locmask;
46 }
47
48 static inline unsigned int
49 ul_dqfifo_base_is_full(ul_dqfifo_base_t *dqf)
50 {
51   ul_dqfifo_loc_t locx = dqf->locin ^ dqf->locout;
52   return (locx && !(locx & dqf->locmask));
53 }
54
55 static inline unsigned int
56 ul_dqfifo_base_is_empty(ul_dqfifo_base_t *dqf)
57 {
58   return (dqf->locin == dqf->locout);
59 }
60
61 #define UL_DQFIFO_CUST_DEC(cust_prefix, cust_data_t, cust_barrier, cust_static_inline) \
62 \
63 typedef struct cust_prefix##_t { \
64   ul_dqfifo_base_t dqf; \
65   cust_data_t *buff; \
66 } cust_prefix##_t; \
67 \
68 cust_static_inline unsigned int \
69 cust_prefix##_loc2idx(cust_prefix##_t *cdqf, ul_dqfifo_loc_t loc) \
70 { \
71   return ul_dqfifo_base_loc2idx(&cdqf->dqf, loc); \
72 } \
73 \
74 cust_static_inline unsigned int \
75 cust_prefix##_is_full(cust_prefix##_t *cdqf) \
76 { \
77   return ul_dqfifo_base_is_full(&cdqf->dqf); \
78 } \
79 \
80 cust_static_inline unsigned int \
81 cust_prefix##_is_empty(cust_prefix##_t *cdqf) \
82 { \
83   return ul_dqfifo_base_is_empty(&cdqf->dqf); \
84 } \
85 \
86 cust_static_inline int \
87 cust_prefix##_put_no_check(cust_prefix##_t *cdqf, const cust_data_t *data) \
88 { \
89   ul_dqfifo_loc_t locin; \
90   cust_barrier; \
91   locin = cdqf->dqf.locin; \
92   cdqf->buff[cust_prefix##_loc2idx(cdqf, locin)] = *data; \
93   cust_barrier; \
94   cdqf->dqf.locin = ++locin; \
95   cust_barrier; \
96   return 1; \
97 } \
98 \
99 cust_static_inline int \
100 cust_prefix##_put(cust_prefix##_t *cdqf, const cust_data_t *data) \
101 { \
102   ul_dqfifo_loc_t locin; \
103   cust_barrier; \
104   if(cust_prefix##_is_full(cdqf)) \
105     return 0; \
106   locin = cdqf->dqf.locin; \
107   cdqf->buff[cust_prefix##_loc2idx(cdqf, locin)] = *data; \
108   cust_barrier; \
109   cdqf->dqf.locin = ++locin; \
110   cust_barrier; \
111   return 1; \
112 } \
113 \
114 cust_static_inline int \
115 cust_prefix##_get(cust_prefix##_t *cdqf, cust_data_t *data) \
116 { \
117   ul_dqfifo_loc_t locout; \
118   cust_barrier; \
119   if(cust_prefix##_is_empty(cdqf)) \
120     return 0; \
121   locout = cdqf->dqf.locout; \
122   *data = cdqf->buff[cust_prefix##_loc2idx(cdqf, locout)]; \
123   cust_barrier; \
124   cdqf->dqf.locout = ++locout; \
125   cust_barrier; \
126   return 1; \
127 } \
128 \
129 cust_static_inline ul_dqfifo_loc_t \
130 cust_prefix##_skip(cust_prefix##_t *cdqf, ul_dqfifo_loc_t locinc) \
131 { \
132   ul_dqfifo_loc_t locout; \
133   ul_dqfifo_loc_t locdiff; \
134   cust_barrier; \
135   locdiff = cdqf->dqf.locin - cdqf->dqf.locout; \
136   if(locinc > locdiff) \
137     locinc = locdiff; \
138   locout = cdqf->dqf.locout + locinc; \
139   cdqf->dqf.locout = locout; \
140   cust_barrier; \
141   return locdiff; \
142 } \
143 \
144 cust_static_inline void \
145 cust_prefix##_flush(cust_prefix##_t *cdqf) \
146 { \
147   cust_barrier; \
148   cdqf->dqf.locout = cdqf->dqf.locin; \
149 } \
150 \
151 cust_static_inline ul_dqfifo_loc_t \
152 cust_prefix##_count(cust_prefix##_t *cdqf) \
153 { ul_dqfifo_loc_t loccount; \
154   cust_barrier; \
155   loccount = cdqf->dqf.locin - cdqf->dqf.locout; \
156   cust_barrier; \
157   return loccount; \
158 } \
159 \
160 cust_static_inline ul_dqfifo_loc_t \
161 cust_prefix##_get_locin(cust_prefix##_t *cdqf) \
162 { \
163   ul_dqfifo_loc_t loc; \
164   cust_barrier; \
165   loc = cdqf->dqf.locin; \
166   cust_barrier; \
167   return loc; \
168 } \
169 \
170 cust_static_inline ul_dqfifo_loc_t \
171 cust_prefix##_get_locout(cust_prefix##_t *cdqf) \
172 { \
173   ul_dqfifo_loc_t loc; \
174   cust_barrier; \
175   loc = cdqf->dqf.locout; \
176   cust_barrier; \
177   return loc; \
178 } \
179 \
180 cust_static_inline void \
181 cust_prefix##_init(cust_prefix##_t *cdqf, cust_data_t *databuff, \
182                         ul_dqfifo_loc_t locmask) \
183 { \
184   cdqf->buff = databuff; \
185   cdqf->dqf.locmask = locmask; \
186   cdqf->dqf.locout = cdqf->dqf.locin = 0; \
187 }
188
189 #define ul_dqfifo_for_last_x(cdqf, limit, loc, data) \
190   for((loc) = (cdqf)->dqf.locout; \
191   (data) = (cdqf)->buff[ul_dqfifo_base_loc2idx(&(cdqf)->dqf, (loc))], \
192   (((loc) != (cdqf)->dqf.locout + (limit)) && ((loc) != (cdqf)->dqf.locin)); (loc)++)
193
194 #define UL_DQFIFO_STATIC_INSTANCE(cust_instance, cust_prefix, slots) \
195 \
196 typeof(*((cust_prefix##_t*)0)->buff) cust_instance##_databuff[slots]; \
197 cust_prefix##_t cust_instance = { \
198   .dqf = {.locmask = slots - 1, .locout = 0, .locin = 0},  \
199   .buff = cust_instance##_databuff,\
200 };
201
202 #endif /*_UL_DQFIFO_H*/