読者です 読者をやめる 読者になる 読者になる

中年engineerの独り言 - crumbjp

LinuxとApacheの憂鬱

c++11 thread on g++ and linux

Check your g++

 $ g++ -v
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC)
This line means...
Thread model: posix

Your g++ ( std::thread in libstdc++.so ) was configured to using posix thread.

So you have to add "-pthread" option to COMPILER and LINKER when you are using std::thread.

In addition, you also have to add "-std=gnu++0x" or "-std=gnu++11" option to COMPILER to enable c++11 features.

Example
compile
g++ thread.cc  -c  -o thread.o  -std=gnu++0x -pthread
link
g++ thread.o -o thread   -pthread

Let's std::thread

Simple case
#include <iostream>
#include <thread>

void thread_handlar(){
  sleep(2);
  std::cout << __PRETTY_FUNCTION__ << std::endl;
}
int main ( int argc , char * argv[]  ){
  std::thread t(thread_handler);
  sleep(1);
  std::cout << __PRETTY_FUNCTION__ << std::endl;
  t.join();
  std::cout << "END" << std::endl;
  return 0;
}
result
int main(int, char**)
void thread_handlar()
END
std::thread instance is movable !!
simple move
int main ( int argc , char * argv[]  ){
  std::thread t;
  t = std::move(std::thread(thread_handlar));
  sleep(1);
  std::cout << __PRETTY_FUNCTION__ << std::endl;
  t.join();
  std::cout << "END" << std::endl;
  return 0;
}
swap
int main ( int argc , char * argv[]  ){
  std::thread t1( thread_handlar );
  std::thread t2( thread_handlar );
  std::cout << t1.get_id() << " " << t2.get_id() << std::endl;
  std::swap(t1,t2);
  std::cout << t1.get_id() << " " << t2.get_id() << std::endl;
  t2.join();
  t1.join();
  return 0;
}
result
140431314597632 140431304107776
140431304107776 140431314597632
So you can store std::thread object to STL containers !!
#include <iostream>
#include <vector>
#include <thread>

void thread_handlar(){
  sleep(2);
  std::cout << __PRETTY_FUNCTION__ << std::endl;
}
typedef std::vector<std::thread> threads_t;
int main ( int argc , char * argv[]  ){
  threads_t threads;
  for ( int i = 0 ; i < 5 ; i++ ) {
    threads.push_back(std::thread(thread_handlar));
  }
  sleep(1);
  for ( threads_t::iterator it(threads.begin()),itend(threads.end());
        it != itend;
        it++ ) {
    it->join();
  }
  std::cout << __PRETTY_FUNCTION__ << std::endl;
  std::cout << "END" << std::endl;
  return 0;
}
result
void thread_handlar()
void thread_handlar()
void thread_handlar()
void thread_handlar()
void thread_handlar()
int main(int, char**)
END

std::thread supports implicit type conversion of arguments.

FROM const char * TO const string &
#include <iostream>
#include <vector>
#include <thread>

void thread_handlar(const std::string &msg){
  sleep(2);
  std::cout << __PRETTY_FUNCTION__ << " : " << msg << std::endl;
}

int main ( int argc , char * argv[]  ){
  std::thread t(std::bind(thread_handlar,"kick by main() !!"));
  std::cout << __PRETTY_FUNCTION__ << std::endl;
  t.join();
  std::cout << "END" << std::endl;
  return 0;
}

std::thread supports class instance.

functor
#include <iostream>
#include <thread>

class MyThread {
public:
  const std::string msg;
  MyThread(const std::string &msg = "default"):msg(msg){}
  void operator()() {
    sleep(2);
    std::cout << __PRETTY_FUNCTION__ << " : " << msg << std::endl;
  }
};

int main ( int argc , char * argv[]  ){
  MyThread mythread("foo");
  std::thread t(mythread);
  std::cout << __PRETTY_FUNCTION__ << std::endl;
  t.join();
  std::cout << "END" << std::endl;
  return 0;
}
Offcause you can do this
  std::thread t(MyThread("foo"));
result
int main(int, char**)
void MyThread::operator()() : foo
END
other member function
#include <iostream>
#include <thread>

class MyThread {
public:
  const std::string msg;
  MyThread(const std::string &msg = "default"):msg(msg){}
  void thread_handlar() {
    sleep(2);
    std::cout << __PRETTY_FUNCTION__ << " : " << msg << std::endl;
  }
};

int main ( int argc , char * argv[]  ){
  MyThread mythread("foo");
  std::thread t( &MyThread::thread_handlar,&mythread);
  std::cout << __PRETTY_FUNCTION__ << std::endl;
  t.join();
  std::cout << "END" << std::endl;
  return 0;
}

std::call_once is available instead of pthread_once

we can control more precisely it by once_flag
#include <iostream>
#include <mutex>
#include <thread>

static std::once_flag flg;
void once(){
  std::cout << __PRETTY_FUNCTION__ << std::endl;
}

void thread_handlar() {
  std::cout << __PRETTY_FUNCTION__ << std::endl;
  for ( int i = 0 ; i < 10 ; i++ ) {
    std::call_once(flg,once);
  }
}

int main ( int argc , char * argv[]  ){
  for ( int i = 0 ; i < 10 ; i++ ) {
    std::thread t( thread_handlar );
    t.detach();
  }
  sleep(1);
  return 0;
}
result
void thread_handlar()
void once()
void thread_handlar()
void thread_handlar()
void thread_handlar()
void thread_handlar()
void thread_handlar()
void thread_handlar()
void thread_handlar()
void thread_handlar()
void thread_handlar()

closure ( since g++ 4.5 )

simple closure
int main ( int argc , char * argv[]  ){
  auto lambda = [](){std::cout << __PRETTY_FUNCTION__ << std::endl; };
  lambda();
}
result
main(int, char**)::<lambda()>
Offcause, you can call directly
int main ( int argc , char * argv[]  ){
  [](){std::cout << __PRETTY_FUNCTION__ << std::endl; }();
}
example
static std::once_flag flg;
int main ( int argc , char * argv[]  ){
void thread_handlar() {
  std::call_once(flg,[](){std::cout << __PRETTY_FUNCTION__ << std::endl;} );
}
with argument
#include <iostream>

struct My {
  const std::string n;
  My(const std::string &n) : n(n){}
  void name() const { 
    std::cout << n << std::endl;
  }
};

int main ( int argc , char * argv[]  ){
  My my("FOO");
  [my](){ my.name(); }();
}
result
FOO
with this
struct My {
  const std::string n;
  My(const std::string &n) : n(n){}
  void name() const { 
    std::cout << n << std::endl;
  }
  void go() {
    [this](){ name();}() ;
  }
};