source: vendor/current/source3/lib/tevent_barrier.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 4.7 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 Implement a barrier
4 Copyright (C) Volker Lendecke 2012
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#include "includes.h"
21#include "tevent_barrier.h"
22#include "lib/util/tevent_unix.h"
23
24struct tevent_barrier_waiter {
25 struct tevent_immediate *im;
26 struct tevent_context *ev;
27 struct tevent_req *req;
28};
29
30struct tevent_barrier {
31 unsigned count;
32 struct tevent_barrier_waiter *waiters;
33 void (*trigger_cb)(void *private_data);
34 void *private_data;
35};
36
37static int tevent_barrier_destructor(struct tevent_barrier *b);
38static void tevent_barrier_release(struct tevent_barrier *b);
39static void tevent_barrier_release_one(struct tevent_context *ctx,
40 struct tevent_immediate *im,
41 void *private_data);
42static void tevent_barrier_release_trigger(struct tevent_context *ctx,
43 struct tevent_immediate *im,
44 void *private_data);
45
46struct tevent_barrier *tevent_barrier_init(
47 TALLOC_CTX *mem_ctx, unsigned count,
48 void (*trigger_cb)(void *private_data), void *private_data)
49{
50 struct tevent_barrier *b;
51 unsigned i;
52
53 if (count == 0) {
54 return NULL;
55 }
56
57 b = talloc(mem_ctx, struct tevent_barrier);
58 if (b == NULL) {
59 return NULL;
60 }
61 b->count = 0;
62 b->trigger_cb = trigger_cb;
63 b->private_data = private_data;
64
65 b->waiters = talloc_array(b, struct tevent_barrier_waiter, count);
66 if (b->waiters == NULL) {
67 goto fail;
68 }
69 for (i=0; i<count; i++) {
70 struct tevent_barrier_waiter *w = &b->waiters[i];
71
72 w->im = tevent_create_immediate(b->waiters);
73 if (w->im == NULL) {
74 goto fail;
75 }
76 w->req = NULL;
77 }
78 talloc_set_destructor(b, tevent_barrier_destructor);
79 return b;
80fail:
81 TALLOC_FREE(b);
82 return NULL;
83}
84
85static int tevent_barrier_destructor(struct tevent_barrier *b)
86{
87 tevent_barrier_release(b);
88 return 0;
89}
90
91struct tevent_barrier_wait_state {
92 struct tevent_barrier *b;
93 int index;
94};
95
96static void tevent_barrier_release(struct tevent_barrier *b)
97{
98 unsigned i;
99
100 for (i=0; i<b->count; i++) {
101 struct tevent_barrier_waiter *w = &b->waiters[i];
102 struct tevent_barrier_wait_state *state;
103
104 if (w->req == NULL) {
105 continue;
106 }
107 tevent_schedule_immediate(
108 w->im, w->ev, tevent_barrier_release_one, w->req);
109
110 state = tevent_req_data(
111 w->req, struct tevent_barrier_wait_state);
112 talloc_set_destructor(state, NULL);
113
114 w->req = NULL;
115 w->ev = NULL;
116 }
117 b->count = 0;
118 if (b->trigger_cb != NULL) {
119 b->trigger_cb(b->private_data);
120 }
121}
122
123static void tevent_barrier_release_one(struct tevent_context *ctx,
124 struct tevent_immediate *im,
125 void *private_data)
126{
127 struct tevent_req *req = talloc_get_type_abort(
128 private_data, struct tevent_req);
129 tevent_req_done(req);
130}
131
132static int tevent_barrier_wait_state_destructor(
133 struct tevent_barrier_wait_state *s);
134
135struct tevent_req *tevent_barrier_wait_send(TALLOC_CTX *mem_ctx,
136 struct tevent_context *ev,
137 struct tevent_barrier *b)
138{
139 struct tevent_req *req;
140 struct tevent_barrier_wait_state *state;
141 struct tevent_barrier_waiter *w;
142 struct tevent_immediate *im;
143
144 req = tevent_req_create(mem_ctx, &state,
145 struct tevent_barrier_wait_state);
146 if (req == NULL) {
147 return NULL;
148 }
149 state->b = b;
150 state->index = b->count;
151
152 w = &b->waiters[b->count];
153 w->ev = ev;
154 w->req = req;
155 b->count += 1;
156
157 talloc_set_destructor(state, tevent_barrier_wait_state_destructor);
158
159 if (b->count < talloc_array_length(b->waiters)) {
160 return req;
161 }
162
163 im = tevent_create_immediate(req);
164 if (tevent_req_nomem(im, req)) {
165 return tevent_req_post(req, ev);
166 }
167 tevent_schedule_immediate(im, ev, tevent_barrier_release_trigger, b);
168 return req;
169}
170
171static int tevent_barrier_wait_state_destructor(
172 struct tevent_barrier_wait_state *s)
173{
174 struct tevent_barrier *b = s->b;
175 b->waiters[s->index].req = b->waiters[b->count-1].req;
176 b->count -= 1;
177 return 0;
178}
179
180static void tevent_barrier_release_trigger(struct tevent_context *ctx,
181 struct tevent_immediate *im,
182 void *private_data)
183{
184 struct tevent_barrier *b = talloc_get_type_abort(
185 private_data, struct tevent_barrier);
186 tevent_barrier_release(b);
187}
188
189int tevent_barrier_wait_recv(struct tevent_req *req)
190{
191 return tevent_req_simple_recv_unix(req);
192}
Note: See TracBrowser for help on using the repository browser.