Joshua Posted May 6, 2014 Share Posted May 6, 2014 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. Quote Link to comment Share on other sites More sharing options...
shadmar Posted May 6, 2014 Share Posted May 6, 2014 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; } Quote HP Omen - 16GB - i7 - Nvidia GTX 1060 6GB Link to comment Share on other sites More sharing options...
Joshua Posted May 6, 2014 Author Share Posted May 6, 2014 @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. Quote Link to comment Share on other sites More sharing options...
shadmar Posted May 6, 2014 Share Posted May 6, 2014 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)); Quote HP Omen - 16GB - i7 - Nvidia GTX 1060 6GB Link to comment Share on other sites More sharing options...
shadmar Posted May 6, 2014 Share Posted May 6, 2014 Haven't tested but should work with any class member or method. I probably dont understand, one of the cpp gurus should probably chip in, I should stick to gpu stuff Quote HP Omen - 16GB - i7 - Nvidia GTX 1060 6GB Link to comment Share on other sites More sharing options...
Joshua Posted May 6, 2014 Author Share Posted May 6, 2014 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. Quote Link to comment Share on other sites More sharing options...
catch22 Posted May 6, 2014 Share Posted May 6, 2014 Hmm, this thread made me think of ClanLib threading, which I always thought was a good model and a slick way to handle it. I've always been torn on threads, theoretically beneficial, fun even, but rarely are there actual good use cases, especially in gaming. http://www.clanlib.org/documentation/3.0/Threading.html Quote Coding for Christ. Link to comment Share on other sites More sharing options...
Recommended Posts
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.