]> matita.cs.unibo.it Git - helm.git/blob - helm/http_getter/threadSafe.ml
544f934f0664cf0d163fab9b9fea412b0dd400dc
[helm.git] / helm / http_getter / threadSafe.ml
1 (*
2  *  Copyright (C) 2003, HELM Team.
3  *
4  *  This file is part of HELM, an Hypertextual, Electronic
5  *  Library of Mathematics, developed at the Computer Science
6  *  Department, University of Bologna, Italy.
7  *
8  *  HELM is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU General Public License
10  *  as published by the Free Software Foundation; either version 2
11  *  of the License, or (at your option) any later version.
12  *
13  *  HELM is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with HELM; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21  *  MA  02111-1307, USA.
22  *
23  *  For details, see the HELM World-Wide-Web page,
24  *  http://cs.unibo.it/helm/.
25  *)
26
27 open Http_getter_debugger;;
28 let debug_print _ = ();;  (* override debugger 'debug_print' *)
29
30 class threadSafe =
31   object (self)
32
33     val mutex = Mutex.create ()
34
35       (** condition variable: 'no readers is currently reading' *)
36     val noReaders = Condition.create ()
37
38       (** readers count *)
39     val mutable readersCount = 0
40
41     method private incrReadersCount = (* internal, not exported *)
42       self#doCritical (lazy (
43         readersCount <- readersCount + 1
44       ))
45
46     method private decrReadersCount = (* internal, not exported *)
47       self#doCritical (lazy (
48         if readersCount > 0 then readersCount <- readersCount - 1;
49       ))
50
51     method private signalNoReaders =  (* internal, not exported *)
52       self#doCritical (lazy (
53         if readersCount = 0 then Condition.signal noReaders
54       ))
55
56     method private doCritical: 'a. 'a lazy_t -> 'a =
57       fun action ->
58         debug_print "<doCritical>";
59         (try
60           Mutex.lock mutex;
61           let res = Lazy.force action in
62           Mutex.unlock mutex;
63           debug_print "</doCritical>";
64           res
65         with e ->
66           Mutex.unlock mutex;
67           raise e);
68
69     method private doReader: 'a. 'a lazy_t -> 'a =
70       fun action ->
71         debug_print "<doReader>";
72         let cleanup () =
73           self#decrReadersCount;
74           self#signalNoReaders
75         in
76         self#incrReadersCount;
77         let res = (try Lazy.force action with e -> (cleanup (); raise e)) in
78         cleanup ();
79         debug_print "</doReader>";
80         res
81
82       (* TODO may starve!!!! is what we want or not? *)
83     method private doWriter: 'a. 'a lazy_t -> 'a =
84       fun action ->
85         debug_print "<doWriter>";
86         self#doCritical (lazy (
87           while readersCount > 0 do
88             Condition.wait noReaders mutex
89           done;
90           let res = Lazy.force action in
91           debug_print "</doWriter>";
92           res
93         ))
94
95   end
96