Thread: Threading Question

  1. #1
    Registered User
    Join Date
    Feb 2008
    Location
    Rochester, NY
    Posts
    27

    Question Threading Question

    I am attempting to create an application which uses Boost::Thread in order to complete a task. I need the program to load data in the background while displaying the data which has currently been loading.

    Currently I have a list of Objects which all have Update and Render methods. In the update function if something needs to load I am attempting to create a thread for the loading. This way I can continuously render without delays from loading. The render only needs to be blocked from occurring when the data is finished loading and being setup for use (binding a texture in OpenGL)

    If I want to create a thread of the Update function in Object I have to declare it as a static method correct? Since static methods are unable to access the non-static members of the Object how do I block the Render method when I need.

    I thought this was where I would use a scoped_lock mutex. Everything I have attempted so far does not seem to work. Making the mutex a member of the Object does not work as the static method does not have access. If I make the mutex static outside of the class I'm confused as to how that will work with multiple update threads running at once. I'd assume things would become very confusing in that situation.

    Thanks for all your help.

    Code:
    //Code taken from Object::Update()
            if(discardLevel != prevDiscardLevel)
    	{
    		prevDiscardLevel = discardLevel;
    		
                    //LoadTexture is a static method of Object
    		boost::thread updateThread(boost::bind(&LoadTexture, texture, glTex, discardLevel));
    	}
    
    //Code taken from Object::updateThread()
    void Object::LoadTexture(Texture* Tex, GLuint &texData, int dLevel)
    {
    	Tex->LoadTexture(dLevel);			//Load specific textures data
    	
    	boost::mutex::scoped_lock lock(tex2GL);
    	
    	glBindTexture(GL_TEXTURE_2D, texData);	//Bind the texture for use
    	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, Tex->GetWidth(),
    			Tex->GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, Tex->GetTexture());
    	
    	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    	
    	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    }
    
    //Code taken from Object::Render()
    void Object::Render()
    {
    	if(!visible)
    		return;
    	
    	boost::mutex::scoped_lock lock(tex2GL);
    	
    	glPushMatrix();
    		
    	glTranslatef(transform.x3y0, transform.x3y1, transform.x3y2);
    	
    	glBindTexture(GL_TEXTURE_2D, glTex);
    	
    	glBegin(GL_QUADS);
    		glTexCoord2f(1.f, 0.f); 
    		glVertex3f(-texture->GetHalfWidth(),-texture->GetHalfHeight(), 0.0f);
    		glTexCoord2f(0.f, 0.f); 
    		glVertex3f(texture->GetHalfWidth(),-texture->GetHalfHeight(), 0.0f);
    		glTexCoord2f(0.f, 1.f); 
    		glVertex3f(texture->GetHalfWidth(),texture->GetHalfHeight(), 0.0f);
    		glTexCoord2f(1.f, 1.f); 
    		glVertex3f(-texture->GetHalfWidth(),texture->GetHalfHeight(), 0.0f);
    	glEnd();
    	
    	glPopMatrix();
    }
    Last edited by CornyKorn21; 05-30-2008 at 07:57 AM. Reason: Adding and fixing code.

  2. #2
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Instead of creating what you're now discovering to be a spaghetti of threads for each object, I'd look into batching the render calls and not calling render on each object. I think you'll find that threads are used in games for things like loading levels, playing music, etc. Large tasks that don't require much synchronization.

  3. #3
    Registered User
    Join Date
    Feb 2008
    Location
    Rochester, NY
    Posts
    27
    Quote Originally Posted by medievalelks View Post
    Instead of creating what you're now discovering to be a spaghetti of threads for each object, I'd look into batching the render calls and not calling render on each object. I think you'll find that threads are used in games for things like loading levels, playing music, etc. Large tasks that don't require much synchronization.
    I can batch render calls. That's no problem.

    My issue is loading content in the background and still continuously render. For what I am doing I can not preload everything.

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    One rule of multithreading is that no object can protect itself from access by multiple threads. Generally, the code (or object, or whatever) that acts on an object A needs to also protect object A. This means, in practice, that the code will lock some mutex before acting on the object.

    One way to handle the problem of loading and rendering in separate threads will go something like this (in pseudocode)
    Code:
    //    loading thread
    while (loading)                 // loading will be set to false when no more data to load
    {
          LoadDataFromSomewhere(data);
          Lock(some_mutex);
          Copy(data, some_shared_object)
          Release(some_mutex);
    }
    
    
    //   rendering thread
    
    while (rendering)    // rendering will be set to false when nothing to render (or when the display closes down)
    {
          Lock(some_mutex);
          Copy(some_shared_object, data_to_render);
          Unlock(mutex);
          Render(data_to_render);
    }
    The point is that the loader thread gets data from somewhere and copies it to a location (eg a queue) that can subsequently be accessed by the rendering thread. The operation of copying to or from that "location" (by either thread) must be protected by a mutex. The render thread repetitively retrieves data from that location. Once the rendering thread has data to render, it renders it.

    There are all sorts of enhancements to this scheme to optimise performance. But the rule of thumb is that the time spent with a mutex locked by any thread must be minimised, and the mutex must be grabbed by any thread accessing the shared "location". That is why the operation of loading data (eg from file) and rendering it (eg to screen) normally will be unprotected by the mutex -- if everything is protected by the mutex, may as well do everything sequentially in one thread.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Alice....
    By Lurker in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 06-20-2005, 02:51 PM
  2. Debugging question
    By o_0 in forum C Programming
    Replies: 9
    Last Post: 10-10-2004, 05:51 PM
  3. Question about pointers #2
    By maxhavoc in forum C++ Programming
    Replies: 28
    Last Post: 06-21-2004, 12:52 PM
  4. Question...
    By TechWins in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 07-28-2003, 09:47 PM
  5. Question, question!
    By oskilian in forum A Brief History of Cprogramming.com
    Replies: 5
    Last Post: 12-24-2001, 01:47 AM