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 INCLUDED_FRAMEWORK_INC_THREADHELP_GATE_HXX
21 : #define INCLUDED_FRAMEWORK_INC_THREADHELP_GATE_HXX
22 :
23 : #include <threadhelp/igate.h>
24 :
25 : #include <boost/noncopyable.hpp>
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 :
43 : @devstatus ready to use
44 : *//*-*************************************************************************************************************/
45 : class Gate : public IGate
46 : , private boost::noncopyable
47 : {
48 :
49 : // public methods
50 :
51 : public:
52 :
53 : /*-****************************************************************************************************
54 : @short ctor
55 : @descr These initialize the object right as an open gate.
56 : *//*-*****************************************************************************************************/
57 0 : inline Gate()
58 : : m_bClosed ( false )
59 0 : , m_bGapOpen ( false )
60 : {
61 0 : open();
62 0 : }
63 :
64 : /*-****************************************************************************************************
65 : @short dtor
66 : @descr Is user forget it - we open the gate ...
67 : blocked threads can running ... but I don't know
68 : if it's right - we are destroyed yet!?
69 : *//*-*****************************************************************************************************/
70 0 : inline virtual ~Gate()
71 0 : {
72 0 : open();
73 0 : }
74 :
75 : /*-****************************************************************************************************
76 : @interface IGate
77 : @short open the gate
78 : @descr A wait() call will not block then.
79 :
80 : @seealso method close()
81 : *//*-*****************************************************************************************************/
82 0 : virtual void open() SAL_OVERRIDE
83 : {
84 : // We must safe access to our internal member!
85 0 : ::osl::MutexGuard aLock( m_aAccessLock );
86 : // Set condition -> wait don't block any longer -> gate is open
87 0 : m_aPassage.set();
88 : // Check if operation was successful!
89 : // Check returns false if condition isn't set => m_bClosed will be true then => we must return false; opening failed
90 0 : m_bClosed = !m_aPassage.check();
91 0 : }
92 :
93 : /*-****************************************************************************************************
94 : @interface IGate
95 : @short close the gate
96 : @descr A wait() call will block then.
97 :
98 : @seealso method open()
99 : *//*-*****************************************************************************************************/
100 0 : virtual void close() SAL_OVERRIDE
101 : {
102 : // We must safe access to our internal member!
103 0 : ::osl::MutexGuard aLock( m_aAccessLock );
104 : // Reset condition -> wait blocks now -> gate is closed
105 0 : m_aPassage.reset();
106 : // Check if operation was successful!
107 : // Check returns false if condition was reseted => m_bClosed will be true then => we can return true; closing ok
108 0 : m_bClosed = !m_aPassage.check();
109 0 : }
110 :
111 : /*-****************************************************************************************************
112 : @interface IGate
113 : @short open gate for current waiting threads
114 : @descr All current waiting threads stand in wait() at line "m_aPassage.wait()" ...
115 : With this call you can open the passage for these waiting ones.
116 : The "gap" is closed by any new thread which call wait() automaticly!
117 :
118 : @seealso method wait()
119 : @seealso method open()
120 : *//*-*****************************************************************************************************/
121 0 : virtual void openGap() SAL_OVERRIDE
122 : {
123 : // We must safe access to our internal member!
124 0 : ::osl::MutexGuard aLock( m_aAccessLock );
125 : // Open passage for current waiting threads.
126 0 : m_aPassage.set();
127 : // Check state of condition.
128 : // If condition is set check() returns true => m_bGapOpen will be true too => we can use it as return value.
129 0 : m_bGapOpen = m_aPassage.check();
130 0 : }
131 :
132 : /*-****************************************************************************************************
133 : @interface IGate
134 : @short must be called to pass the gate
135 : @descr If gate "open" => wait() will not block.
136 : If gate "closed" => wait() will block till somewhere open it again.
137 : If gap "open" => currently waiting threads unblocked, new ones blocked
138 :
139 : @seealso method wait()
140 : @seealso method open()
141 :
142 : @param "pTimeOut", optional parameter to wait a certain time
143 : @return true, if wait was successful (gate was opened)
144 : false, if condition has an error or timeout was reached!
145 :
146 : @onerror We return false.
147 : *//*-*****************************************************************************************************/
148 0 : virtual bool wait( const TimeValue* pTimeOut = NULL ) SAL_OVERRIDE
149 : {
150 : // We must safe access to our internal member!
151 0 : ::osl::ClearableMutexGuard aLock( m_aAccessLock );
152 : // If gate not closed - caller can pass it.
153 0 : bool bSuccessful = true;
154 0 : if( m_bClosed )
155 : {
156 : // Otherwise first new thread must close an open gap!
157 0 : if( m_bGapOpen )
158 : {
159 0 : m_bGapOpen = false;
160 0 : m_aPassage.reset();
161 : }
162 : // Then we must release used access lock -
163 : // because next call will block ...
164 : // and if we hold the access lock nobody else can use this object without a dadlock!
165 0 : aLock.clear();
166 : // Wait for opening gate ...
167 0 : bSuccessful = ( m_aPassage.wait( pTimeOut ) == ::osl::Condition::result_ok );
168 : }
169 :
170 0 : return bSuccessful;
171 : }
172 :
173 : // private member
174 :
175 : private:
176 :
177 : ::osl::Mutex m_aAccessLock;
178 : ::osl::Condition m_aPassage;
179 : bool m_bClosed;
180 : bool m_bGapOpen;
181 :
182 : }; // class Gate
183 :
184 : } // namespace framework
185 :
186 : #endif // INCLUDED_FRAMEWORK_INC_THREADHELP_GATE_HXX
187 :
188 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|