Jump to content

Attempt At Multithreading in C++


TylerH
 Share

Recommended Posts

Well, with the current Vex Studios project, we were throwing ideas around and wanted to have a real progress bar on our loading screen, instead of a "Loading..." text while the Leadwerks LoadScene function halted the main thread.

 

In an attempt to suit that idea, and test how many, if any, of the Leadwerks functions will run in a seperate thread, we went ahead and changed up our Level Manager to call LoadScene in its own little thread. Here is some slight source code:

 

unsigned __stdcall LoadLevelFunc( void* pArguments )
{
printf( "In second thread...\n" );

Game::Globals:_LevelManager::getInstance()->m_eScene = LoadScene(Game::Globals:_LevelManager::getInstance()->m_sLevel);

_endthreadex( 0 );
return 0;
} 

bool CLevelManager::Load()
{
if(m_sLevel == "") return false;

//m_eScene = LoadScene(m_sLevel);
m_eScene = NULL;

HANDLE hThread;
unsigned threadID;

printf( "Creating second thread...\n" );

// Create the second thread.
hThread = (HANDLE)_beginthreadex( NULL, 0, &LoadLevelFunc, NULL, 0, &threadID );

WaitForSingleObject( hThread, INFINITE );

Collisions(3,2,1);
Collisions(2,3,1);
Collisions(1,1,1);
Collisions(3,1,1);
Collisions(2,1,1);
Collisions(3,3,1);
Collisions(2,2,1);

if(m_eScene!=NULL)
{
	std::cout << "Scene Children: " << CountChildren(m_eScene) << "\n";
	for(int i = 1; i<=CountChildren(m_eScene); i++)
	{
		ProcessEntity(GetChild(m_eScene, i));
	}
}

return m_eScene!=NULL;
}

 

The Level Manager was coded by Jeremy, and I added in the threaded function a short bit ago.

 

Now here is the COOL part.

 

LoadScene didn't crash immediately. Leadwerks ran it.

 

it loaded the first model...the first mesh for that model...the material file. No problems.

 

It failed to load every single texture for the model.

 

It loaded the shader in the material file fine.

 

Shader compilation failed because the textures were all null and not loaded...

 

Printed full mesh.frag source with proper defines to the console, then the program terminated (which Leadwerks seems to do when a Shader fails to compile).

 

 

 

So, threading failed, but these are some good signs.

 

Maybe this will spearhead Leadwerks Corporation to look into atleast making the functions of the engine thread safe, for reasons like this. Even things like networking Leadwerks entities, Loading like in this case, or doing some kind of data streaming in the background. This doesn't require the Leadwerks Engine to be threaded at all. It simply requires that the engine commands be thread safe, and capable of being run asynchronously.

 

Or it could be simply something wrong in the texture loading code :blink:.

 

Hoping this gets us somewhere!

 

Cheers,

Tyler

  • Upvote 1

52t__nvidia.png nVidia 530M cpu.gif Intel Core i7 - 2.3Ghz 114229_30245_16_hardware_memory_ram_icon.png 8GB DDR3 RAM Windows7_Start.gif Windows 7 Ultimate (64x)

-----

IconVisualStudio16.png Visual Studio 2010 Ultimate google-Chrome.png Google Chrome PhotoshopLinkIndicator.png Creative Suite 5 icon28.gif FL Studio 10 MicrosoftOfficeLive.png Office 15

-----

csharp.png Expert cpp.png Professional lua_icon.png Expert BMX Programmer

-----

i-windows-live-messenger-2009.pngskype-icon16.pngaim_online.pnggmail.pngicon_48x48_prism-facebook.pngtunein-web.pngyahoo.giftwitter16.png

Link to comment
Share on other sites

Just throwing ideas out, but couldn't you simulate this without threading? By parsing the sbx file yourself you can store all things that need to be loaded in a container. Then over multiple cycles load a few things in the container. This would allow you to keep the main loop running to give you a better progress bar. You could also get a count of how many things need to be loaded to give an accurate progress bar. Sure while it's loading 1 model in the container it would be frozen for a second or so, but if you don't have anything moving around constantly the user wouldn't notice. For that game I'd put up a cool 2D drawing in the background (because the art style is very cool) and use a progress bar on top of it.

 

That being said, yeah thread safe would be nice, but until then above is how I would handle it if I cared enough about that limitation.

  • Downvote 1
Link to comment
Share on other sites

Sure, there are ways to hack around it, and we already have such ways implemented, or are working on them.

 

I really am not comfortable with custom parsing the SBX file, because half of the stuff in there isn't doable with the procedural command set, i.e. Multiple vegetation layers, Some of the script stuff I am sure, etc.

 

It would be great if we could get the source code to LoadScene, and be able to customize it in our own language, then I could make it thread safe.

  • Upvote 1

52t__nvidia.png nVidia 530M cpu.gif Intel Core i7 - 2.3Ghz 114229_30245_16_hardware_memory_ram_icon.png 8GB DDR3 RAM Windows7_Start.gif Windows 7 Ultimate (64x)

-----

IconVisualStudio16.png Visual Studio 2010 Ultimate google-Chrome.png Google Chrome PhotoshopLinkIndicator.png Creative Suite 5 icon28.gif FL Studio 10 MicrosoftOfficeLive.png Office 15

-----

csharp.png Expert cpp.png Professional lua_icon.png Expert BMX Programmer

-----

i-windows-live-messenger-2009.pngskype-icon16.pngaim_online.pnggmail.pngicon_48x48_prism-facebook.pngtunein-web.pngyahoo.giftwitter16.png

Link to comment
Share on other sites

I was just thinking that from what Josh has said in the past that making things thread safe wasn't a huge priority for him. I just really doubt it'll be looked at anytime soon and I'd be nervous if he did it anyway because I'm guessing it would introduce all sorts of bugs at first and make us unhappy. :blink:

 

I seem to recall more than just LoadScene() would need to be changed because if something was 1/2 loaded and you call the rendering method it would hose things up because it would try to render something that isn't fully loaded yet. Something like that. I'm not a big threaded guy. I have a couple threaded apps at work and they are a pain in the wonderful person to debug with VS's stepping through code. I'm having to freeze threads and all that ****.

  • Downvote 1
Link to comment
Share on other sites

Well, I know nothing is borked outside of LoadScene here, because even though I call it in a seperate thread, I use WaitForSingleObject( hThread, INFINITE );

So the main thread is basically sleeping until the LoadScene thread is done, which should give the same effect as calling LoadScene in the same thread, except for the cosmetics and such of the structure.

 

 

The idea here is that running non-mutable code in a secondary thread shouldn't cause problems. Now, I could see the issue of say, calling PositionEntity, RotateEntity, etc. in a secondary thread, or whatever. Actually, if you use semaphores and mutexes correctly, you wouldn't need to worry, threading would basically take care of itself...

  • Upvote 1

52t__nvidia.png nVidia 530M cpu.gif Intel Core i7 - 2.3Ghz 114229_30245_16_hardware_memory_ram_icon.png 8GB DDR3 RAM Windows7_Start.gif Windows 7 Ultimate (64x)

-----

IconVisualStudio16.png Visual Studio 2010 Ultimate google-Chrome.png Google Chrome PhotoshopLinkIndicator.png Creative Suite 5 icon28.gif FL Studio 10 MicrosoftOfficeLive.png Office 15

-----

csharp.png Expert cpp.png Professional lua_icon.png Expert BMX Programmer

-----

i-windows-live-messenger-2009.pngskype-icon16.pngaim_online.pnggmail.pngicon_48x48_prism-facebook.pngtunein-web.pngyahoo.giftwitter16.png

Link to comment
Share on other sites

The idea here is that running non-mutable code in a secondary thread shouldn't cause problems. Now, I could see the issue of say, calling PositionEntity, RotateEntity, etc. in a secondary thread, or whatever. Actually, if you use semaphores and mutexes correctly, you wouldn't need to worry, threading would basically take care of itself...[/font]

 

I found everything to do with LE is not thread safe, even simple stuff like EntityPosition.

 

I would really like LE (or bits of) to be thread safe so I could sub-divide up my AI stuff into threads. It would be a big bonus if a single place like RenderWorld or RenderLights which are intensive were made thread safe.

Link to comment
Share on other sites

Just thought of another thing that would be great for making "thread safe". Raycasting (linepick), basically a working game will be doing 49% rendering, 29% pyhsics, 20% line pick and 2% other stuff IMHO. Linepicks are expensive so it would be great to be able to split them into a thread taking requests off a queue.

Link to comment
Share on other sites

I am going to be implementing a job queue and thread pool system to handle game logic, so it would be great if we could expand that to atleast calling engine commands.

 

This doesn't require the engine to be compiled in Blitzmax multithreaded mode or anything, just some basic checks on commands to make sure the memory they are accessing (models, etc.) are truely accessible and not in use.

 

This is done by simply using semaphores, more specifically the mutex semaphore, which is quite easy to implement.

 

 

If I or someone else were to write an example of such an implementation in Blitzmax, do you (Josh) think this may be viable?

52t__nvidia.png nVidia 530M cpu.gif Intel Core i7 - 2.3Ghz 114229_30245_16_hardware_memory_ram_icon.png 8GB DDR3 RAM Windows7_Start.gif Windows 7 Ultimate (64x)

-----

IconVisualStudio16.png Visual Studio 2010 Ultimate google-Chrome.png Google Chrome PhotoshopLinkIndicator.png Creative Suite 5 icon28.gif FL Studio 10 MicrosoftOfficeLive.png Office 15

-----

csharp.png Expert cpp.png Professional lua_icon.png Expert BMX Programmer

-----

i-windows-live-messenger-2009.pngskype-icon16.pngaim_online.pnggmail.pngicon_48x48_prism-facebook.pngtunein-web.pngyahoo.giftwitter16.png

Link to comment
Share on other sites

I do/did use Boost, but I prefer my own implementation, because it removes the overhead boost has from implementing for multiple platforms where I am using Windows exclusively. If you check out the boost hpp headers, you will see it uses Win32 critical sections for its mutex class on Windows.

 

EDIT: Actually, better than anything are the Intel Threaded Building Blocks, especially if you are on an Intel architecture CPU. Not sure if AMD has an equivalent.

52t__nvidia.png nVidia 530M cpu.gif Intel Core i7 - 2.3Ghz 114229_30245_16_hardware_memory_ram_icon.png 8GB DDR3 RAM Windows7_Start.gif Windows 7 Ultimate (64x)

-----

IconVisualStudio16.png Visual Studio 2010 Ultimate google-Chrome.png Google Chrome PhotoshopLinkIndicator.png Creative Suite 5 icon28.gif FL Studio 10 MicrosoftOfficeLive.png Office 15

-----

csharp.png Expert cpp.png Professional lua_icon.png Expert BMX Programmer

-----

i-windows-live-messenger-2009.pngskype-icon16.pngaim_online.pnggmail.pngicon_48x48_prism-facebook.pngtunein-web.pngyahoo.giftwitter16.png

Link to comment
Share on other sites

This is not my first try to implement multithreading with LWE, and I must say calling engine commands in different threads == fail!

I solved it by using queue's to stash update data and updating it in the main loop. Yes I know, this is a wonderful person to handle. For animated loadingscreen I used windows GDI, a lame and unsafe hack. That the reason why leadwerks should have a render and an update thread...

Link to comment
Share on other sites

I do/did use Boost, but I prefer my own implementation, because it removes the overhead boost has from implementing for multiple platforms where I am using Windows exclusively. If you check out the boost hpp headers, you will see it uses Win32 critical sections for its mutex class on Windows.

 

EDIT: Actually, better than anything are the Intel Threaded Building Blocks, especially if you are on an Intel architecture CPU. Not sure if AMD has an equivalent.

 

I thought BOOST was multi platform and was going to be adopted as a ANSI standard?

Link to comment
Share on other sites

It is. Thats why he said he prefers his own because of the overhead from boost, since he is only on a win machine

I'm surprised it doesn't use conditional compilation to avoid additional overhead! Thats how things like that are normally handled in C and C++. Exactly what is the additional overhead?

Intel Core i5 2.66 GHz, Asus P7P55D, 8Gb DDR3 RAM, GTX460 1Gb DDR5, Windows 7 (x64), LE Editor, GMax, 3DWS, UU3D Pro, Texture Maker Pro, Shader Map Pro. Development language: C/C++

Link to comment
Share on other sites

It does use conditional compiling. I just tend to not like having that extra code there if I am never going to be compiling on a platform that uses it.

 

To be honest, my implementation is the same as boost's for Windows, but my implementation is also the same as the implementation all PC Games use, for example Crysis, since you can openly check out their source code in the Mod SDK.

52t__nvidia.png nVidia 530M cpu.gif Intel Core i7 - 2.3Ghz 114229_30245_16_hardware_memory_ram_icon.png 8GB DDR3 RAM Windows7_Start.gif Windows 7 Ultimate (64x)

-----

IconVisualStudio16.png Visual Studio 2010 Ultimate google-Chrome.png Google Chrome PhotoshopLinkIndicator.png Creative Suite 5 icon28.gif FL Studio 10 MicrosoftOfficeLive.png Office 15

-----

csharp.png Expert cpp.png Professional lua_icon.png Expert BMX Programmer

-----

i-windows-live-messenger-2009.pngskype-icon16.pngaim_online.pnggmail.pngicon_48x48_prism-facebook.pngtunein-web.pngyahoo.giftwitter16.png

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...