Ticket #500: atlas-threading-osxfix-08282011.patch
File atlas-threading-osxfix-08282011.patch, 5.5 KB (added by , 13 years ago) |
---|
-
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();