'전체'에 해당되는 글 8건

  1. 2012.05.10 다양한 형태의 생성자를 사용하여 인스턴스 생성이 가능한 MetaClass 구현 by 1stPasa
  2. 2009.08.08 POD(Plain Old Data) & Non POD by 1stPasa (1)
  3. 2008.08.12 operator new 와 new operator by 1stPasa
  4. 2008.07.26 SetThreadAffinityMask by 1stPasa
  5. 2008.07.26 Command Pattern - 일반화 구현 by 1stPasa
  6. 2008.06.07 자꾸 까먹는 회전 행렬 by 1stPasa
  7. 2008.05.25 MersenneTwister - Advanced 난수발생기 by 1stPasa
  8. 2008.05.25 CriticalSection Wrapping by 1stPasa

GilGil 님의 글을 보고 영감을 얻어 구현해 보았습니다.

MetaClass 를 이용해 인스턴스 생성시 대상 클래스의 생성자 타입 의존성을 없애려는 시도인데 템플릿이 좀 과한듯도 싶네요.


어찌되었건. 인자가 한개건 두개건( 지금은 최대 2개까지만 구현했습니다 ) 혹은 디폴트생성자건 마음대로 골라서

메타클래스에게 클래스 생성을 위임할수 있도록 구현하는데 목적을 두었습니다

일반적인 팩토리 패턴의 구현과는 다소 다른데요.. 설명하자니 길어서 우선 소스부터 적어버려야 겠네요

struct Point
{
 int x;
 int y;
};   class Shape
{
public:
 virtual void Draw() = 0;
};   class Circle : public Shape
{
 public:
  Circle(){printf("Circle Def\n");}
  Circle(bool visible){}
  Circle(Point,int){}
  Circle(Point,Point){printf("Circle Two pts\n");}
  virtual void Draw(){}
};   class Ellipse : public Shape
{
 public:
  Ellipse(){printf("Ellipse Def\n");}
  Ellipse(bool visible){}
  Ellipse(Point,int){}
  Ellipse(Point,Point){printf("Ellipse Two pts\n");}
  virtual void Draw(){}
};   class Triangle : public Shape
{
 public:
  Triangle(){printf("Triangle Def\n");}
  Triangle(bool visible){}
  Triangle(Point,Point,Point){}
  virtual void Draw(){}
};   class Rectangle : public Shape
{
 public:
  Rectangle(){printf("Rectangle Def\n");}
  Rectangle(bool visible){}
  Rectangle(Point,Point){printf("Rectangle Two pts\n");}
  virtual void Draw(){}
};


이런 클래스 들이 있다고 가정했을때

아래와 같이 이용할 수 있습니다.


typedef Constructor<> DefaultConstructor;
typedef Constructor<bool> BooleanConstructor;
typedef Constructor<Point,Point> TwoPointConstructor;   typedef DefaultConstructor::MetaClassList DefMetaList;
typedef TwoPointConstructor::MetaClassList TwoPtsMetaList;   REGISTER_METACLASS( Circle, Shape, DefaultConstructor )
REGISTER_METACLASS( Ellipse, Shape, DefaultConstructor )
REGISTER_METACLASS( Triangle, Shape, DefaultConstructor )
REGISTER_METACLASS( Rectangle, Shape, DefaultConstructor )   REGISTER_METACLASS( Circle, Shape, TwoPointConstructor )
REGISTER_METACLASS( Ellipse, Shape, TwoPointConstructor )
REGISTER_METACLASS( Rectangle, Shape, TwoPointConstructor )
 
int main()
{
 int i;    DefMetaList *def_ml = VMetaClassMap::getMetaClassList<DefaultConstructor>("Shape");
 TwoPtsMetaList *two_ml = VMetaClassMap::getMetaClassList<TwoPointConstructor>("Shape");    if( def_ml )
 {
  DefMetaList::iterator it;
  for(it = def_ml->begin() ; it != def_ml->end(); it++)
   Shape *sh = (Shape*)(*it)->getFactory()->construct();
 }
  
 if( two_ml )
 {
  TwoPtsMetaList::iterator it;
  Point pt;     for(it = two_ml->begin() ; it != two_ml->end(); it++)
   Shape *sh = (Shape*)(*it)->getFactory()->construct(pt,pt);
 }  
 return 0;
}

템플릿 클래스를 사용하기 때문에 사실 카테고리도 "Shape" 와 같은 문자열이 아니라 실제 타입 단위로 지정할 수 있지만

굳이 그렇게 구현하지는 않았습니다. (그런데 글을 쓰면서 보니 그것도 상당히 좋은 기능이라는 생각이 드네요.. ^^; )


또한, 생성자의 매개변수를 템플릿 인자로 받는 Constructor 가 구분자(?) 처럼 사용되기 때문에

예제에서 보인 클래스들 처럼 부모가 같은 클래스가 아니어도 하나의 카테고리로 묶어버릴수 있다는 장점이 있죠.

서로 전혀 상관이 없는 클래스들 일 지라도 단순히 같은 형태의 생성자만 보유하고 있다면

같은 카테고리로 묶어두었다가 리스팅 하고, 인스턴스를 생성할 수 있습니다.


몇년전에 작성했던 Functor 를 기반으로 팩토리 패턴을 나름 확장하고

나름 의미있다고 생각했던 문자열 기반 categorization 정도만 구현한 코드라고 할 수 있겠네요

재미삼에 업무시간에 짬짬히 한거라... 코드가 영 깔끔치 못해도 아이디어 공유차원의 코드니까 이해해 주세용


DeligatingConstruct.tar


아 참고로 g++ version 4.4.3 을 이용했습니다

Posted by 1stPasa

댓글을 달아 주세요


Plain Old Data(POD)

C의 struct나 built-in-type 과 동일한 메모리 구조를 갖는 object를 의미.
memset, memcpy에 의한 단순 메모리 복사가 가능한 메모리 구조를 갖는다.
POD 의 조건은 다음과 같다

1. built-in type
2. 가상 함수가 없고 사용자 정의 할당자와 소멸자를 가지지 않은 class의  object
3. non POD를 non-static 멤버로 가지지 않은 class의 object

가상함수가 존재할경우 추가정보가 필요하므로 Non POD 임이 명백하지만
할당자와 소멸자를 갖는 Class 의 경우 할당자와 소멸자의 존재 자체가 메모리 구조를 바꿀이유는 없다
하지만 할당자와 소멸자의 경우

class NPOD
    {
    int x_;
    char* buf_;

    NPOD() : buf_(0) {}
    ~NPOD() { delete buf_; }
    NPOD& operator=(const NPOD& other)
        {
        x_ = other.x_;
        int bufLen = strlen(other.buf_);
        buf_ = new char[bufLen+1];
        memcpy(buf_, other.buf_, bufLen);
        }
    }

NPOD t1, t2;
...
t1 = t2;
memcpy(&t1, &t2);



위와 같은 경우 memcpy 의 결과가 t1=t2 의 결과와 같지 않게 된다.
따라서 규격에서는 할당자와 소멸자가 유저에 의해 정의되어있는 Class 는 Non POD 로 정의한다.

마지막으로 static 멤버의 경우 object에 포함되는것이 아니기 때문에 Non POD 이건 POD 이건 상관이 없다.
따라서 POD가 되려면 non static 멤버로는 POD만을 가져야만 한다.


출처
http://gpgstudy.com/forum/viewtopic.php?t=10148&view=previous

Posted by 1stPasa

댓글을 달아 주세요

  1. Richardml 2014.12.24 05:37  댓글주소  댓글쓰기 수정/삭제

    이용약관위배로 관리자 삭제된 댓글입니다.

Widget *w = new Widget();

위와같이 클래스를 동적할당하면 C++은 두단계를 거쳐서 Widget의 인스턴스를 만들어 낸다.

우선 operator new 를 거쳐 메모리를 allocation 하는 작업이 선행되는데

코드를 살펴보면 단순히 malloc 을 사용해 메모리를 할당만 해줄 뿐이다.

사용자는 이 operator new 를 오버로딩 함으로써 특정 타입의 메모리 allocation을 컨트롤 할수 있다.

하지만 이대로는 Widget의 생성자가 호출이 되지 않은, 쓰레기만 차있는 메모리일 뿐인데

이 공간에 의미를 부여해주는것이 ( 그래봤자 생성자를 호출해줄 뿐. )

new operator 의 역할이다.


new operator는 건네받은 메모리 공간을 this 포인터로 밀어넣고

생성자를 호출해줌으로써 클래스 구실을 할수 있도록 만들어준다.

생성자 역시 하나의 ( this call type 의 )멤버 함수이므로  메모리에

인스턴스화 되지 않은채로는 호출할 방도가 없다.


Widget::Widget() 이런식으로 호출할수도 없는노릇이니..

생성자를 호출해주고 사용가능한 메모리 공간으로 만들어주는것은 인라인 어셈을 쓰지 않고서는

언뜻 c++ 문법만으로는 불가능해 보인다

하지만 아래와 같이 가능하다

new ( (void*) ptr ) Widget( );


위의 코드는 ptr 이 가리키는 메모리 공간을 필두로 Widget 클래스의 생성자를 호출해준다.

생성자의 인수에 따라 복사생성자를 포함한 어떠한 생성자도 호출이 가능하다

위의 코드를 디스어셈블리 해보면 operator new 가 한번 호출되는것을 확인할수 있는데.

그때의 operator new는 메모리를 할당하는것이 아니고 단지 전달받은 ptr을 돌려주기만 할 뿐이다.

그냥, 아무 하는일 없는 operator new가 한번 호출된다고 생각하면 된다.

Posted by 1stPasa

댓글을 달아 주세요

Thread Handle을 인수로 받아 특정 코어에서 해당 Thread를 실행하도록 지정해주는 함수.

0x01 부터 순서대로 한비트씩 쉬프트 하면 원하는 코어를 결정할수 있다.

주의할점은 하나의 Thread는 여러개의 코어가 모두 실행시킬수 있는데

만약 첫번째 코어와 두번째 코어가 모두 실행 가능하도록 설정하고 싶다면

01 과 10 의 OR 연산결과값인 0x03 을 설정하면 되는것이다.

만약 코어 1,2,3 에서 실행가능하게 하고 싶다면

001 , 010  그리고 100 를 OR 연산하여 호출해주면 된다.


아래의 코드는

SetThreadAffinityMask 를 테스트해보는 예제인데

주석처리된 부분을 그대로 두고 실행하면 재미있는 결과를 얻을수 있다.

실행하면 Core의 수를 출력한뒤 코어의 갯수에 해당하는 Thread를 생성하고

무한루프를 돌려서 CPU 점유율을 100%로 만들어 버린다.

그리고 콘솔창에서 숫자키 1~9까지의 숫자를 사용해 원하는 번호의 Thread를 정상종료

시킬수 있는데. 만약 듀얼코어에서 쓰레드 하나만 죽인다면 50%의 점유율을 차지하게 될것은

당연한 이치이지만. SetThreadAffinityMask 를 사용하지 않았을 경우와 사용했을 경우의

점유율 그래프를 본다면 이마를 탁 치게 될것이다. ( 벌써 알고 계셨다면.. 굳ㅋ )

#include <iostream>
#include <conio.h>
#include <windows.h>


using namespace std;

DWORD WINAPI ThreadProc(LPVOID arg)
{
 while( *((bool*)(arg))  )Sleep(0);

 return 0;
}

int main(int argc, char argv[])
{
 SYSTEM_INFO info;
 GetSystemInfo(&info);

 cout << info.dwNumberOfProcessors << endl;

 bool *flag = new bool[ info.dwNumberOfProcessors ];

 HANDLE *hTrhead = new HANDLE[info.dwNumberOfProcessors];

 for(int i = 0 ; i < info.dwNumberOfProcessors ; i++ )
 {
  flag[i] = true;
  hTrhead[i] = CreateThread(0,0,ThreadProc,&flag[i],0,0);
  //SetThreadAffinityMask( hTrhead[i]  , 1 << i );
 }


 char c;
 while(1)
 {
  c = getch();

  if( c >= '1' && c <= '9' )
   flag[ c-'1' ] = false;

  if( c == 13 )
   break;
 }

 return 0;
}

사용자 삽입 이미지

사용자 삽입 이미지

사용자 삽입 이미지


가운데 있는 사진이 SetThreadAffinityMask 를 사용하지 않아서

코어가 쓰레드의 삽질을 같이 보듬어주고 있는경우고

아래의 사진은 SetThreadAffinityMask를 통해 하나의 코어가 하나의 쓰레드만 담당하여

2번째 쓰레드를 죽이고나니 개미와 베짱이를 연출시킨 상황이다.


Posted by 1stPasa

댓글을 달아 주세요

커맨드 패턴을 Function 과 Method 에 대해 일반화 하고

인수타입과 리턴타입에 대해서도 일반화 하였다.

한글이름도 어려운 명시적 템플릿 구체화까지 써가면서도

인수타입이 void 인경우에 대해 NoArg란 이름을 붙여 따로 정의할수밖에 없었던 이유는

생각지 못했던 Ambigious 문제가 발생했기 때문이다. ( 겪고보니 당연한 일이었지만.. )

결국 클래스의 종류는

Command ( 상위 클래스 )
MethodCommand, MethodCommandNoArg
FunctionCommand, FunctionCommandNoArg

다섯가지나 된다.. 사용할때 올바른 인스턴스를 만들어주는게 번거로우므로

MakeCommand 란 함수를 만들었는데 이것역시 템플릿 함수임에도 불구하고 4가지 버전이나 된다.

그놈의 void가 문제지.. return type 으로도 안되고 Argument로 넣을수도 없으니 별도로 구체화 시킬수밖에..ㅋ

아래는 그렇게 구현한 Command 패턴들과 MakeCommand 코드이다.

#pragma once
template <typename _A, typename _R>
class Command
{
public:
 virtual _R Fire(_A) = 0;
};

template<typename _T, typename _A, typename _R>
class MethodCommand : public Command<_A,_R>
{
 _T *m_obj;
 _R (_T::*m_mf)(_A);
public:
 MethodCommand(_T * object, _R (_T::*method)(_A)) : m_obj(object), m_mf(method) {}
 virtual inline _R Fire(_A arg){ return (m_obj->*m_mf)(arg);}
};

template<typename _T, typename _A>
class MethodCommand<_T,_A,void> : public Command<_A,void>
{
 _T *m_obj;
 void (_T::*m_mf)(_A);
public:
 MethodCommand(_T * object, void (_T::*method)(_A)) : m_obj(object), m_mf(method) {}
 virtual inline void Fire(_A arg){(m_obj->*m_mf)(arg);}
};

template <typename _T, typename _R>
class MethodCommandNoArg : public Command<void,_R>
{
 _T *m_obj;
 _R (_T::*m_mf)();
public:
 MethodCommandNoArg(_T * object, _R (_T::*method)()) : m_obj(object), m_mf(method) {}
 virtual inline _R Fire(void){ return (m_obj->*m_mf)();}
};

template <typename _T>
class MethodCommandNoArg<_T,void> : public Command<void,void>
{
 _T *m_obj;
 void (_T::*m_mf)();
public:
 MethodCommandNoArg(_T * object, void (_T::*method)()) : m_obj(object), m_mf(method) {}
 virtual inline void Fire(void){ (m_obj->*m_mf)();}
};

template <typename _A,typename _R>
class FunctionCommand : public Command<_A,_R>
{
 _R (*m_mf)(_A);
public:
 FunctionCommand(_R (*func)(_A)) : m_mf(func){}
 virtual inline _R Fire(_A arg){ return (*m_mf)(arg); }
};

template <typename _A>
class FunctionCommand<_A,void> : public Command<_A,void>
{
 void (*m_mf)(_A);
public:
 FunctionCommand(void (*func)(_A)) : m_mf(func){}
 virtual inline void Fire(_A arg){ (*m_mf)(arg); }
};

template <typename _R>
class FunctionCommandNoArg : public Command<void,_R>
{
 _R (*m_mf)(void);
public:
 FunctionCommandNoArg(_R (*func)(void)) : m_mf(func){}
 virtual inline _R Fire(void){ return (*m_mf)(); }
};

template <>
class FunctionCommandNoArg<void> : public Command<void,void>
{
 void (*m_mf)(void);
public:
 FunctionCommandNoArg(void (*func)(void) ) : m_mf(func){}
 virtual inline void Fire(void){ (*m_mf)(); }
};

template <typename _T, typename _A, typename _R>
Command<_A,_R>* MakeCommand( _T *target, _R (_T::*method)(_A) )
{
 return new MethodCommand<_T,_A,_R>( target, method );
}

template <typename _T, typename _R>
Command<void,_R>* MakeCommand( _T *target,  _R (_T::*method)(void) )
{
 return new MethodCommandNoArg<_T,_R>( target, method );
}

template <typename _A, typename _R>
Command<_A,_R>* MakeCommand( _R (*function)(_A) )
{
 return new FunctionCommand<_A,_R>( function );
}

template < typename _R>
Command<void,_R>* MakeCommand(_R (*function)(void) )
{
 return new FunctionCommandNoArg<_R>( function );
}

Command<_A , _R>  
-  _A : 인수 타입
-  _R : 반환 타입

간단하게 시작했는데 100줄을 넘겨버렸다.. ㅎㅎ

아래는 예제코드로서

void 와 void가 아닌 타입들을 대입할수 있다고 생각하면 되겠다.

위에서 말한것과 같이 void 의 경우 return 타입으로 쓸수 없기 때문에

return func1(); 과 같은 형태로 사용할수도 없고.

func1( arg ); 와 같은형태로 인수로 넣을수도 없다.

#include "Command.h"
#include <iostream>
using namespace std;

class MyClass
{
public:
 void method1()
 {
  cout << "void Method(void)" << endl;
 }

 int method2(int a)
 {
  cout << "int Method(int)" << endl;
  return a;
 }

 int method3(void* a)
 {
  cout << "int Method(void*)" << endl;
  return 10;
 }

 void method4(int a)
 {
  cout << "void Method(int)" << endl;
 }
};

void func1()
{
 cout << "void function(void)" << endl;
}

int func2(int a)
{
 cout << "int function(int)" << endl;
 return a;
}

int func3(void* a)
{
 cout << "int function(void*)" << endl;
 return 10;
}

void func4(int a)
{
 cout << "void function(int)" << endl;
}


int main(int argc, char* argv[])
{
 MyClass a;

 Command<void,void> *m1 = MakeCommand(&a, &MyClass::method1 );
 Command<int,int> *m2 = MakeCommand(&a, &MyClass::method2 );
 Command<void*,int> *m3 = MakeCommand(&a, &MyClass::method3 );
 Command<int,void> *m4 = MakeCommand(&a, &MyClass::method4 );
 
 Command<void,void> *f1 = MakeCommand(func1);
 Command<int,int> *f2 = MakeCommand(func2);
 Command<void*,int> *f3 = MakeCommand(func3);
 Command<int,void> *f4 = MakeCommand(func4);
 
 m1->Fire();
 m2->Fire(10);
 m3->Fire(NULL);
 m4->Fire(10);

 f1->Fire();
 f2->Fire(10);
 f3->Fire(NULL);
 f4->Fire(10);

 return 0;
}

생각같아선 C#의 델리게이트처럼 인수의 갯수도 일반화 시켜버리고 싶지만..

아무리 생각해도 인라인어셈을 동원하지 않고는 구현이 불가능한것 같다.

그렇게되면 컴파일타임 에러체크가 안되므로 패스하고

결국 이쯤에서 마무리를 짓는것이 좋을듯.
Posted by 1stPasa

댓글을 달아 주세요

사용자 삽입 이미지
Posted by 1stPasa

댓글을 달아 주세요

Game Programming Gems 4권에 나오는 난수발생기 이다.

본문에 따르면 c의 rand 함수보다 빠르고 주기가 길다( 반복이 일어나기까지 2^19937 - 1 )

따라서 무작위성이 보장되고 아울러 64비트로의 확장도 용이하다

하물며 c의 rand 함수는 16비트밖에 안되기때문에

rand 함수보다는 훨씬 유용하다 할만하다.


코드상에 있는 무지막지한 배열은 seed 정도로 보면 되는데

저부분에 들어갈 값을 srand() + rand() 조합으로 넣어주면

더욱 훌륭한 난수발생기가 될수 있겠다.

아래의 코드는 MT 부분만 따온것.

클래스 생성하고 Rand() 혹은 Rand64() 함수만 호출하면 된다.

의외로 기능에 비해 동작 원리랄건 별것 없지만 자세한 내용은 책에..ㅋㅋ

#include <iostream>
#include <cassert>
// Specialized templates to compute powers of two at compile time
// (template metaprogramming)
template<int N>
struct Pow2
{
    enum { value = 2 * Pow2<N - 1>::value };
};
template<>
struct Pow2<0>
{
    enum { value = 1 };
};
template<int N>
struct Pow2Minus1
{
    enum { value = Pow2<N - 1>::value - 1 + Pow2<N - 1>::value };
};
// This is defined in C99, but not C++ yet (June 2003)
typedef unsigned long uint32_t;
#if defined(_WIN32)
typedef unsigned __int64 uint64_t;
#elif defined (__GNUC__)
typedef unsigned long long uint64_t;
#endif
// Parameters for MT19937
// See Matsumoto for definition of parameters, and
// alternate parameters for different k-distributions.
static const int      MT_W = 32;            // word size
static const int      MT_N = 624;           // degree of recursion
static const int      MT_M = 397;           // middle term
static const int      MT_R = 31;            // separation point of one word
static const uint32_t MT_A = 0x9908b0df;    // vector parameter a (matrix A)
static const int      MT_U = 11;            // integer parameter u
static const int      MT_S = 7;             // integer parameter s
static const uint32_t MT_B = 0x9d2c5680;    // vector parameter b
static const int      MT_T = 15;            // integer parameter t
static const uint32_t MT_C = 0xefc60000;    // vector parameter c
static const int      MT_L = 18;            // integer parameter l
// Autogenerate the masks based on the R parameter. All of the
// proposed MT parameters have a 32-bit word size, so I assume that.
static const uint32_t MT_LLMASK = Pow2Minus1<MT_R>::value;
static const uint32_t MT_UMASK  = 0xffffffff - Pow2Minus1<MT_R>::value;
// All values for the array are fine initial seed choices, except for
// an array of all zeros.
static uint32_t s_aMT[MT_N] = {
       2,    3,    5,    7,   11,   13,   17,   19,   23,   29,
      31,   37,   41,   43,   47,   53,   59,   61,   67,   71,
      73,   79,   83,   89,   97,  101,  103,  107,  109,  113,
     127,  131,  137,  139,  149,  151,  157,  163,  167,  173,
     179,  181,  191,  193,  197,  199,  211,  223,  227,  229,
     233,  239,  241,  251,  257,  263,  269,  271,  277,  281,
     283,  293,  307,  311,  313,  317,  331,  337,  347,  349,
     353,  359,  367,  373,  379,  383,  389,  397,  401,  409,
     419,  421,  431,  433,  439,  443,  449,  457,  461,  463,
     467,  479,  487,  491,  499,  503,  509,  521,  523,  541,
     547,  557,  563,  569,  571,  577,  587,  593,  599,  601,
     607,  613,  617,  619,  631,  641,  643,  647,  653,  659,
     661,  673,  677,  683,  691,  701,  709,  719,  727,  733,
     739,  743,  751,  757,  761,  769,  773,  787,  797,  809,
     811,  821,  823,  827,  829,  839,  853,  857,  859,  863,
     877,  881,  883,  887,  907,  911,  919,  929,  937,  941,
     947,  953,  967,  971,  977,  983,  991,  997, 1009, 1013,
    1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
    1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
    1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
    1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
    1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
    1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
    1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
    1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583,
    1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657,
    1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
    1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
    1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889,
    1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987,
    1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053,
    2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129,
    2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213,
    2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287,
    2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357,
    2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
    2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531,
    2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617,
    2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687,
    2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741,
    2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819,
    2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
    2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
    3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079,
    3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181,
    3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257,
    3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331,
    3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413,
    3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511,
    3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571,
    3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643,
    3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727,
    3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821,
    3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907,
    3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989,
    4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057,
    4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139,
    4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231,
    4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297,
    4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409,
    4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493,
    4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583,
    4591, 4597, 4603, 4621
};
class MersenneTwister
{
    int m_ix;     void Regenerate(); public:
    MersenneTwister();     uint32_t Rand();
    uint64_t Rand64();
};
void MersenneTwister::Regenerate()
{
    // NOTE: this should be unrolled in an optimized version
    // to eliminate the modulus operator.
    for(int kk = 0; kk < MT_N; kk++)
    {
        uint32_t ui = (s_aMT[kk] & MT_UMASK) | (s_aMT[(kk + 1) % MT_N] & MT_LLMASK);
        s_aMT[kk] = s_aMT[(kk + MT_M) % MT_N] ^ (ui >> 1) ^ ((ui & 0x00000001) ? MT_A : 0);
    }
}
MersenneTwister::MersenneTwister() :
    m_ix(0)
{
    // s_aMT is already initialized with the first N primes.
    Regenerate();
}
uint32_t MersenneTwister::Rand()
{
    if (m_ix == MT_N)
    {
        m_ix = 0;         Regenerate();
    }     uint32_t y;
    y = s_aMT[m_ix++];
    y ^= y >> MT_U;
    y ^= y << MT_S & MT_B;
    y ^= y << MT_T & MT_C;
    y ^= y >> MT_L;     return y;
}
uint64_t MersenneTwister::Rand64()
{
    uint64_t ui64;     ui64 = Rand();
    ui64 <<= 32;
    ui64 |= Rand();     return ui64;
}
Posted by 1stPasa

댓글을 달아 주세요

class critical_section
{
  public:
        critical_section() { InitializeCriticalSection(&m_cs);}
        ~critical_section() { DeleteCriticalSection(&m_cs);}

        void enter() { EnterCriticalSection(&m_cs);}
        void leave() { LeaveCriticalSection(&m_cs);}

  private:
        CRITICAL_SECTION m_cs; };


Ambulant 라는 오픈소스 프로그램에서 사용하던 크리티컬 섹션 래퍼 코드.

10줄남짓의 코드를 짜는것조차 귀찮아서 그대로 긁어왔음..

인라인처리 될테니 오버헤드도 없고

귀차니스트에겐 최고의 선물입니다ㅋㅋ
Posted by 1stPasa

댓글을 달아 주세요