본문 바로가기

카테고리 없음

IStaticPage

가끔씩 정적인 형태의 데이터 처리가 필요할때가 있다.

예를 들어, 어떠한 프로그램(프로세서)에서는 데이터를 기록하는 역활을 하고
다른 프로그램(프로세서)는 기록된 데이터를 조회하고 데이터를 갱신할 필요가 있는 경우...

어떤 분들은 "그냥 공유메모리 만들어서 사용하면 안되나?"
하실지도 모른다..

물론 맞는 말이다..

그런데 내가 위와 같은 처리가 필요하게 된 경우에는 조건이 있었다.
   1. 조회를 하는 프로세서 입장에서 가능 빠른 조회가 가능해야 한다.
   2. 갱신할 경우 데이터의 안정성이 보장되어야 한다.
      : 즉, 기록하는 프로그램(프로세서)에서 새로운 신규 데이터를 추가/삭제시 
        다른 프로그램(프로세서)에 안정성 보장해야 한다.
   3. 저장 데이터에 구조체 또는 변수형태로 바로 접근하고 싶다.
   4. lock-free형태를 원한다.
   5. template 형태이었으면 한다.
   6. 검색이 필요한 경우 STL의 iterator와 같은 방식을 사용하고 싶다.

이 조건을 만족시킬수 있는 여러 방식을 생각해 봤다. 마땅히 위의 조건을 충분히 충족시킬수 있는 대안이 없었다.

일반적으로 데이터를 관리하기 위해서, 데이터베이스나 b+tree와 같은 isam형태를 많이 사용하는데
데이터 관리적인 면에서는 효율적이고 여러조건에 만족스러운데.. 문제는 데이터를 직접 조작하지 못하고
사용하는데 복잡하다는 것이었다.. 또한 데이터의 정확성을 위해 lock 처리가 들어가게 되면 필요이상으로
느려진다는 것이었다.

나는 단순한 처리를 하기원했다..  그러면서.. 효율적이길 원했다...


다음은 예제이다..

struct NamePolicy {
   char name[40];
   int    count;
};

bool NamePolicyCompare( const NamePolicy &__x, const NamePolicy &__y) {
     return strcmp( __x.name, __y.name) < 0;
}

IStaticPage<NamePolicy, NamePolicyCompare> NameStaticPage;
...
NameStaticPage::build( 1024, pShareMemoryPtr, maxShareMemory);
NameStaticPage page(pShareMemoryPtr, maxShareMemory);

NamePolicy _i; strcpy( _i.name, "test");
page[_i].count = 12;
...
// 항목을 찾습니다.
NameStaticPage::iterator it = page.find( _i); // 항목을 찾는다.
if (it != page.end())
{
   it->count++;
}

it = page.append(_i, 1024);
strcpy( (char *)((*it) + 1), "1024 만큼의 버퍼 공간이 추가로 존재합니다.");

 page.commit(); // 다른 프로세서에서 접근가능하도록 기록한다.

// 동시에 여러 항목을 찾습니다.
std::pair<NameStaticPage::iterator, NameStaticPage::iterator> r = page.equal_range( _i);
for (; r.first != r.second; r.first++)
{
   fprintf( stderr, " name: '%s' - %d\n", r.first->name, r.first->count);
}

// 저장된 모든 항목을 얻는다.
for (it = page.begin(); it != page.end(); it++)
   if (it.valid())
   {
      fprintf( stderr, " name: '%s' - %d\n", it->name, it->count);
   }

위의 예는 간략해 보이지만, 
page에 저장된 모든 데이터는 공유메모리에 적재되고 다른 프로세서에서 위와 같은 방식으로
접근이 가능하다.. 또한, 데이터에 직접 접근가능하다..