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 : #include "EventThread.hxx"
21 : #include <comphelper/guarding.hxx>
22 : #include <tools/debug.hxx>
23 : #include <boost/scoped_ptr.hpp>
24 :
25 : namespace frm
26 : {
27 :
28 : using namespace ::com::sun::star::uno;
29 : using namespace ::com::sun::star::awt;
30 : using namespace ::com::sun::star::lang;
31 :
32 0 : OComponentEventThread::OComponentEventThread( ::cppu::OComponentHelper* pCompImpl ) :
33 0 : m_pCompImpl( pCompImpl )
34 : {
35 :
36 0 : increment(m_refCount);
37 :
38 : // Hold a reference of the Control
39 : {
40 0 : InterfaceRef xIFace(static_cast<XWeak*>(pCompImpl));
41 0 : query_interface(xIFace, m_xComp);
42 : }
43 :
44 : // and add us at the Control
45 : {
46 0 : Reference<XEventListener> xEvtLstnr = static_cast<XEventListener*>(this);
47 0 : m_xComp->addEventListener( xEvtLstnr );
48 : }
49 :
50 0 : decrement(m_refCount);
51 0 : }
52 :
53 0 : OComponentEventThread::~OComponentEventThread()
54 : {
55 :
56 : DBG_ASSERT( m_aEvents.empty(),
57 : "OComponentEventThread::~OComponentEventThread: Didn't call dispose?" );
58 :
59 0 : impl_clearEventQueue();
60 0 : }
61 :
62 0 : Any SAL_CALL OComponentEventThread::queryInterface(const Type& _rType) throw (RuntimeException, std::exception)
63 : {
64 0 : Any aReturn;
65 :
66 0 : aReturn = OWeakObject::queryInterface(_rType);
67 :
68 0 : if (!aReturn.hasValue())
69 0 : aReturn = ::cppu::queryInterface(_rType,
70 : static_cast<XEventListener*>(this)
71 0 : );
72 :
73 0 : return aReturn;
74 : }
75 :
76 0 : void OComponentEventThread::impl_clearEventQueue()
77 : {
78 0 : while ( m_aEvents.size() )
79 : {
80 0 : delete *m_aEvents.begin();
81 0 : m_aEvents.erase( m_aEvents.begin() );
82 : }
83 0 : m_aControls.erase( m_aControls.begin(), m_aControls.end() );
84 0 : m_aFlags.erase( m_aFlags.begin(), m_aFlags.end() );
85 0 : }
86 :
87 0 : void OComponentEventThread::disposing( const EventObject& evt ) throw ( ::com::sun::star::uno::RuntimeException, std::exception)
88 : {
89 0 : if( evt.Source == m_xComp )
90 : {
91 0 : ::osl::MutexGuard aGuard( m_aMutex );
92 :
93 : // Remove EventListener
94 0 : Reference<XEventListener> xEvtLstnr = static_cast<XEventListener*>(this);
95 0 : m_xComp->removeEventListener( xEvtLstnr );
96 :
97 : // Clear EventQueue
98 0 : impl_clearEventQueue();
99 :
100 : // Free the Control and set pCompImpl to 0,
101 : // so that the thread knows, that it should terminate.
102 0 : m_xComp = 0;
103 0 : m_pCompImpl = 0;
104 :
105 : // Wake up the thread and terminate
106 0 : m_aCond.set();
107 0 : terminate();
108 : }
109 0 : }
110 :
111 0 : void OComponentEventThread::addEvent( const EventObject* _pEvt, bool bFlag )
112 : {
113 0 : Reference<XControl> xTmp;
114 0 : addEvent( _pEvt, xTmp, bFlag );
115 0 : }
116 :
117 0 : void OComponentEventThread::addEvent( const EventObject* _pEvt,
118 : const Reference<XControl>& rControl,
119 : bool bFlag )
120 : {
121 0 : ::osl::MutexGuard aGuard( m_aMutex );
122 :
123 : // Put data into the queue
124 0 : m_aEvents.push_back( cloneEvent( _pEvt ) );
125 :
126 0 : Reference<XWeak> xWeakControl(rControl, UNO_QUERY);
127 0 : Reference<XAdapter> xControlAdapter = xWeakControl.is() ? xWeakControl->queryAdapter() : Reference<XAdapter>();
128 0 : m_aControls.push_back( xControlAdapter );
129 :
130 0 : m_aFlags.push_back( bFlag );
131 :
132 : // Wake up thread
133 0 : m_aCond.set();
134 0 : }
135 :
136 0 : void OComponentEventThread::implStarted( )
137 : {
138 0 : acquire( );
139 0 : }
140 :
141 0 : void OComponentEventThread::implTerminated( )
142 : {
143 0 : release( );
144 0 : }
145 :
146 0 : void SAL_CALL OComponentEventThread::kill()
147 : {
148 0 : OComponentEventThread_TBASE::terminate();
149 0 : OComponentEventThread_TBASE::join();
150 :
151 0 : implTerminated( );
152 0 : }
153 :
154 0 : void SAL_CALL OComponentEventThread::onTerminated()
155 : {
156 0 : OComponentEventThread_TBASE::onTerminated();
157 :
158 0 : implTerminated( );
159 0 : }
160 :
161 0 : void OComponentEventThread::run()
162 : {
163 0 : osl_setThreadName("frm::OComponentEventThread");
164 :
165 0 : implStarted( );
166 :
167 : // Hold on to ourselves, so that we're not deleted if a dispose is called at some point in time
168 0 : InterfaceRef xThis(static_cast<XWeak*>(this));
169 :
170 : do
171 : {
172 0 : ::osl::MutexGuard aGuard(m_aMutex);
173 :
174 0 : while( m_aEvents.size() > 0 )
175 : {
176 : // Get the Control and hold on to it so that it cannot be deleted during actionPerformed
177 0 : Reference<XComponent> xComp = m_xComp;
178 0 : ::cppu::OComponentHelper *pCompImpl = m_pCompImpl;
179 :
180 0 : ThreadEvents::iterator firstEvent( m_aEvents.begin() );
181 0 : boost::scoped_ptr<EventObject> pEvt(*firstEvent);
182 0 : m_aEvents.erase( firstEvent );
183 :
184 0 : ThreadObjects::iterator firstControl( m_aControls.begin() );
185 0 : Reference<XAdapter> xControlAdapter = *firstControl;
186 0 : m_aControls.erase( firstControl );
187 :
188 0 : ThreadBools::iterator firstFlag( m_aFlags.begin() );
189 0 : bool bFlag = *firstFlag;
190 0 : m_aFlags.erase( firstFlag );
191 :
192 : {
193 0 : MutexRelease aReleaseOnce(m_aMutex);
194 : // Because a queryHardRef can throw an Exception, it shoudln't be called when
195 : // the mutex is locked.
196 0 : Reference<XControl> xControl;
197 0 : if ( xControlAdapter.is() )
198 0 : query_interface(xControlAdapter->queryAdapted(), xControl);
199 :
200 0 : if( xComp.is() )
201 0 : processEvent( pCompImpl, pEvt.get(), xControl, bFlag );
202 : }
203 0 : }
204 :
205 : // After a Dispose, we do not know the Control anymore.
206 : // Thus, we must not wait either.
207 0 : if( !m_xComp.is() )
208 0 : return;
209 :
210 : // Reset waiting condition
211 0 : m_aCond.reset();
212 : {
213 0 : MutexRelease aReleaseOnce(m_aMutex);
214 : // And wait ... if, in the meantime, an Event came in after all
215 0 : m_aCond.wait();
216 0 : }
217 : }
218 0 : while( true );
219 : }
220 :
221 :
222 : } // namespace frm
223 :
224 :
225 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|