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

Author Topic: VS 11, and variadic templates with std::thread  (Read 14054 times)

0 Members and 1 Guest are viewing this topic.

Flash619

  • Full Member
  • ***
  • Posts: 142
    • View Profile
Re: VS 11, and variadic templates with std::thread
« Reply #15 on: November 06, 2012, 05:15:23 pm »
Yes, I spoke about std::bind and the fact that you have to pass the this pointer of the object on which you want to call the member function.
...Do you mean something like this?
std::thread RunningLoadingScreen(std::bind(&LoadingScreens::RunLoadingScreen,CurrLoadScreen,glWindow));
 

A better idea would be to learn it ;)
See the documentation of Boost.Bind, for example.
But what does Boost.Bind have to do with std::ref ? o.O;

I tried shoving in std::ref() like:
std::thread RunningLoadingScreen(&LoadingScreens::RunLoadingScreen,std::ref(CurrLoadScreen,glWindow));
 

Just to see what would happen, but it tells me that it does not match the arguments list. *I figured something like that would happen, but I had to try.*

By the way, instead of bind(), you can achieve the same functionality with a functor (=function object). It is simpler if you don't know the standard library functionals, but it requires more code.

I would rather just *try* to learn the usual way of doing it instead of having to go even further around obstacles. That's why it probably seems like I'm asking stupid questions. XD I'll admit I don't know everything. >_>

EDIT

Also I tried multiples of std::ref to try to find the proper argument method.
std::thread RunningLoadingScreen(&LoadingScreens::RunLoadingScreen,std::ref(CurrLoadScreen),std::ref(glWindow));
 

Seems to make it quiet down, but I'm almost certain its incorrect, and it still gives me the "does not evaluate to a function taking two arguments" error.
« Last Edit: November 06, 2012, 05:17:40 pm by Flash619 »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: VS 11, and variadic templates with std::thread
« Reply #16 on: November 06, 2012, 05:23:22 pm »
It doesn't make sense to explain specific parts such as std::ref() if you haven't understood the whole concept of functionals. You should inform yourself about the following topics, in this order:
  • Function objects and operator()
  • std::function (see Boost.Function doc)
  • std::bind() (see Boost.Bind doc)
For the problem shown here, the first point is enough, the others offer only convenience. The C++11 standard library has adopted many parts from Boost, so the usage is often the same.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Flash619

  • Full Member
  • ***
  • Posts: 142
    • View Profile
Re: VS 11, and variadic templates with std::thread
« Reply #17 on: November 06, 2012, 05:31:02 pm »
It doesn't make sense to explain specific parts such as std::ref() if you haven't understood the whole concept of functionals.

But I'm not really asking to know about std::ref(), just really focusing on how I can actually get my thread to start up so it doesn't take me 15 hours to get a simple loading screen setup. >_> *and trust me, it probably will take longer than that*.

I'm really just trying to figure out, how to make the lovely "error C2064: term does not evaluate to a function taking 2 arguments" that has been bugging my error log for the last 45min, go away. Sure it would be awesome to sit down with a huge book about functionals and references, and binding objects. But I usually learn things backwards. *mainly because I cant actually retain knowledge from reading books *like in my sociology class* * So forgive me if I seem like I'm rushing in, I'm really not. Well, to me I'm not anyways.

Usually my process is as follows:
  • Start programming.
  • Run into an error.
  • Spend a while fixing the error.
  • Finally find a workable solution to the error.
  • Inspect how the solution works.
  • Do research as to why it works, and how it works.
  • Remember it for the future.
  • Continue programming.

That pretty much sums up how I learn things, and retain the information.
« Last Edit: November 06, 2012, 05:36:50 pm by Flash619 »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: VS 11, and variadic templates with std::thread
« Reply #18 on: November 06, 2012, 05:46:28 pm »
Usually my process is as follows:
  • Start programming.
  • Run into an error.
  • Spend a while fixing the error.
  • Finally find a workable solution to the error.
  • Inspect how the solution works.
  • Do research as to why it works, and how it works.
  • Remember it for the future.
  • Continue programming.
Trial and error is a very bad approach in C++. Not only that you run into errors all the time, but by "fixing" them (i.e. finding workarounds), you don't know learn how to do things the right way, and often there is even the possibility that you introduce bugs (undefined behavior, for example).

The time you waste pointlessly in "fixing" and asking in forums would be much better invested in reading books. Of course, not everybody learns well from books, but don't use this as an excuse -- there is no way around theory if you want to write good code :)

I don't expect you to learn about Boost.Function and Boost.Bind, that is why I wrote "the first point is enough". Function objects is really something every C++ programmer should know, so take the time to learn it. This is not something you use once for the thread and then never again, functors will certainly prove useful. Already because STL algorithms operate on them.
« Last Edit: November 06, 2012, 05:49:07 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Flash619

  • Full Member
  • ***
  • Posts: 142
    • View Profile
Re: VS 11, and variadic templates with std::thread
« Reply #19 on: November 06, 2012, 05:53:35 pm »
The time you waste pointlessly in "fixing" and asking in forums would be much better invested in reading books. Of course, not everybody learns well from books, but don't use this as an excuse -- there is no way around theory if you want to write good code :)

I don't expect you to learn about Boost.Function and Boost.Bind, that is why I wrote "the first point is enough". Function objects is really something every C++ programmer should know, so take the time to learn it. This is not something you use once for the thread and then never again, functors will certainly prove useful. Already because STL algorithms operate on them.

Well of course I want to learn just about everything eventually. But for now I'm trying to focus on why my thread won't work. Yea trial and error is a pain. But how else would I ever find out things don't work that way? Sure I can learn a bunch about functors, but it wont actually come out and tell me "this is why your thread is not working." So if I don't understand how the thread is supposed to work, and why my threads arguments are not working now, it would just teach me about functors, then afterwords, I would be in the same situation I am now, only I would know functors. Make sense?

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: VS 11, and variadic templates with std::thread
« Reply #20 on: November 06, 2012, 06:13:08 pm »
Make sense?
No.

The reason why your thread is not working is the wrong usage of functors. It has absolutely nothing to do with threading. This problem may reoccur in various other situations, and exactly because of that it doesn't help you if you only get something working without understanding it.

And instead of continuing this meaningless discussion, you should finally realize that you would have already learned everything you need in the time you have wasted so far, and additionally you could use the gained knowledge in the future for other problems. So please be wise enough and spend 15 minutes on the usage and definition of functors, this is well-invested time.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Flash619

  • Full Member
  • ***
  • Posts: 142
    • View Profile
Re: VS 11, and variadic templates with std::thread
« Reply #21 on: November 06, 2012, 06:37:31 pm »
And instead of continuing this meaningless discussion, you should finally realize that you would have already learned everything you need in the time you have wasted so far, and additionally you could use the gained knowledge in the future for other problems. So please be wise enough and spend 15 minutes on the usage and definition of functors, this is well-invested time.

I highly doubt that in one hours time, I could have read up on everything, deciphered and understood what they actually mean in the documentation, and somehow figured out my problem and solved it. Just as I don't think this discussion is meaningless. I see several good things that have already come from it. I'm planning on reading through it all, but can't help but wonder *Will I actually remember this at a later point in time.*

But for the sake of pleasing you I will read up on the above topic's in the order in which you listed them, and get back to you with questions *if I find any*.

EDIT

Found a really nice article about functors. ^_^
« Last Edit: November 06, 2012, 06:47:01 pm by Flash619 »

mercurio7891

  • Jr. Member
  • **
  • Posts: 89
    • View Profile
Re: VS 11, and variadic templates with std::thread
« Reply #22 on: November 06, 2012, 08:47:04 pm »
A bit late to this post. Your original code don't work because std::thread requires a function to execute not a member function.

void LoadingScreens::RunLoadingScreen(LoadingScreen LS,EngineWindow& glWindow);

is a member function of class LoadingScreens. Now in C++ in order to execute a member function (i.e non-static function) there must aways be a calling class object. Notice how to call a class member function, you have to create a class object and call using it e.g

LoadingScreens screens_1;
LoadingScreens* screens_2 = new LoadingScreens;
screens_1.SuperFuncOne();
screens_2->SuperFuncOne();

by simply passing in only the function signature &LoadingScreen::RunLoadingScreen to the std:thread constructor, it still requires a vital piece of information to run the member. Which is of course from which class object should this member function be called from?

Following Nexus point, this is where stuff from the <functional> header comes into play. First you have to convert the member function into a regular function. this is where std::mem_fn is used. By calling

auto thread_friendly_func = std::mem_fn(&LoadingScreens::RunLoadingScreen);

thread_friendly_func is now a regular function pointer which points to a function similar to below:

MyNewFunc(LoadingScreens* object, LoadingScreen LS,EngineWindow& glWindow);

Now that we have a regular function, we can easily pass that function signature to std::thread and set the arguments for it.

std::thread RunningLoadingScreen(thread_friendly_func, screens_1, CurrLoadScreen, glWindow);

P.S I have no idea if in your original post LoadingScreens and LoadingScreen are the different or just a typo error. I treat them as different.

regards
« Last Edit: November 06, 2012, 08:49:58 pm by mercurio7891 »

Flash619

  • Full Member
  • ***
  • Posts: 142
    • View Profile
Re: VS 11, and variadic templates with std::thread
« Reply #23 on: November 06, 2012, 09:06:14 pm »
P.S I have no idea if in your original post LoadingScreens and LoadingScreen are the different or just a typo error. I treat them as different.

Oh, that was because I didn't show the header file. ^^;; LoadingScreen is a struct that holds variables for each type of loading screen, and LoadingScreens is the name of the class. :)

But wouldn't you have to initialize "thread_friendly_func" first? Either that or microsoft claims the error is because it is being initialized by itself which I don't really see happening.

Because I looked up, and tried what you said. but It still gives two errors:

Quote
Error   2   error C3536: 'RunLoadingScreenT': cannot be used before it is initialized   
Error   1   error C3867: 'LoadingScreens::RunLoadingScreen': function call missing argument list; use '&LoadingScreens::RunLoadingScreen' to create a pointer to member

Thank you for your help tho, because even after reading about functors, I'm still pretty much clueless as to how they are relevant to what I am doing, or even how to make this work. I mean, I completely understand the operator() and functors.......but I have not functors in any of my code so I fail to see how its aparent to my problem..... *sigh..... I'm honestly starting to wonder if I'll actually ever get threads working... I mean. All I wanted was a simple thread to work. I shutter to think if I wanted to pass four arguments XD, But really, every example I find they don't have to switch out functions and such. Or do half of all of this work. And here I do all of this work, and it still doesn't work. Its rather frustrating at times.
« Last Edit: November 06, 2012, 09:35:39 pm by Flash619 »

Flash619

  • Full Member
  • ***
  • Posts: 142
    • View Profile
Re: VS 11, and variadic templates with std::thread
« Reply #24 on: November 06, 2012, 10:02:15 pm »
I mean, here so that you can see the whole picture:

LoadingScreens.cpp
#include "stdafx.h"
#include "LoadingScreens.h"
void LoadingScreens::Display(_LST ST,EngineWindow& glWindow)
{
        IsLoading=true;

        LoadingScreen CurrLoadScreen;

        switch(ST){
        case GNS_Cold:
                CurrLoadScreen = GNS_Cold_F();
                break;
        default:
                return;
        }
        LoadingScreens loadingScreens;
        auto RunLoadingScreenT = std::mem_fn(&LoadingScreens::RunLoadingScreen);
        std::thread t(RunLoadingScreenT,loadingScreens,CurrLoadScreen,glWindow);
}
LoadingScreens::LoadingScreen LoadingScreens::GNS_Cold_F()
{
        LoadingScreen GNS_Cold_LS;
        GNS_Cold_LS.LST_Alias = LoadingScreens::_LST::GEN_Cold;
    GNS_Cold_LS.IsStatic = true;
        GNS_Cold_LS.ResourcePath = "Resource/LoadingScreens/Genesis/Cold/Loading_Main.png";

        return GNS_Cold_LS;
}
void LoadingScreens::RunLoadingScreen(LoadingScreen LS,EngineWindow& glWindow) //This should run in a thread.
{
        if(LS.IsStatic){
                sf::Sprite LSS;
                LSS.setTexture(texture.getTexture(LS.ResourcePath));
                LSS.setPosition(glWindow.GetCenter().x,glWindow.GetCenter().y);
                glWindow.draw(LSS);
                glWindow.display();
        }else{
                        sfe::Movie LSM;
                        if(!LSM.openFromFile(LS.ResourcePath))
                        {
                                return;
                        }
                        LSM.setPosition(glWindow.GetCenter().x,glWindow.GetCenter().y);
                        LSM.play();
                        while(IsLoading)
                        {
                                glWindow.draw(LSM);
                                glWindow.display();
                        }
        }
}

 

LoadingScreens.h
#ifndef LOADINGSCREENS_H
#define LOADINGSCREENS_H
#include "stdafx.h"
#include "SpriteUtilities.h"
#include <SFML\Graphics.hpp>
#include <thread>
#include <sfeMovie\Movie.hpp>
#include <functional>
class LoadingScreens{
        Texture texture;
public:
        enum _LST{GNS_Cold,GNS_Anim,GEN_Cold,GEN_Anim,LVL_GEN_Cold,LVL_GEN_Anim};
        void Display(_LST,EngineWindow&);
        void Recall();
private:
        struct LoadingScreen
        {
        public:
                _LST LST_Alias;
                std::string ResourcePath;
                bool IsStatic;
                bool IsGeneric;
                std::string Args;
        };

        bool IsLoading;

        LoadingScreen GNS_Cold_F();

        void RunLoadingScreen(LoadingScreen,EngineWindow&);

};
#endif
 

I mean. I really don't see why this is not working at this point. I personally think this should have worked a long time ago. but as always, I am missing some small key of information that's probably ruining the entire thing.

EDIT

So I have it working with:

std::thread t(&LoadingScreens::RunLoadingScreen,&loadingScreens,CurrLoadScreen,glWindow);
 

But now I get errors from a sf::NonCopyable. So It must be trying to make a copy of "glWindow" but glWindow has inheritance with sf::renderWindow which explains where the error comes from. Is there a way to pass it as a reference?

EDIT

AHA! I knew it! I feel so proud. XD std::ref, I love you.

I will now continue to learn about functors and base C++ knowledge.
« Last Edit: November 06, 2012, 10:25:10 pm by Flash619 »