C++ Native AOP의 가능성.

Aspected Oriented Programming(AOP)을 가장 잘 지원하고 있는 언어를 꼽으라면, 숨도 쉬지않고 Java를 선택할 수 있겠다. Java의 경우에는 주로, VM코드를 직접 수정하는 방식으로 구현하는 모양인데, C++에서 기계어를 고치고 있을 수는 없는 것 아닌가.. 상상만 해도 우울하다.

그렇다고 해서 C++에서 AOP를 포기할 수는 없는 노릇! 고민을 해보았다.

생각해보니, AOP의 가장 큰 개념concept은 실행중인 로직과 수직이 되는 코드를 삽입하는 것이다. 즉, AspectJ에서 이야기하는 pointcut(그중에서도 특히 함수가 실행되기 전의 point인 before와 함수 실행 후인 after)이 가장 큰 개념이라고 보여진다.

그렇다면! C++에서도 로직의 중간에 어떤 코드를 강제로 삽입할 수 있으면 되는 것 아닌가? 라는 생각이 들었다. 하지만, 애석하게도 C++에서 코드를 삽입할 방법은 보이지 않았다. 물론, Macro와 Preprocesor를 과도하게 사용하면 가능하겠지만, 이는 C++의 순수성을 훼손하는 일이라 생각되므로 일단 제외하였다.

그러던 찰나, 다음과 같은 코드가 눈에 들어왔다.

{
    SpinLock::guard g(info_set_guard_);
    info_set_.insert(data);
}

그때 디버깅 하던 코드에서 사용하던 부분인데, info_set_의 멀티쓰레딩 안정성을 위해 SpinLock을 guard를 이용해 블럭내에서 자동으로 획득acquire/해제release를 해주는 코드다. 물론, 명시적으로 획득/해제를 해주는 코드는 없다! guard에 의해 자동으로 수행된다. 자동으로.

“Eureka!”

라고 외치고, 담배를 한대 피워물며 고민해보았다. guard를 잘 사용하면, 특정 코드 블럭에 대해서 AOP(혹은 그와 유사한 무엇)을 적용할 수 있지 않을까? 라는 생각.

다음과 같이 말이다.


class logging_guard
{
public:
logging_guard(const char* block_name)
: block_(block_name)
{
std::cout << "entering block = " << block_ << std::endl; } ~logging_guard() { std::cout << "leaving block = " << block_ << std::endl; } private: const char* block_; }; void test() { logging_guard lg("test()"); std::cout << "running test" << std::endl; } [/cpp] 확실히 이런 식으로 작성하면 block에 대한 수직적 코드 삽입이 가능해진다. 하지만, 이런 방식은 코드를 삽입할 point와 삽입할 코드가 명확히 구분되지 않는다는 점에서 좀 모자라다. 그렇다면, tagging 기법을 적용해보자. [cpp] class test_tag{}; template
class cut
{
public:
void before(const char* block)
{
}
void after(const char* block)
{
}
};

template<>
class cut
{
public:
void before(const char* block)
{
std::cout << "entering block = " << block << std::endl; } void after(const char* block) { std::cout << "leaving block = " << block << std::endl; } }; template
class cut_guard
{
public:
cut_guard(const char* block_name)
: block_(block_name)
{
cut().before(block_);
}
~cut_guard()
{
cut().after(block_);
}
private:
const char* block_;
};

void test()
{
cut_guard cg(“test()”);
std::cout << "running test" << std::endl; } [/cpp] 이러면(이런 개념을 이용하면), cut_guard부분에 삽입할 코드는 cut가 되고, 사용자가 정의하지 않았다면, 자연스럽게 아무 일도 하지 않는 코드를 생성하게 되므로 금상첨화다. 다만, cut_guard의 인스턴스 선언을 삽입할 부분에 타이핑 쳐야한다는 부담은 있지만 말이다.

물론, 위의 경우는 해당 포인트에 한종류의 코드만 넣을 수 있다는 엄청난 단점이 존재한다. 그리고, 각 포인트에서 인수parameter를 넘길 수도 없다. 이런 문제는 singleton, boost::mpl, boost::preprocessor를 사용하면 쉽게 해결할 수 있다. 이 해결책들은 Flowcut!의 소개글이 될지도 모르는 다음 글에 나올 예정이다. 🙂

to be continued…

글쓴이: crowmania

Chief Developer in Somansa Guitar/Vocal in Tonics Member of Justice Party

“C++ Native AOP의 가능성.”의 4개의 생각

  1. RAII를 가지고 뭔가 만드셨군요. AOP를 공부한 적이 없는데 이번 기회에 좀 해야겠네요. 🙂

    Flowcut! 소개 글 빨리 올려주세요~ @_@

  2. java 에서건 c++ 에서건 제가 테스트해본것으로는 새로운 소스 코드를 생성해서 컴파일 하는 것으로 보였습니다. (로그가 그렇게 나와요.. 코드생성… 컴파일… 식으로.. )

    AOP 를 스터디하고 느낀건…
    모든 부분에서는 아니고 적정한 부분에서는 굉장한 방법이 될 수 있겠다는 생각…
    실제로 디버깅이 어케될까는 젤 큰 궁금점이였습니다. -.-;;

  3. iwongu//
    네. RAII를 가지고 뭔가 이상한걸 만들어버렸습니다. 🙂

    문제는, mpl을 이해하지 못하면 상당히 어려운 코드가 되어버리는 녀석이 있어서, 이걸 어찌 쉽게 설명하나 고민중이네요. 🙂

    zoops//
    Source to Source컴파일 방식이죠. 하지만, Source to Source방식은 범용IDE에 적용하는게 꽤나 까다로워지고 이리저리 귀찮아서…

    아마 Flowcut!의 디버깅은 일반 c++디버깅과 별 차이가 없을걸로 생각합니다. (별도로 컴파일을 안하거든요! 우훗!)

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다