So I discovered that gcc already had a working implementation of std::atomic so I wanted to try it out, here is my example using boost thread 1.48 and std::atomic:
#include <iostream>
#define BOOST_THREAD_USE_LIB
#include <boost/thread.hpp>
#include <atomic>
#include <string>
using namespace std;
using namespace boost;
class Server
{
public:
atomic<bool> running;
thread main_server_thread;
void func1()
{
while(running)
{
//do stuff
}
}
void func2()
{
while(running)
{
//do stuff
}
}
void func3()
{
while(running)
{
//do stuff
}
}
void func4()
{
string input;
while(running)
{
//do stuff
input.clear();
getline(cin,input);
if(input=="quit")running=false;
}
}
void main_function()
{
thread thrd1(bind(&Server::func1,this));
thread thrd2(bind(&Server::func2,this));
thread thrd3(bind(&Server::func3,this));
thread thrd4(bind(&Server::func4,this));
while(running)
{
//do stuff
}
thrd1.join();
thrd2.join();
thrd3.join();
thrd4.join();
}
Server()
{
running=true;
main_server_thread = thread(&Server::main_function,this);
}
};
int main()
{
Server* serv = new Server();
serv->main_server_thread.join();
return 0;
}
Now while running remains true all is fine but when the user inputs quit and running is set to false some threads end and some don’t. This happens with and without optimizations. Is this working as intended? In my understanding of atomics the reads shouldn’t conflict with the one write so the threads should see the running=false at some point.
EDIT:
Disassembly of func1:
void func1()
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 18 sub $0x18,%esp
{
while(running)
6: 90 nop
7: 8b 45 08 mov 0x8(%ebp),%eax
a: 89 04 24 mov %eax,(%esp)
d: e8 00 00 00 00 call 12 <__ZN6Server5func1Ev+0x12>
12: 84 c0 test %al,%al
14: 75 f1 jne 7 <__ZN6Server5func1Ev+0x7>
{
//do stuff
}
}
16: c9 leave
17: c3 ret
As the disassembly shows, this program, when compiled with mingw, does not treat
runningas an atomic: it is loaded with a regularmov 0x8(%ebp),%eaxwithout synchronization.Compare to the output of gcc-4.6.2 on linux/x86_64:
Either mingw doesn’t support that yet, or something is missing in its configuration.