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

Author Topic: sf::Thread and know if it's running?  (Read 6558 times)

0 Members and 1 Guest are viewing this topic.

Mars_999

  • Full Member
  • ***
  • Posts: 103
    • View Profile
    • Email
sf::Thread and know if it's running?
« on: April 10, 2012, 01:21:35 am »
I am going to guess the answer is this....

If I have a sf::Thread running how can I check if it's still active with sf::Thread?

I don't see anything in the docs to do

thread.isActive();

so I am guessing here that I would need to make a bool variable or something in that thread and check it from another thread to see if that function is still running?

Thanks...

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10801
    • View Profile
    • development blog
    • Email
Re: sf::Thread and know if it's running?
« Reply #1 on: April 10, 2012, 02:01:57 am »
Yes. ;)

SFML just provides the basic abstraction, so one can use threads cross platform. Anything more than starting, waiting or terminating has to be implemented on your own. And never forget about all the race conditions etc. that can occure when programming parallel stuff. :)

AFAIK setting a boolean variable is an atomic operation so it would be quite possible to check the operation status with such a variable. But you can't check the variable if you put it in the thread you want to check since it isn't valid anymore as soon as the thread finishes, but putting it outside would work.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Re: sf::Thread and know if it's running?
« Reply #2 on: April 10, 2012, 02:54:24 am »
What exploiter said and I am not sure I haven't paid much attention to the keyword volatile and how it works with boolean variables. But maybe it's a good idea to declare such check/control structures to be volatile even if it's just a boolean? Cause even if setting the boolean variable is an atomic operation you could still be reading a cached value right? So volatile would force the CPU to flush the cache and reload that boolean. Or something like that. I am not a 100% sure as I haven't paid much attention to it. Just put it out there in case it was interesting.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

MonkeyKnight

  • Newbie
  • *
  • Posts: 14
    • View Profile
    • Email
Re: sf::Thread and know if it's running?
« Reply #3 on: April 17, 2012, 01:51:02 am »
I use volatile any time I am using a var between threads.

If I am not mistaken, it has nothing to do with atomic writes. More because your compiler can optimize (for binary size) memory mapped variables out of scope. Not so much in C++, since you typically have little reason to optimize your compiling to that degree and there is typically less use of pointers between threads. In the embedded world, it is definitely needed.

A good rule of thumb is when you are running multiple threads, and something isn't getting checked or set, slap volatile on it and clean & build.


Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Re: sf::Thread and know if it's running?
« Reply #4 on: April 17, 2012, 09:01:12 am »
Quote
I use volatile any time I am using a var between threads.
Volatile for multi-threading is useless[1].

Also there's absolutely no guarantee that any operation, even on built-in types, is atomic! Always protect shared memory, in any cases. C++11 comes with some features for enabling atomic operations[2]. Without you have to rely on your compiler's features, thus not staying portable.

Save yourself the trouble and race conditions and protect your memory.

[1] http://en.wikipedia.org/wiki/Volatile_variable#In_C_and_C.2B.2B
[2] http://www.open-std.org/JTC1/sc22/wg21/docs/papers/2007/n2427.html

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: sf::Thread and know if it's running?
« Reply #5 on: April 17, 2012, 10:56:27 am »
Quote
Volatile for multi-threading is useless
It doesn't make a variable thread-safe, but it is not completely useless.
If one thread only reads a value while the other writes it, volatile will be required so that the compiler doesn't optimize away the read operations in the first thread -- because it wrongly thinks that the variable never changes.
Laurent Gomila - SFML developer

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: sf::Thread and know if it's running?
« Reply #6 on: April 17, 2012, 11:22:08 am »
Quote
It doesn't make a variable thread-safe, but it is not completely useless.
You are correct. It is not useless. It is in fact far worse, counter-productive.

Quote
If one thread only reads a value while the other writes it, volatile will be required so that the compiler doesn't optimize away the read operations in the first thread -- because it wrongly thinks that the variable never changes.
Citing from http://kernel.org/doc/Documentation/volatile-considered-harmful.txt:

Quote
The key point to understand with regard to volatile is that its purpose is to suppress optimization, which is almost never what one really wants to do.
Quote
Consider a typical block of kernel code:

    spin_lock(&the_lock);
    do_something_on(&shared_data);
    do_something_else_with(&shared_data);
    spin_unlock(&the_lock);

If all the code follows the locking rules, the value of shared_data cannot change unexpectedly while the_lock is held.  Any other code which might want to play with that data will be waiting on the lock.  The spinlock primitives act as memory barriers - they are explicitly written to do so - meaning that data accesses will not be optimized across them.  So the compiler might think it knows what will be in shared_data, but the spin_lock() call, since it acts as a memory barrier, will force it to forget anything it knows.  There will be no optimization problems with accesses to that data.
Moral of the story? Proper usage of synchronization objects almost always takes care of compiler optimization issues without completely suppressing all forms of optimization.

If anyone thinks they can be lazy and just toss in a volatile keyword without proper synchronization to take care of strange multi-threading behavior: You are playing a very dangerous game.

And for those of you who wondered, I was interested and had time on my hands so I did read all the web references in the article Tank mentioned.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

The_Cleaner

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: sf::Thread and know if it's running?
« Reply #7 on: April 17, 2012, 01:57:53 pm »
Much agreed...
Whenever dealing with passing variables around threads, I found creating setter's and getter's with the mutex lock and unlock around the variable, easiest to deal with. This way you never deal with lock and unlock individually ( yes I am aware of the Lock object as well ).

But Mars was asking about how to determine if a thread is running...

Personally, I'm a fan of only having a thread as long as you need it, and do not like  the open a thread now and keep brute forcing it 'alive'. But dealing with critical hardware myself at work, I understand the concern on running threads and wondering if they are running or not.

That said... here is what I've learned in dealing with threads:
First is the "isActive()" is a bit ambiguous. Often the better question is, "is this a deadlock, or race condition?"
Most will say best way to handle race conditions and deadlocks is to avoid them. This is definitely something to strive for but anyone working on a project with many people can tell you, you don't always have control on all of the factors involved. If you do however, make sure you think of all the ways out of your loops ( have sentinels for any condition if it's important, it's worth the extra checks ).

If it's really important to restart a hung thread, you could use a timer that is reset every loop and check that timer from another thread to see if it got past an arbitrary point, and terminate the 'stalled' thread. Again, it's better to figure out why the thread stalled, and add a sentinel for that condition, so the thread can exit on it's own.

If I was way off the mark and all you wanted to know was if the function ran through to completion and the thread object is just sitting idle, ( then like you said initially ) just set a Boolean that the function was finished. Boolean values are expected atomic in nature.

You can also call wait() but that is blocking, so if you are concerned of a deadlock that won't help.

hope that helped!
 


eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10801
    • View Profile
    • development blog
    • Email
Re: sf::Thread and know if it's running?
« Reply #8 on: April 17, 2012, 05:23:27 pm »
Volatile for multi-threading is useless.
So the problem is that diffrent compilers don't follow excatly the standard?
I mean from the theoretical point of view, as it's taught at universities, it should have a usefull effect, shouldn't it.

Thanks for pointing that out. Just wanted to write here again and explain what volatile is for, since I've learned it in a lecture today.

Personally, I'm a fan of only having a thread as long as you need it, and do not like  the open a thread now and keep brute forcing it 'alive'.
This may work for some tasks but it won't help if you're trying to write a multithread application.
Also what would be the sense of using threads if you only run one at a time? In my opinion this would be equal to a sequential program... ::)

First is the "isActive()" is a bit ambiguous. Often the better question is, "is this a deadlock, or race condition?"
Most will say best way to handle race conditions and deadlocks is to avoid them. This is definitely something to strive for but anyone working on a project with many people can tell you, you don't always have control on all of the factors involved. If you do however, make sure you think of all the ways out of your loops ( have sentinels for any condition if it's important, it's worth the extra checks ).
Checking if a taks is still being worked on and writing lock and race condition free applications are two completly diffrent topics.
If you can't coordinate lock and race condition freedom within your team, either your team structur or your application design is wrong.
In my opinion it's just wrong to write code that determinse if an application is in a deadlock situation or has trouble with race conditions, it seems like a very ugly hack. (Then again I haven't worked on a big project with a team)

If I was way off the mark and all you wanted to know was if the function ran through to completion and the thread object is just sitting idle, ( then like you said initially ) just set a Boolean that the function was finished. Boolean values are expected atomic in nature.

It seems someone didn't read what Tank wrote and linked to...
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

MonkeyKnight

  • Newbie
  • *
  • Posts: 14
    • View Profile
    • Email
Re: sf::Thread and know if it's running?
« Reply #9 on: April 17, 2012, 07:55:57 pm »
This is off the main topic from the OP, but I feel that I have been called out. I also feel that the OP has the answer to the original question.


If anyone thinks they can be lazy and just toss in a volatile keyword without proper synchronization to take care of strange multi-threading behavior: You are playing a very dangerous game.

If this was aimed at me, perhaps my quick reply painted a distinctly different picture of how I code.


Quote
If one thread only reads a value while the other writes it, volatile will be required so that the compiler doesn't optimize away the read operations in the first thread -- because it wrongly thinks that the variable never changes.
Citing from http://kernel.org/doc/Documentation/volatile-considered-harmful.txt:

This is the point that I was trying to make. From what I understand, this is the only reason to use it.


Quote
It doesn't make a variable thread-safe, but it is not completely useless.
You are correct. It is not useless. It is in fact far worse, counter-productive.

Not sure where you are going with this one, but seems to me like it's the opposite of your previous quote...


Moral of the story? Proper usage of synchronization objects almost always takes care of compiler optimization issues without completely suppressing all forms of optimization.

This is all with the assumption that there is enough memory on the device that you are coding on to create and use proper sync objects. In the embedded world space isn't a luxury, in fact most of the time it is the challenge. The only place that I have ever needed volatile is on embedded devices. That is when volatile is needed most (In my experience). But then again if you are on a device that you can use all the proper objects that you need, you probably are not optimizing for compilation size, therefor rendering volatile useless. Maybe this is the situation that you were alluding to in the previous quote?

Silvah

  • Guest
Re: sf::Thread and know if it's running?
« Reply #10 on: April 17, 2012, 08:20:53 pm »
If one thread only reads a value while the other writes it, volatile will be required so that the compiler doesn't optimize away the read operations in the first thread -- because it wrongly thinks that the variable never changes.
Why would a compiler do that? To create a thread, you have to call a function from the system API, passing the thread entry point as an argument. As the compiler knows nothing about the called function, it cannot assume anything. In particular, it cannot assume that the thread entry point is dead. Thus, the compiler sees that in some part of the code some variable gets written, and in some other part of the code the same variable gets read. Because it knows nothing about when exactly the variable is written, it leaves both reads and writes alone.

When I say "it knows nothing about when the variable is written", I assume that at least one of these is true:
  • The compiler is threading-aware (if the platform supports threading, you can be virtually certain it is; if the compiler supports C++11, is has to be)
  • Between the reads, there's an intervening call to a function compiler knows nothing about

Because 1. is true on every compiler that could possibly be used by a programmer who doesn't deal with really weird platforms, and is surely true on all platforms supported by SFML, the only reason compiler could optimize the reads out is due to undefined behavior in the code, or a compiler bug. In the first case, fix your code. In the second case, report the bug and maybe upgrade your compiler.

In the case only 2. is true, you're dealing with a weird compiler for a weird system, so you should be very well aware of its quirks, because it's relatively unlikely that's the only one. And even then, the compiler probably doesn't do any aggressive optimizations, so you could get away without volatile.

All that assumes the compiler sees the whole program during its optimization stage. If it doesn't, there are even more optimization barriers, so the point still stands.

Bear in mind that I'm being theoretical here, everything I just said is based on knowledge about data- and control-flow analysis, and guarantees provided by the standard. So, do you really know a compiler where you really need a volatile in order to make the situation in question work?

This is all with the assumption that there is enough memory on the device that you are coding on to create and use proper sync objects.
A spinlock can take as little as one byte. Or even zero bytes, if you can squash it together with something else - remember that the simplest kind of spinlock needs only a single bit. Yet it's often more than enough to do proper synchronization. If you run on a single CPU, you won't even need any instructions to issue memory barriers.

The only place that I have ever needed volatile is on embedded devices. That is when volatile is needed most (In my experience).
Yes, but it's all about unusual kinds of memory, like memory-mapped registers. You can do proper synchronization without volatile.