-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathchanStrFIFO.c
117 lines (109 loc) · 2.44 KB
/
chanStrFIFO.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
* pthreadChannel - an implementation of channels for pthreads
* Copyright (C) 2016-2024 G. David Butler <gdb@dbSystems.com>
*
* This file is part of pthreadChannel
*
* pthreadChannel is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* pthreadChannel is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdarg.h>
#include "chan.h"
#include "chanStrFIFO.h"
struct chanStrFIFOc {
void (*f)(void *); /* free routine */
void (*d)(void *); /* item dequeue routine */
void **q; /* circular store */
unsigned int s; /* store size */
unsigned int h; /* store head */
unsigned int t; /* store tail */
};
#define C ((struct chanStrFIFOc *)c)
static void
chanStrFIFOd(
void *c
,chanSs_t s
){
if (!c)
return;
if (s & chanSsCanGet && C->d)
do {
C->d(C->q[C->h]);
if (++C->h == C->s)
C->h = 0;
} while (C->h != C->t);
C->f(C->q);
C->f(c);
}
static chanSs_t
chanStrFIFOi(
void *c
,chanSo_t o
,chanSw_t w
,void **v
){
if (!c)
return (0);
if (o == chanSoPut) {
C->q[C->t] = *v;
if (++C->t == C->s)
C->t = 0;
if (C->t == C->h)
return (chanSsCanGet);
} else {
*v = C->q[C->h];
if (++C->h == C->s)
C->h = 0;
if (C->h == C->t)
return (chanSsCanPut);
}
return (chanSsCanGet | chanSsCanPut);
(void) w;
}
#undef C
chanSs_t
chanStrFIFOa(
void *(*a)(void *, unsigned long)
,void (*f)(void *)
,void (*u)(void *)
,int (*w)(void *, chanSs_t)
,void *x
,chanSd_t *d
,chanSi_t *i
,void **v
,va_list l
){
struct chanStrFIFOc *c;
unsigned int s;
if (!v)
return (0);
*v = 0;
s = va_arg(l, unsigned int);
if (!a || !f || !s)
return (0);
if (!(c = a(0, sizeof (*c)))
|| !(c->q = a(0, s * sizeof (*c->q)))) {
f(c);
return (0);
}
c->s = s;
c->h = c->t = 0;
c->f = f;
c->d = u;
*d = chanStrFIFOd;
*i = chanStrFIFOi;
*v = c;
return (chanSsCanPut);
(void)x;
(void)w;
}