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

Author Topic: Threads causing event blocking?  (Read 1338 times)

0 Members and 2 Guests are viewing this topic.

Wnt2bsleepin

  • Guest
Threads causing event blocking?
« on: February 17, 2013, 08:57:45 pm »
Hello, I am getting the hang of sfml and C++ and I have a small issue with the events for two windows being interrupted. According to the tutorials, the window creation and event interception must occur in the same thread, which I believe I have done correctly. However, I have another thread that is animating a green ball in one of the windows. Whenever I have that thread enabled, all events to the windows do not occur.

#include <SFML/Graphics.hpp>
#include <iostream>
#include <ios>
#include <SFML/Window.hpp>
#include <SFML/OpenGL.hpp>
#include "main.h"

using namespace std;

//Hardcoded in.
bool running = true, runningSecondary = true;
const int XSize = 800, YSize = 600;
double countX = 0;
double countY = 0;

using sf::Thread;


//Draws the ball and returns the circle object back.
sf::CircleShape drawCircle(sf::RenderWindow* window2, sf::CircleShape circle = sf::CircleShape(100.f))
{
                 
                circle.setFillColor(sf::Color::Green);
                window2->clear();
                window2->draw(circle);
                window2->display();  
                return circle;
}

//Changes the position of the ball.
void changePos(bool reverse, char choice)
{
        if(reverse)
        {
                switch (choice)
                {

                case 'b':
                        countX -= .05;
                        countY -= .05;
                        break;
                case 'x':
                        countX -= .05;
                        break;
                case 'y':
                        countY -= .05;
                        break;
                }

        }

        else
        {
                switch (choice)
                {

                case 'b':
                        countX += .05;
                        countY += .05;
                        break;
                case 'x':
                        countX += .05;
                        break;
                case 'y':
                        countY += .05;
                        break;
                }
        }



}

//Animates the moving of the ball.
void animate(animateThread& at)
{
        sf::CircleShape circle = at.circle;
        sf::RenderWindow* window2 = at.renderWindow;  
        int circleDiameter = circle.getRadius() * 2;
       
        while(runningSecondary)
        {
                 
               
                if(countX >= 799 - circleDiameter)
                {
                        cout << circle.getPosition().x << " XXXXXX" << endl;
                        changePos(true, 'x');
                }

                else if(countY >= 599 - circleDiameter)
                {
                        cout << circle.getPosition().y << " YYYYYYYYY" << endl;
                        changePos(true, 'y');
                }

                else if((countX >= 799 - circleDiameter) && (countY >= 599 - circleDiameter))
                {
                        changePos(true, 'b');
                }

                else{changePos(false, 'b'); }

                circle.setPosition(countX,countY);
                drawCircle(window2, circle);
        }
}


int main()
{
   
       
    sf::Window window(sf::VideoMode(XSize, YSize), "OpenGL", sf::Style::Default, sf::ContextSettings(32)); //OpenGl Window
        sf::RenderWindow window2(sf::VideoMode(XSize,YSize), "Graphics"); //SFML Graphics Window
       
       
        window.setVerticalSyncEnabled(true);
        glDisable(GL_DEPTH_TEST);
   
   
   sf::CircleShape circle = drawCircle(&window2); //Draw the circle in the origin.
   
        //Main event loops.
        while (running)
    {
        // handle events
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
            {
                // end the program
                running = false;
            }
            else if (event.type == sf::Event::Resized)
            {
                // adjust the viewport when the window is resized
                glViewport(0, 0, event.size.width, event.size.height);
            }
        }

                sf::Event Event_Window2;
                while(window2.pollEvent(Event_Window2))
                {
                        if(Event_Window2.type == sf::Event::Closed)
                        {
                                running = false;
                        }

                        else if(Event_Window2.type == sf::Event::KeyPressed)
                        {
                                if(Event_Window2.key.code == sf::Keyboard::P)
                                {
                                        runningSecondary = false;
                                }
                       
                        }

                         else if (Event_Window2.type == sf::Event::Resized)
            {
                // adjust the viewport when the window is resized
                glViewport(0, 0, Event_Window2.size.width, Event_Window2.size.height);
            }

                }

               
               
                 
               
                //Creates a struct containing the initial circle object and the window.  
                animateThread at;
                at.circle = circle;
                at.renderWindow = &window2;
                 
                //Threads the animation so it doesn't interfere with the Event catching.
                //animate is the name of the method, at is the struct object.
                Thread animationThread(&animate, at);
                animationThread.launch();
               
                //OpenGL Implementation Attempt.

        // clear the buffers
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // draw...

                glBegin(GL_TRIANGLES);
                glVertex3f(100.0f, 100.0f, 20.0f);
                glVertex3f(150.0f, 100.0f, 20.0f);
                glVertex3f(125.0f, 50.0f, 20.0f);
                glEnd();
               
               
        // end the current frame (internally swaps the front and back buffers)
        window.display();
    }

    // release resources...

    return 0;
}
 

I thought this was the proper way to handle animation, so it doesn't interfere with the GUI aspect itself. Any help is much appreciated.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Threads causing event blocking?
« Reply #1 on: February 17, 2013, 10:12:45 pm »
You're creating/launching/destroying the thread at every iteration of your main loop. But since the thread never ends, your main thread gets stuck at the end of the first iteration, waiting endlessly for the thread to be finished.

And no, running a second loop in a parallel thread is not the correct way to handle animations. Just handle it directly in your main thread ;)

You should really avoid threads, you need to learn more before using them, and most important, you overuse them. You don't need them for such simple tasks.
Laurent Gomila - SFML developer

Wnt2bsleepin

  • Guest
Re: Threads causing event blocking?
« Reply #2 on: February 18, 2013, 01:51:25 am »
Thank you. I am more familiar with Swing and Java, and most background tasks there (Connecting to a server) are done in a thread.

I can't believe I didn't see that it was in the while loop  :'(

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11032
    • View Profile
    • development blog
    • Email
Re: Threads causing event blocking?
« Reply #3 on: February 18, 2013, 02:02:34 am »
Thank you. I am more familiar with Swing and Java, and most background tasks there (Connecting to a server) are done in a thread.
Well the animation is not a background task, but it's next to drawing your stuff the main task of your game/application.

A rule of thumb for threads would be, to only use them if you a) need something non blocking (e.g. networking) or b) hit performance issues in some parts of the logic and need to parallelize the algorithm if possible at all.
The problem with using threads is, that correct synchronization is a very complex and hard topic. If you're not experienced with it at all or only merely, you shouldn't be working with them (if you care about properly working software).
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Wnt2bsleepin

  • Guest
Re: Threads causing event blocking?
« Reply #4 on: February 18, 2013, 10:27:46 pm »
You guys are very helpful, thanks.

Right now I am just messing around and getting the hang of C++ a bit more. These tidbits of information are very helpful.