#include <stdio.h>
#include <iostream>
#include <vector>
#include <boost/pool/singleton_pool.hpp>
#include <boost/pool/pool_alloc.hpp>


template<typename T,  unsigned int NEXT_SIZE = 32U, unsigned int  MAX_POOL_SIZE = 0U>
class CMemoryPoolT
{
public:
     static void* operator new(size_t size)
     {
          return boost::singleton_pool<T,
               sizeof(T),
               boost::default_user_allocator_new_delete,
               boost::details::pool::default_mutex,
               NEXT_SIZE,
               MAX_POOL_SIZE>::malloc();
     }

     static void operator delete(void* p)
     {
          boost::singleton_pool<T,
               sizeof(T),
               boost::default_user_allocator_new_delete,
               boost::details::pool::default_mutex,
               NEXT_SIZE,
               MAX_POOL_SIZE>::free(p);
     }
};


class CMemoryPoolTest  :public CMemoryPoolT<CMemoryPoolTest>
{
public:
     char Dumy[124] ;
};


int _tmain(int argc, _TCHAR* argv[])
{
     using std::vector ;

     CMemoryPoolTest *p = new CMemoryPoolTest() ;

     delete p ;

     printf("Using MemoryPool... \n") ;


     return 0;
}


위와 같이 작성을 하면 아주 편하게 사용할수 있다

 

메모리 풀을 적용하고 싶은 클래스에 CMemoryPoolT을 상속해주고  

템플릿 명시를 자기 클래스 이름으로 적어 놓는다.

 

명시를 하는 이유는 A라는 클래스가 있고 B라는 클래스 있다고 치면 A라는 클래스와 B라는 클래스를 다른 클래스이므로 메모리를 관리 할때 따로 관리 하는게 편하다.

 

따로 관리를 하기위해 태그를 붙이는 거라 생각을 하면 쉽다.

개인적으로 boost보다는 ACE를 더 선호 합니다.


개인적으로 boost도 훌륭한 라이브러리라고 생각하지만 너무 심각하게 메타프로그래밍이라.. 

자칫 처음 쓰는 사람들에게는 어렵게 느껴질수 있습니다.

거기에다 ACE에서는 꽤나 실용적인 로직들이 많이 존재합니다.


어차피 gethostbyname으로  도메인의 아이피를 얻을때  해당 도메인에 속해 있는 모든 아이피 목록을 가져 오는 경우는 드뭅니다. 

해당 도메인에 아이피가 하나만 걸려 있거나, 여러개 걸려 있어도 로드밸런싱을 위해 당장 필요한 아이피  하나만 가져와서 씁니다.

 ACE_INET_Addr  google_addr;

 google_addr.set( 80, "google.com");

 strcpy(szServerIP, google_addr.get_host_addr());

참 단순한 로직입니다. 3줄이면 간단하게 아이피를 가져옵니다. 3줄도 많다구요?


 ACE_INET_Addr  google_addr( 80, "google.com");

 strcpy(szServerIP, google_addr.get_host_addr());

더 짧게 하면 두 줄 이군요...


거기다  내부 로직을 살펴 보면 gethostbyname을 쓰지 않고 gethostbyname_r을 사용하고 있습니다. 

즉 Thread Safe하다는 것이죠!



'C++ > ACE' 카테고리의 다른 글

플랫폼 독립적인 설정파일 로딩 로직  (0) 2014.09.16
ACE_dev_pool_reactor 쓰레드 안정성에 대해  (0) 2014.09.16

리눅스 계열이든 윈도우 계열이든 서버 모듈을 개발시  설정 문서에서 값을 읽어오는 건 필수적이다.

윈도우에서 가장 쉽게 쓸수 있는 GetPrivateProfileString는 윈도우에서만 사용을 할 수 있다.

다음 ACE 라이브러리 함수를 사용하면  리눅스든 윈도우든 똑같이 작동을 한다.

 

물론 윈도우에서만 개발 하는 사람들은  소스가 많이 길어지니 불편할듯... 하다.

리눅스 개발자는 이거라도 해주면 고마워 한다..

 

 

#include <ace/OS.h>
#include <ace/Configuration.h>
#include <ace/Configuration_Import_Export.h>

 

int ACE_TMAIN()
{        ACE_Configuration_Heap config ;

        if(config.open() == -1)
        {
                ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("config open error\n")), -1) ;
        }
               
        ACE_Ini_ImpExp config_importer(config) ;

       
        if(config_importer.import_config("as.conf")== -1)
        {
                ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("not found conf file\n")), -1) ;
        }
               
       
        ACE_Configuration_Section_Key secion ;
        if(config.open_section(config.root_section(), ACE_TEXT("CONF"), 0, secion) == -1 )
        {
                ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("secion open error\n")), -1) ;
        }
               
        ACE_TString strData ;

        if(config.get_string_value(secion, ACE_TEXT("result"), strData) == -1  )
        {
                ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("Get String Value Error\n")), -1) ;
        }                                 
               
       
        printf("%s\n", strData.c_str());
                
        config.remove_section(config.root_section(), ACE_TEXT("CONF"), 0) ;
                
        return 0 ;
}

 

 

 

 

그럼 프로그램에서 읽어들이는 설정 문서 파일의 이름은 as.conf 이고 안에 내용은 다음과 같다.[CONF]
result=  reading conf

 

 

 

결과적으로  프로그램 실행을 했을시 콘솔에 찍히는 내용은 다음과 같다.

 

 reading conf

'C++ > ACE' 카테고리의 다른 글

초간단 도메인으로 IP 주소 얻기  (0) 2014.09.16
ACE_dev_pool_reactor 쓰레드 안정성에 대해  (0) 2014.09.16

 

리눅스에서 ACE를 관련하여 Reactor 패턴을 구현을 할때  대부분 ACE_Dev_poll_Reactor에 관심을

많이 가질것이다.  왜냐 하면 하면  리눅스  2.4 이상의 커널에서 ACE를 빌드를 할때 ACE_HAS_EVENT_POLL 를 추가하면 리눅스에서 IOCP에 필적하는 Epoll을 사용 할 수 있기 때문이다.  물론 IOCP 자체가 Proactor 기반이고 Epoll은 Reactor 기반인지라 비교 하기에는 무리가 있기는 하지만.. 어차피 리눅스 자체가 Reactor에 최적화가 되어 있고 윈도우는 Proactor에 최적화 되어 있는

각 운영체제에서 최고의 효율을 낸다는 사실에서 비견을 할만하다.

 

하지만 ACE_TP_Reactor은 내부적으로 리더/팔로우 패턴으로 쓰레드 풀을 사용 되어 있다고 한다.

 

그런데 ACE_Dev_Poll_Reactor을 확인 하여 보았을때 이 역시 내부적으로 쓰레드풀을 사용하는지

 

아니면  Epoll 관련 함수가 자체적으로 Thread Safe해서인지  TP_Reactor 과 마찬가지로

 

run_reactor_events_loop를  복수의 쓰레드를 통해서 사용되어도 문제가 없는거 같다.

 

 

내부의 Handle_Event 함수도 쓰레드 세이프하게 되어 있고. Owner 내부에서도 사용되지를 않는데

 

마음놓고 TP_Reactor와 똑같은 방식으로 사용을 하면 될 듯 합니다. 

 

또한 구글 검색에서 건졌는데 ACE의 창시자 더글라스 교수님이 친절한 답변도 볼 수 있었습니다 :D

 

Hi Rafi,

> A small question.  May Dev_Poll_Reactor be driven by
> multiple-threads simultaneously, or something like TP_Reactor is
> needed?

You can use multiple threads.  BTW, to ensure that we have proper
version/platform/compiler information, please make sure you fill out
the appropriate problem report form (PRF), which is in

$ACE_ROOT/PROBLEM-REPORT-FORM
$TAO_ROOT/PROBLEM-REPORT-FORM

or in

$ACE_ROOT/BUG-REPORT-FORM
$TAO_ROOT/BUG-REPORT-FORM

in older versions of ACE+TAO.  Make sure to include this information
when asking any questions about ACE+TAO since otherwise we have to
"guess" what version/platform/compiler/options you've using, which is
very error-prone and slows down our responsiveness.  If you don't use
the PRF, therefore, it is less likely that someone from the core
ACE+TAO developer team will be able to answer your question.
Naturally, we encourage and appreciate other members of the ACE+TAO
user community who can respond to questions that they have the answers
to.

Thanks,

        Doug
-- 
Dr. Douglas C. Schmidt                       Professor and Associate Chair
Electrical Engineering and Computer Science  TEL: (615) 343-8197
Vanderbilt University                        WEB: 
www.dre.vanderbilt.edu/~schmidt
Nashville, TN 37203                          NET: d.schmidt@xxxxxxxxxxxxxx

P.S 그런데 ACE 5.7에서  Dev_Pool_Reactor과 관련하여 쓰레드 안정성에 대해 FIX 하였다는 글을 본 적이 있었는데 아무튼.. 왠만하면 Dev_Poll 에서 멀티 쓰레드를 사용할려면 5.7 이상 사용하시는게 좋을 듯 합니다.

'C++ > ACE' 카테고리의 다른 글

초간단 도메인으로 IP 주소 얻기  (0) 2014.09.16
플랫폼 독립적인 설정파일 로딩 로직  (0) 2014.09.16

간단한 TBB  parallel_for  예제  

여기서는 람다를 사용을 하고 있지만...

아직 C++0x가 적용 안된 컴파일러 (Windows의 경우 visual studio 2008 이하) 는 람다 함수를 사용 할 수가 없다.

람다 함수를 사용하는 대신에 functor를 이용 해야 한다.

[-] Collapse  

#include <stdio.h>
#include <tchar.h>
#include <tbb/task_scheduler_init.h>
#include <tbb/parallel_for.h>
#include <tbb/blocked_range.h>
#include <tbb/atomic.h> // atomic
#include <tbb/mutex.h> // 뮤텍스



#ifdef _DEBUG
#pragma  comment(lib, "tbb_debug.lib")
#else
#pragma  comment(lib, "tbb.lib")
#endif // _DEBUG



using namespace tbb ;

int main(int argc, _TCHAR* argv[])
{
    task_scheduler_init init ;

    //int nOut = 0 ;
    atomic<int> nOut ;
    nOut  = 0 ;


    parallel_for(blocked_range<int>(0, 100000),
        [&nOut](const blocked_range<int>& iter)
    {
        for (int n = iter.begin() ; n != iter.end() ; ++n)
        {
            nOut += 1 ;
        }
    }
    ,  auto_partitioner()) ;

    printf("Result %d\n", nOut) ;



    // 다른 락거는 방법

    tbb::mutex _lock;
    int   _sum = 0;
    parallel_for(blocked_range<int>(0, 100000),
        [&_lock, &_sum](const blocked_range<int>& iter)
    {
        int sum = 0;
        for (int n = iter.begin() ; n != iter.end() ; ++n)
        {
            sum += 1 ;
        }

        _lock.lock() ;
        _sum += sum ;
        _lock.unlock() ;
    },  auto_partitioner()) ;

    printf("Result2 : %d\n", _sum) ;

    getchar() ;
    return 0;
}

'C++ > Intell C++' 카테고리의 다른 글

간단한 TBB parallel_reduce 예제  (0) 2014.09.16
간단한 TBB parallel_while 예제  (0) 2014.09.16
간단한 TBB parallel_sort 예제  (0) 2014.09.16
간단한 TBB parallel_invoke 예제  (1) 2014.09.16

parallel_for문과는 달리  합산 및 정산을 할때 동기화 이슈가 없다.

각각 쓰레드 별로  body 객체가 생성이 되고  연산후

join문에서 합산되기때문이다.

 

 

[-] Collapse
#include <stdio.h>
#include <tchar.h>
#include <tbb/tbb.h>


#ifdef _DEBUG
#pragma  comment(lib, "tbb_debug.lib")
#else
#pragma  comment(lib, "tbb.lib")
#endif // _DEBUG

using namespace tbb;

class CSumBody
{
public:
    CSumBody()
    {
        sum_ = 0 ;
    }

    CSumBody(CSumBody &body, split)
    {
        sum_ = 0 ;
    }

    void operator()(const tbb::blocked_range<__int64> &iter)
    {
        for (__int64 n = iter.begin() ; n != iter.end() ; ++n)
        {
            sum_ += 1 ;
        }
    }

    void join(const CSumBody &body)
    {
        sum_ += body.sum_ ;
    }
public:
    __int64 sum_ ;
};



int _tmain(int argc, _TCHAR* argv[])
{

    tick_count start,stop;
    __int64 sum = 0 ;
    task_scheduler_init  init ;


    start = tick_count::now();

    CSumBody body ;
    parallel_reduce(blocked_range<__int64>(0, 1000000000), body, auto_partitioner()) ;


    stop = tick_count::now();
    printf("Result %d  \t시간 %f\n", body.sum_, (stop - start).seconds()) ;

    getchar() ;
    return 0;
}






'C++ > Intell C++' 카테고리의 다른 글

간단한 TBB parallel_for 예제  (0) 2014.09.16
간단한 TBB parallel_while 예제  (0) 2014.09.16
간단한 TBB parallel_sort 예제  (0) 2014.09.16
간단한 TBB parallel_invoke 예제  (1) 2014.09.16

범위를 알 수 없을 때 사용하는 while문을 병렬화 시킨 로직이다.

그리고 type은 정해져 있지 않으므로 포인터를 이용하여 리스트 자료구조를  순회를 할때도 문제 없다

 

 

 

[-] Collapse
#include <stdio.h>
#include <tchar.h>
#include <time.h>
#include <tbb/tbb.h>
#include <tbb/parallel_while.h>

#ifdef _DEBUG
#pragma  comment(lib, "tbb_debug.lib")
#else
#pragma  comment(lib, "tbb.lib")
#endif // _DEBUG

using namespace tbb;

class CItemStream
{
public:
    CItemStream(int n) : num(n) {}

    // 여기서는 카운터 연산만 처리 해야함... 여기에서는 동기화 이슈가 없음
    bool pop_if_present(int &count)
    {
        // 언제 끝날지 모르게 하기 위해서 rand 함수를 사용
        // 실제로 count를 이용할 경우에는  if (func(num) == 0) 등등 꼴리는데로 사용!!!
        if(!(rand() % 10  != 0))
        {
            printf("루프종료...\n") ;
            return false ;
        }
        printf("Count %d\n", num) ;
        count = num ;
        num++ ;
        return true ;
    }
public:
    int num ;
};

class CBody
{
public:
    // 실제로 자료에 대한 처리는 여기서 해야 함
    void operator()(int n) const
    {
        printf("count : %d에 대한 처리 \n", n ) ;
    }
    typedef int argument_type ;
};

int _tmain(int argc, _TCHAR* argv[])
{
    srand((unsigned int)time(0)) ;
    // 아래 직렬로직을  TBB로 병렬화 루틴...
    // 단 카운트가 순서대로 처리 되지 않는다.

// int num = 0 ;
// while (rand() % 10 == 0 )
// {
// printf("count : %d에 대한 처리 \n", num ) ;
// num++ ;
// }


    parallel_while<CBody> w ;
    CItemStream stream_(0) ;
    CBody body ;

    w.run(stream_, body) ;
    printf("루프 끝\n") ;


    getchar() ;
    return 0;
}

'C++ > Intell C++' 카테고리의 다른 글

간단한 TBB parallel_for 예제  (0) 2014.09.16
간단한 TBB parallel_reduce 예제  (0) 2014.09.16
간단한 TBB parallel_sort 예제  (0) 2014.09.16
간단한 TBB parallel_invoke 예제  (1) 2014.09.16

병렬 처리 쓰레드로 정렬을 한다. 

정렬할 데이터가 많고 CPU 코어 갯수가 높을 수록 일반 sort보다 많이 빨라지게 된다.

parallel_while이나 다른 알고리즘에 비해 아주 간단하게 쓸 수 있다.. -ㅅ-...

 

여기서는 람다를 사용을 하고 있지만...

아직 C++0x가 적용 안된 컴파일러 (Windows의 경우 visual studio 2008 이하) 는 람다 함수를 사용 할 수가 없다.

람다 함수를 사용하는 대신에 functor를 이용 해야 한다.

 

 

[-] Collapse
#include <stdio.h>
#include <tchar.h>
#include <time.h>
#include <tbb/tbb.h>

#ifdef _DEBUG
#pragma  comment(lib, "tbb_debug.lib")
#else
#pragma  comment(lib, "tbb.lib")
#endif // _DEBUG

using namespace tbb ;

class CNObject
{
public:
    bool operator<(const CNObject & t) const
    {
        return  (data < t.data) ;
    }
public:
    int data ;
    char dumy ;
};

int _tmain(int argc, _TCHAR* argv[])
{
    task_scheduler_init init ;
    srand((unsigned int)time(NULL)) ;
    printf("병렬 처리 정렬 알고리즘\n") ;

    // 정렬을 테스트를 위한 데이터 생성
    CNObject aValue[10] ;
    for (int n = 0 ; n < 10 ; ++n )
    {
        aValue[n].data = rand() % 10 ;
        printf("%d ", aValue[n].data) ;
    }
    printf("\n") ;

    // 연산자 오버로딩을 이용한 연산
    parallel_sort(aValue, aValue + 10 ) ;

    for (int n = 0  ; n < 10 ; ++n )
    {
        printf("%d ", aValue[n].data) ;
    }
    printf("\n") ;

    // 이번엔 람다를 이용해서 정렬
    parallel_sort(aValue, aValue + 10,
        [](const CNObject &t1, const CNObject &t2)->bool
    {
        return (t1.data > t2.data);
    }) ;

    for (int n = 0  ; n < 10 ; ++n )
    {
        printf("%d ", aValue[n].data) ;
    }
    printf("\n") ;

    getchar() ;
    return 0;
}


'C++ > Intell C++' 카테고리의 다른 글

간단한 TBB parallel_for 예제  (0) 2014.09.16
간단한 TBB parallel_reduce 예제  (0) 2014.09.16
간단한 TBB parallel_while 예제  (0) 2014.09.16
간단한 TBB parallel_invoke 예제  (1) 2014.09.16

여러 루틴이 순서와 상관 없이 병렬로 실행되게 하고 싶을때 사용을 한다.

 

parallel_invoke 루틴은 반환할때는 모든 처리 루틴이 전부 동작되고 난 다음에야 리턴이 된다.

 

총 9개 까지 람다식 및 functor가 등록 될 수 있다.

 

 

[-] Collapse
#include <stdio.h>
#include <tchar.h>
#include <time.h>
#include <tbb/tbb.h>

#ifdef _DEBUG
#pragma  comment(lib, "tbb_debug.lib")
#else
#pragma  comment(lib, "tbb.lib")
#endif // _DEBUG

using namespace tbb ;



int _tmain(int argc, _TCHAR* argv[])
{
    task_scheduler_init init ;
    parallel_invoke(
        []() -> void
    {
        ::Sleep(1000);
        ::printf("finish : %d\n", 1000);
    },
        []() -> void
    {
        ::Sleep(10000);
        ::printf("finish : %d\n", 10000);
    }) ;

    printf("모든 작업 종료 \n") ;

    getchar() ;
    return 0;
}

'C++ > Intell C++' 카테고리의 다른 글

간단한 TBB parallel_for 예제  (0) 2014.09.16
간단한 TBB parallel_reduce 예제  (0) 2014.09.16
간단한 TBB parallel_while 예제  (0) 2014.09.16
간단한 TBB parallel_sort 예제  (0) 2014.09.16

+ Recent posts