Jump to content

Thread and Mutex Objects


Joshua
 Share

Recommended Posts

How is it possible to use the Thread and Mutex objects with class object methods? I have only been able to figure out how to use the Thread and Mutex objects with free object methods.

 

so instead of:

 

Object* UpdateChunk(Object* obj)
{
mutex->Lock();
esChunk* chunk = (esChunk*)obj;
chunk->Update(1.0f);
mutex->Unlock();
return NULL;
}
// --------------------
// Updates the esScene.
// --------------------
void esScene::Update(float deltaTime)
{
int index = 0;
for(unsigned int x = 0; x < 2; x++)
for(unsigned int z = 0; z < 2; z++)
for(unsigned int y = 0; y < 2; y++)
{
if(m_chunks.at(index)->IsSetup())
 if(m_chunks.at(index)->IsDirty())
 {

 thread = Thread::Create(UpdateChunk, (Object*) m_chunks.at(index));

 }
//m_chunks.at(index)->Update(deltaTime);
index++;

}

} // end void esScene::Update(float deltaTime)
// -----------------------------------------------------------------------------------------

 

I can do this:

 

Object* esScene::UpdateChunk(Object* obj)
{
 Vec4* data = (Vec4*) obj;
mutex->Lock();
esChunk* chunk = (esChunk*)obj;
GetChunk(data.x, data.y, data.z)->Update(data.w);
mutex->Unlock();
return NULL;
}
// --------------------
// Updates the esScene.
// --------------------
void esScene::Update(float deltaTime)
{
int index = 0;
for(unsigned int x = 0; x < 2; x++)
for(unsigned int z = 0; z < 2; z++)
for(unsigned int y = 0; y < 2; y++)
{
if(m_chunks.at(index)->IsSetup())
 if(m_chunks.at(index)->IsDirty())
 {

 thread = Thread::Create(UpdateChunk, (Object*) new Vec4(x, y, z, deltaTime));

 }

index++;

}

} // end void esScene::Update(float deltaTime)
// -----------------------------------------------------------------------------------------

 

thread and mutex are global in this scope however, I would prefer to have them objects of the esScene class structure. I have tried to create a function pointer that resides inside the class, however, this option does not seem to work. It appears that I need an instance of the class in order to get the function pointer however, there seems to be a big difference in how object member functions and free functions are handled.

Link to comment
Share on other sites

Here is my superquick test, turning a box on a second thread : (not sure if this is what you wanted)

 

#include "App.h"

using namespace Leadwerks;

App::App() : window(NULL), context(NULL), world(NULL), camera(NULL) {}

App::~App() { delete world; delete window; }

Vec3 camerarotation;
#if defined (PLATFORM_WINDOWS) || defined (PLATFORM_MACOS)
bool freelookmode = true;
#else
bool freelookmode = false;
#endif

Mutex* mutex = NULL;

Model* m = NULL;


Object* ThreadFunction(Object* object)
{
   for (int i = 0; i<1000; i++)
   {
       //Lock the mutex so the two threads don't interfere with each other
       mutex->Lock();
       m->Turn(0.1, 0.1, 0.1);
       mutex->Unlock();
       Time::Delay(10);
   }

   //Create something to give back to the main thread

   return 0;
}

bool App::Start()
{
   //Initialize Steamworks (optional)
   /*if (!Steamworks::Initialize())
   {
   System::Print("Error: Failed to initialize Steam.");
   return false;
   }*/

   //Create a window
   window = Leadwerks::Window::Create("cpp_worlds");

   //Create a context
   context = Context::Create(window);


   mutex = Mutex::Create();


   //Create a world
   world = World::Create();

   camera = Camera::Create();
   camera->Move(0, 2, -5);

   //Load the map
   std::string mapname = System::GetProperty("map", "Maps/start.map");
   Map::Load(mapname);

   m = Model::Box();
   m->Move(0, 3, 0);

   Thread* thread = Thread::Create(ThreadFunction);

   return true;
}

bool App::Loop()
{

   //Close the window to end the program
   if (window->Closed()) return false;

   //Press escape to end freelook mode
   if (window->KeyHit(Key::Escape))
   {
       if (!freelookmode) return false;
       freelookmode = false;
       window->ShowMouse();
   }

   Leadwerks::Time::Update();

   world->Update();
   world->Render();

   context->Sync(false);

   return true;
}

HP Omen - 16GB - i7 - Nvidia GTX 1060 6GB

Link to comment
Share on other sites

@Shadmar, your example above still uses a Free Function for the thread entry point. I am looking to use a Class Member Function as the thread entry point. Using a Class Member Function as the entry point for a thread would allow me to remove global scope variables from my source. It would also minimize the number of typecasting and the creation of new instanced objects needed.

Link to comment
Share on other sites

Can't you just cast it

 

Object* ThreadFunction(Object* object)
{
       for (int i = 0; i<1000; i++)
       {
               //Lock the mutex so the two threads don't interfere with each other
               mutex->Lock();
               static_cast<Model*>(object)->Turn(0.1, 0.1, 0.1);
               mutex->Unlock();
               Time::Delay(10);
       }

       //Create something to give back to the main thread

       return 0;
}

//Create something to give back to the main thread

return 0;
}

 

Then in App::Start() do something like :

 

Model* m = Box::Create();
Thread* thread = Thread::Create(ThreadFunction,static_cast<Object*>(m));

HP Omen - 16GB - i7 - Nvidia GTX 1060 6GB

Link to comment
Share on other sites

Not currently. A static_cast would require the given cast object to be of a related class, ex, derived from Object to allow for up-casts or down-casts. I could allow my own game objects to inherit from the Object* class however, this is not entirely desired for my purposes. For example, I may want to pass in the current class instance to gain access to its contents for some kind of manipulation.

 

Passing in the current class instance casted to an Object* to the thread entry point and casting it back to an instance of the appripriate class to call functions to interact with private or protected class variables is what I currently do, however I feel this is an unnecessary work-around. I think there should be a way in which I would be able to create a thread entry point from within a class which already has access to its private and protected members.

 

For example.

 

In my Scene class I have a std::vector of Chunk* objects. I want to be able to add/remove chunks from this std::vector in a separate thread because my scene can be from 1 to n chunks in size where n is limited to some finite number of chunks I want to be loaded at any given time.

 

I want to be able to access the scenes std::vector directly, allowing me to add a new chunk without having to create a function outside the scope of my Scene class to add the chunk to the Scene std::vector.

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...