PostThreadMessage()를 이용한 쓰레드에 메세지 전송

● 알아두어야 할 사항
1. 윈도우 OS시스템에서는 자동적으로(GetMessage()호출시?) 메세지 큐를 각각 쓰레드마다 생성한다.
2. Posted Message를 위한 메세지 큐의 크기는 Windows 2000이나 XP인경우
   10000이다. (최소 값: 4000) 이 값은 아래 윈도우즈 레지스트리에
   HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Windows/
     USERPostMessageLimit
   정의 한다.
3. PostThreadMessage()로 보내어지는 메세지는 윈도우와 관련이 없다.


● 결론
1. 간단한 메세지만 전송받아 처리 하는 쓰레드인 경우는 큐만든다고 삽질하지 말자.
2. 기본에 충실하자.
3. 옛날에 삽질한게 억울하다.

// --------------------------------------------------------------------------
//  예제
// --------------------------------------------------------------------------
CAppModule _Module;

DWORD WINAPI BackgroundThread (LPVOID param)
{
 MSG msg;

 while (GetMessage(&msg, NULL, 0, 0))
 {
  ATLTRACE (_T("hwnd    = %x \r\n"),    msg.hwnd    );
  ATLTRACE (_T("message = %x \r\n"),    msg.message );
  ATLTRACE (_T("wParam  = %x \r\n"),    msg.wParam  );
  ATLTRACE (_T("lParam  = %x \r\n"),    msg.lParam  );
  ATLTRACE (_T("time    = %d \r\n"),    msg.time    );
  ATLTRACE (_T("pt      = %d %d \r\n"), msg.pt.x, msg.pt.y);
  ATLTRACE (_T("\r\n"));

  Sleep (1000);

  while (::PeekMessage (&msg, NULL, WM_USER, WM_USER+5, PM_REMOVE));
 }

 ATLTRACE (_T("BackgroundThread(): End \r\n"));

 return msg.wParam;
}

int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWNORMAL)
{
 CMessageLoop theLoop;
 _Module.AddMessageLoop(&theLoop);

 CMainFrame wndMain;

 DWORD  dwThreadId  = 0;
 HANDLE hThread     = CreateThread (NULL, 0, BackgroundThread, NULL, 0, &dwThreadId);
 wndMain.m_ThreadId = dwThreadId;

 if(wndMain.CreateEx() == NULL)
 {
  ATLTRACE(_T("Main window creation failed!\n"));
  return 0;
 }
 
 wndMain.ShowWindow(nCmdShow);

 int nRet = theLoop.Run();

 _Module.RemoveMessageLoop();

 WaitForSingleObject (hThread, INFINITE);
 CloseHandle (hThread);

 return nRet;
}
// --------------------------------------------------------------------------

LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
 ...
 SetTimer (1, 10);

 return 0;
}

LRESULT CMainFrame::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
 bHandled = FALSE;
 KillTimer (1);
 PostThreadMessage (m_ThreadId, WM_QUIT, 0, 0);

 return 0;
}

LRESULT CMainFrame::OnTimer (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
 static int i = 0;

 PostThreadMessage (m_ThreadId, WM_USER+(++i%5), 1, 2);

 return 0;
}
// --------------------------------------------------------------------------
// 출력결과
// --------------------------------------------------------------------------
hwnd    = 0
message = 403
wParam  = 1
lParam  = 2
time    = 73702525
pt      = 0 0

hwnd    = 0
message = 400
wParam  = 1
lParam  = 2
time    = 73703559
pt      = 0 0

hwnd    = 0
message = 400
wParam  = 1
lParam  = 2
time    = 73704571
pt      = 0 0

hwnd    = 0
message = 403
wParam  = 1
lParam  = 2
time    = 73705596
pt      = 0 0

hwnd    = 0
message = 403
wParam  = 1
lParam  = 2
time    = 73706642
pt      = 0 0

hwnd    = 0
message = 400
wParam  = 1
lParam  = 2
time    = 73707702
pt      = 0 0

hwnd    = 0
message = 403
wParam  = 1
lParam  = 2
time    = 73708749
pt      = 0 0

hwnd    = 0
message = 400
wParam  = 1
lParam  = 2
time    = 73709776
pt      = 0 0

CMessageLoop::Run - exiting
BackgroundThread(): End
'BackgroundThread' (0x8706cf42) 스레드가 0 (0x0) 코드에서 끝났습니다.
모듈 언로드: commctrl.dll
모듈 언로드: oleaut32.dll
모듈 언로드: ole32.dll
모듈 언로드: rpcrt4.dll
모듈 언로드: lpcrt.dll
'[6702ec62] Test.exe' 프로그램이 1 (0x1) 코드에서 끝났습니다.

 

 

Posted by 셈말짓기 :

 typedef struct _PRIORITY_LEVEL
 {
  int   priority;
  TCHAR name[32];
 } PRIORITY_LEVEL;

 PRIORITY_LEVEL Priority_Levels[] =
 {
  { THREAD_PRIORITY_TIME_CRITICAL , _T("THREAD_PRIORITY_TIME_CRITICAL") },
  { THREAD_PRIORITY_HIGHEST       , _T("THREAD_PRIORITY_HIGHEST      ") },
  { THREAD_PRIORITY_ABOVE_NORMAL  , _T("THREAD_PRIORITY_ABOVE_NORMAL ") },
  { THREAD_PRIORITY_NORMAL        , _T("THREAD_PRIORITY_NORMAL       ") },
  { THREAD_PRIORITY_BELOW_NORMAL  , _T("THREAD_PRIORITY_BELOW_NORMAL ") },
  { THREAD_PRIORITY_LOWEST        , _T("THREAD_PRIORITY_LOWEST       ") },
  { THREAD_PRIORITY_ABOVE_IDLE    , _T("THREAD_PRIORITY_ABOVE_IDLE   ") },
  { THREAD_PRIORITY_IDLE          , _T("THREAD_PRIORITY_IDLE         ") }
 };
 HANDLE Current_Thread = GetCurrentThread();
 int    Current_Priority;
 int    i;

 for (i=0; i<sizeof(Priority_Levels)/sizeof(PRIORITY_LEVEL); i++)
 {
  SetThreadPriority (Current_Thread, Priority_Levels[i].priority);
  Current_Priority = CeGetThreadPriority (Current_Thread);
 
  ATLTRACE (_T("SetThreadPriority(%d:%s) => CeGetThreadPriority()=%d \r\n"),
  Priority_Levels[i].priority,
  Priority_Levels[i].name,
  Current_Priority);

 }
---------------------------------------------------------------------------------------------- SetThreadPriority(0:THREAD_PRIORITY_TIME_CRITICAL) => CeGetThreadPriority()=248
 SetThreadPriority(1:THREAD_PRIORITY_HIGHEST      ) => CeGetThreadPriority()=249
 SetThreadPriority(2:THREAD_PRIORITY_ABOVE_NORMAL ) => CeGetThreadPriority()=250
 SetThreadPriority(3:THREAD_PRIORITY_NORMAL       ) => CeGetThreadPriority()=251
 SetThreadPriority(4:THREAD_PRIORITY_BELOW_NORMAL ) => CeGetThreadPriority()=252
 SetThreadPriority(5:THREAD_PRIORITY_LOWEST       ) => CeGetThreadPriority()=253
 SetThreadPriority(6:THREAD_PRIORITY_ABOVE_IDLE   ) => CeGetThreadPriority()=254
 SetThreadPriority(7:THREAD_PRIORITY_IDLE         ) => CeGetThreadPriority()=255

Posted by 셈말짓기 :

비디오 포맷

2008. 9. 22. 12:20 from 셈말짓기/헤아림

# 아날로그 비디오 포맷
1. Composite : NTSC, PAL
2. S-Video(Y+C)
3. 아날로그 RGB: D-Sub 모니터
4. YPbPr

# 디지털 비디오 포맷
1. CCIR 656 (H/V Sync포함)
2. CCIR 601
2. YCrCb
3. YUV
4. RGB
Posted by 셈말짓기 :

[가수 변환식] (가수 범위= +1.0 > x > -1.0 )

아래 Code에서 xbits는 부호비트를 포함한 값이다.
-----------------------------------------------------------------------------
#include <windows.h>
#include <math.h>
#include <stdio.h>
#include <tchar.h>

DWORD ConvertMantissaToXBits (double value, DWORD xbits=24)
{
 if (xbits>31 || xbits<12)
  return 0;

 static const DWORD MASK[33] =
 {
  /* 00 */ 0x00000000,
  /* 01 */ 0x00000001,/* 02 */ 0x00000003,/* 03 */ 0x00000007,/* 04 */ 0x0000000f,
  /* 05 */ 0x0000001f,/* 06 */ 0x0000003f,/* 07 */ 0x0000007f,/* 08 */ 0x000000ff,
  /* 09 */ 0x000001ff,/* 10 */ 0x000003ff,/* 11 */ 0x000007ff,/* 12 */ 0x00000fff,
  /* 13 */ 0x00001fff,/* 14 */ 0x00003fff,/* 15 */ 0x00007fff,/* 16 */ 0x0000ffff,
  /* 17 */ 0x0001ffff,/* 18 */ 0x0003ffff,/* 19 */ 0x0007ffff,/* 20 */ 0x000fffff,
  /* 21 */ 0x001fffff,/* 22 */ 0x003fffff,/* 23 */ 0x007fffff,/* 24 */ 0x00ffffff,
  /* 25 */ 0x01ffffff,/* 26 */ 0x03ffffff,/* 27 */ 0x07ffffff,/* 28 */ 0x0fffffff,
  /* 29 */ 0x1fffffff,/* 30 */ 0x3fffffff,/* 31 */ 0x7fffffff,/* 32 */ 0xffffffff
 };

 DWORD  result = 0;
 DWORD  h      = 0;
 double m      = 0.0;

 if (value>=1.0 || value<-1.0)
  return MASK[xbits] & (~(1<<(xbits-1)));

 //m = pow (2.0, double(xbits-1)) * value;
 m = (1<<(xbits-1)) * value;
 h = DWORD (m);

 result = h&MASK[xbits];

 return result;
}

double ConvertXBitsToMantissa (DWORD value, DWORD xbits=24)
{
 if (xbits>31 || xbits<12)
  return 0.0;

 double     result  = 0.0;
 signed int n       = 0;

 n = value<<(32-xbits);
 n = n    >>(32-xbits); // no moved signal flag

 //result = n/pow (2.0, double(xbits-1));
 result = double(n)/(1<<(xbits-1));

 return result;
}

int _tmain(int argc, _TCHAR* argv[])
{
 DWORD  bits = 24;
 double v;
 DWORD  h;
 double f;
 int    i;
 double s;

 v = -1;
 s =  0.1;
 for (i=0; i<22; i++)
 {
  h = ConvertMantissaToXBits(v,bits);
  f = ConvertXBitsToMantissa(h,bits);

  printf ("Mant->xBits(%+.3f)= 0x%08x : ",  v, h);
  printf ("xBits->Mant(0x%08x)= %+.3f\r\n", h, f);

  v = v+s;
 }

 return 0;
}
-----------------------------------------------------------------------------
Mant->xBits(-1.000)= 0x00800000 : xBits->Mant(0x00800000)= -1.000
Mant->xBits(-0.900)= 0x008ccccd : xBits->Mant(0x008ccccd)= -0.900
Mant->xBits(-0.800)= 0x0099999a : xBits->Mant(0x0099999a)= -0.800
Mant->xBits(-0.700)= 0x00a66667 : xBits->Mant(0x00a66667)= -0.700
Mant->xBits(-0.600)= 0x00b33334 : xBits->Mant(0x00b33334)= -0.600
Mant->xBits(-0.500)= 0x00c00000 : xBits->Mant(0x00c00000)= -0.500
Mant->xBits(-0.400)= 0x00cccccd : xBits->Mant(0x00cccccd)= -0.400
Mant->xBits(-0.300)= 0x00d9999a : xBits->Mant(0x00d9999a)= -0.300
Mant->xBits(-0.200)= 0x00e66667 : xBits->Mant(0x00e66667)= -0.200
Mant->xBits(-0.100)= 0x00f33334 : xBits->Mant(0x00f33334)= -0.100
Mant->xBits(-0.000)= 0x00000000 : xBits->Mant(0x00000000)= +0.000
Mant->xBits(+0.100)= 0x000ccccc : xBits->Mant(0x000ccccc)= +0.100
Mant->xBits(+0.200)= 0x00199999 : xBits->Mant(0x00199999)= +0.200
Mant->xBits(+0.300)= 0x00266666 : xBits->Mant(0x00266666)= +0.300
Mant->xBits(+0.400)= 0x00333333 : xBits->Mant(0x00333333)= +0.400
Mant->xBits(+0.500)= 0x003fffff : xBits->Mant(0x003fffff)= +0.500
Mant->xBits(+0.600)= 0x004ccccc : xBits->Mant(0x004ccccc)= +0.600
Mant->xBits(+0.700)= 0x00599999 : xBits->Mant(0x00599999)= +0.700
Mant->xBits(+0.800)= 0x00666666 : xBits->Mant(0x00666666)= +0.800
Mant->xBits(+0.900)= 0x00733333 : xBits->Mant(0x00733333)= +0.900
Mant->xBits(+1.000)= 0x007fffff : xBits->Mant(0x007fffff)= +1.000
Mant->xBits(+1.100)= 0x007fffff : xBits->Mant(0x007fffff)= +1.000

Posted by 셈말짓기 :

#include <stdio.h>
#include <tchar.h>
#include <math.h>

#define LENGTH       32
#define SIGN_BIT     31
#define EXPONENT_MSB 30
#define EXPONENT_LSB 23
#define MANTISSA_MSB 22
#define MANTISSA_LSB  0

float hex_to_float (unsigned int value)
{
 int   sign;
 int   exp;
 int   man;
 float result;

 sign = (value & (1 << SIGN_BIT)) != 0;
#pragma warning( push )
#pragma warning( disable : 4307 ) // '-' : integral constant overflow.
 exp  = ((value & ( (2<<EXPONENT_MSB) - (1<<EXPONENT_LSB) )) >> EXPONENT_LSB)
  - (1 << (EXPONENT_MSB - EXPONENT_LSB))
  - (MANTISSA_MSB - MANTISSA_LSB);
#pragma warning( pop )

 man  = ((value & ( (2<<MANTISSA_MSB) - (1<<MANTISSA_LSB) )) >> MANTISSA_LSB)
  + (2 << (MANTISSA_MSB - MANTISSA_LSB));

 result = man * pow((float)2, (float)exp) * (sign ? -1 : 1);

 return result;
}

int _tmain(int argc, _TCHAR* argv[])
{
 union
 {
  unsigned int n;
  float        f;
 } value;

 int   i;
 float f;


 value.f =(float)   0;
 f       =(float)-1.1;

 for (i=0; i<10; i++)
 {
  printf ("%+e=0x%08x:hex_to_float()=%+e \r\n", value.f, value.n, hex_to_float(value.n));
  value.f += f;
 }

 return 0;
}
-----------------------------------------------------------------------------
+0.000000e+000=0x00000000:hex_to_float()=+0.000000e+000
-1.100000e+000=0xbf8ccccd:hex_to_float()=-1.100000e+000
-2.200000e+000=0xc00ccccd:hex_to_float()=-2.200000e+000
-3.300000e+000=0xc0533334:hex_to_float()=-3.300000e+000
-4.400000e+000=0xc08ccccd:hex_to_float()=-4.400000e+000
-5.500000e+000=0xc0b00000:hex_to_float()=-5.500000e+000
-6.600000e+000=0xc0d33333:hex_to_float()=-6.600000e+000
-7.700000e+000=0xc0f66666:hex_to_float()=-7.700000e+000
-8.800000e+000=0xc10ccccd:hex_to_float()=-8.800000e+000
-9.900001e+000=0xc11e6667:hex_to_float()=-9.900001e+000


-----------------------------------------------------------------------------

부동소수점 표현의 국제표준은 IEEE 754입니다.

-----------------------------------------------------------------------------

< float >
C의 float타입은 IEEE 754의 single precision 플로팅포인트를 구현한 것으로,
다음과 같은 포맷을 가집니다.
sign : bit31 (1비트)
exponent : bit30~bit23 (8비트)
mantissa : bit22~bit0 (23비트)

이때, 가수부(만티사)는 정수부분을 1로 정규화한 2진소수표현이며, 지수부(exponent)는
원래 지수에 바이어스 127을 더한 값입니다.
부호비트는 0이면 양수, 1이면 음수입니다.

가수부의 23비트가 100 0000 0000 0000 0000 0000 이라면, 이때 이 부동소수의 가수는
2진소수로 1.1이 되어, 10진법으로는 1 + 1/2 = 1.5가 됩니다.

지수부의 표현이 1000 0000 이라면, 이 값은 바이어스 127, 즉 111 1111이 더해진 수
이므로 실제 지수는 128 - 127 = 1이 됩니다.

따라서, 0 100 0000 100 0000 0000 0000 0000 0000 으로 표현되는 부동소수는
따라서, [0] [100 0000 0] [100 0000 0000 0000 0000 0000] 으로 표현되는 부동소수는
1.5 * 2^1 = 3.0 을 표현하게 됩니다.

single precision의 유효숫자는 가수의 비트길이 (정수부분 포함)24에 의해 결정되며,
2^24 은 약 10^7.2 이므로, 유효숫자는 약 7자리가 됩니다.

-----------------------------------------------------------------------------

< double >
C의 double타입은 IEEE 754의 double precision 플로팅포인트를 구현한 것으로,
다음과 같은 포맷을 가집니다.
sign : bit63 (1비트)
exponent : bit62~bit52 (11비트)
mantissa : bit51~bit0 (52비트)

이때, single precision과는 지수부의 바이어스가 1023이라는 것만 다르고, 나머지
표현방법은 동일합니다.

double precision의 유효숫자 역시 정수부분을 포함한 가수의 비트길이 53에 의해 결정되며,
2^53 은 약 10^15.9 이므로, 유효숫자는 약 약 15자리가 됩니다.

-----------------------------------------------------------------------------

< 예외 정의 >
1. 플로팅포인트 표현에서 모든 비트가 0인 수는 0으로 정의합니다.
2. 지수부의 모든 비트가 0인 수는 가수의 정수부분을 0으로 계산합니다.
3. 지수부의 모든 비트가 1이고, 가수부의 모든 비트가 0이면 무한대로 정의합니다.
4. 지수부의 모든 비트가 1이고, 가수부가 0이 아니면 NaN (Not a Number)로 정의하여
   예외를 발생하게 됩니다.


Posted by 셈말짓기 :