Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #ifndef __FRAMEWORK_THREADHELP_GATE_HXX_
21 : #define __FRAMEWORK_THREADHELP_GATE_HXX_
22 :
23 : #include <threadhelp/inoncopyable.h>
24 : #include <threadhelp/igate.h>
25 :
26 : #include <osl/mutex.hxx>
27 : #include <osl/conditn.hxx>
28 :
29 : namespace framework{
30 :
31 : /*-************************************************************************************************************//**
32 : @short implement a gate to block multiple threads at same time or unblock all
33 : @descr A gate can be used as a negative-condition! You can open a "door" - wait() will not block ...
34 : or you can close it - wait() blocks till open() is called again.
35 : As a special feature you can open the gate a little bit by sing openGap().
36 : Then all currently waiting threads are running immediately - but new ones are blocked!
37 :
38 : @attention To prevent us against wrong using, the default ctor, copy ctor and the =operator are maked private!
39 :
40 : @implements IGate
41 : @base IGate
42 : INonCopyable
43 :
44 : @devstatus ready to use
45 : *//*-*************************************************************************************************************/
46 : class Gate : public IGate
47 : , private INonCopyable
48 : {
49 : //-------------------------------------------------------------------------------------------------------------
50 : // public methods
51 : //-------------------------------------------------------------------------------------------------------------
52 : public:
53 :
54 : /*-****************************************************************************************************//**
55 : @short ctor
56 : @descr These initialize the object right as an open gate.
57 :
58 : @seealso -
59 :
60 : @param -
61 : @return -
62 :
63 : @onerror -
64 : *//*-*****************************************************************************************************/
65 520 : inline Gate()
66 : : m_bClosed ( sal_False )
67 520 : , m_bGapOpen ( sal_False )
68 : {
69 520 : open();
70 520 : }
71 :
72 : /*-****************************************************************************************************//**
73 : @short dtor
74 : @descr Is user forget it - we open the gate ...
75 : blocked threads can running ... but I don't know
76 : if it's right - we are destroyed yet!?
77 :
78 : @seealso -
79 :
80 : @param -
81 : @return -
82 :
83 : @onerror -
84 : *//*-*****************************************************************************************************/
85 154 : inline virtual ~Gate()
86 308 : {
87 154 : open();
88 154 : }
89 :
90 : /*-****************************************************************************************************//**
91 : @interface IGate
92 : @short open the gate
93 : @descr A wait() call will not block then.
94 :
95 : @seealso method close()
96 :
97 : @param -
98 : @return -
99 :
100 : @onerror -
101 : *//*-*****************************************************************************************************/
102 59765 : inline virtual void open()
103 : {
104 : // We must safe access to our internal member!
105 59765 : ::osl::MutexGuard aLock( m_aAccessLock );
106 : // Set condition -> wait don't block any longer -> gate is open
107 59765 : m_aPassage.set();
108 : // Check if operation was successful!
109 : // Check returns false if condition isn't set => m_bClosed will be true then => we must return false; opening failed
110 59765 : m_bClosed = ( m_aPassage.check() == sal_False );
111 59765 : }
112 :
113 : /*-****************************************************************************************************//**
114 : @interface IGate
115 : @short close the gate
116 : @descr A wait() call will block then.
117 :
118 : @seealso method open()
119 :
120 : @param -
121 : @return -
122 :
123 : @onerror -
124 : *//*-*****************************************************************************************************/
125 58571 : inline virtual void close()
126 : {
127 : // We must safe access to our internal member!
128 58571 : ::osl::MutexGuard aLock( m_aAccessLock );
129 : // Reset condition -> wait blocks now -> gate is closed
130 58571 : m_aPassage.reset();
131 : // Check if operation was successful!
132 : // Check returns false if condition was reseted => m_bClosed will be true then => we can return true; closing ok
133 58571 : m_bClosed = ( m_aPassage.check() == sal_False );
134 58571 : }
135 :
136 : /*-****************************************************************************************************//**
137 : @interface IGate
138 : @short open gate for current waiting threads
139 : @descr All current waiting threads stand in wait() at line "m_aPassage.wait()" ...
140 : With this call you can open the passage for these waiting ones.
141 : The "gap" is closed by any new thread which call wait() automaticly!
142 :
143 : @seealso method wait()
144 : @seealso method open()
145 :
146 : @param -
147 : @return -
148 :
149 : @onerror -
150 : *//*-*****************************************************************************************************/
151 0 : inline virtual void openGap()
152 : {
153 : // We must safe access to our internal member!
154 0 : ::osl::MutexGuard aLock( m_aAccessLock );
155 : // Open passage for current waiting threads.
156 0 : m_aPassage.set();
157 : // Check state of condition.
158 : // If condition is set check() returns true => m_bGapOpen will be true too => we can use it as return value.
159 0 : m_bGapOpen = ( m_aPassage.check() == sal_True );
160 0 : }
161 :
162 : /*-****************************************************************************************************//**
163 : @interface IGate
164 : @short must be called to pass the gate
165 : @descr If gate "open" => wait() will not block.
166 : If gate "closed" => wait() will block till somewhere open it again.
167 : If gap "open" => currently waiting threads unblocked, new ones blocked
168 :
169 : @seealso method wait()
170 : @seealso method open()
171 :
172 : @param "pTimeOut", optional parameter to wait a certain time
173 : @return true, if wait was successful (gate was opened)
174 : false, if condition has an error or timeout was reached!
175 :
176 : @onerror We return false.
177 : *//*-*****************************************************************************************************/
178 166 : inline virtual sal_Bool wait( const TimeValue* pTimeOut = NULL )
179 : {
180 : // We must safe access to our internal member!
181 166 : ::osl::ClearableMutexGuard aLock( m_aAccessLock );
182 : // If gate not closed - caller can pass it.
183 166 : sal_Bool bSuccessful = sal_True;
184 166 : if( m_bClosed == sal_True )
185 : {
186 : // Otherwise first new thread must close an open gap!
187 0 : if( m_bGapOpen == sal_True )
188 : {
189 0 : m_bGapOpen = sal_False;
190 0 : m_aPassage.reset();
191 : }
192 : // Then we must release used access lock -
193 : // because next call will block ...
194 : // and if we hold the access lock nobody else can use this object without a dadlock!
195 0 : aLock.clear();
196 : // Wait for opening gate ...
197 0 : bSuccessful = ( m_aPassage.wait( pTimeOut ) == ::osl::Condition::result_ok );
198 : }
199 :
200 166 : return bSuccessful;
201 : }
202 :
203 : //-------------------------------------------------------------------------------------------------------------
204 : // private member
205 : //-------------------------------------------------------------------------------------------------------------
206 : private:
207 :
208 : ::osl::Mutex m_aAccessLock ;
209 : ::osl::Condition m_aPassage ;
210 : sal_Bool m_bClosed ;
211 : sal_Bool m_bGapOpen ;
212 :
213 : }; // class Gate
214 :
215 : } // namespace framework
216 :
217 : #endif // #ifndef __FRAMEWORK_THREADHELP_GATE_HXX_
218 :
219 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|