Ticket #500: atlasthreading-wmifix-09032011.patch
File atlasthreading-wmifix-09032011.patch, 8.2 KB (added by , 13 years ago) |
---|
-
source/lib/sysdep/os/win/wmi.cpp
1 /* Copyright (c) 201 0Wildfire Games1 /* Copyright (c) 2011 Wildfire Games 2 2 * 3 3 * Permission is hereby granted, free of charge, to any person obtaining 4 4 * a copy of this software and associated documentation files (the … … 42 42 43 43 static ModuleInitState initState; 44 44 45 static bool didInitCOM = false; 46 45 47 static Status Init() 46 48 { 47 49 HRESULT hr; … … 49 51 hr = CoInitialize(0); 50 52 ENSURE(hr == S_OK || hr == S_FALSE); // S_FALSE => already initialized 51 53 54 // balance calls to CoInitialize and CoUninitialize 55 if (hr == S_FALSE) 56 CoUninitialize(); 57 else if (hr == S_OK) 58 didInitCOM = true; 59 52 60 hr = CoInitializeSecurity(0, -1, 0, 0, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, 0, EOAC_NONE, 0); 53 61 if(FAILED(hr)) 54 62 WARN_RETURN(ERR::_2); … … 75 83 { 76 84 pSvc->Release(); 77 85 78 // note: don't shut down COM because other modules may still be using it. 79 //CoUninitialize(); 86 if (didInitCOM) 87 { 88 /* From MSDN documentation: A thread must call CoUninitialize once for each successful call 89 * it has made to the CoInitialize or CoInitializeEx function, including any call that returns 90 * S_FALSE. Only the CoUninitialize call corresponding to the CoInitialize or CoInitializeEx 91 * call that initialized the library can close it. 92 * 93 * So it should be perfectly safe to call this, since it balances out the CoInitialize in Init 94 */ 95 CoUninitialize(); 96 didInitCOM = false; 97 } 80 98 } 81 99 82 100 void wmi_Shutdown() -
source/lib/sysdep/os/win/wsysdep.cpp
459 459 return INFO::OK; 460 460 } 461 461 462 // Balance call to CoInitialize, which must have been successful 463 CoUninitialize(); 464 462 465 WARN_RETURN(StatusFromWin()); 463 466 } 464 467 -
source/ps/GameSetup/GameSetup.cpp
102 102 #define MUST_INIT_X11 0 103 103 #endif 104 104 105 #if OS_WIN 106 extern void wmi_Shutdown(); 107 #endif 108 105 109 #include <iostream> 106 110 107 111 ERROR_GROUP(System); … … 683 687 delete &g_Profiler; 684 688 delete &g_ProfileViewer; 685 689 TIMER_END(L"shutdown misc"); 690 691 #if OS_WIN 692 TIMER_BEGIN(L"shutdown wmi"); 693 wmi_Shutdown(); 694 TIMER_END(L"shutdown wmi"); 695 #endif 686 696 } 687 697 688 698 #if OS_UNIX -
source/tools/atlas/GameInterface/GameLoop.cpp
1 /* Copyright (C) 201 0Wildfire Games.1 /* Copyright (C) 2011 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 73 73 static GameLoopState state; 74 74 GameLoopState* g_GameLoop = &state; 75 75 76 static void* LaunchWindow(void* data)77 {78 debug_SetThreadName("atlas_window");79 76 80 const wchar_t* windowName = reinterpret_cast<const wchar_t*>(data);81 Atlas_StartWindow(windowName);82 return NULL;83 }84 85 // Work out which Atlas window to launch, given the command-line arguments86 static const wchar_t* FindWindowName(const CmdLineArgs& UNUSED(args))87 {88 return L"ScenarioEditor";89 // (This is a bit pointless - there's no choice since we've deleted the ActorViewer)90 }91 92 77 static ErrorReactionInternal AtlasDisplayError(const wchar_t* text, size_t flags) 93 78 { 94 79 // TODO: after Atlas has been unloaded, don't do this … … 114 99 while (more && timer_Time() - startTime < maxTime); 115 100 } 116 101 117 bool BeginAtlas(const CmdLineArgs& args, const DllLoader& dll) 102 static void* RunGame(void *data) 118 103 { 119 // Load required symbols from the DLL 120 try 121 { 122 dll.LoadSymbol("Atlas_StartWindow", Atlas_StartWindow); 123 dll.LoadSymbol("Atlas_SetMessagePasser", Atlas_SetMessagePasser); 124 dll.LoadSymbol("Atlas_SetDataDirectory", Atlas_SetDataDirectory); 125 dll.LoadSymbol("Atlas_GLSetCurrent", Atlas_GLSetCurrent); 126 dll.LoadSymbol("Atlas_GLSwapBuffers", Atlas_GLSwapBuffers); 127 dll.LoadSymbol("Atlas_NotifyEndOfFrame", Atlas_NotifyEndOfFrame); 128 dll.LoadSymbol("Atlas_DisplayError", Atlas_DisplayError); 129 dll.LoadSymbol("Atlas_ReportError", Atlas_ReportError); 130 dll.LoadSymbol("ShareableMalloc", ShareableMallocFptr); 131 dll.LoadSymbol("ShareableFree", ShareableFreeFptr); 132 } 133 catch (PSERROR_DllLoader&) 134 { 135 debug_warn(L"Failed to initialise DLL"); 136 return false; 137 } 104 debug_SetThreadName("game_thread"); 138 105 139 // Construct a message passer for communicating with Atlas 140 MessagePasserImpl msgPasser; 141 AtlasMessage::g_MessagePasser = &msgPasser; 106 // Set new main thread so that all the thread-safety checks pass 107 ThreadUtil::SetMainThread(); 142 108 143 // Pass our message handler to Atlas 144 Atlas_SetMessagePasser(&msgPasser); 109 const CmdLineArgs args = *reinterpret_cast<const CmdLineArgs*>(data); 145 110 146 // Tell Atlas the location of the data directory 147 const Paths paths(args); 148 Atlas_SetDataDirectory(paths.RData().string().c_str()); 111 MessagePasserImpl* msgPasser = (MessagePasserImpl*)AtlasMessage::g_MessagePasser; 149 112 150 113 // Register all the handlers for message which might be passed back 151 114 RegisterHandlers(); 152 153 // Create a new thread, and launch the Atlas window inside that thread 154 const wchar_t* windowName = FindWindowName(args); 155 pthread_t uiThread; 156 pthread_create(&uiThread, NULL, LaunchWindow, reinterpret_cast<void*>(const_cast<wchar_t*>(windowName))); 157 115 158 116 // Override ah_display_error to pass all errors to the Atlas UI 159 117 AppHooks hooks = {0}; 160 118 hooks.display_error = AtlasDisplayError; … … 199 157 200 158 { 201 159 IMessage* msg; 202 while ((msg = msgPasser .Retrieve()) != NULL)160 while ((msg = msgPasser->Retrieve()) != NULL) 203 161 { 204 162 recent_activity = true; 205 163 … … 294 252 // (TODO: This should probably be done with something like semaphores) 295 253 Atlas_NotifyEndOfFrame(); // (TODO: rename to NotifyEndOfQuiteShortProcessingPeriodSoPleaseSendMeNewMessages or something) 296 254 SDL_Delay(50); 297 if (!msgPasser .IsEmpty())255 if (!msgPasser->IsEmpty()) 298 256 break; 299 257 time = timer_Time(); 300 258 } … … 306 264 } 307 265 } 308 266 267 return NULL; 268 } 269 270 bool BeginAtlas(const CmdLineArgs& args, const DllLoader& dll) 271 { 272 // Load required symbols from the DLL 273 try 274 { 275 dll.LoadSymbol("Atlas_StartWindow", Atlas_StartWindow); 276 dll.LoadSymbol("Atlas_SetMessagePasser", Atlas_SetMessagePasser); 277 dll.LoadSymbol("Atlas_SetDataDirectory", Atlas_SetDataDirectory); 278 dll.LoadSymbol("Atlas_GLSetCurrent", Atlas_GLSetCurrent); 279 dll.LoadSymbol("Atlas_GLSwapBuffers", Atlas_GLSwapBuffers); 280 dll.LoadSymbol("Atlas_NotifyEndOfFrame", Atlas_NotifyEndOfFrame); 281 dll.LoadSymbol("Atlas_DisplayError", Atlas_DisplayError); 282 dll.LoadSymbol("Atlas_ReportError", Atlas_ReportError); 283 dll.LoadSymbol("ShareableMalloc", ShareableMallocFptr); 284 dll.LoadSymbol("ShareableFree", ShareableFreeFptr); 285 } 286 catch (PSERROR_DllLoader&) 287 { 288 debug_warn(L"Failed to initialise DLL"); 289 return false; 290 } 291 292 // Construct a message passer for communicating with Atlas 293 // (here so that it's scope lasts beyond the game thread) 294 MessagePasserImpl msgPasser; 295 AtlasMessage::g_MessagePasser = &msgPasser; 296 297 // Pass our message handler to Atlas 298 Atlas_SetMessagePasser(&msgPasser); 299 300 // Tell Atlas the location of the data directory 301 const Paths paths(args); 302 Atlas_SetDataDirectory(paths.RData().string().c_str()); 303 304 // run the rest of the engine in a new thread 305 pthread_t engineThread; 306 pthread_create(&engineThread, NULL, RunGame, reinterpret_cast<void*>(const_cast<CmdLineArgs*>(&args))); 307 308 // start Atlas UI on main thread 309 Atlas_StartWindow(L"ScenarioEditor"); 310 311 // Wait for the engine to exit 312 pthread_join(engineThread, NULL); 313 309 314 // TODO: delete all remaining messages, to avoid memory leak warnings 310 315 311 // Wait for the UI to exit312 pthread_join(uiThread, NULL);316 // Restore main thread 317 ThreadUtil::SetMainThread(); 313 318 314 319 // Clean up 315 320 View::DestroyViews();