/* A C-program for MT19937: Integer     version                   */
/*  genrand() generates one pseudorandom unsigned integer (32bit) */
/* which is uniformly distributed among 0 to 2^32-1  for each     */
/* call. sgenrand(seed) set initial values to the working area    */
/* of 624 words. Before genrand(), sgenrand(seed) must be         */
/* called once. (seed is any 32-bit integer except for 0).        */
/*   Coded by Takuji Nishimura, considering the suggestions by    */
/* Topher Cooper and Marc Rieffel in July-Aug. 1997.              */

/* This library is free software; you can redistribute it and/or   */
/* modify it under the terms of the GNU Library General Public     */
/* License as published by the Free Software Foundation; either    */
/* version 2 of the License, or (at your option) any later         */
/* version.                                                        */
/* This library is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of  */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.            */
/* See the GNU Library General Public License for more details.    */
/* You should have received a copy of the GNU Library General      */
/* Public License along with this library; if not, write to the    */
/* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   */
/* 02111-1307  USA                                                 */

/* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura.       */
/* Any feedback is very welcome. For any question, comments,       */
/* see http://www.math.keio.ac.jp/matumoto/emt.html or email       */
/* matumoto@math.keio.ac.jp                                        */

#include<stdio.h>

/* Period parameters */ 
#define N 624
#define M 397
#define MATRIX_A 0x9908b0df   /* constant vector a */
#define UPPER_MASK 0x80000000 /* most significant w-r bits */
#define LOWER_MASK 0x7fffffff /* least significant r bits */

/* Tempering parameters */  
#define TEMPERING_MASK_B 0x9d2c5680
#define TEMPERING_MASK_C 0xefc60000
#define TEMPERING_SHIFT_U(y)  (y >> 11)
#define TEMPERING_SHIFT_S(y)  (y << 7)
#define TEMPERING_SHIFT_T(y)  (y << 15)
#define TEMPERING_SHIFT_L(y)  (y >> 18)

static unsigned long mt[N]; /* the array for the state vector  */
static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */

/* initializing the array with a NONZERO seed */
void
sgenrand(seed)
    unsigned long seed; 
{
    /* setting initial seeds to mt[N] using         */
    /* the generator Line 25 of Table 1 in          */
    /* [KNUTH 1981, The Art of Computer Programming */
    /*    Vol. 2 (2nd Ed.), pp102]                  */
    mt[0]= seed & 0xffffffff;
    for (mti=1; mti<N; mti++)
        mt[mti] = (69069 * mt[mti-1]) & 0xffffffff;
}

unsigned long
genrand()
{
    unsigned long y;
    static unsigned long mag01[2]={0x0, MATRIX_A};
    /* mag01[x] = x * MATRIX_A  for x=0,1 */

    if (mti >= N) { /* generate N words at one time */
        int kk;

        if (mti == N+1)   /* if sgenrand() has not been called, */
            sgenrand(4357); /* a default initial seed is used   */

        for (kk=0;kk<N-M;kk++) {
            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
            mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
        }
        for (;kk<N-1;kk++) {
            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
            mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
        }
        y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
        mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];

        mti = 0;
    }
 
    y = mt[mti++];
    y ^= TEMPERING_SHIFT_U(y);
    y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
    y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
    y ^= TEMPERING_SHIFT_L(y);

    return y;
}

/* this main() outputs first 1000 generated numbers  */
main()
{
    int j;

    sgenrand(4357); /* any nonzero integer can be used as a seed */
    for (j=0; j<1000; j++) {
        printf("%12u ", genrand());
        if (j%8==7) printf("\n");
    }
    printf("\n");
}

안정적인 DNS서비스 DNSEver DNS server, DNS service
Posted by 키르히아이스
,

출처 :

http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNo=20&no=4472&ref=1503

 


1. 동기 
- window프로그래밍이나 mfc 프로그래밍을 할 때, 에러나 내부적인 상태를 표현하기 위해서 
  기존의 경우 MessageBox()를 이용했으나 어떤 상태등을 표시하기엔 상당히 귀찮았죠. 
  그래서 마치 자바 처럼 따로 콘솔창을 띄워서 알리고 싶은 사항을 그곳에 표시함으로써 
  프로그램의 디버깅용 창을 따로 띄워 놓는 것입니다. 
   (특히 화면 갱신에 대한 내용등을 처리할 때는 이렇게 하면 상당히 편리 하겠죠)

2. 사용법 
- 1. 클래스를 프로젝트에 포함 
  2. stdafx.h 에 #include "debugconsole.h" 
  3. CONSOLE("화면 갱신했습니다. 지금 값은 %d 입니다.", i);       // 이런 식으로 사용. 

3. 사용된 내용. (단순히 사용이 아니라 좀 더 자세히 알고 싶은 분들만 읽어보시길.. ^_^)
기본적으로는 콘솔을 띄우고, 상태를 표시하는 것이지만 몇가지 내용이 들어갔으니 잘 봐주시길... 

* 콘솔창 띄우기
    AllocConsole();             // 콘솔창 만든다.
    m_hOut = GetStdHandle(STD_OUTPUT_HANDLE);     // 콘솔창의 핸들 가져옴.
    WriteConsole(m_hOut, strBuffer, strlen(strBuffer), &dwWrite, NULL); // 콘솔창에 쓸때
    FreeConsole();              // 콘솔창을 없앰.
이건 몇가지 간단한 api만 알고 계시면 됩니다. ^_^

* singleton (단일체) 
이유 : 프로그래머가 debugconsole 클래스를 위한 객체를 따로 생성하지 않아도 될뿐만 아니라
            전체 프로그램에서 디버깅 콘솔창은 딱 1개만 띄운다는 것을 보장해줌.
코드 : 
        static CDebugConsole& getConsole()     // 해당 클래스 안에 있음. 
        { 
                static CDebugConsole gt; 
                return gt; 
        } 
설명 : 그러니까 매번 젤 위에 CDebugConsole g_console; 이런식으로 전역 변수로 선언하지 않고, 
            헤더만 포함한 후에 쓰기만 하면 되도록 할 수 있도록 하기 위한 것이구요. 
             (프로그램 실행시 자동으로 객체가 생성됩니다.)
            static의 특성을 이용한 것입니다. 
            특히, debugging console 창이 2개가 뜰 순 없기 때문에 단일체의 개념이 맞다고 할 수 있죠. 
            프로그램 안에서 딱 하나만 존재해야 하고, 언제든지 써야 한다면, 단일체를 사용하시구요. 
            제가 쓴 단일체는 제일 기본적인 단일체고 좀 더 다양한 단일체를 쓰고 싶으신 분은 
            More Effective C++ 의 item 26을 참조하시기 바랍니다 ^_^ 
            Game Gems 1에도 있군요. 
             
*  " ... " 키워드의 사용 
이유 : 만약에 그냥 print(char* szMsg)라고 한다면, 표현이 상당히 제한 될 수 있지만, 
            " ... " 을 통해서 print( " 하하 나는 %d 번째 실행됐다. " , i ); 나 %s 등등으로 자유롭게 표시 가능. 
코드 : 
void CDebugConsole::print(TCHAR *tszMsg, ...) 

    TCHAR strBuffer[512]; 

    va_list args; 
    va_start(args, tszMsg); 
    _vsntprintf( strBuffer, 512, tszMsg, args ); 
    va_end(args); 

        DWORD dwWrite; 
        WriteConsole(m_hOut, strBuffer, _tcslen(strBuffer), &dwWrite, NULL); 

설명 : 여기서 va_list나 va_start 등등 평소 자주(?) 못보던 함수들이 보이시죠? 
           (물론 " ... "이 생소하신 분들도 많으시겠지만 ㅡ.ㅡ...) 
            자세하게 할 껀 없고, 그냥 이런 식으로 인자값의 제약을 뛰어 넘었다는 것을 봐주세요 ^_^

* DEFINE의 사용.
자...여기까지 공부하신 분이라면, 이제 프로그램에서 객체를 생성하지 않고도 단지 헤더파일만 포함한 담에
CDebugConsole::getConsole().print( "지금은 %d번째 화면 갱신을 했습니다. " , i );
라고만 쓰면 디버깅 콘솔에 표현이 되지만......타자치기엔 너무 길죠? ^_^
그래서 혹시라도

#define CONSOLE(x) CDebugConsole::getConsole().print(x)

라고 선언해서 쓰신다는 분이 있으면, 70점 정도 드리겠습니다....
왜 100점을 못 드리냐면, 저렇게 해서는 뒤에 다중 인자값을 줄 수 없기 때문입니다.
(컴파일은 되지만, %d 의 표현이 안 먹습니다.)
제대로 하기 위해서는

#define CONSOLE CDebugConsole::getConsole().print

이렇게 해주셔야 합니다.
그리고 혹시 디버깅 창이니까...릴리즈 외에 디버깅 용으로만 띄우겠다...이러시는 분들은
#if defined(DEBUG) | defined(_DEBUG)
#define CONSOLE CDebugConsole::getConsole().print
#else
#define CONSOLE(x)
#endif

이렇게 처리해 주시면, 디버깅 시에는 작동하고 디버깅을 하지 않는다면, 깨끗하게 사라집니다.
근데, 어??? 이상하다 왜 CONSOLE(x)라고 썼지?? (x) 붙이지 말라며????
라고 궁금해 하실 분들이 계실껍니다.
그렇다면, 아래의 코드를 봐주세요 ^_^. 

CONSOLE("화면 갱신 %d 번 했네\n", i++);

여기서 릴리즈 모드일때는 CONSOLE의 내용이 없어진다고 생각하지만
만약 #define CONSOLE 로 썼다면, i++는 작동합니다.
#define CONSOLE(x)는 i를 작동하지 않게 합니다. 사실 어느정도 수준으로 남겨 놓느냐는 프로그래머의 선택이지만, 작동하지 않는 것이 좀 더 직관적이죠. i++같은 것들이 남는 다고 생각하면, 상당히 피곤해지기 시작하겠죠.
그리고, #define CONSOLE(x)는 릴리즈 컴파일시에 warning이 생깁니다...음 2개다 문법을 제대로 사용하면, 문제가 없이 쓸 수 있지만, 어떤 것을 선택하냐는 프로그래머 맘이겠죠 ^_^;

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

랜덤함수  (0) 2011.08.13
랜덤함수 C Source  (0) 2011.08.13
도스&콘솔 프로그램 관련(창안띄우기,StdOut, Wait)  (0) 2011.08.13
다중 쓰레드와 C++  (0) 2011.08.13
날짜 스트링을 CTime 으로 변환  (0) 2011.08.13
안정적인 DNS서비스 DNSEver DNS server, DNS service
Posted by 키르히아이스
,

출처 :

http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNo=20&no=278&ref=200

 

이 코드는 DOS 프로그램 또는 Win32 Console 모드 프로그램을 외부실행화일로
사용하고자 할때 문제가 되는 다음 세가지 항목을 해결하는 방법을
담고있습니다.

1. 콘솔창(DOS창) 창 안띄우기.
2. 끝날때까지 기다리기(실행이 끝난것을 감지하기)
3. 출력되는 내용을 화일로 저장하기
(만일 이 부분을 사용하시기 원치 않으시면 STARTF_USESTDHANDLES 를 삭제해 주세요)

void CTttDlg::OnOK() 
{
  // TODO: Add extra validation here
  PROCESS_INFORMATION pInfo;
  STARTUPINFO         sInfo;
  DWORD               exitCode;
  
  HANDLE hOut = CreateFile("stdinout.txt", GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  
  sInfo.cb              = sizeof(STARTUPINFO);
  sInfo.lpReserved      = NULL;
  sInfo.lpReserved2     = NULL;
  sInfo.cbReserved2     = 0;
  sInfo.lpDesktop       = NULL;
  sInfo.lpTitle         = NULL;
  sInfo.dwFlags         = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
  sInfo.dwX             = 0;
  sInfo.dwY             = 0;
  sInfo.dwFillAttribute = 0;
  sInfo.wShowWindow     = SW_HIDE;
  sInfo.hStdOutput      = hOut;
  
  if (!CreateProcess(NULL,
    "command.com /c lha a tt",
    NULL,
    NULL,
    TRUE,
    0,
    NULL,
    "c:\\",
    &sInfo,
    &pInfo)) {
    printf("ERROR: Cannot launch child process\n");
    exit(1);
  }
  
  // Give the process time to execute and finish
  WaitForSingleObject(pInfo.hProcess, INFINITE);
  
  if (GetExitCodeProcess(pInfo.hProcess, &exitCode))
  {
    switch(exitCode)
    {
    case STILL_ACTIVE: printf("Process is still active\n");
      break;
    default:           printf("Exit code = %d\n", exitCode);
      break;
    }
  }
  else {
    printf("GetExitCodeProcess() failed\n");
  }
  
  CloseHandle(hOut);
}

위의 CreateProcess()를 호출하는 부분에서
"Command.com /c"를 호출하는 부분이 있는데 이렇게 해주지 않으면
호출하는 프로그램이 DOS 프로그램인 경우 자동으로 창이 닫히지
않는 문제가 발생하기 때문입니다.

< 참고 >

HOWTO: Access Child Process Exit Code from 32-Bit Parent Proc.
Article ID: Q131775

안정적인 DNS서비스 DNSEver DNS server, DNS service
Posted by 키르히아이스
,
이현창 (아주대학교) 29/06/2003
프로젝트에 다중 쓰레드를 도입하면 동기화나 종료 처리 등의 문제로 고려해야 할 사항들이 곱절 이상이나 늘어나게 된다. 그럼에도 불구하고 다중 쓰레드를 사용하는 이유는 프로그램의 성능을 향상시켜 주기 때문이다. 여기서 성능을 향상시켜 준다는 말이 무엇을 의미하는지는 좀더 생각해 볼 필요가 있다. 또한 어떻게 해야 성능이 향상되는지도 알아 볼 필요가 있다.
다중 쓰레드에 대해 공부해 본 적이 있다면 많은 책과 기사에서 다중 쓰레드의 사용을 될 수 있으면 자제하라고 권장한다는 사실을 알고 있을 것이다. 일단 프로젝트에 다중 쓰레드를 도입하면 동기화나 종료 처리 등의 문제로 고려해야 할 사항들이 곱절 이상이나 늘어나게 된다.

상식적으로 생각해도 알 수 있듯이 코드 한 줄을 고치는 데도 많은 고민을 해야 하며, 문제 상황이 항상 재현되는 것이 아니기 때문에 디버깅 시에도 많은 고생을 하게 된다. 그럼에도 불구하고 다중 쓰레드를 사용하는 이유는 프로그램의 성능을 향상시켜 주기 때문이다. 그런데 여기서 성능을 향상시켜 준다는 말이 무엇을 의미하는지는 좀더 생각해 볼 필요가 있다.

또한 어떻게 해야 성능이 향상되는지도 알아 볼 필요가 있다. 실제로 다중 쓰레드를 사용한 프로젝트 중에는 성능 향상은 별로 보이지 않고, 다중 쓰레드 도입으로 인한 문제점만 고스란히 떠안고 있는 경우가 많기 때문이다.

다중 쓰레드의 도입 시기
컴퓨터에 설치된 MSDN이나 웹에서 ‘Win32 Multithreading Performance’라는 제목의 기사를 찾아보자. 이 기사는 1996년도 1월에 작성된 기사이지만 언제 다중 쓰레드를 적용하는 것이 좋은지 아주 훌륭하게 설명하고 있다. 그렇기 때문에 필자는 새로운 설명 방식과 예제를 구상하는 시간에 차라리 이 기사의 주요 내용에 자세한 설명과 그림을 추가해 여러분의 이해를 돕는 것이 더 효율적일 것이라는 결정을 내렸다. 이 단락을 읽고 나면 여러분은 어떤 상황에서 다중 쓰레드를 사용해야 하는지 판단할 수 있는 능력을 지니게 될 것이다. 크게 세 가지의 주요 관점을 기준으로 설명을 하려고 한다.

전체 작업의 완료 시간
CPU가 하나만 존재하는 시스템에서 실제로 두 작업이 동시에 실행되는 것은 불가능하다. CPU가 아주 짧은 시간 간격으로 두 작업을 번갈아가며 실행시키기 때문에 우리에게 마치 동시에 실행되는 것처럼 느껴지는 것뿐이다. 이 때 우리가 간과해서는 안될 사실은 두 작업 사이를 오가는 과정(context switching)에서 오버헤드가 발생한다는 점과 쓰레드를 생성하는 일 역시 시간을 소모하는 작업이라는 점이다. 예를 들어 두 개의 작업 A, B가 있다고 하자. 이 경우 다중 쓰레드를 사용한 경우와 그렇지 않은 경우의 전체 작업의 완료시간은 다음과 같다. 다중 쓰레드를 사용한 경우가 보다 비효율적이라는 것을 알 수 있다

◆ 다중 쓰레드를 사용한 경우의 전체 작업 완료 시간
= A의 작업 시간 + B의 작업 시간 + Context Switching 소요 시간 + 쓰레드 생성 소요 시간

◆ 다중 쓰레드를 사용하지 않은 경우의 전체 작업 완료 시간
= A의 작업 시간 + B의 작업 시간

하지만 이는 A, B가 작업 시간 내내 순수하게 CPU만 사용한다는 가정에서만 성립된다. A, B의 작업 시간 중에 I/O 요청을 기다리는 시간이 포함된다면 문제가 달라진다. 예들 들어 A의 주요 작업 내용이 메모리의 데이터를 특정 파일에 기록하는 것이라고 가정하자. 파일에 기록하는 작업은 하드디스크와 같은 하드웨어에 기록을 요청한 후에 하드웨어에서 완료 응답이 도착할 때까지 기다리는 방식으로 진행된다. 그런데 이렇게 하드웨어의 응답을 기다리는 동안에는 CPU를 사용하지 않기 때문에 다른 작업이 CPU를 사용할 수 있다. 다시 말해 A가 I/O 요청을 기다리는 동안에는 B가 자신의 작업을 수행할 수 있다는 말이다. 그래서 다중 쓰레드를 사용한 경우 전체 작업의 완료 시간은 다음과 같이 다시 계산될 수 있다.

다중 쓰레드를 사용한 경우의 전체 작업 완료 시간
= A의 작업 시간 - A의 I/O 요청 대기 시간 + B의 작업 시간 + Context Switching 소요 시간 + 쓰레드 생성 소요 시간

결론적으로 I/O 작업은 다중 쓰레드의 좋은 대상이 된다고 할 수 있다. 운영체제의 발전 역사를 보더라도 하나의 시스템에 여러 사용자 프로그램을 동시에 적재해 실행하기 시작한 계기도 한 프로세스가 I/O 요청을 기다리는 동안에 다른 프로세스가 CPU를 사용할 수 있다는 사실을 운영체제 설계자들이 깨달았기 때문이다.

##########0*평균 처리 시간
앞서 CPU 연산의 경우 다중 쓰레드는 전체 작업 완료 시간을 단축하는 데 도움이 되지 않는다는 점을 확인했다. 그러나 우리의 관심사를 평균 처리 시간으로 옮기게 되면 CPU 연산의 경우에도 다중 쓰레드를 사용해 성능을 향상시킬 수 있다는 점을 확인할 수 있다. <그림 1>을 보면서 설명하도록 하겠다.

작업 A, B, C는 각각 1, 4, 3의 작업 시간을 갖으며 CPU 연산이다. 이 때 A, B, C의 순서대로 작업을 실행시킨다고 해보자. 그러면 작업 A는 바로 시작해서 작업 시간인 1만큼의 시간이 경과한 후에 완료될 것이다. 작업 B의 경우는 A가 끝나는 시간인 1만큼 기다렸다가 작업 시간인 4만큼의 시간이 경과한 후에 완료될 것이다. 전체적으로 볼 때 작업 B는 5만큼의 시간이 지난 후에 완료되는데 이 시간을 처리 시간(Turnaround Time)이라고 부르도록 하자.

처리 시간 = 대기 시간 + 작업 시간

같은 식으로 C의 처리 시간은 8이 된다. 이 글에서는 이러한 처리 시간의 평균을 ‘평균 처리 시간’이라고 부르도록 하겠다. 이제부터 우리는 다중 쓰레드를 사용하는 것이 어떻게 평균 처리 시간을 줄일 수 있는지 확인시켜 줄 예제 하나를 보게 될 것이다.

##########1*
<그림 2> 평균 처리 시간의 감소 예

이런 종류의 문헌에서 자주 등장하는 슈퍼마켓에서의 계산 예를 들어보자. 슈퍼마켓에서 여러 손님들이 자신이 필요한 물건을 고른 후에 계산을 하려고 한다. 그리고 점원은 딱 한 명밖에 없다. 한 명의 점원이 여러 손님의 물품을 계산하는 방법으로 크게 두 가지를 생각해 볼 수 있다. 하나는 사람들을 한 줄로 세우고 차례로 계산을 해주고, 다른 하나는 여러 개의 계산대에 사람들을 여러 줄로 세우고 한 번에 한 계산대씩 돌아가면서 차례로 계산을 해주는 방법이다. 그림을 좀더 설명하면 이렇다.

 

출처 : http://www.zdnet.co.kr/builder/dev/c/0,39030803,10062429,00.htm

안정적인 DNS서비스 DNSEver DNS server, DNS service
Posted by 키르히아이스
,