웹 서핑 중 C++11의 기능 중 Visual Studio 2013에도 추가된 'Non-static data member initializers, Variadic templates, Initializer lists, Alias templates' 기능을 맛 볼 수 있는 코드를 보아서 소개한다.

 

테스트는 간단하게 웹 컴파일러를 이용했다.

웹 컴파일러: http://melpon.org/wandbox/

 

코드(출처: http://d.hatena.ne.jp/osyo-manga/20131027/1382882447 )

#include <iostream>

#include <vector>

#include <string>

 

// Variadic templates

template<typename... Args>

void func(Args... args)

{

// Initializer lists

for(auto&& n : { args... })

{

std::cout << n << std::endl;

}

}

 

template<typename T>

struct X

{

T value;

X(int n) : value(n){}

};

 

struct person

{

// Non-static data member initializers

int age = 13;

std::string name = "homu";

};

 

 

// Aliases templates

template<typename T>

using my_vector = std::vector<X<T>>;

 

int main()

{

std::cout << "Aliases templates, Initializer lists" << std::endl;

my_vector<int> v = { X<int>{1}, X<int>{2}, X<int>{3}};

 

for(auto&& n : v)

{

std::cout << n.value << std::endl;

}

std::cout << std::endl;

 

 

std::cout << "Variadic templates" << std::endl;

func(1.1, 2.2, 3.3, 4.4, 5.5);

std::cout << std::endl;

 

 

std::cout << "Non-static data member initializers" << std::endl;

person homu;

std::cout << homu.name << std::endl;

std::cout << homu.age << std::endl;

 

return 0;

}

< 결과 >

 

위 코드는 Visual Studio 2013에서도 잘 돌아가며 VS 2013에서는 C++11 기능 중 아래의 것이 새롭게 구현 되었다.

Non-static data member initializers

Variadic templates

Initializer lists

Default template arguments for function templates

Alias templates

Delegating constructors

Explicit conversion operators

Raw string literals

Defaulted and deleted functions

 

더 자세한 정보는 http://msdn.microsoft.com/en-us/library/vstudio/hh567368.aspx 를 참고.

 

 

신고
by 흥배 2014.02.17 08:00

ini 파일 형식으로 된 설정 파일을 읽을 때 사용한다.

[ZoneServer]
CHANNEL_COUNT = 10
CHANNEL_USER_COUNT = 200


  • 헤더 파일
1
#include "Poco/Util/IniFileConfiguration.h"
  • 사용 예

ini 파일 읽기에 실패하는 경우 에외가 발생하므로 예외 처리를 해야 한다(예외 종류에 따라서 실패 이유를 알 수 있다).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
try
{
    Poco::AutoPtr<Poco::Util::IniFileConfiguration> pZoneServerConf(new Poco::Util::IniFileConfiguration("test.ini"));
    m_ZoneConfig.nMaxChannelCount       = pZoneServerConf->getInt( "ZoneServer.CHANNEL_COUNT" );
    m_ZoneConfig.nMaxChannelUserCount   = pZoneServerConf->getInt( "ZoneServer.CHANNEL_USER_COUNT" );
}
catch ( Poco::FileNotFoundException e ) // 파일이 없는 경우
{
    SERVER_LOG("Init", LOG_LEVEL::error, "%s", e.displayText().c_str());
    return false;
}
catch ( Poco::NotFoundException& e )    // 설정 키워드가 없는 경우
{
    SERVER_LOG("Init", LOG_LEVEL::error, "%s", e.displayText());
    return false;
}


저작자 표시
신고
by 흥배 2013.11.11 08:00

POCO 라이브러리를 다운로드 한 후 압축을 풀면 루트 디렉토리에 VC 버전에 맞는 .cmd 파일이 있음. 

예를들면 VC++(VS 2012)의 경우 build_vs110.cmd 파일을 실행한다. 


실행하면 각 라이브러리 디렉토리마다 VS 프로젝트 파일이 생성된다. 



다양한 라이브러리 중 사용할 라이브러리 디렉토리에 들어간 후 VC 버전에 맞는 프로젝트 파일을 열어서 빌드하면 된다.
보통 Foundation, Util, XML, Net 디렉토리의 라이브러리를 빌드한다.
빌드를 하면 32비트 버전은 lib 디렉토리에, 64비트 버전은 lib64 디렉토리에 lib 파일을 생성한다.



lib 파일 빌드가 끝나면 이것을 사용할 프로젝트에서 헤더파일과 lib 디렉토리를 추가한다.


헤더 파일을 추가할 때 해당 디렉토리의 include 디렉토리까지 포함한다. 

예) Foundation의 경우 Foundation\include 

저작자 표시
신고
by 흥배 2013.09.13 08:00

사용법 및 소개 http://ikpil.com/1057 
(일본어) https://sites.google.com/site/boostjp/tips/scope_guard 
(일본어) C++11 람다 대응 http://d.hatena.ne.jp/faith_and_brave/20111125/1322199381 
(일본어) this 캡쳐하기 http://d.hatena.ne.jp/faith_and_brave/20120703/1341298054 


  • 스코프 내의 모든 변수를 캡쳐하기(C++11 전용)

BOOST_SCOPE_EXIT_ALL을 사용한다. 클래스의 멤버 변수도 사용할 수 있음

1
2
3
4
5
6
7
8
9
10
11
12
13
14
CPacketSend kPacketSend( SAD_REP_CHECK_ACCOUNT );
BYTE nErrorCode = E_SAI_REP_CHECK_ACCOUNT::FLAG_CHECK_OK;
     
BOOST_SCOPE_EXIT_ALL(&)
{
    if( nErrorCode != E_SAI_REP_CHECK_ACCOUNT::FLAG_CHECK_OK )
    {
    kPacketSend << nErrorCode;
    kPacketSend << nClientSocketIndexInLoginServer;
    kPacketSend << dwLoginUniqueSocketID;
    kPacketSend << iLoginServerNumber;
    GET_NETWORK_INTERFACE()->SendToServer( iServer, kPacketSend);
    }
};
  • BOOST_SCOPE_EXIT를 사용할 때 조심할 점

이것을 사용하는 스코프 내에서 BOOST_SCOPE_EXIT를 정의하기 전에 return 문을 사용하면 안된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
void Check()
{
   ...........
   if( ... )
   {
     return;
   }
 
   // 아래가 호출되지 않는다
   BOOST_SCOPE_EXIT_ALL(&)
   {
   }
}

올바르게 사용하려면 아래와 같이 바꾸어야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void Check()
{
   ...........
   // 아래가 호출되지 않는다
   BOOST_SCOPE_EXIT_ALL(&)
   {
   }
    
   ....
   if( ... )
   {
     return;
   }
 
    
}


저작자 표시
신고
by 흥배 2013.09.10 08:00

경고 나오지 않도록 #pragma warning( disable : 경고 번호 )

경고 다시 나오도록 #pragma warning( default : 경고 번호 )

경고가 에러가 되도록 #pragma warning( error : 경고 번호 )

반복되는 경고가 한번만 나오도록 #pragma warning( once : 경고 번호 )

저작자 표시
신고
by 흥배 2013.09.06 08:00

unique_lock는 쉽게 말하면 lock_guard에 기능이 더해진 것이라고 볼 수 있습니다.

lock_guard의 경우 정의와 동시에 락을 걸고, 파괴될 때만 락을 풀 수 있습니다.

 

그에 비해 unique_lock은 정의와 동시에 락을 걸 수도 있고, 또는 뒤에 락을 걸 수도 있습니다. 또 락을 푸는 것도 원하는 대로 조절이 가능하며 try_lock이나 try_lock_for, try_lock_until 등도 지원합니다. 그리고 unique_lock끼리 소유한 뮤텍스 객체를 서로 교환도 할 수 있으며, 뮤텍스 객체를 얻거나 해제할 수도 있습니다.

 

간단한 경우에는 lock_guard가 사용하기 편하지만 뮤텍스를 다양하게 사용하고 싶은 경우에는 unique_lock이 훨씬 더 좋습니다.

 

 

unique_lock 생성

unique_lock 클래스의 생성자는 다양한 방법으로 뮤텍스를 사용할 수 있도록 여러 버전이 준비 되어 있습니다.

 

unique_lock() noexcept;

unique_lock(unique_lock&& Other) noexcept;

explicit unique_lock(mutex_type& Mtx);

unique_lock(mutex_type& Mtx, adopt_lock_t Adopt);

unique_lock(mutex_type& Mtx, defer_lock_t Defer) noexcept;

unique_lock(mutex_type& Mtx, try_to_lock_t Try);

template<class Rep, class Period>

   unique_lock(mutex_type& Mtx,

      const chrono::duration<Rep, Period> Rel_time);

template<class Clock, class Duration>

   unique_lock(mutex_type& Mtx,

      const chrono::time_point<Clock, Duration> Abs_time);

unique_lock(mutex_type& Mtx,

   const xtime *Abs_time) noexcept;

 

unique_lock의 사용 예는 아래와 같습니다.

 

std::mutex m;

....

// 락을 만들고 동시에 뮤텍스의 소유권을 가진다

std::unique_lock lck(m, std::adopt_lock);

 

 

std::mutex m;

....

// 락을 만들지만 뮤텍스의 소유권은 가지지 않는다

std::unique_lock lck(m,std::defer_lock);      

...

if (lck.try_lock()) {

....

}                   

 

 

std::unique_lock<std::timed_mutex>

        lk(m,std::chrono::milliseconds(3));

....

if(lk) {

    process(data);

}                   

 

 

 

unique_lock 멤버 함수

 

- void lock();

- mutex_type *mutex() const _NOEXCEPT;

- explicit operator bool() _NOEXCEPT

- unique_lock& operator=(

    unique_lock&& Other

  ) _NOEXCEPT;

- bool owns_lock() const _NOEXCEPT;

- mutex_type *release() _NOEXCEPT;

- void swap(

    unique_lock& Other

  ) _NOEXCEPT;

- bool try_lock() _NOEXCEPT;

- template<class Rep,

    class Period>

  bool try_lock_for(

     const chrono::duration<Rep,

     Period>& Rel_time

  );

- template<class Clock, class Duration>

    bool try_lock_until(const chrono::time_point<Clock, Duration>& Abs_time);

    bool try_lock_until(const xtime *Abs_time);

- void unlock();

 

저작자 표시
신고
by 흥배 2013.07.15 08:00

앞 선 글 중 ‘std::thread - 2. Join’에서 join을 호출하지 않은 경우 에러 창이 발생하였습니다.


 

이것은 C++11 thread 사양에 의해서 thread 오브젝트가 파괴될 때 join이나 detach를 호출하지 않은 경우 std::terminate를 호출하여 프로그램을 종료하도록 되어 있기 때문입니다.

 

< 예제. 9 >

#include <thread>

#include <iostream>

 

int main()

{

           int nThreadRunCount = 0;

          

           {

                      std::thread Thread = std::thread( [&] ()

                       {

                          for( int i = 0; i < 10; ++i )

                          {

                                ++nThreadRunCount;

                                                               

                                std::cout << "Thread1 ID : " << Thread.get_id() << std::endl;

                          }

                       } );

           }

 

           getchar();

           return 0;

}

 


<예제.9>를 실행하면 에러가 발생하고 아래의 콜스택을 보면



thread 오브젝트의 소멸자에서 terminate를 호출하는 것을 알 수 있습니다.



이것으로 thread에 대해서 기능 위주로 간단하게 살펴 보았습니다. 앞으로 공부해야 할 것들이 더 있어서 남은 것들을 설명 후 다시 thread 사용에 대해서 깊게 들어 가겠습니다.

 

다음부터는 병렬 프로그래밍에서 절대 빠질 수 없는 동기화 객체에 대해서 설명하겠습니다.

 

 

저작자 표시
신고
by 흥배 2013.05.28 08:00

http://vsts2010.tistory.com/530 

에 연재한 글을 모아서 보관겸 공유합니다.



VC10_SafeInt.pdf


저작자 표시
신고
by 흥배 2013.05.24 08:00

sleep_for sleep_until 함수는 스레드를 일시 중지 시킬 때 사용하는 것입니다.

이 두 함수의 차이는 이름에서 쉽게 알 수 있는데 sleep_for는 특정 시간 동안 일시 중지 시키고 싶을 때(. 6초 동안 중지) 사용하고, sleep_until는 어떤 시간이 될 때까지(. 1410분까지) 중지 시킬 때 사용합니다.

 

sleep_for sleep_until 함수는 thread의 멤버는 아니고 this_thread 네임 스페이스에 속해 있습니다.

 

< 예제. 8 >

#include <iostream>

#include <chrono>

#include <thread>

 

int main()

{

           std::cout << "sleep_for 테스트 시작" << std::endl;

   

           std::chrono::seconds dura( 3 );

   

 

           std::chrono::system_clock::time_point StartTime = std::chrono::system_clock::now();

 

           std::this_thread::sleep_for( dura );

   

           std::chrono::system_clock::time_point EndTime = std::chrono::system_clock::now();

 

           std::chrono::seconds sec = std::chrono::duration_cast<std::chrono::seconds>(EndTime - StartTime);

          

           std::cout << "경과 시간()" << sec.count() << std::endl;

 

 

 

          

           std::cout << "sleep_until 테스트 시작" << std::endl;

 

           StartTime = std::chrono::system_clock::now();

 

           std::chrono::seconds dura_sec( 5 );

           std::this_thread::sleep_until( StartTime + dura_sec );

          

           EndTime = std::chrono::system_clock::now();

 

           sec = std::chrono::duration_cast<std::chrono::seconds>(EndTime - StartTime);

          

           std::cout << "경과 시간()" << sec.count() << std::endl;

}

 

< 실행 결과 > 


 

yield는 스레드가 자신에게 할당 되어 있는 시간을 포기하고 다른 실행 스레드에게 처리를 양도합니다.

std::this_thread::yield();

저작자 표시
신고
by 흥배 2013.05.20 08:00

hardware_concurrency()는 하드웨어 스레드 컨텍스트 수를 알려 주는 함수입니다.

스레드 컨텍스트는 CPU , 코어 수, 하이퍼 스레드와 관계가 있습니다.

 

하드웨어 스레드 컨텍스트 수는 Windows '작업 관리자' '성능' 탭에서 볼 수 있습니다.





제 컴퓨터는 CPU 하나에 코어는 4개이고, 하이퍼 스레딩을 지원하지 않는 CPU라서 CPU 사용 현황에 4개의 그림만 나옵니다. 그래서 저는 hardware_concurrency() 함수를 실행하면 결과는 4가 나옵니다.

 

관례적으로 프로그램에서 멀티 스레드를 만들 때 (하드웨어 스레드 컨텍스트 수 * 2) +1 이라는 공식으로 나온 수 만큼 만들면 좋다고 합니다. 이때 hardware_concurrency() 함수를 사용하면 좋습니다.

그리고 만약 hardware_concurrency()를 사용할 수 없는 경우라면 0 을 반환 합니다.

 

< 예제. 7 >

#include <thread>

#include <iostream>

 

 

int main()

{

           std::cout << "하드웨어 컨텍스트 수 : " << std::thread::hardware_concurrency() << std::endl;

 

           return 0;

}

 

< 실행 결과 >


저작자 표시
신고
by 흥배 2013.05.10 08:00
| 1 2 3 4 |