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