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