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