Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: RenderWindow as a parameter of a member function in a thread  (Read 3495 times)

0 Members and 1 Guest are viewing this topic.

Offerus

  • Newbie
  • *
  • Posts: 4
    • View Profile
RenderWindow as a parameter of a member function in a thread
« on: November 07, 2017, 11:20:21 pm »
Hello everyone,
I'm trying to start a member function in a new thread, which works fine, but i can not manage to use a render window as a parameter of the member function. Here is an small example of what i'm struggling with:

This code works perfectly fine:
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <iostream>
#include <thread>

class ClassWithThread
{
public:

    ClassWithThread()
    : m_thread(&ClassWithThread::f, this)
    {
                i = 4;
    }

    void f()
    {
        std::cout << i << std::endl;
    }

private:

    std::thread m_thread;
    int i;
};

int main (){
        ClassWithThread x;
        x.f();
return 0;
}
 

But if i try to use a render window inside the member function, i get a long error message that i don't really understand:

#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <iostream>
#include <thread>

class ClassWithThread
{
public:

    ClassWithThread()
    : m_thread(&ClassWithThread::f, this)
    {
                i = 4;
    }

    void f(sf::RenderWindow& window)
    {
        std::cout << i << std::endl;
    }

private:

    std::thread m_thread;
    int i;
};

int main (){
        ClassWithThread x;
        // create the window
        sf::RenderWindow window(sf::VideoMode(1920, 1080), "MyWindow");
        x.f(window);
return 0;
}
 

With the error (sorry, some of it is in german):
(click to show/hide)

I already tried to commit the window as a pointer or as a reference. I'm using linux debian testing with g++ 4:7.2.0-1d1 and libsfml 2.4.

Has anyone an idea what i'm doing wrong?

dabbertorres

  • Hero Member
  • *****
  • Posts: 506
    • View Profile
    • website/blog
Re: RenderWindow as a parameter of a member function in a thread
« Reply #1 on: November 07, 2017, 11:25:25 pm »
Check your constructor, and the constructors of std::thread. (http://en.cppreference.com/w/cpp/thread/thread/thread)

If you're constructing a std::thread with a function that has non-optional arguments, you must pass them at construction time.

For reference, this is the error that tells you what is going wrong here:
Quote
In file included from main.cpp:4:0:
/usr/include/c++/7/thread: In instantiation of ‘struct std::thread::_Invoker<std::tuple<void (ClassWithThread::*)(sf::RenderWindow&), ClassWithThread*> >’:
/usr/include/c++/7/thread:127:22:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (ClassWithThread::*)(sf::RenderWindow&); _Args = {ClassWithThread*}]’
main.cpp:11:41:   required from here
/usr/include/c++/7/thread:240:2: error: no matching function for call to ‘std::thread::_Invoker<std::tuple<void (ClassWithThread::*)(sf::RenderWindow&), ClassWithThread*> >::_M_invoke(std::thread::_Invoker<std::tuple<void (ClassWithThread::*)(sf::RenderWindow&), ClassWithThread*> >::_Indices)’
  operator()()
  ^~~~~~~
(The arguments in your constructor don't match up with the expected)
« Last Edit: November 07, 2017, 11:30:20 pm by dabbertorres »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10819
    • View Profile
    • development blog
    • Email
Re: RenderWindow as a parameter of a member function in a thread
« Reply #2 on: November 08, 2017, 08:36:55 am »
Then again if you have trouble using std::thread to begin with, you probably shouldn't use multi-threading. Using multiple threads doesn't just make things faster/better, but it makes things a lot more complex and you need a lot more understanding of how to deal with shared resources, locks, mutexes, race conditions, dead locks, starvation problem, etc.

tl;dr don't do it unless you have the required experience.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Offerus

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: RenderWindow as a parameter of a member function in a thread
« Reply #3 on: November 08, 2017, 09:08:15 am »
@dabbertorres
Until now i couldn't figure out how to pass the argument, even with your link. I tried several variations of this:

#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <iostream>
#include <thread>

class ClassWithThread
{
public:

    ClassWithThread(sf::RenderWindow& window)
    : m_thread(&ClassWithThread::f, this)
    {
                i = 4;
                m_window = window;
    }

    void f()
    {
        std::cout << i << std::endl;
    }

private:
        sf::RenderWindow& m_window;
    std::thread m_thread;
    int i;
};

int main (){
        // create the window
       sf::RenderWindow window(sf::VideoMode(1920, 1080), "MyWindow");
        ClassWithThread x(window);

        x.f();
return 0;
}
 

@eXpl0it3r
I would like to avoid threads, but i thought it is my only option: I wrote a game with monsters one has to destroy. So i wrote a class for the monster and it moves on the gamefield. But now i want two ( or better 20  ;) ) monsters simultaneously. If i call the member function for moving monsters one after another, they are not moving at the same time :) . So i thougt every monster needs its own thread.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10819
    • View Profile
    • development blog
    • Email
Re: RenderWindow as a parameter of a member function in a thread
« Reply #4 on: November 08, 2017, 09:23:50 am »
That assumption is wrong. ;)

Why would they not be moving simultaneously?
A position change can only be "seen" once you render the objects, so between frames you can move them one after the other and once they're rendered they all moved simultaneously.

Depending on the physics, you may have to do collision detection and resolve multiple times, but that might already be too "advanced" and a simpler solution will work just as well.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Offerus

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: RenderWindow as a parameter of a member function in a thread
« Reply #5 on: November 08, 2017, 10:12:00 am »
Thats true. Then i have to rearrange the program and create a new class for managing all the monsters, instead of letting every monster manage itself.

By the way, is there a smarter solution for creating multiple monsters, all with individual positions and health points, than writing:

Monster M1;
Monster M2;
Monster M3;
Monster M4;
Monster M5;
      .
      .
      .

M1.m_run() // m_run is the member function to move the monster
M2.m_run()
M3.m_run()
M4.m_run()
M5.m_run()
      .
      .
      .
 
« Last Edit: November 08, 2017, 10:13:55 am by Offerus »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: RenderWindow as a parameter of a member function in a thread
« Reply #6 on: November 08, 2017, 10:23:35 am »
std::vector<Monster> monsters;

// Or, if Monster is not copyable:

std::vector<std::unique_ptr<Monster>> monsters;

If you don't know what I'm talking about -- and since you ask, you probably not :) -- then you'd better learn more about the C++ language before trying to create a game.
Laurent Gomila - SFML developer

Offerus

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: RenderWindow as a parameter of a member function in a thread
« Reply #7 on: November 08, 2017, 10:35:15 am »
Oh, i think we had this one in the lecture at any time, but i never needed it. I think it's the lack of experience  ;)

Thanks, your suggestions really helped!