Commit | Line | Data |
---|---|---|
1b85337d ACM |
1 | /* |
2 | * Copyright (C) 2014, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> | |
3 | * | |
4 | * Released under the GPL v2. (and only v2, not any later version) | |
5 | */ | |
6 | #include "array.h" | |
7 | #include <errno.h> | |
8 | #include <fcntl.h> | |
9 | #include <poll.h> | |
10 | #include <stdlib.h> | |
11 | #include <unistd.h> | |
12 | ||
13 | void fdarray__init(struct fdarray *fda, int nr_autogrow) | |
14 | { | |
15 | fda->entries = NULL; | |
2171a925 | 16 | fda->priv = NULL; |
1b85337d ACM |
17 | fda->nr = fda->nr_alloc = 0; |
18 | fda->nr_autogrow = nr_autogrow; | |
19 | } | |
20 | ||
21 | int fdarray__grow(struct fdarray *fda, int nr) | |
22 | { | |
2171a925 | 23 | void *priv; |
1b85337d | 24 | int nr_alloc = fda->nr_alloc + nr; |
2171a925 | 25 | size_t psize = sizeof(fda->priv[0]) * nr_alloc; |
1b85337d ACM |
26 | size_t size = sizeof(struct pollfd) * nr_alloc; |
27 | struct pollfd *entries = realloc(fda->entries, size); | |
28 | ||
29 | if (entries == NULL) | |
30 | return -ENOMEM; | |
31 | ||
2171a925 ACM |
32 | priv = realloc(fda->priv, psize); |
33 | if (priv == NULL) { | |
34 | free(entries); | |
35 | return -ENOMEM; | |
36 | } | |
37 | ||
1b85337d ACM |
38 | fda->nr_alloc = nr_alloc; |
39 | fda->entries = entries; | |
2171a925 | 40 | fda->priv = priv; |
1b85337d ACM |
41 | return 0; |
42 | } | |
43 | ||
44 | struct fdarray *fdarray__new(int nr_alloc, int nr_autogrow) | |
45 | { | |
46 | struct fdarray *fda = calloc(1, sizeof(*fda)); | |
47 | ||
48 | if (fda != NULL) { | |
49 | if (fdarray__grow(fda, nr_alloc)) { | |
50 | free(fda); | |
51 | fda = NULL; | |
52 | } else { | |
53 | fda->nr_autogrow = nr_autogrow; | |
54 | } | |
55 | } | |
56 | ||
57 | return fda; | |
58 | } | |
59 | ||
60 | void fdarray__exit(struct fdarray *fda) | |
61 | { | |
62 | free(fda->entries); | |
2171a925 | 63 | free(fda->priv); |
1b85337d ACM |
64 | fdarray__init(fda, 0); |
65 | } | |
66 | ||
67 | void fdarray__delete(struct fdarray *fda) | |
68 | { | |
69 | fdarray__exit(fda); | |
70 | free(fda); | |
71 | } | |
72 | ||
73 | int fdarray__add(struct fdarray *fda, int fd, short revents) | |
74 | { | |
2171a925 ACM |
75 | int pos = fda->nr; |
76 | ||
1b85337d ACM |
77 | if (fda->nr == fda->nr_alloc && |
78 | fdarray__grow(fda, fda->nr_autogrow) < 0) | |
79 | return -ENOMEM; | |
80 | ||
81 | fda->entries[fda->nr].fd = fd; | |
82 | fda->entries[fda->nr].events = revents; | |
83 | fda->nr++; | |
2171a925 | 84 | return pos; |
1b85337d ACM |
85 | } |
86 | ||
2171a925 | 87 | int fdarray__filter(struct fdarray *fda, short revents, |
258e4bfc WN |
88 | void (*entry_destructor)(struct fdarray *fda, int fd, void *arg), |
89 | void *arg) | |
1b85337d ACM |
90 | { |
91 | int fd, nr = 0; | |
92 | ||
93 | if (fda->nr == 0) | |
94 | return 0; | |
95 | ||
96 | for (fd = 0; fd < fda->nr; ++fd) { | |
2171a925 ACM |
97 | if (fda->entries[fd].revents & revents) { |
98 | if (entry_destructor) | |
258e4bfc | 99 | entry_destructor(fda, fd, arg); |
2171a925 | 100 | |
1b85337d | 101 | continue; |
2171a925 | 102 | } |
1b85337d | 103 | |
2171a925 | 104 | if (fd != nr) { |
1b85337d | 105 | fda->entries[nr] = fda->entries[fd]; |
2171a925 ACM |
106 | fda->priv[nr] = fda->priv[fd]; |
107 | } | |
1b85337d ACM |
108 | |
109 | ++nr; | |
110 | } | |
111 | ||
112 | return fda->nr = nr; | |
113 | } | |
114 | ||
115 | int fdarray__poll(struct fdarray *fda, int timeout) | |
116 | { | |
117 | return poll(fda->entries, fda->nr, timeout); | |
118 | } | |
119 | ||
120 | int fdarray__fprintf(struct fdarray *fda, FILE *fp) | |
121 | { | |
122 | int fd, printed = fprintf(fp, "%d [ ", fda->nr); | |
123 | ||
124 | for (fd = 0; fd < fda->nr; ++fd) | |
125 | printed += fprintf(fp, "%s%d", fd ? ", " : "", fda->entries[fd].fd); | |
126 | ||
127 | return printed + fprintf(fp, " ]"); | |
128 | } |