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 :
21 : #include "rtl/logfile.hxx"
22 :
23 : #include <osl/file.hxx>
24 : #include <osl/signal.h>
25 :
26 : #include "tools/tools.h"
27 : #include "tools/debug.hxx"
28 : #include "tools/resmgr.hxx"
29 :
30 : #include "comphelper/processfactory.hxx"
31 :
32 : #include "unotools/syslocaleoptions.hxx"
33 : #include "unotools/fontcfg.hxx"
34 :
35 : #include "vcl/svapp.hxx"
36 : #include "vcl/wrkwin.hxx"
37 : #include "vcl/cvtgrf.hxx"
38 : #include "vcl/image.hxx"
39 : #include "vcl/settings.hxx"
40 : #include "vcl/unowrap.hxx"
41 : #include "vcl/configsettings.hxx"
42 : #include "vcl/lazydelete.hxx"
43 : #include "vcl/temporaryfonts.hxx"
44 :
45 : #ifdef WNT
46 : #include <svsys.h>
47 : #include <process.h> // for _beginthreadex
48 : #include <ole2.h> // for _beginthreadex
49 : #endif
50 :
51 : #ifdef ANDROID
52 : #include <cppuhelper/bootstrap.hxx>
53 : #include <jni.h>
54 : #endif
55 :
56 : #include "salinst.hxx"
57 : #include "salwtype.hxx"
58 : #include "svdata.hxx"
59 : #include "dbggui.hxx"
60 : #include "accmgr.hxx"
61 : #include "idlemgr.hxx"
62 : #include "outdev.h"
63 : #include "outfont.hxx"
64 : #include "print.h"
65 : #include "salsys.hxx"
66 : #include "saltimer.hxx"
67 : #include "salimestatus.hxx"
68 : #include "impimagetree.hxx"
69 : #include "xconnection.hxx"
70 :
71 : #include "osl/process.h"
72 : #include "com/sun/star/lang/XMultiServiceFactory.hpp"
73 : #include "com/sun/star/lang/XComponent.hpp"
74 :
75 : #include "cppuhelper/implbase1.hxx"
76 : #include "uno/current_context.hxx"
77 :
78 : #if OSL_DEBUG_LEVEL > 0
79 : #include <typeinfo>
80 : #include "rtl/strbuf.hxx"
81 : #endif
82 :
83 : using ::rtl::OUString;
84 : using namespace ::com::sun::star;
85 :
86 : // =======================================================================
87 :
88 0 : oslSignalAction SAL_CALL VCLExceptionSignal_impl( void* /*pData*/, oslSignalInfo* pInfo)
89 : {
90 : static bool bIn = false;
91 :
92 : // if we crash again, bail out immediatly
93 0 : if ( !bIn )
94 : {
95 0 : sal_uInt16 nVCLException = 0;
96 :
97 : // UAE
98 0 : if ( (pInfo->Signal == osl_Signal_AccessViolation) ||
99 : (pInfo->Signal == osl_Signal_IntegerDivideByZero) ||
100 : (pInfo->Signal == osl_Signal_FloatDivideByZero) ||
101 : (pInfo->Signal == osl_Signal_DebugBreak) )
102 0 : nVCLException = EXC_SYSTEM;
103 :
104 : // RC
105 0 : if ((pInfo->Signal == osl_Signal_User) &&
106 : (pInfo->UserSignal == OSL_SIGNAL_USER_RESOURCEFAILURE) )
107 0 : nVCLException = EXC_RSCNOTLOADED;
108 :
109 : // DISPLAY-Unix
110 0 : if ((pInfo->Signal == osl_Signal_User) &&
111 : (pInfo->UserSignal == OSL_SIGNAL_USER_X11SUBSYSTEMERROR) )
112 0 : nVCLException = EXC_DISPLAY;
113 :
114 : // Remote-Client
115 0 : if ((pInfo->Signal == osl_Signal_User) &&
116 : (pInfo->UserSignal == OSL_SIGNAL_USER_RVPCONNECTIONERROR) )
117 0 : nVCLException = EXC_REMOTE;
118 :
119 0 : if ( nVCLException )
120 : {
121 0 : bIn = true;
122 :
123 0 : SolarMutexGuard aLock;
124 :
125 : // do not stop timer because otherwise the UAE-Box will not be painted as well
126 0 : ImplSVData* pSVData = ImplGetSVData();
127 0 : if ( pSVData->mpApp )
128 : {
129 0 : sal_uInt16 nOldMode = Application::GetSystemWindowMode();
130 0 : Application::SetSystemWindowMode( nOldMode & ~SYSTEMWINDOW_MODE_NOAUTOMODE );
131 0 : pSVData->mpApp->Exception( nVCLException );
132 0 : Application::SetSystemWindowMode( nOldMode );
133 : }
134 0 : bIn = false;
135 :
136 0 : return osl_Signal_ActCallNextHdl;
137 : }
138 : }
139 :
140 0 : return osl_Signal_ActCallNextHdl;
141 :
142 : }
143 :
144 : // =======================================================================
145 8 : int ImplSVMain()
146 : {
147 : // The 'real' SVMain()
148 : RTL_LOGFILE_CONTEXT( aLog, "vcl (ss112471) ::SVMain" );
149 :
150 8 : ImplSVData* pSVData = ImplGetSVData();
151 :
152 : DBG_ASSERT( pSVData->mpApp, "no instance of class Application" );
153 :
154 8 : int nReturn = EXIT_FAILURE;
155 :
156 8 : sal_Bool bInit = InitVCL();
157 :
158 8 : if( bInit )
159 : {
160 : // call application main
161 8 : pSVData->maAppData.mbInAppMain = sal_True;
162 8 : nReturn = pSVData->mpApp->Main();
163 8 : pSVData->maAppData.mbInAppMain = sal_False;
164 : }
165 :
166 8 : if( pSVData->mxDisplayConnection.is() )
167 : {
168 2 : pSVData->mxDisplayConnection->terminate();
169 2 : pSVData->mxDisplayConnection.clear();
170 : }
171 :
172 : // This is a hack to work around the problem of the asynchronous nature
173 : // of bridging accessibility through Java: on shutdown there might still
174 : // be some events in the AWT EventQueue, which need the SolarMutex which
175 : // - on the other hand - is destroyed in DeInitVCL(). So empty the queue
176 : // here ..
177 8 : uno::Reference< lang::XComponent > xComponent(pSVData->mxAccessBridge, uno::UNO_QUERY);
178 8 : if( xComponent.is() )
179 : {
180 0 : sal_uLong nCount = Application::ReleaseSolarMutex();
181 0 : xComponent->dispose();
182 0 : Application::AcquireSolarMutex(nCount);
183 0 : pSVData->mxAccessBridge.clear();
184 : }
185 :
186 8 : DeInitVCL();
187 8 : return nReturn;
188 : }
189 :
190 8 : int SVMain()
191 : {
192 : // #i47888# allow for alternative initialization as required for e.g. MacOSX
193 : extern sal_Bool ImplSVMainHook( int* );
194 :
195 : int nRet;
196 8 : if( ImplSVMainHook( &nRet ) )
197 0 : return nRet;
198 : else
199 8 : return ImplSVMain();
200 : }
201 : // This variable is set, when no Application object is instantiated
202 : // before SVInit is called
203 : static Application * pOwnSvApp = NULL;
204 : // Exception handler. pExceptionHandler != NULL => VCL already inited
205 : oslSignalHandler pExceptionHandler = NULL;
206 :
207 90 : class Application_Impl : public Application
208 : {
209 : public:
210 0 : int Main() { return EXIT_SUCCESS; };
211 : };
212 :
213 0 : class DesktopEnvironmentContext: public cppu::WeakImplHelper1< com::sun::star::uno::XCurrentContext >
214 : {
215 : public:
216 98 : DesktopEnvironmentContext( const com::sun::star::uno::Reference< com::sun::star::uno::XCurrentContext > & ctx)
217 98 : : m_xNextContext( ctx ) {}
218 :
219 : // XCurrentContext
220 : virtual com::sun::star::uno::Any SAL_CALL getValueByName( const rtl::OUString& Name )
221 : throw (com::sun::star::uno::RuntimeException);
222 :
223 : private:
224 : com::sun::star::uno::Reference< com::sun::star::uno::XCurrentContext > m_xNextContext;
225 : };
226 :
227 16 : uno::Any SAL_CALL DesktopEnvironmentContext::getValueByName( const rtl::OUString& Name) throw (uno::RuntimeException)
228 : {
229 16 : uno::Any retVal;
230 :
231 16 : if ( Name == "system.desktop-environment" )
232 : {
233 16 : retVal = uno::makeAny( Application::GetDesktopEnvironment() );
234 : }
235 0 : else if( m_xNextContext.is() )
236 : {
237 : // Call next context in chain if found
238 0 : retVal = m_xNextContext->getValueByName( Name );
239 : }
240 16 : return retVal;
241 : }
242 :
243 662 : sal_Bool InitVCL()
244 : {
245 : RTL_LOGFILE_CONTEXT( aLog, "vcl (ss112471) ::InitVCL" );
246 :
247 662 : if( pExceptionHandler != NULL )
248 564 : return sal_False;
249 :
250 98 : TemporaryFonts::clear();
251 :
252 98 : if( ! ImplGetSVData() )
253 90 : ImplInitSVData();
254 :
255 98 : if( !ImplGetSVData()->mpApp )
256 : {
257 90 : pOwnSvApp = new Application_Impl();
258 : }
259 98 : InitSalMain();
260 :
261 : /*AllSettings aAS;
262 : Application::SetSettings( aAS );// ???
263 : */
264 98 : ImplSVData* pSVData = ImplGetSVData();
265 :
266 : // SV bei den Tools anmelden
267 98 : InitTools();
268 :
269 : // Main-Thread-Id merken
270 98 : pSVData->mnMainThreadId = ::osl::Thread::getCurrentIdentifier();
271 :
272 : // Sal initialisieren
273 : RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ ::CreateSalInstance" );
274 98 : pSVData->mpDefInst = CreateSalInstance();
275 98 : if ( !pSVData->mpDefInst )
276 0 : return sal_False;
277 : RTL_LOGFILE_CONTEXT_TRACE( aLog, "} ::CreateSalInstance" );
278 :
279 : // Desktop Environment context (to be able to get value of "system.desktop-environment" as soon as possible)
280 : com::sun::star::uno::setCurrentContext(
281 98 : new DesktopEnvironmentContext( com::sun::star::uno::getCurrentContext() ) );
282 :
283 : // Initialize application instance (should be done after initialization of VCL SAL part)
284 98 : if( pSVData->mpApp )
285 : // call init to initialize application class
286 : // soffice/sfx implementation creates the global service manager
287 98 : pSVData->mpApp->Init();
288 :
289 : // Fetch AppFileName and make it absolute before the workdir changes...
290 98 : rtl::OUString aExeFileName;
291 98 : osl_getExecutableFile( &aExeFileName.pData );
292 :
293 : // convert path to native file format
294 98 : rtl::OUString aNativeFileName;
295 98 : osl::FileBase::getSystemPathFromFileURL( aExeFileName, aNativeFileName );
296 98 : pSVData->maAppData.mpAppFileName = new String( aNativeFileName );
297 :
298 : // Initialize global data
299 98 : pSVData->maGDIData.mpScreenFontList = new ImplDevFontList;
300 98 : pSVData->maGDIData.mpScreenFontCache = new ImplFontCache( sal_False );
301 98 : pSVData->maGDIData.mpGrfConverter = new GraphicConverter;
302 :
303 : // Set exception handler
304 98 : pExceptionHandler = osl_addSignalHandler(VCLExceptionSignal_impl, NULL);
305 :
306 : // initialise debug data
307 : DBGGUI_INIT();
308 :
309 98 : return sal_True;
310 : }
311 :
312 : #ifdef ANDROID
313 :
314 : extern "C" __attribute__ ((visibility("default"))) void
315 : InitVCLWrapper()
316 : {
317 : uno::Reference<uno::XComponentContext> xContext( cppu::defaultBootstrap_InitialComponentContext() );
318 : uno::Reference<lang::XMultiComponentFactory> xFactory( xContext->getServiceManager() );
319 :
320 : uno::Reference<lang::XMultiServiceFactory> xSM( xFactory, uno::UNO_QUERY_THROW );
321 :
322 : comphelper::setProcessServiceFactory( xSM );
323 :
324 : InitVCL();
325 : }
326 :
327 : #endif
328 :
329 : namespace
330 : {
331 :
332 : /** Serves for destroying the VCL UNO wrapper as late as possible. This avoids
333 : crash at exit in some special cases when a11y is enabled (e.g., when
334 : a bundled extension is registered/deregistered during startup, forcing exit
335 : while the app is still in splash screen.)
336 : */
337 6 : class VCLUnoWrapperDeleter : public cppu::WeakImplHelper1<com::sun::star::lang::XEventListener>
338 : {
339 : virtual void SAL_CALL disposing(lang::EventObject const& rSource) throw(uno::RuntimeException);
340 : };
341 :
342 : void
343 2 : VCLUnoWrapperDeleter::disposing(lang::EventObject const& /* rSource */)
344 : throw(uno::RuntimeException)
345 : {
346 2 : ImplSVData* const pSVData = ImplGetSVData();
347 2 : if (pSVData && pSVData->mpUnoWrapper)
348 : {
349 2 : pSVData->mpUnoWrapper->Destroy();
350 2 : pSVData->mpUnoWrapper = NULL;
351 : }
352 2 : }
353 :
354 : }
355 :
356 8 : void DeInitVCL()
357 : {
358 8 : ImplSVData* pSVData = ImplGetSVData();
359 8 : pSVData->mbDeInit = sal_True;
360 :
361 8 : vcl::DeleteOnDeinitBase::ImplDeleteOnDeInit();
362 :
363 : // give ime status a chance to destroy its own windows
364 8 : delete pSVData->mpImeStatus;
365 8 : pSVData->mpImeStatus = NULL;
366 :
367 : #if OSL_DEBUG_LEVEL > 0
368 : rtl::OStringBuffer aBuf( 256 );
369 : aBuf.append( "DeInitVCL: some top Windows are still alive\n" );
370 : long nTopWindowCount = Application::GetTopWindowCount();
371 : long nBadTopWindows = nTopWindowCount;
372 : for( long i = 0; i < nTopWindowCount; i++ )
373 : {
374 : Window* pWin = Application::GetTopWindow( i );
375 : // default window will be destroyed further down
376 : // but may still be useful during deinit up to that point
377 : if( pWin == pSVData->mpDefaultWin )
378 : nBadTopWindows--;
379 : else
380 : {
381 : aBuf.append( "text = \"" );
382 : aBuf.append( rtl::OUStringToOString( pWin->GetText(), osl_getThreadTextEncoding() ) );
383 : aBuf.append( "\" type = \"" );
384 : aBuf.append( typeid(*pWin).name() );
385 : aBuf.append( "\", ptr = 0x" );
386 : aBuf.append( sal_Int64( pWin ), 16 );
387 : aBuf.append( "\n" );
388 : }
389 : }
390 : DBG_ASSERT( nBadTopWindows==0, aBuf.getStr() );
391 : #endif
392 :
393 8 : ImplImageTreeSingletonRef()->shutDown();
394 :
395 8 : osl_removeSignalHandler( pExceptionHandler);
396 8 : pExceptionHandler = NULL;
397 :
398 : // Debug Daten zuruecksetzen
399 : DBGGUI_DEINIT();
400 :
401 : // free global data
402 8 : delete pSVData->maGDIData.mpGrfConverter;
403 :
404 8 : if( pSVData->mpSettingsConfigItem )
405 8 : delete pSVData->mpSettingsConfigItem, pSVData->mpSettingsConfigItem = NULL;
406 8 : if( pSVData->maGDIData.mpDefaultFontConfiguration )
407 0 : delete pSVData->maGDIData.mpDefaultFontConfiguration, pSVData->maGDIData.mpDefaultFontConfiguration = NULL;
408 8 : if( pSVData->maGDIData.mpFontSubstConfiguration )
409 0 : delete pSVData->maGDIData.mpFontSubstConfiguration, pSVData->maGDIData.mpFontSubstConfiguration = NULL;
410 :
411 8 : if ( pSVData->maAppData.mpIdleMgr )
412 2 : delete pSVData->maAppData.mpIdleMgr;
413 8 : Timer::ImplDeInitTimer();
414 :
415 8 : if ( pSVData->maWinData.mpMsgBoxImgList )
416 : {
417 0 : delete pSVData->maWinData.mpMsgBoxImgList;
418 0 : pSVData->maWinData.mpMsgBoxImgList = NULL;
419 : }
420 8 : if ( pSVData->maCtrlData.mpCheckImgList )
421 : {
422 0 : delete pSVData->maCtrlData.mpCheckImgList;
423 0 : pSVData->maCtrlData.mpCheckImgList = NULL;
424 : }
425 8 : if ( pSVData->maCtrlData.mpRadioImgList )
426 : {
427 0 : delete pSVData->maCtrlData.mpRadioImgList;
428 0 : pSVData->maCtrlData.mpRadioImgList = NULL;
429 : }
430 8 : if ( pSVData->maCtrlData.mpPinImgList )
431 : {
432 0 : delete pSVData->maCtrlData.mpPinImgList;
433 0 : pSVData->maCtrlData.mpPinImgList = NULL;
434 : }
435 8 : if ( pSVData->maCtrlData.mpSplitHPinImgList )
436 : {
437 0 : delete pSVData->maCtrlData.mpSplitHPinImgList;
438 0 : pSVData->maCtrlData.mpSplitHPinImgList = NULL;
439 : }
440 8 : if ( pSVData->maCtrlData.mpSplitVPinImgList )
441 : {
442 0 : delete pSVData->maCtrlData.mpSplitVPinImgList;
443 0 : pSVData->maCtrlData.mpSplitVPinImgList = NULL;
444 : }
445 8 : if ( pSVData->maCtrlData.mpSplitHArwImgList )
446 : {
447 0 : delete pSVData->maCtrlData.mpSplitHArwImgList;
448 0 : pSVData->maCtrlData.mpSplitHArwImgList = NULL;
449 : }
450 8 : if ( pSVData->maCtrlData.mpSplitVArwImgList )
451 : {
452 0 : delete pSVData->maCtrlData.mpSplitVArwImgList;
453 0 : pSVData->maCtrlData.mpSplitVArwImgList = NULL;
454 : }
455 8 : if ( pSVData->maCtrlData.mpDisclosurePlus )
456 : {
457 0 : delete pSVData->maCtrlData.mpDisclosurePlus;
458 0 : pSVData->maCtrlData.mpDisclosurePlus = NULL;
459 : }
460 8 : if ( pSVData->maCtrlData.mpDisclosureMinus )
461 : {
462 0 : delete pSVData->maCtrlData.mpDisclosureMinus;
463 0 : pSVData->maCtrlData.mpDisclosureMinus = NULL;
464 : }
465 8 : if ( pSVData->mpDefaultWin )
466 : {
467 8 : delete pSVData->mpDefaultWin;
468 8 : pSVData->mpDefaultWin = NULL;
469 : }
470 :
471 8 : if ( pSVData->mpUnoWrapper )
472 : {
473 : try
474 : {
475 : uno::Reference<lang::XComponent> const xDesktop(
476 4 : comphelper::getProcessServiceFactory()->createInstance(
477 2 : OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop"))),
478 2 : uno::UNO_QUERY_THROW)
479 : ;
480 2 : xDesktop->addEventListener(new VCLUnoWrapperDeleter());
481 : }
482 0 : catch (uno::Exception const&)
483 : {
484 : // ignore
485 : }
486 : }
487 :
488 8 : if( pSVData->mpApp )
489 : {
490 8 : sal_uLong nCount = Application::ReleaseSolarMutex();
491 : // call deinit to deinitialize application class
492 : // soffice/sfx implementation disposes the global service manager
493 : // Warning: After this call you can't call uno services
494 8 : pSVData->mpApp->DeInit();
495 8 : Application::AcquireSolarMutex(nCount);
496 : }
497 :
498 8 : if ( pSVData->maAppData.mpSettings )
499 : {
500 8 : if ( pSVData->maAppData.mpCfgListener )
501 : {
502 8 : pSVData->maAppData.mpSettings->GetSysLocale().GetOptions().RemoveListener( pSVData->maAppData.mpCfgListener );
503 8 : delete pSVData->maAppData.mpCfgListener;
504 : }
505 :
506 8 : delete pSVData->maAppData.mpSettings;
507 8 : pSVData->maAppData.mpSettings = NULL;
508 : }
509 8 : if ( pSVData->maAppData.mpAccelMgr )
510 : {
511 0 : delete pSVData->maAppData.mpAccelMgr;
512 0 : pSVData->maAppData.mpAccelMgr = NULL;
513 : }
514 8 : if ( pSVData->maAppData.mpAppFileName )
515 : {
516 8 : delete pSVData->maAppData.mpAppFileName;
517 8 : pSVData->maAppData.mpAppFileName = NULL;
518 : }
519 8 : if ( pSVData->maAppData.mpAppName )
520 : {
521 8 : delete pSVData->maAppData.mpAppName;
522 8 : pSVData->maAppData.mpAppName = NULL;
523 : }
524 8 : if ( pSVData->maAppData.mpDisplayName )
525 : {
526 8 : delete pSVData->maAppData.mpDisplayName;
527 8 : pSVData->maAppData.mpDisplayName = NULL;
528 : }
529 8 : if ( pSVData->maAppData.mpEventListeners )
530 : {
531 2 : delete pSVData->maAppData.mpEventListeners;
532 2 : pSVData->maAppData.mpEventListeners = NULL;
533 : }
534 8 : if ( pSVData->maAppData.mpKeyListeners )
535 : {
536 0 : delete pSVData->maAppData.mpKeyListeners;
537 0 : pSVData->maAppData.mpKeyListeners = NULL;
538 : }
539 8 : if ( pSVData->maAppData.mpPostYieldListeners )
540 : {
541 0 : delete pSVData->maAppData.mpPostYieldListeners;
542 0 : pSVData->maAppData.mpPostYieldListeners = NULL;
543 : }
544 :
545 8 : if ( pSVData->maAppData.mpFirstHotKey )
546 0 : ImplFreeHotKeyData();
547 8 : if ( pSVData->maAppData.mpFirstEventHook )
548 0 : ImplFreeEventHookData();
549 :
550 8 : ImplDeletePrnQueueList();
551 8 : delete pSVData->maGDIData.mpScreenFontList;
552 8 : pSVData->maGDIData.mpScreenFontList = NULL;
553 8 : delete pSVData->maGDIData.mpScreenFontCache;
554 8 : pSVData->maGDIData.mpScreenFontCache = NULL;
555 8 : ImplFreeOutDevFontData();
556 :
557 8 : if ( pSVData->mpResMgr )
558 : {
559 8 : delete pSVData->mpResMgr;
560 8 : pSVData->mpResMgr = NULL;
561 : }
562 :
563 8 : ResMgr::DestroyAllResMgr();
564 :
565 : // destroy all Sal interfaces before destorying the instance
566 : // and thereby unloading the plugin
567 8 : delete pSVData->mpSalSystem;
568 8 : pSVData->mpSalSystem = NULL;
569 8 : delete pSVData->mpSalTimer;
570 8 : pSVData->mpSalTimer = NULL;
571 :
572 : // Sal deinitialisieren
573 8 : DestroySalInstance( pSVData->mpDefInst );
574 :
575 8 : DeInitTools();
576 :
577 8 : DeInitSalMain();
578 :
579 8 : if( pOwnSvApp )
580 : {
581 0 : delete pOwnSvApp;
582 0 : pOwnSvApp = NULL;
583 : }
584 :
585 8 : TemporaryFonts::clear();
586 8 : }
587 :
588 : // only one call is allowed
589 : struct WorkerThreadData
590 : {
591 : oslWorkerFunction pWorker;
592 : void * pThreadData;
593 100 : WorkerThreadData( oslWorkerFunction pWorker_, void * pThreadData_ )
594 : : pWorker( pWorker_ )
595 100 : , pThreadData( pThreadData_ )
596 : {
597 100 : }
598 : };
599 :
600 : #ifdef WNT
601 : static HANDLE hThreadID = 0;
602 : static unsigned __stdcall _threadmain( void *pArgs )
603 : {
604 : OleInitialize( NULL );
605 : ((WorkerThreadData*)pArgs)->pWorker( ((WorkerThreadData*)pArgs)->pThreadData );
606 : delete (WorkerThreadData*)pArgs;
607 : OleUninitialize();
608 : hThreadID = 0;
609 : return 0;
610 : }
611 : #else
612 : static oslThread hThreadID = 0;
613 : extern "C"
614 : {
615 100 : static void SAL_CALL MainWorkerFunction( void* pArgs )
616 : {
617 100 : ((WorkerThreadData*)pArgs)->pWorker( ((WorkerThreadData*)pArgs)->pThreadData );
618 100 : delete (WorkerThreadData*)pArgs;
619 100 : hThreadID = 0;
620 100 : }
621 : } // extern "C"
622 : #endif
623 :
624 100 : void CreateMainLoopThread( oslWorkerFunction pWorker, void * pThreadData )
625 : {
626 : #ifdef WNT
627 : // sal thread alway call CoInitializeEx, so a sysdepen implementation is necessary
628 :
629 : unsigned uThreadID;
630 : hThreadID = (HANDLE)_beginthreadex(
631 : NULL, // no security handle
632 : 0, // stacksize 0 means default
633 : _threadmain, // thread worker function
634 : new WorkerThreadData( pWorker, pThreadData ), // arguments for worker function
635 : 0, // 0 means: create immediatly otherwise use CREATE_SUSPENDED
636 : &uThreadID ); // thread id to fill
637 : #else
638 100 : hThreadID = osl_createThread( MainWorkerFunction, new WorkerThreadData( pWorker, pThreadData ) );
639 : #endif
640 100 : }
641 :
642 100 : void JoinMainLoopThread()
643 : {
644 100 : if( hThreadID )
645 : {
646 : #ifdef WNT
647 : WaitForSingleObject(hThreadID, INFINITE);
648 : #else
649 98 : osl_joinWithThread(hThreadID);
650 98 : osl_destroyThread( hThreadID );
651 : #endif
652 : }
653 100 : }
654 :
655 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|