boost 페이지
를 보면 다음 구문으로 join에 멤버함수에 대한 역할을 알 수 있다
In order to wait for a thread of execution to finish, the join()
or timed_join()
member functions of the boost::thread
object must be used.
번역하기 귀찮은 사람들을 위해 써놓자면
끝내기위한 쓰래드실행을 기다리기위해서, join()
또는 timed_join()
boost::thread
오브젝트의 멤버함수들이 사용되어져야한다.
임을 알 수 있다 ∴ .join() 함수 - 쓰레드가 종료될 때까지 대기하게된다
p.s waitForSingleObject 쯤으로 생각해 두면 될듯, 아래 포스트들은 역시 Boost::thread에 관한 실행 예제들과 좀 더 자세한 멤버들에 대한 내용이다
[condition 과 mutex 의 사용시 주의사항]
//condition 을 사용하기전에 주의해야하는 점이 아래 나온다
//A condition object is always used in conjunction with a mutex object(an object whose type is a model of a Mutex or one of its refinements).
//The mutex object must be locked prior to waiting on the condition, which is verified by passing a lock object
//http://www.boost.org/doc/libs/1_34_0/doc/html/boost/condition.html 에서 발췌
condition 을 사용하기전에 반드시 mutex를 lock 건것에 대한 변수로 wait 해야 된다는것.
다시말해 condition 은 뮤텍스를 lock 한 객체를 받아야야하고 이것
_condition.wait(lock); 로 대기상태로 두고, // lock 은 뮤텍스를 락한것
다른 스레드에서 _condition.notify_one(); or _condition.notify_all(); 로 wait 하고 있는 lock 을 깨울 수 있다
boost::mutex::scoped_lock lock(_mutex);
while(true){
_condition.wait(lock); //checkThread 함수 자체가 멈춘다
runThread();
}
http://www.boost.org/doc/libs/1_41_0/doc/html/thread/thread_management.html#thread.thread_management.threadgroup
Joining and detaching
When the boost::thread
object that represents a thread of execution is destroyed the thread becomes detached. Once a thread is detached, it will continue executing until the invocation of the function or callable object supplied on construction has completed, or the program is terminated. A thread can also be detached by explicitly invokingthe detach()
member function on the boost::thread
object. In this case, the boost::thread
object ceases to represent the now-detached thread, and instead representsNot-a-Thread.
In order to wait for a thread of execution to finish, the join()
or timed_join()
member functions of the boost::thread
object must be used. join()
will block the calling thread until the thread represented by the boost::thread
object has completed. If the thread of execution represented by the boost::thread
object has already completed, or the boost::thread
object represents Not-a-Thread, then join()
returns immediately. timed_join()
is similar, except that a call to timed_join()
will also return if the thread being waited for does not complete when the specified time has elapsed.
쓰래드가
boost 라이브러리의 thread를 사용할 때 sleep을 사용할 일이 자주 생기는데
boost::thread::sleep 함수는 사용하기가 좀 번거롭습니다.
대신 boost::this_thread::sleep 함수를 사용하면 됩니다.
[code cpp]boost::this_thread::sleep(boost::posix_time::milliseconds(30));[/code]
인자로 사용되는 boost::posix_time::milliseconds 대신boost::posix_time::seconds 함수 등으로 시간 단위를 지정할 수 있습니다.
http://jeremyko.blogspot.kr/2012/03/boost-thread-13.html
http://cafe.naver.com/totalprogramming/14 에서 일부 발췌
쓰레드 함수에 파라메터를 넘겨줘야 하면 -> boost::bind를 쓰자
클래스 멤버 함수를 쓰레드로 돌릴 경우에도, bind를 써야 하고,
전역에 있는 함수를 쓰레드로 돌릴 경우는 bind를 사용하지 않아도 된다.
전역 변수이고 클래스 함수이고의 구분은 컴파일러가~알아서~한다
참조 헤더파일
#include <boost/thread.hpp>
가변 인수를 받아들이는 thread함수. 생성자일 경우
Thread Constructor with arguments
void CKsc::start()
{
thread_ = new boost::thread( boost::bind(&CKsc::f, this, 1, 2, this ));
}
생성과 동시에 thread 함수인 f가 돌기 시작한다.
두번째 매개 변수는 첫번째로 넘긴 CKsc::f의 대상 객체가 된다. 위의 예제에서는 CKsc객체 내에서 호출을 하기 때문에
this가 가능한것이다. 외부에서 할 경우에는
CKsc a;
boost::thread* thread_ = new boost::thread( boost::bind(&CKsc::f, a, 1, 2, this ));
혹은
boost::thread* thread_ = new boost::thread( boost::bind(&CKsc::f, &a, 1, 2, this ));
boost는 쓰레드 함수 지정시 이미 쓰레드는 자동으로 수행된다는 점이다
이렇게 하면 된다.
첫번째 처럼 하면 a가 복사되어 넘어가게 되는것이고, 두번째 예제처럼 하면 포인터가 넘어가서 공유가 된다.
void hello(const char* s)
...
int main() {
thread t( bind(&hello, ",world") );
http://cafe.naver.com/javacircle/12487
#include <iostream>
#include <boost/thread.hpp>
using namespace std;
using namespace boost;
void show_a() // 100만번 'a'를 출력
{
for(int i=0; i!=1000000; ++i)
cout << 'a';
}
void show_b() // 100만번 'b'를 출력
{
for(int i=0; i!=1000000; ++i)
cout << 'b';
}
int main()
{
thread ta( &show_a ); // show_a 함수를 실행하는 스레드를 실행
thread tb( &show_b ); // show_b 함수를 실행하는 스레드를 실행
ta.join();
tb.join(); // join() 함수로, 스레드가 종료될때까지 대기.
return 0;
}
실행결과:
thread1
aaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbb
aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbb
aaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbb
....
http://www.viper.pe.kr/cgi-bin/moin.cgi/Boost/Thread_1
차례
1. 참고링크 [Bottom] [Top]
Boost Thread Library - http://www.boost.org/libs/thread/doc/
Boost/Thread 2 - Boost::thread 의 기타 라이브러리 정리
2. boost::thread 라이브러리 [Bottom] [Top]
boost::thread 라이브러리에 대한 설명
3. <boost/thread/thread.hpp> 헤더 파일 [Bottom] [Top]
- Toggle line numbers
namespace boost { class thread; class thread_group; }
3.1. thread 클래스 [Bottom] [Top]
Thread 객체를 생성하는 클래스로 boost::thread 라이브러리 의 핵심 Thread 클래스.
- 생성자Toggle line numbers
thread( const boost::function0< void >& threadfunc );
- 쓰레드 객체를 생성한다.
생성자의 매개변수는 반환값이 void 형이고 매개변수가 없는 함수 또는 함수 객체를 전달한다. 자세한 것은 functionN<> 클래스를 참고한다.
- 멤버 함수
- join() 함수 - 쓰레드가 종료될 때까지 대기한다.
- sleep( xt ) 함수 - xt 로 지정된 시간 만큼 쓰레드를 대기한다.
- yield() 함수 - 쓰레드를 Ready 상태로 전환하고 Context Switching 한다.
3.2. thread_group 클래스 [Bottom] [Top]
Thread 객체를 생성하고 관리해주는 Thread Manager.
- 멤버 함수
- create_thread( threadfunc ) 함수 - 쓰레드를 생성한 후 쓰레드 관리 컨테이너에 추가한다.
- add_thread( thrd ) 함수 - 생성된 쓰레드를 쓰레드 관리 컨테이너에 추가한다.
- remove_thread( thrd ) 함수 - 지정된 쓰레드를 쓰레드 관리 컨테이너에서 삭제한다.
- join_all() 함수 - 모든 쓰레드가 종료될 때까지 대기한다.
- size() 함수 - 현재 쓰레드 관리 컨테이너의 크기 (쓰레드 개수) 를 구한다.
http://blog.naver.com/pronaman/60125230225
Boost.Thread는 데이터 공유의 실행 스레드를 사용 가능하게 하고, 스레드를 이동시킬 수 있으며 스레드간에 데이터를 동기화하는 함수를 제공한다.
#include <boost/thread.hpp>
사용방식은 다음과 같다.
- 스레드함수가 외부에 있을때 : boost::thread myThread( &func );
- 스레드함수가 클래스의 멤버 함수일때 : boost::thread myThread( boost::bind(&ClassName::func, this) );
간단한 사용법은 다음과 같다.
#include "boost/thread.hpp"
#include <iostream>
#include <time.h>
void ThFunc(void *p, int a, int b, int c, int d)
{
const char *pszMessage = (const char *)p;
std::cout << pszMessage << ":" << (a+b+c+d) << std::endl;
boost::this_thread::sleep(boost::posix_time::seconds(2)); // 2초 동안 정지
}
int main(int argc, char **argv)
{
static const char *pszMessage = "boost thread";
boost::thread t(ThFunc, (void *)pszMessage, 1, 1024, 2048, 4096); // 여러개의 인자를 쓰레드 함수에 전달 할 수 있음.
t.timed_join(boost::posix_time::seconds(1)); // 1초 동안 쓰레드 종료 대기
t.join(); // 쓰레드 종료 대기 (무한)
return 0;
}
여러개의 스레드간의 임계영역 처리시 호환성때문에 윈도우의 크리티컬 섹션과 같은 클래스는 없는것 같다. 뮤텍스로 처리한다.
사용법은 다음과 같다.
boost::mutex mutexVar; // Lock을 걸 mutex 변수
/////////////////////////////////////////
스레드 합수 안에서 스코프를 만들어 락을 처리하는 것이 좋다.
{
boost::mutex::scoped_lock( mutexVar ); // Mutex Lock이 걸림
}
스레드를 실행 후 정지시켰다가 특정 시점에 활성화 하고자 할 경우 윈도에서는 이벤트 객체를 사용했으나 boost는
condition 이란 객체를 사용한다. 컨디션은 쓰레드를 잠들게 하고 동작하게 하는 제어 변수로 사용될 수 있다.
condition.wait(mutexVar);
스레드에서 이와 같이 선언한 경우 스레드가 멈추게 된다. 이때 다음 함수로 활성화할 수 있다.
condition.notify_one(); // 잠들어있는 것중에서 경쟁적으로 한개만 깨울때
condition.notify_all(); // 잠들어있는 모든 녀석을 깨울때
----------------------------------------------------------------------------------
- Thread를 제어하는 2가지: Mutex 와 condition
- Mutex : 운영체제에서 익히나온 것이다. Thread 가 동시다발적으로 어느 특정 리소스를 사용할때, 한개의 Thread만 사용하게 하고싶을때 사용하는 녀석이다. 제대로 사용하지 않으면 성능저하를 일으키니 디자인설계때부터 조심히 사용해야 하는 녀석이다. 추천하는
- header : #include <boost/thread/mutex.hpp>
- 추천하는 것 : boost::mutex::scoped_lock
- 이유 : 사용하기 편하다. 이 변수를 괄호 안에 선언하게 되면 괄호의 끝을 만날때까지 잠금이 되고, 괄호를 벗어나게되면 락이 풀린다. (이에 대한 원리는 간단히 생각해보면 되는데, 생성자에서 락을 걸고, 소멸자에서 락을 푸는 코드를 삽입한 것이다)boost::mutex mutexVar; // Lock을 걸 mutex 변수
if ( test_module == true )
{
boost::mutex::scoped_lock( mutexVar ); // Mutex Lock이 걸림
// Do something
} // 이 시점에서 락이 풀린다. - condition : 쓰레드를 잠들게 하고 동작하게 하는 제어 변수. 보통 어떤 값을 기다릴때 while 로 돌리는 방법이나 sleep 을 줘서 일정시간마다 체크하는 경우가 있는데 이는 대부분 비효율적이며, 데이터가 아직 완성이 안되어있으면 잠들어있다가 완료시점에 신호를 보내어 깨어나게 한다. 기억해야 할 점은, 만약 집단의 쓰레드들을 관리해서 경쟁적으로 한개씩 깨어나게 하고 싶다면 하나의 condition 변수를 쓰레드들 사이에서 공유해야 한다.void threadFunction(void)
{
while( true )
{
boost::mutex::scoped_lock lock( mutexVar );
// Thread 초기화 작업
condition.wait(mutexVar); // 현재 실행중인 Thread는 대기모드로
// 들어가고 mutexVar로 걸린 락이 해지
// 된다.// 외부 코드에서 깨우고 싶을때..
condition.notify_one(); // 잠들어있는 것중에서 경쟁적으로 한개만 깨울때
condition.notify_all(); // 잠들어있는 모든 녀석을 깨울때
The Boost.Threads Library
http://diehard98.tistory.com/141
Thread Creation
boost::thread는 std::fstream 클래스가 파일을 표현하는 것과 같은 방식으로 스레드의 실행을 표현한다. Default 생성자가 현재의 실행 스레드를 나타내는 객체를 생성한다. 오버로딩된 생성자는 입력 변수가 없고 리턴하는 것이 없는 함수 객체를 받는다. 이 생성자는 새로운 실행 스레드를 시작하는데 이는 결국 함수 객체의 호출이며 해당 함수의 호출이다.#include <boost/thread/thread.hpp> #include <iostream>void hello() { std::cout << "Hello world, I'm a thread!" << std::endl; } int main(int argc, char* argv[]) { boost::thread thrd(&hello); thrd.join(); return 0; }
Mutexes
- 다른 스레드가 뮤텍스를 잠그지 않을때까지 대기
- 만약 다른 스레드가 뮤텍스를 잠궈놓은 상태라면 바로 리턴하기
- 다른 스레드가 뮤텍스를 잠그지 않을때까지 대기 하거나 혹은 일정 시간만 대기 하다가 리턴
#include <boost/thread/thread.hpp> #include <boost/thread/mutex.hpp> #include <iostream>boost::mutex io_mutex;
struct count { count(int id) : id(id) { }
void operator()() { for (int i = 0; i < 10; ++i) { boost::mutex::scoped_lock lock(io_mutex); std::cout << id << ": " << i << std::endl; } }
int id; }; int main(int argc, char* argv[]) { boost::thread thrd1(count(1)); boost::thread thrd2(count(2)); thrd1.join(); thrd2.join(); return 0; }
Listing 3: Using the Boost.Bind library to simplify the code in Listing 2
// This program is identical to
// listing2.cpp except that it
// uses Boost.Bind to simplify
// the creation of a thread that
// takes data.
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <iostream>
boost::mutex io_mutex;
void count(int id)
{
for (int i = 0; i < 10; ++i)
{
boost::mutex::scoped_lock
lock(io_mutex);
std::cout << id << ": " <<
i << std::endl;
}
}
int main(int argc, char* argv[])
{
boost::thread thrd1(boost::bind(&count, 1));
boost::thread thrd2(boost::bind(&count, 2));
thrd1.join();
thrd2.join();
return 0;
}
#include <boost/thread/thread.hpp> #include <boost/thread/mutex.hpp> #include <boost/bind.hpp> #include <iostream>
boost::mutex io_mutex;
void count(int id) { for (int i = 0; i < 10; ++i) { boost::mutex::scoped_lock lock(io_mutex); std::cout << id << ": " << i << std::endl; } } int main(int argc, char* argv[]) { boost::thread thrd1(boost::bind(&count, 1)); boost::thread thrd2(boost::bind(&count, 2)); thrd1.join(); thrd2.join(); return 0; }
Condition Variables
#include <boost/thread/thread.hpp> #include <boost/thread/mutex.hpp> #include <boost/thread/condition.hpp> #include <iostream>const int BUF_SIZE = 10; const int ITERS = 100;
boost::mutex io_mutex;
class buffer{ public: typedef boost::mutex::scoped_lock scoped_lock; buffer(): p(0), c(0), full(0){ }
void put(int m){ scoped_lock lock(mutex); if (full == BUF_SIZE) { { boost::mutex::scoped_lock lock(io_mutex);
std::cout <<"Buffer is full. Waiting..."<< std::endl; } while (full == BUF_SIZE) cond.wait(lock); }
buf[p] = m; p = (p+1) % BUF_SIZE; ++full; cond.notify_one();
}
int get(){ scoped_lock lk(mutex); if (full == 0){ { boost::mutex::scoped_lock lock(io_mutex);
std::cout <<"Buffer is empty. Waiting..."<< std::endl; } while (full == 0) cond.wait(lk); }
int i = buf[c]; c = (c+1) % BUF_SIZE; --full; cond.notify_one(); return i;
} private: boost::mutex mutex; boost::condition cond; unsigned int p, c, full; int buf[BUF_SIZE]; };
buffer buf;
void writer(){ for (int n = 0; n < ITERS; ++n){ { boost::mutex::scoped_lock lock(io_mutex); std::cout << "sending: "<< n << std::endl; }
buf.put(n); } }
void reader(){ for (int x = 0; x < ITERS; ++x){ int n = buf.get(); { boost::mutex::scoped_lock lock(io_mutex); std::cout << "received: " << n << std::endl; } } }
int main(int argc, char* argv[]) { boost::thread thrd1(&reader); boost::thread thrd2(&writer); thrd1.join(); thrd2.join(); return 0;
}
Thread Local Storage
#include <boost/thread/thread.hpp> #include <boost/thread/mutex.hpp> #include <boost/thread/tss.hpp> #include <iostream>boost::mutex io_mutex; boost::thread_specific_ptr<int> ptr;
struct count{
count(int id) : id(id) { }
void operator()(){ if (ptr.get() == 0) ptr.reset(new int(0));
for (int i = 0; i < 10; ++i) { (*ptr)++; boost::mutex::scoped_lock lock(io_mutex); std::cout << id << ": "<< *ptr << std::endl; }
}
int id;
};
int main(int argc, char* argv[]) { boost::thread thrd1(count(1)); boost::thread thrd2(count(2)); thrd1.join(); thrd2.join(); return 0;
}
Once Routines
Listing 6: A very simple use of boost::call_once
#include <boost/thread/thread.hpp> #include <boost/thread/once.hpp> #include <iostream>int i = 0; boost::once_flag flag = BOOST_ONCE_INIT;
void init() { ++i; }
void thread1() { boost::call_once(&init, flag); }
int main(int argc, char* argv[]) { boost::thread thrd1(&thread1); boost::thread thrd2(&thread1); thrd1.join(); thrd2.join(); std::cout << i << std::endl; return 0; }
The Future of Boost.Threads
Notes
[1] The POSIX standard defines multithreaded support in what’s commonly known as the pthread library. This provides multithreaded support for a wide range of operating systems, including Win32 through the pthreads-win32 port. However, this is a C library that fails to address some C++ concepts and is not available on all platforms.
[2] Visit the Boost website at <http://www.boost.org>.
[3] See Bjorn Karlsson’s article, “Smart Pointers in Boost,” in C/C++ Users Journal, April 2002.
[4] Douglas Schmidt, Michael Stal, Hans Rohnert, and Frank Buschmann. Pattern-Oriented Software Architecture Volume 2 —Patterns for Concurrent and Networked Objects (Wiley, 2000).
'메타프로그래밍 > Boost::' 카테고리의 다른 글
boost::random (0) | 2013.01.29 |
---|---|
Boost::mpl (0) | 2012.12.25 |
boost::weak_ptr (0) | 2012.11.24 |
boost::shared_ptr (0) | 2012.11.18 |
boost::function (0) | 2012.11.13 |