Jump to content

Unable to use std::thread t(func_pointer);

ClobberXD

First, my environment:

  • VS2015 Community w/ Qt Add-In.
  • It was working perfectly for a very long time, started throwing errors only after installing Qt Add-In (or started throwing errors only in Qt Projects?! - After installing Qt Add-In, I'm working with only Qt Projects...)

Here's the problem - I cannot invoke the default constructor for the std::thread class: I'll attach an image to also show the errors (instead of using the code tags)

 

Capture.JPG

 

I'm creating a vector of n threads (n=number of threads that can be concurrently executed) if a condition is satisfied, and if not, I create a single thread and invoke the same function: void CPUBench(long &);. Also please answer the questions asked within the code... I'll be precise: With or without parameters, I can't pass a function pointer to a thread object's constructor, but no errors are thrown when I don't create an object at all.

 

Nothing to see here ;)

Link to comment
Share on other sites

Link to post
Share on other sites

10 hours ago, Anand_Geforce said:

First, my environment:

  • VS2015 Community w/ Qt Add-In.
  • It was working perfectly for a very long time, started throwing errors only after installing Qt Add-In (or started throwing errors only in Qt Projects?! - After installing Qt Add-In, I'm working with only Qt Projects...)

Here's the problem - I cannot invoke the default constructor for the std::thread class: I'll attach an image to also show the errors (instead of using the code tags)

 

Capture.JPG

 

I'm creating a vector of n threads (n=number of threads that can be concurrently executed) if a condition is satisfied, and if not, I create a single thread and invoke the same function: void CPUBench(long &);. Also please answer the questions asked within the code... I'll be precise: With or without parameters, I can't pass a function pointer to a thread object's constructor, but no errors are thrown when I don't create an object at all.

 

What's the error on the second call?

Is CPUBench a static method?

 

First ones error is clear: this will call CPUBench(i) and use the result (void) to initialize std::thread.

It's the same as calling: std::thread(void)

Desktop: Intel i9-10850K (R9 3900X died 😢 )| MSI Z490 Tomahawk | RTX 2080 (borrowed from work) - MSI GTX 1080 | 64GB 3600MHz CL16 memory | Corsair H100i (NF-F12 fans) | Samsung 970 EVO 512GB | Intel 665p 2TB | Samsung 830 256GB| 3TB HDD | Corsair 450D | Corsair RM550x | MG279Q

Laptop: Surface Pro 7 (i5, 16GB RAM, 256GB SSD)

Console: PlayStation 4 Pro

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, mathijs727 said:

What's the error on the second call?

Is CPUBench a static method?

 

First ones error is clear: this will call CPUBench(i) and use the result (void) to initialize std::thread.

It's the same as calling: std::thread(void)

Here's how I've declared CPUBench():

class Ash
{
	...
    
  public:
	void CPUBench(long &);
	...
}

The simplest declaration ever - but why the error? Qt Addin messed up project settings? I couldn't find anything using Google...

 

Here's my second error:

 

Capture.jpg

 

Also how do I resolve the first error?

 

Thanks! Been waiting a long time for a reply to this... :)

Nothing to see here ;)

Link to comment
Share on other sites

Link to post
Share on other sites

2 hours ago, Anand_Geforce said:

Here's how I've declared CPUBench():


class Ash
{
	...
    
  public:
	void CPUBench(long &);
	...
}

The simplest declaration ever - but why the error? Qt Addin messed up project settings? I couldn't find anything using Google...

 

Here's my second error:

 

Capture.jpg

 

Also how do I resolve the first error?

 

Thanks! Been waiting a long time for a reply to this... :)

The function should be declared static:

static void CPUBench(long &)

 

BTW: there is no reason to use a reference here since long is a basic type.

 

Ill look into it further when I have access to my PC (< 1 hour)

Desktop: Intel i9-10850K (R9 3900X died 😢 )| MSI Z490 Tomahawk | RTX 2080 (borrowed from work) - MSI GTX 1080 | 64GB 3600MHz CL16 memory | Corsair H100i (NF-F12 fans) | Samsung 970 EVO 512GB | Intel 665p 2TB | Samsung 830 256GB| 3TB HDD | Corsair 450D | Corsair RM550x | MG279Q

Laptop: Surface Pro 7 (i5, 16GB RAM, 256GB SSD)

Console: PlayStation 4 Pro

Link to comment
Share on other sites

Link to post
Share on other sites

Ok, took a minute and made a working example:

#include <vector>
#include <thread>
#include <iostream>

class Ash
{
public:
	static void CPUBench(long x)
	{
		std::cout << "Thread id " << std::this_thread::get_id() << \
			"input: " << x << std::endl;
	}
};

int main()
{
	std::vector<std::thread> threads;

	for (int i = 0; i < std::thread::hardware_concurrency(); i++)
	{
		threads.push_back(std::thread(Ash::CPUBench, i));
	}

	for (int i = 0; i < std::thread::hardware_concurrency(); i++)
	{
		threads[i].join();
	}

#ifdef _WIN32
	system("PAUSE");
#endif
}

As I mentioned before, long& makes no sense unless you're changing the variable that you've passed in.

The CPUBench function should be a static method.

If you need access to the current instance then pass that as argument (be carefull of race conditions!).

Desktop: Intel i9-10850K (R9 3900X died 😢 )| MSI Z490 Tomahawk | RTX 2080 (borrowed from work) - MSI GTX 1080 | 64GB 3600MHz CL16 memory | Corsair H100i (NF-F12 fans) | Samsung 970 EVO 512GB | Intel 665p 2TB | Samsung 830 256GB| 3TB HDD | Corsair 450D | Corsair RM550x | MG279Q

Laptop: Surface Pro 7 (i5, 16GB RAM, 256GB SSD)

Console: PlayStation 4 Pro

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, mathijs727 said:

The CPUBench function should be a static method.

If you need access to the current instance then pass that as argument (be carefull of race conditions!).

It doesn't have to be static, but if it isn't you need to pass a pointer to an instance when calling the function.

Ash a;
for (int i = 0; i < std::thread::hardware_concurrency(); i++)
{
    threads.emplace_back(&Ash::CPUBench, &a, i);
}

 

1474412270.2748842

Link to comment
Share on other sites

Link to post
Share on other sites

20 hours ago, mathijs727 said:

The function should be declared static:

static void CPUBench(long &)

 

BTW: there is no reason to use a reference here since long is a basic type.

 

Ill look into it further when I have access to my PC (< 1 hour)

Why static? And all normal functions were working with std::thread() :S - why not now??? And yes, I'm modifying the parameter, as I cannot return values from threads in a simple, elegant manner (too many new stuff to learn :()

 

17 hours ago, fizzlesticks said:

It doesn't have to be static, but if it isn't you need to pass a pointer to an instance when calling the function.


Ash a;
for (int i = 0; i < std::thread::hardware_concurrency(); i++)
{
    threads.emplace_back(&Ash::CPUBench, &a, i);
}

 

Will try that - I'll let you know! Thanks ! :)

Nothing to see here ;)

Link to comment
Share on other sites

Link to post
Share on other sites

27 minutes ago, Anand_Geforce said:

Why static? And all normal functions were working with std::thread() :S - why not now??? And yes, I'm modifying the parameter, as I cannot return values from threads in a simple, elegant manner (too many new stuff to learn :()

 

Will try that - I'll let you know! Thanks ! :)

In that case you have to use a pointer and not a reference (otherwise you'll get errors involving "std::invoke").

 

Using the variable "i" to store the result doesnt make sense because you can only access it's value from within the loop.

But to safely access that variable from within the loop you have to wait for the thread to finish.

This would make you're programming basically single threaded, because you have to wait for the previous thread to finish before you can start a new one.

Since it looks to me like you're building a simple benchmark application, I've assumed that the result of CPUBench is the number of calculations (???) that should be summed up for the final result.

 

To safely modify a variable from multiple threads you'll have to use atomic variables or locks to prevent race conditions. In this case an atomic variable will do (faster then locks on most systems).

Because changing atomic variables is a slower operation then changing local variables, I would suggest keeping a local variable for the calculation count and then summing that up at the end of the CPUBench function.

#include <vector>
#include <thread>
#include <iostream>
#include <atomic>

class Ash
{
public:
    void CPUBench(std::atomic<int> * const globalResult)
    {
        // Do calculations with "localResult"
        long localResult = 5;

        // Atomic variables are (way) more expensive then local variables.
        // So store the results in a local variable and add them to the global result once.
        *globalResult += localResult;
    }
};

int main()
{
    std::vector<std::thread> threads;
    std::atomic<int> result = 0;
    int numCores = std::thread::hardware_concurrency();

    Ash object = Ash();

    for (int i = 0; i < numCores; i++)
    {
        // Same as:
        //threads.push_back(std::thread(&Ash::CPUBench, object, &result));
        // But a little tiny bit more efficient then move operation of a rvalue.
        threads.emplace_back(&Ash::CPUBench, object, &result);
    }

    for (int i = 0; i < numCores; i++)
    {
        threads[i].join();
    }

    std::cout << "You did " << result << " number of calculations using " << numCores << " cores." << std::endl;

#ifdef _WIN32
    system("PAUSE");
#endif
}

 

Desktop: Intel i9-10850K (R9 3900X died 😢 )| MSI Z490 Tomahawk | RTX 2080 (borrowed from work) - MSI GTX 1080 | 64GB 3600MHz CL16 memory | Corsair H100i (NF-F12 fans) | Samsung 970 EVO 512GB | Intel 665p 2TB | Samsung 830 256GB| 3TB HDD | Corsair 450D | Corsair RM550x | MG279Q

Laptop: Surface Pro 7 (i5, 16GB RAM, 256GB SSD)

Console: PlayStation 4 Pro

Link to comment
Share on other sites

Link to post
Share on other sites

16 minutes ago, mathijs727 said:

This would make you're programming basically single threaded, because you have to wait for the previous thread to finish before you can start a new one.

Since it looks to me like you're building a simple benchmark application, I've assumed that the result of CPUBench is the number of calculations (???) that should be summed up for the final result.

 

To safely modify a variable from multiple threads you'll have to use atomic variables or locks to prevent race conditions. In this case an atomic variable will do (faster then locks on most systems).

Because changing atomic variables is a slower operation then changing local variables, I would suggest keeping a local variable for the calculation count and then summing that up at the end of the CPUBench function.

 

Yes it is a benchmarking application (both single-core and multi-core) which I've talked about here:

I've also created a vector for holding the values of each CPUBench instance, and I'll sum it up in the end... I replaced all that with 'i' just for simplicity :) I think it'll work fine won't it?

Nothing to see here ;)

Link to comment
Share on other sites

Link to post
Share on other sites

2 hours ago, Anand_Geforce said:

Yes it is a benchmarking application (both single-core and multi-core) which I've talked about here:

I've also created a vector for holding the values of each CPUBench instance, and I'll sum it up in the end... I replaced all that with 'i' just for simplicity :) I think it'll work fine won't it?

That will work fine too

Desktop: Intel i9-10850K (R9 3900X died 😢 )| MSI Z490 Tomahawk | RTX 2080 (borrowed from work) - MSI GTX 1080 | 64GB 3600MHz CL16 memory | Corsair H100i (NF-F12 fans) | Samsung 970 EVO 512GB | Intel 665p 2TB | Samsung 830 256GB| 3TB HDD | Corsair 450D | Corsair RM550x | MG279Q

Laptop: Surface Pro 7 (i5, 16GB RAM, 256GB SSD)

Console: PlayStation 4 Pro

Link to comment
Share on other sites

Link to post
Share on other sites

12 hours ago, mathijs727 said:

That will work fine too

OK, right - one more clarification - in my first post, I had also tried to create a thread like this:

void Progress();

int main()
{
  std::thread(Progress); // No errors (from intellisense at least)...
}

void Progress()
{
  .
  .
  .
}

As you can see, I haven't created a thread object, and instead, I've directly called the std::thread::thread() constructor... I believe I can't detach() / join() the thread, but are there any other disadvantages?

 

And also, why did you insist on making CPUBench() static? What does it do, and how does it help?

Nothing to see here ;)

Link to comment
Share on other sites

Link to post
Share on other sites

39 minutes ago, Anand_Geforce said:

As you can see, I haven't created a thread object, and instead, I've directly called the std::thread::thread() constructor... I believe I can't detach() / join() the thread, but are there any other disadvantages?

Depending on the implementation and the type of function you're trying to call, 2 things can happen. Either the thread will never start and the program will continue or it will start then immediately be deconstructed and kill your program. If option 1 happens, there was no point in creating the thread since it does nothing. If option 2 happens your program dies. So either way there is no reason to ever do that.

1474412270.2748842

Link to comment
Share on other sites

Link to post
Share on other sites

On 27.8.2016 at 3:40 PM, Anand_Geforce said:

 And yes, I'm modifying the parameter, as I cannot return values from threads in a simple, elegant manner (too many new stuff to learn :()

Why not use a function object as i explained in this thread:

https://linustechtips.com/main/topic/619862-initializing-each-thread-in-vector/#comment-8049964

 

The object can hold all the information you want to be retrieved afterward.

Link to comment
Share on other sites

Link to post
Share on other sites

On 8/29/2016 at 1:00 AM, Unimportant said:

Why not use a function object as i explained in this thread:

https://linustechtips.com/main/topic/619862-initializing-each-thread-in-vector/#comment-8049964

 

The object can hold all the information you want to be retrieved afterward.

I didn't want to try anything new, as Qt itself is a very big step for me... My original approach works anyway. But why doesn't the std::thread::thread() constructor work? It worked with normal projects... but not after starting to work with Qt - any idea why? Thanks!

Nothing to see here ;)

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×