Skip to content
Newer
Older
100644 403 lines (333 sloc) 12.5 KB
fccc685 Initial open-source release
MLstate authored Jun 21, 2011
1 (*
2 Copyright © 2011 MLstate
3
4 This file is part of OPA.
5
6 OPA is free software: you can redistribute it and/or modify it under the
7 terms of the GNU Affero General Public License, version 3, as published by
8 the Free Software Foundation.
9
10 OPA is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
13 more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with OPA. If not, see <http://www.gnu.org/licenses/>.
17 *)
18
19 exception Syscall (* temporary, could probably be removed for new scheduler *)
20
21 (**
22 Module to manage asynchronous operations.
23
24 @author Henri Binsztok
25 @author Laurent Le Brun
26 @author Frederic Ye
27 @author Cedric Soulas
28 @author Hugo Venturini
29 *)
30
31 (**
32 This module provides functions to register
33 - asynchronous operations : [listen], [read] and [write] over sockets and file descriptors.
34 - asynchronous calculations : [sleep], [timer] and [yield].
35
36 The scheduler is asynchronous and non-preemptive {e i.e.} operations and calculation are registers
37 for sometime later in the future and they cannot interrupt one another.
38 The general mechanism is to register operations ([read], [write], [listen]) and calculation
39 ([sleep], [timer], [yield]) and to call for their execution ([wait]).
40 *)
41
42 (** {6 Types} *)
43
44 type t
45 (** The type of schedulers *)
46
47 type connection_info = { (* Temporarily exported for debug *)
48 addr : NetAddr.t; (* the connection type *)
49 conn_id : int (* the unique id of the connection *)
50 }
51 (** The type of connections *)
52
53 type async_key
54 (** The type of a key associated to an asynchronous job. See [listen] and [sleep]. *)
55
56 (** {6 Exceptions} *)
57
58 exception Timeout
59 (** Raised when a timeout expires. *)
60
61 exception Connection_closed
62 (** Raised when trying to connect through a closed connection. *)
63
64 exception Busy_direction
65 (** Raised when another read event is already waiting for data on that connection *)
66
67 exception StopTimer
68 (** Raised to stop the [timer] *)
69
70 exception Empty
71 (** Raised when there is nothing queued in the scheduler *)
72
73 exception Unbound_key
74 (** Raised when an key of type [async_key] is unbound *)
75
76 (** {6 Control of the scheduler} *)
77
78 val make : ?is_server:bool -> unit -> t
79 (** @return a fresh [Scheduler.t]
80 @param is_server (optional argument) Setting this parameter to true adds a server startup message. Default: [false]
81 *)
82
83 val default : t
84 (** A default scheduler *)
85
86 val wait : t -> block:bool -> bool
87 (** [wait sched block] Performs the following action in that order:
88 - Executes functions corresponding to operations which reached a deadline.
89 - Execute the next pending operation.
90
91 @param block Boolean stating whether the waiting blocks or not
92 {e i.e.} if [block] then it waits until any incoming operation,
93 otherwise it returns right after the end of execution.
94
95 @return [true] if there still are any pending events or any opened connections, [false] otherwise.
96 *)
97
98 val is_empty : t -> bool
99 (** @return [true] if and only if there is nothing queued in the scheduler, {e e.g.} no connections
100 open and no events or timeouts pending. This method is needed since [wait]
101 processes one event and may return [false] whether something was done or
102 not. *)
103
104 (** {6 Manipulation of connections} *)
105
106 val make_connection : t -> ?register:bool -> NetAddr.t -> connection_info
107 (** @return a fresh connection.
108 @param register States whether the new connection should be registered in the scheduler provided or not. Default: [true]
109 *)
110
111 val remove_connection :
112 t -> connection_info -> unit
113 (**
114 Removes the given connection.
115 *)
116
117 val check_connection :
118 t -> connection_info -> bool
119 (**
120 @return [true] if the given connection is registered in the given scheduler, [false] otherwise.
121 *)
122
123 val get_connection_addr: connection_info -> NetAddr.t
124 (**
125 @return the address of the given connection.
126 *)
127
128 val get_connection_inet_addr : connection_info -> Unix.inet_addr
129
130 val get_connection_fd : connection_info -> Unix.file_descr
131
132 val nb_of_connection : t -> int
133 (**
134 @return the number of registered connections in the given scheduler
135 *)
136
137 val get_connection_secured_from_normal : connection_info -> Ssl.socket -> connection_info
138 (**
139 Creates a secured connection from a given connection and a given socket.
140 *)
141
142 (** {6 Asynchronous operation over [connection_info]} *)
143
144 (**
145 An operation is register in a given scheduler and is set over a connection. It must
146 provide a continuation, among other parameters specific to each operation e.g. a string to write.
147
148 A {b continuation} is a function which returns [unit] and which will be executed when
149 the corresponding operation is triggered.
150
151 An continuation to handle errors can be provide. If an error happen, this error continuation will be used *instead* of the normal continuation.
152
153 Beside [listen], any operation can be registered with a timeout and/or an error continuation.
154 This allows you a fine-grained handling of continuations over time. But {b with great power comes
155 great responsabilities}. The policy is the following: if you don't provide any error continuation,
156 we'll handle the connection you provided at registration, fine. But if you decide to provide an error
157 continuation, you will have to explicitly remove the connection (see [remove_connection] above).
158 *)
159
160 val listen :
161 t ->
162 connection_info ->
163 ?timeout:Time.t ->
164 ?err_cont:(exn -> unit) ->
165 (unit -> unit)
166 -> async_key
167 (**
168 Listen for events onto the given connection.
169 @return the associated key that can be used with [abort].
170 *)
171
172 val listen_once :
173 t ->
174 connection_info ->
175 ?timeout:Time.t ->
176 ?err_cont:(exn -> unit) ->
177 (unit -> unit)
178 -> unit
179 (**
180 Listen for one event coming on a given connection.
181 *)
182
183 val connect :
184 t ->
185 connection_info ->
186 ?timeout:Time.t ->
187 ?err_cont:(exn -> unit) ->
188 (unit -> unit)
189 -> unit
190 (**
191 Connect on a given connection.
192 *)
193
194 val read_more :
195 t ->
196 connection_info ->
197 ?read_max:int ->
198 ?block_size:int ->
199 ?timeout:Time.t ->
200 FBuffer.t ->
201 ?size_max:int ->
202 ?err_cont:(exn -> unit) ->
203 (int * FBuffer.t -> unit) -> unit
204 (** Reads more data over a [connection_info], appending those new data in the providing buffer
205 @raise Busy_direction exception is raised when another callback is already waiting
206 for datas on that [connection_info] *)
207
208 val read_content :
209 t ->
210 connection_info ->
211 ?read_max:int ->
212 ?block_size:int ->
213 ?timeout:Time.t ->
214 Rcontent.content ->
215 ?size_max:int ->
216 ?err_cont:(exn -> unit) ->
217 (int * Rcontent.content -> unit) -> unit
218
219 val read_more2 :
220 t ->
221 connection_info ->
222 ?read_max:int ->
223 ?timeout:Time.t ->
224 Buffer.t ->
225 ?size_max:int ->
226 ?err_cont:(exn -> unit) ->
227 (int * Buffer.t -> unit) -> unit
228
a12b805 @nrs135 [feature] appruntime: Added read_more4, same as read_more2 but for Bu…
nrs135 authored Sep 13, 2011
229 val read_more4 :
230 t ->
231 connection_info ->
232 ?read_max:int ->
233 ?timeout:Time.t ->
234 Buf.t ->
235 ?size_max:int ->
236 ?err_cont:(exn -> unit) ->
237 (int * Buf.t -> unit) -> unit
238
fccc685 Initial open-source release
MLstate authored Jun 21, 2011
239 val read :
240 t ->
241 connection_info ->
242 ?timeout:Time.t ->
243 ?err_cont:(exn -> unit) ->
244 (int * string -> unit) -> unit
245 (** Reads over a [connection_info], a maximum of 4096 characters.
246 @raise Busy_direction exception is raised when another callback is already waiting
247 for datas on that [connection_info] *)
248
249 val read_from :
250 t ->
251 connection_info ->
252 ?timeout:Time.t ->
253 ?err_cont:(exn -> unit) ->
254 (int * Unix.sockaddr * string -> unit) -> unit
255 (** Reads over a [connection_info], a maximum of 4096 characters. The difference with
256 [read] is that the callback is additionally informed of the address of the sender
257 of the message. This is useful for un-connected UDP communication.
258 @raise Busy_direction exception is raised when another callback is already waiting
259 for data on that [connection_info] *)
260
261 val read_until :
262 t ->
263 connection_info ->
264 (int * string -> bool) ->
265 ?block_size:int ->
266 ?timeout:Time.t ->
267 ?err_cont:(exn -> unit) ->
268 (int * string -> unit) -> unit
269 (** [read_until sched conn read_cond cont] reads over a [connection_info],
270 until read_cond returns true from the provided couple (number of characters, data) read.
271 It can be used, for example, to read a minimum number of characters or for your callback
272 to be called only if the data ends with certain characters.
273 @raise Busy_direction exception is raised when another callback is already waiting
274 for datas on that [connection_info] *)
275
276 val read_min :
277 t ->
278 connection_info ->
279 int ->
280 ?block_size:int ->
281 ?timeout:Time.t ->
282 ?err_cont:(exn -> unit) ->
283 (int * string -> unit) -> unit
284 (** [read_min sched conn read_min cont] reads over a [connection_info],
285 a minimum of [read_min] characters.
286 @raise Busy_direction exception is raised when another callback is already waiting
287 for datas on that [connection_info] *)
288
289 val read_lines :
290 t ->
291 connection_info ->
292 ?block_size:int ->
293 ?timeout:Time.t ->
294 ?err_cont:(exn -> unit) ->
295 (int * string -> unit) -> unit
296 (** [read_lines sched conn cont] reads over a [connection_info],
297 and call you callback only if last characters are "\r\n",
298 it means only when the data is a line or a set of lines.
299 @raise Busy_direction exception is raised when another callback is already waiting
300 for datas on that [connection_info] *)
301
302 val read_all :
303 t ->
304 connection_info ->
305 ?read_max:int option->
306 ?block_size:int ->
307 ?timeout:Time.t ->
308 ?buf:FBuffer.t ->
309 ?size_max:int ->
310 ?err_cont:(exn -> unit) ->
311 (int * FBuffer.t -> unit) -> unit
312 (** Reads until the connection is closed.
313 It means your callback will be called only at the end of the connection.
314 See [read] for further information.
315 @raise Connection_closed exception is raised when the connection on which it was reading is closed.
316 *)
317
318 val write :
319 t ->
320 connection_info ->
321 ?block_size:int ->
322 ?timeout:Time.t ->
323 string ->
68933f7 @nrs135 [feature] mongo: Partial version of mongo wire protocol.
nrs135 authored Sep 9, 2011
324 ?len:int ->
fccc685 Initial open-source release
MLstate authored Jun 21, 2011
325 ?err_cont:(exn -> unit) ->
326 (int -> unit) -> unit
327 (** Writes over a [connection_info]
328 Several writes on the same connection are permited. In this case,
329 datas will be written in the same order as the [write] declarations.
330 *)
331
332 val write_to :
333 t ->
334 connection_info ->
335 Unix.sockaddr ->
336 ?block_size:int ->
337 ?timeout:Time.t ->
338 string ->
339 ?err_cont:(exn -> unit) ->
340 (int -> unit) -> unit
341 (** Writes over a [connection_info]
342 Several writes on the same connection are permited. In this case,
343 datas will be written in the same order as the [write] declarations.
344 *)
345
346 (** {6 Asynchronous calculation} *)
347
348 val sleep : t -> Time.t -> (unit -> unit) -> async_key
349 (**
350 [sleep sched x f] schedules the execution of [f] in time interval [x] in [sched]
351 @return the associated key that can be used with [abort].
352 *)
353
354 val abort : t -> async_key -> unit
355 (**
356 [abort sched key] abort the pending job associated the [key].
357 @raise Unbound_key if the key is unbound
358 *)
359
360 val timer : t -> Time.t -> (unit -> unit) -> unit
361 (** [timer sched x f] schedules the execution of [f] every time interval [x] in [sched].
362
363 If you don't define an explicit stop to the timer, it will be call forever (and ever).
364 Although you might have excellent reasons not to stop the timer, feel free to copy the
365 following PATTERN:
366 {v
367 let f () =
368 if <condition> then <do_somthing>
369 else raise Scheduler.StopTimer;
370 in Scheduler.timer sched x f;
371
372 v}
373 *)
374
375
376 val push : t -> (unit -> unit) -> unit
377 (** [push sched f] Push in [sched] the task [f]. *)
378
379 val at_exit : t -> (unit -> unit) -> unit
380 (** [at_exit sched f] Push in [sched] the task [f] to be done at the end of the program. *)
381
382 val flush : ?f:(unit -> unit) -> t -> unit
383 (** Execute all asynchronous calculation and operation. Optionally given [f] will be evaluated after
384 performing any scheduled operation. *)
385
386 val loop_until : t -> (unit -> bool) -> unit
387 (** [flush_until sched cond] Execute all asynchronous calculation and operation until [cond ()] is true
388 @raise Empty if cond not satisfied and there is nothing queued in the scheduler.
389 @raise Reentrant_routine if another [wait], [flush] or [flush_until] is yet in progress.
390 *)
391
392 val finalise : t -> ('a -> unit) -> 'a -> unit
393 (**
394 [finalise sched f v] registers f as a finalisation function for v.
395 It is permited, and only with this finalisation function, to use the
396 scheduler inside the finalisation function.
397 WARNING: contrary to [Gc.finalise], the order of calls
398 to finalisation functions is not guarantee.
399 *)
400
401 val run : t -> unit
402 (** Like [flush] but catch all exn *)
Something went wrong with that request. Please try again.