Сейчас на форуме: tyns777 (+4 невидимых)

 eXeL@B —› Программирование —› Небольшие полезные коды
<< . 1 . 2 . 3 .
Посл.ответ Сообщение

Ранг: 47.1 (посетитель), 2thx
Активность: 0.030
Статус: Участник

Создано: 09 февраля 2010 18:42 · Поправил: Vol4ok
· Личное сообщение · #1

Часто во время написания проектов возникают небольшие, но при этом довольно общие задачи, которые потом могут быть использованы в будущем, вот эта тема как раз для этого. В этой теме предлагаю размещать небольшие фрагменты кода, которые могут применятся в повседневной практике системного программирования.

В этом топике можно
- размещать только свои коды, а не копировать из общедоступных источников
- желательно хорошо протестировать код, прежде чем разместить его. Если вы не уверены, что код работает точно будет работать так как надо на всех ОС и всех процах, то надо пометить - где и каким образом тестировался этот код, или вообще написать что код не тестирован (хорошо подумав при это, стоит ли вообще такой код размещать).
- нормально его оформить, чтобы тот кому этот код пригодится смог разобраться в нем быстрее чем писать это же с нуля. Обязательно должны быть описания входных и выходных данных. Крайне приветствуются цели создания кода, основные требования которым он удовлетворяет, и описание того как работает этот код.

Также приветствуются багфиксы, замечания по коду и варианты оптимизации.

Итак начну с себя. Недавно столкнулся с необходимостью делать высокоточные паузы в работе кода, в моем случае необходимо было достигать точности десятых милисекунд. В итоге я написал микросекундный таймер

Code:
  1. #define YIELD_LOOP 200
  2. #define get_interval_in_us(_t1_,_t2_,_fq_) (int)((_t2_.QuadPart - _t1_.QuadPart)*1000000 / _fq_.QuadPart)
  3.  
  4. static int g_sleep_error = 1000;
  5.  
  6. void precision_sleep(int timeout)
  7. {
  8.          int i;
  9.          int sleep_time;
  10.          int real_sleep_time;
  11.  
  12.          LARGE_INTEGER t2;
  13.          LARGE_INTEGER t1;
  14.          LARGE_INTEGER fq;
  15.  
  16.          QueryPerformanceCounter(&t1);
  17.          QueryPerformanceFrequency(&fq);
  18.  
  19.          if (timeout > g_sleep_error) {
  20.                  sleep_time = timeout - g_sleep_error;
  21.                  Sleep(sleep_time/1000);
  22.          }
  23.  
  24.          QueryPerformanceCounter(&t2);
  25.  
  26.          real_sleep_time = get_interval_in_us(t1,t2,fq);
  27.  
  28.          if (timeout < real_sleep_time)
  29.                  g_sleep_error += (real_sleep_time - timeout)/2;
  30.          else if (g_sleep_error > 2000)
  31.                  g_sleep_error -= min((timeout - real_sleep_time)/2, g_sleep_error/2);
  32.  
  33.          while (get_interval_in_us(t1,t2,fq) < timeout) {
  34.                  for (i=0;i<YIELD_LOOP;i++)
  35.                         YieldProcessor();
  36.                  //Sleep(0);
  37.                  QueryPerformanceCounter(&t2);
  38.          }
  39. }

- timeout - время таймаута в микросекундах

код рекомендуется выполнять с повышением точности обыкновенного слипа, например так:

#include <Mmsystem.h>
...
timeBeginPeriod(1);
precision_sleep(timeout);
timeEndPeriod(1);

Код делает таймауты с микросекундой точностью. Как извесно простой Sleep имеет огромную погрешность, допутим Sleep(1) - в нормальных условиях выполнется около 10-15мс (1,5-2мс при установке timeBeginPeriod(1)). Высокая точность достигается за счет использования цикла опроса высокоточного системного таймера (период <1нс - на современных компах и 300-400нс на более старых). Минимальная погрешность данной функции равна времени вызова QueryPerformanceCounter - которое на современных компах равно 200-300нс, на компах по старше может доходить до микросекунды. Ес-но в условиях нехватки процессорного времени погрешность может значительно возрастать.

Конечно такой метод измерения сильно грузит проц, поэтому при ожидании более 1мс будет использоваться обыкновенный слип, но поскольку он имеет большую погрешность, то динамически в при многократном вызове, precision_sleep проводит пересчет предельной погрешности слипа, подгоняя его под оптимальное значение, при котором будет сохранена хорошая точность при минимальной нагрузке на процессор. Однако не смотря на это всегда имеется вероятность того что слип превысит предельное время и внесет дополнительную погрешность.

Код тестировался на 2х ядероном компе с процом core2duo и на старом одноядерном Celeron-е
При тестировании интервалов больших 3мс загрузка процессора скачет 1% до 15%, при интервалах больих 10мс в средем чтото около 2-3%. Хуже всего дело обстоит с таймаутами порядка 1мс и менее, загрузка может быть очень большой, так как слип в этом случае не работает, чуть чуть улутшить положение можно если заменить
for (i=0;i<YIELD_LOOP;i++)
YieldProcessor();
на Sleep(0), будет небольшая потеря точности, на моем компе Sleep(0) работает примерно за 1-2мкс (на старых компах может быть еще больше) когда YIELD_LOOP работает < 1 мкс

Данный код может быть использован при написании сетевых приложений, например для того чтобы точно регуоировать скорость выходного трафика.



Ранг: 30.0 (посетитель), 4thx
Активность: 0.030.01
Статус: Участник

Создано: 02 июня 2010 23:16 · Поправил: punxer
· Личное сообщение · #2

Code:
  1. void ViewLastError(void)
  2. {
  3. void* cstr;
  4.          FormatMessage(
  5.                  FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  6.                  NULL,
  7.                  GetLastError(),
  8.                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  9.                  (LPTSTR) &cstr,
  10.                  0,
  11.                  NULL
  12.          );
  13.          MessageBox(0,(LPCSTR)cstr,"ERROR",MB_OK);
  14.  
  15. }




Ранг: 30.0 (посетитель), 4thx
Активность: 0.030.01
Статус: Участник

Создано: 02 июня 2010 23:22
· Личное сообщение · #3

Подмена ввода, возможна глобально. txt содержит выводимую строку


Code:
  1. hhookHooks=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC) HookProc, (HINSTANCE) hInstance, 0);
  2.  
  3. LRESULT WINAPI HookProc(int nCode, WPARAM wParam, LPARAM lParam) 
  4. {        
  5.          MSG     *lpMsg;
  6.          static int pos;
  7.          if (nCode >= 0)
  8.          {
  9.                  lpMsg = (MSG *) lParam;
  10.                  switch (nCode)     
  11.                  {           
  12.                         case HC_ACTION: 
  13.                               if (lpMsg->message==WM_CHAR)
  14.                               {
  15.                               //KeyPress Handling
  16.                                    if (lpMsg->wParam==VK_BACK)
  17.                                    {
  18.                                        if (pos>0)pos--;
  19.                                    }
  20.                                    else if (lpMsg->wParam==VK_RETURN)
  21.                                    {
  22.                                        pos=0;
  23.                                    }
  24.                                    else 
  25.                                    {
  26.                                        if (pos==lstrlen((const char *)txt)) pos=0;
  27.                                        lpMsg->wParam=(char)*(txt+pos);
  28.                                        pos++;
  29.                                    }                       
  30.                               }
  31.                               return CallNextHookEx(0, nCode, wParam, lParam);
  32.                         default:
  33.                               return CallNextHookEx(0, nCode, wParam, lParam);
  34.                  }
  35.          }
  36.          else
  37.          {
  38.                  return CallNextHookEx(0, nCode, wParam, lParam);
  39.          }
  40.  




Ранг: 57.1 (постоянный), 3thx
Активность: 0.040
Статус: Участник

Создано: 17 июня 2010 20:23
· Личное сообщение · #4

Каждый раз начиная проект по разработке программы консольного типа мне становится влом парсить опции командной строки и если их там слишком много, то в разы ломает.

Для этой цели написал небольшую библиотеки с небольшим классом, помогающая парсить опции командной строки.

Будут замечания, пишите, мыло в readme.txt, который внутри архива.

e6bb_17.06.2010_CRACKLAB.rU.tgz - cmdline_lib.rar




Ранг: 324.3 (мудрец), 222thx
Активность: 0.480.37
Статус: Участник

Создано: 17 июня 2010 20:37
· Личное сообщение · #5

punxer

1) строку
return CallNextHookEx(0, nCode, wParam, lParam);
веде убрать, оставить только в конце функции

2) WM_CHAR не будет работать для других клавиш

-----
IZ.RU




Ранг: 57.1 (постоянный), 3thx
Активность: 0.040
Статус: Участник

Создано: 18 июня 2010 00:02
· Личное сообщение · #6

[bugfix] - Допустимо было писать "/argum:2323 /help /argum:5454" , а повторение опций некорректно.

ЗЫ:
Модераторам просьба обновить тот линк, который через пост выше

От модератора: обновил. хотя я думаю, мог бы обновить и сам



Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 11 июля 2010 00:51 · Поправил: Clerk
· Личное сообщение · #7

Code:
  1. X86_PAGE_SIZE     equ 1000H
  2.  
  3. %GET_CURRENT_GRAPH_ENTRY macro
  4.          Call GetGraphReference
  5. endm
  6.  
  7. %GET_GRAPH_ENTRY macro PGET_CURRENT_GRAPH_ENTRY
  8.          Call PGET_CURRENT_GRAPH_ENTRY
  9. endm
  10.  
  11. %GET_GRAPH_REFERENCE macro
  12. GetGraphReference::
  13.          pop eax
  14.          ret
  15. endm
  16.  
  17.          assume fs:nothing
  18. SEH_Prolog proc C
  19.          pop ecx
  20.          push ebp
  21.          push eax
  22.          Call SEH_GetRef
  23.          push eax
  24.          push dword ptr fs:[0]
  25.          mov dword ptr fs:[0],esp
  26.          jmp ecx
  27. SEH_Prolog endp
  28.  
  29. ; o Не восстанавливаются Ebx, Esi и Edi.
  30. ;
  31. SEH_Epilog proc C
  32.          pop ecx
  33.          pop dword ptr fs:[0]
  34.          lea esp,[esp + 3*4]
  35.          jmp ecx
  36. SEH_Epilog endp
  37.  
  38. SEH_GetRef proc C
  39.          %GET_CURRENT_GRAPH_ENTRY
  40.          mov eax,dword ptr [esp + 4]
  41.          mov edx,dword ptr [esp]   ; ~ nt!ExecuteHandler2().
  42.          mov esp,dword ptr [esp + 2*4]      ; (esp) -> ExceptionList
  43.          mov ecx,EXCEPTION_RECORD.ExceptionAddress[eax]
  44.          mov eax,EXCEPTION_RECORD.ExceptionCode[eax]
  45.          mov ebp,dword ptr [esp + 3*4]
  46.          jmp dword ptr [esp + 2*4]
  47. SEH_GetRef endp
  48.  
  49.          %GET_GRAPH_REFERENCE
  50.  
  51. ; +
  52. ;Проверяет валидность заголовка модуля.
  53. ;
  54. LdrImageNtHeader proc ImageBase:PVOID, ImageHeader:PIMAGE_NT_HEADERS
  55.          mov edx,ImageBase
  56.          mov eax,STATUS_INVALID_IMAGE_FORMAT
  57.          assume edx:PIMAGE_DOS_HEADER
  58.          cmp [edx].e_magic,'ZM'
  59.          jne @f
  60.          add edx,[edx].e_lfanew
  61.          assume edx:PIMAGE_NT_HEADERS
  62.          cmp [edx].Signature,'EP'
  63.          jne @f
  64.          cmp [edx].FileHeader.SizeOfOptionalHeader,sizeof(IMAGE_OPTIONAL_HEADER32)
  65.          jne @f
  66.          cmp [edx].FileHeader.Machine,IMAGE_FILE_MACHINE_I386
  67.          jne @f
  68.          test [edx].FileHeader.Characteristics,IMAGE_FILE_32BIT_MACHINE
  69.          je @f
  70.          mov ecx,ImageHeader
  71.          xor eax,eax
  72.          mov dword ptr [ecx],edx
  73. @@:
  74.          ret
  75. LdrImageNtHeader endp

Получаем базу ntdll:
Code:
  1. ; +
  2. ;
  3. LdrGetNtImageBase proc uses ebx esi edi NtImageBase:PVOID
  4. Local ImageHeader:PIMAGE_NT_HEADERS
  5.          Call SEH_Epilog_Reference1
  6.          Call SEH_Prolog
  7.          xor eax,eax
  8.          bt dword ptr fs:[-1],0    ; #GP
  9.          jmp Exit1
  10. SEH_Epilog_Reference1:
  11.          %GET_CURRENT_GRAPH_ENTRY
  12. Exit1:
  13.          Call SEH_Epilog
  14.          test eax,eax     ; #STATUS_ACCESS_VIOLATION
  15.          jnz @f
  16.          mov eax,STATUS_UNSUCCESSFUL
  17.          jmp Exit
  18. @@:
  19. ; Scan
  20.          Call SEH_Epilog_Reference2
  21.          Call SEH_Prolog
  22.          mov ebx,edx
  23.          and ebx,NOT(X86_PAGE_SIZE - 1)
  24. @@:
  25.          invoke LdrImageNtHeader, Ebx, addr ImageHeader
  26.          test eax,eax
  27.          jz @f
  28.          sub ebx,X86_PAGE_SIZE
  29.          jmp @b
  30. @@:
  31.          mov ecx,NtImageBase
  32.          mov dword ptr [ecx],ebx
  33.          jmp Exit2
  34. SEH_Epilog_Reference2:
  35.          %GET_CURRENT_GRAPH_ENTRY
  36. Exit2:
  37.          Call SEH_Epilog
  38. Exit:
  39.          ret
  40. LdrGetNtImageBase endp

и ядра:
Code:
  1. ; +
  2. ; o PASSIVE_LEVEL|APC_LEVEL, IF = 1.
  3. ;
  4. LdrGetNtImageBase proc uses ebx esi edi NtImageBase:PVOID
  5. Local IDTR[8]:BYTE
  6. Local ImageHeader:PIMAGE_NT_HEADERS
  7.          Call SEH_Epilog_Reference
  8.          Call SEH_Prolog
  9.          sidt qword ptr [IDTR]
  10.          mov eax,dword ptr [IDTR + 2]       ; IDT Base
  11.          movzx ebx,word ptr [eax + 2AH*8 + 6]        ; KiGetTickCount, Hi
  12.          shl ebx,16
  13.          mov bx,word ptr [eax + 2AH*8]      ; Lo
  14.          and ebx,NOT(X86_PAGE_SIZE - 1)
  15. @@:
  16.          invoke LdrImageNtHeader, Ebx, addr ImageHeader
  17.          test eax,eax
  18.          jz @f
  19.          sub ebx,X86_PAGE_SIZE
  20.          jmp @b
  21. @@:
  22.          mov ecx,NtImageBase
  23.          mov dword ptr [ecx],ebx
  24.          jmp Exit
  25. SEH_Epilog_Reference:
  26.          %GET_CURRENT_GRAPH_ENTRY
  27. Exit:
  28.          Call SEH_Epilog
  29.          ret
  30. LdrGetNtImageBase endp





Ранг: 324.3 (мудрец), 222thx
Активность: 0.480.37
Статус: Участник

Создано: 27 июля 2010 03:23 · Поправил: DenCoder
· Личное сообщение · #8

Code:
  1. BYTE StartMd5[0x10] =
  2. {
  3.          0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
  4.          0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10
  5. };
  6.  
  7. void Cmd5Dlg::CalcMd5(int CharCount, char* s, char* Md5)
  8. {
  9.          BYTE Buffer[0x40];
  10.          //HCRYPTHASH hHash;
  11.          //CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
  12.          //DWORD HashDataLen = 0x10, DataLen = 4;
  13.          //CryptHashData(hHash, (BYTE*)s, CharCount, 0);
  14.          //CryptGetHashParam(hHash, HP_HASHVAL, (BYTE*)Md5, &HashDataLen, 0);
  15.          //CryptDestroyHash(hHash);
  16.  
  17.          _asm
  18.          {
  19.                  lea edi, Buffer
  20.                  mov edx, edi
  21.                  mov esi, s
  22.                  mov ecx, CharCount
  23.                  mov ebx, ecx
  24.                  cmp ecx, 4
  25.                  jb LeastBytesCopy
  26.  
  27.                  shr ecx, 2
  28.                  rep movsd
  29.  
  30. LeastBytesCopy:
  31.                  mov ecx, ebx
  32.                  and ecx, 3
  33.                  rep movsb
  34.  
  35.                  mov byte ptr [edi], 0x80
  36.                  inc edi
  37.                  mov ecx, ebx
  38.                  sub ecx, 0x3F
  39.                  neg ecx
  40.                  xor eax, eax
  41.                  rep stosb
  42.  
  43.                  shl ebx, 3
  44.                  mov [edx + 0x38], ebx
  45.                  
  46.                  lea esi, StartMd5
  47.                  mov edi, Md5
  48.                  mov eax, edi
  49.                  mov ecx, 4
  50.                  rep movsd
  51.  
  52.                  push eax;//Md5
  53.                  //edx - Buffer
  54.                  mov ecx, [eax];//A0
  55.                  mov ebx, [eax + 4];//A1
  56.                  mov esi, [eax + 8];//A2
  57.                  mov eax, [eax + 0xC];//A3
  58.          }
  59. #define A0 ecx
  60. #define A1 ebx
  61. #define A2 esi
  62. #define A3 eax
  63.  
  64. #define XOR(A) _asm xor edi, A
  65. #define XOR2(A, B) _asm mov edi, A;\r\n\
  66.                                               _asm xor edi, B
  67. #define OR(A) _asm or edi, A
  68. #define NOT(A) _asm not A
  69. #define AND(A) _asm and edi, A
  70. #define ADD(A) _asm add edi, A
  71. #define ADDDATA(D) _asm add edi, [edx + D]
  72. #define ROTATE(A, N) _asm rol A, N
  73. #define ADDTO(A) _asm add A, edi
  74. #define ADD2(A, B) _asm add A, B
  75.  
  76.          //1
  77.          //A0 = ((A3 ^ A2 & A1) ^ A3 + D76AA478 + D0 + A0) <<- 7 + A1
  78.          _asm mov edi, A3
  79.          XOR(A2);
  80.          AND(A1);
  81.          XOR(A3);
  82.          ADD(0xD76AA478);
  83.          ADDDATA(0);
  84.          ADDTO(A0);
  85.          ROTATE(A0, 7);
  86.          ADD2(A0, A1);
  87.  
  88.          //A3 = ((A2 ^ A1 & A0) ^ A2 + E8C7B756 + D4 + A3) <<- C + A0
  89.          _asm mov edi, A2
  90.          XOR(A1);
  91.          AND(A0);
  92.          XOR(A2);
  93.          ADD(0xE8C7B756);
  94.          ADDDATA(4);
  95.          ADDTO(A3);
  96.          ROTATE(A3, 0xC);
  97.          ADD2(A3, A0);
  98.  
  99.          //A2 = ((A1 ^ A0 & A3) ^ A1 + 242070DB + D8 + A2) <<- 11 + A3
  100.          _asm mov edi, A1
  101.          XOR(A0);
  102.          AND(A3);
  103.          XOR(A1);
  104.          ADD(0x242070DB);
  105.          ADDDATA(8);
  106.          ADDTO(A2);
  107.          ROTATE(A2, 0x11);
  108.          ADD2(A2, A3);
  109.  
  110.          //A1 = ((A0 ^ A3 & A2) ^ A0 + C1BDCEEE + DC + A1) <<- 16 + A2
  111.          _asm mov edi, A0
  112.          XOR(A3);
  113.          AND(A2);
  114.          XOR(A0);
  115.          ADD(0xC1BDCEEE);
  116.          ADDDATA(0xC);
  117.          ADDTO(A1);
  118.          ROTATE(A1, 0x16);
  119.          ADD2(A1, A2);
  120.  
  121.          //2
  122.          //A0 = ((A3 ^ A2 & A1) ^ A3 + F57C0FAF + D10 + A0) <<- 7 + A1
  123.          _asm mov edi, A3
  124.          XOR(A2);
  125.          AND(A1);
  126.          XOR(A3);
  127.          ADD(0xF57C0FAF);
  128.          ADDDATA(0x10);
  129.          ADDTO(A0);
  130.          ROTATE(A0, 7);
  131.          ADD2(A0, A1);
  132.  
  133.          //A3 = ((A2 ^ A1 & A0) ^ A2 + 4787C62A + D14 + A3) <<- C + A0
  134.          _asm mov edi, A2
  135.          XOR(A1);
  136.          AND(A0);
  137.          XOR(A2);
  138.          ADD(0x4787C62A);
  139.          ADDDATA(0x14);
  140.          ADDTO(A3);
  141.          ROTATE(A3, 0xC);
  142.          ADD2(A3, A0);
  143.  
  144.          //A2 = ((A1 ^ A0 & A3) ^ A1 + A8304613 + D18 + A2) <<- 11 + A3
  145.          _asm mov edi, A1
  146.          XOR(A0);
  147.          AND(A3);
  148.          XOR(A1);
  149.          ADD(0xA8304613);
  150.          ADDDATA(0x18);
  151.          ADDTO(A2);
  152.          ROTATE(A2, 0x11);
  153.          ADD2(A2, A3);
  154.  
  155.          //A1 = ((A0 ^ A3 & A2) ^ A0 + FD469501 + D1C + A1) <<- 16 + A2
  156.          _asm mov edi, A0
  157.          XOR(A3);
  158.          AND(A2);
  159.          XOR(A0);
  160.          ADD(0xFD469501);
  161.          ADDDATA(0x1C);
  162.          ADDTO(A1);
  163.          ROTATE(A1, 0x16);
  164.          ADD2(A1, A2);
  165.  
  166.          //3
  167.          //A0 = ((A3 ^ A2 & A1) ^ A3 + 698098D8 + D20 + A0) <<- 7 + A1
  168.          _asm mov edi, A3
  169.          XOR(A2);
  170.          AND(A1);
  171.          XOR(A3);
  172.          ADD(0x698098D8);
  173.          ADDDATA(0x20);
  174.          ADDTO(A0);
  175.          ROTATE(A0, 7);
  176.          ADD2(A0, A1);
  177.  
  178.          //A3 = ((A2 ^ A1 & A0) ^ A2 + 8B44F7AF + D24 + A3) <<- C + A0
  179.          _asm mov edi, A2
  180.          XOR(A1);
  181.          AND(A0);
  182.          XOR(A2);
  183.          ADD(0x8B44F7AF);
  184.          ADDDATA(0x24);
  185.          ADDTO(A3);
  186.          ROTATE(A3, 0xC);
  187.          ADD2(A3, A0);
  188.  
  189.          //A2 = ((A1 ^ A0 & A3) ^ A1 + FFFF5BB1 + D28 + A2) <<- 11 + A3
  190.          _asm mov edi, A1
  191.          XOR(A0);
  192.          AND(A3);
  193.          XOR(A1);
  194.          ADD(0xFFFF5BB1);
  195.          ADDDATA(0x28);
  196.          ADDTO(A2);
  197.          ROTATE(A2, 0x11);
  198.          ADD2(A2, A3);
  199.  
  200.          //A1 = ((A0 ^ A3 & A2) ^ A0 + 895CD7BE + D2C + A1) <<- 16 + A2
  201.          _asm mov edi, A0
  202.          XOR(A3);
  203.          AND(A2);
  204.          XOR(A0);
  205.          ADD(0x895CD7BE);
  206.          ADDDATA(0x2C);
  207.          ADDTO(A1);
  208.          ROTATE(A1, 0x16);
  209.          ADD2(A1, A2);
  210.  
  211.          //4
  212.          //A0 = ((A3 ^ A2 & A1) ^ A3 + 6B901122 + D30 + A0) <<- 7 + A1
  213.          _asm mov edi, A3
  214.          XOR(A2);
  215.          AND(A1);
  216.          XOR(A3);
  217.          ADD(0x6B901122);
  218.          ADDDATA(0x30);
  219.          ADDTO(A0);
  220.          ROTATE(A0, 7);
  221.          ADD2(A0, A1);
  222.  
  223.          //A3 = ((A2 ^ A1 & A0) ^ A2 + FD987193 + D34 + A3) <<- C + A0
  224.          _asm mov edi, A2
  225.          XOR(A1);
  226.          AND(A0);
  227.          XOR(A2);
  228.          ADD(0xFD987193);
  229.          ADDDATA(0x34);
  230.          ADDTO(A3);
  231.          ROTATE(A3, 0xC);
  232.          ADD2(A3, A0);
  233.  
  234.          //A2 = ((A1 ^ A0 & A3) ^ A1 + A679438E + D38 + A2) <<- 11 + A3
  235.          _asm mov edi, A1
  236.          XOR(A0);
  237.          AND(A3);
  238.          XOR(A1);
  239.          ADD(0xA679438E);
  240.          ADDDATA(0x38);
  241.          ADDTO(A2);
  242.          ROTATE(A2, 0x11);
  243.          ADD2(A2, A3);
  244.  
  245.          //A1 = ((A0 ^ A3 & A2) ^ A0 + 49B40821 + D3C + A1) <<- 16 + A2
  246.          _asm mov edi, A0
  247.          XOR(A3);
  248.          AND(A2);
  249.          XOR(A0);
  250.          ADD(0x49B40821);
  251.          ADDDATA(0x3C);
  252.          ADDTO(A1);
  253.          ROTATE(A1, 0x16);
  254.          ADD2(A1, A2);
  255.  
  256.  
  257.          //5
  258.          //A0 = ((A2 ^ A1 & A3) ^ A2 + F61E2562 + D4 + A0) <<- 5 + A1
  259.          _asm mov edi, A2
  260.          XOR(A1);
  261.          AND(A3);
  262.          XOR(A2);
  263.          ADD(0xF61E2562);
  264.          ADDDATA(0x4);
  265.          ADDTO(A0);
  266.          ROTATE(A0, 5);
  267.          ADD2(A0, A1);
  268.  
  269.          //A3 = ((A1 ^ A0 & A2) ^ A1 + C040B340 + D18 + A3) <<- 9 + A0
  270.          _asm mov edi, A1
  271.          XOR(A0);
  272.          AND(A2);
  273.          XOR(A1);
  274.          ADD(0xC040B340);
  275.          ADDDATA(0x18);
  276.          ADDTO(A3);
  277.          ROTATE(A3, 9);
  278.          ADD2(A3, A0);
  279.  
  280.          //A2 = ((A0 ^ A3 & A1) ^ A0 + 265E5A51 + D2C + A2) <<- E + A3
  281.          _asm mov edi, A0
  282.          XOR(A3);
  283.          AND(A1);
  284.          XOR(A0);
  285.          ADD(0x265E5A51);
  286.          ADDDATA(0x2C);
  287.          ADDTO(A2);
  288.          ROTATE(A2, 0xE);
  289.          ADD2(A2, A3);
  290.  
  291.          //A1 = ((A3 ^ A2 & A0) ^ A3 + E9B6C7AA + D0 + A1) <<- 14 + A2
  292.          _asm mov edi, A3
  293.          XOR(A2);
  294.          AND(A0);
  295.          XOR(A3);
  296.          ADD(0xE9B6C7AA);
  297.          ADDDATA(0x0);
  298.          ADDTO(A1);
  299.          ROTATE(A1, 0x14);
  300.          ADD2(A1, A2);
  301.  
  302.          //6
  303.          //A0 = ((A2 ^ A1 & A3) ^ A2 + D62F105D + D14 + A0) <<- 5 + A1
  304.          _asm mov edi, A2
  305.          XOR(A1);
  306.          AND(A3);
  307.          XOR(A2);
  308.          ADD(0xD62F105D);
  309.          ADDDATA(0x14);
  310.          ADDTO(A0);
  311.          ROTATE(A0, 5);
  312.          ADD2(A0, A1);
  313.  
  314.          //A3 = ((A1 ^ A0 & A2) ^ A1 + 02441453 + D28 + A3) <<- 9 + A0
  315.          _asm mov edi, A1
  316.          XOR(A0);
  317.          AND(A2);
  318.          XOR(A1);
  319.          ADD(0x02441453);
  320.          ADDDATA(0x28);
  321.          ADDTO(A3);
  322.          ROTATE(A3, 9);
  323.          ADD2(A3, A0);
  324.  
  325.          //A2 = ((A0 ^ A3 & A1) ^ A0 + D8A1E681 + D3C + A2) <<- E + A3
  326.          _asm mov edi, A0
  327.          XOR(A3);
  328.          AND(A1);
  329.          XOR(A0);
  330.          ADD(0xD8A1E681);
  331.          ADDDATA(0x3C);
  332.          ADDTO(A2);
  333.          ROTATE(A2, 0xE);
  334.          ADD2(A2, A3);
  335.  
  336.          //A1 = ((A3 ^ A2 & A0) ^ A3 + E7D3FBC8 + D10 + A1) <<- 14 + A2
  337.          _asm mov edi, A3
  338.          XOR(A2);
  339.          AND(A0);
  340.          XOR(A3);
  341.          ADD(0xE7D3FBC8);
  342.          ADDDATA(0x10);
  343.          ADDTO(A1);
  344.          ROTATE(A1, 0x14);
  345.          ADD2(A1, A2);
  346.  
  347.          //7
  348.          //A0 = ((A2 ^ A1 & A3) ^ A2 + 21E1CDE6 + D24 + A0) <<- 5 + A1
  349.          _asm mov edi, A2
  350.          XOR(A1);
  351.          AND(A3);
  352.          XOR(A2);
  353.          ADD(0x21E1CDE6);
  354.          ADDDATA(0x24);
  355.          ADDTO(A0);
  356.          ROTATE(A0, 5);
  357.          ADD2(A0, A1);
  358.  
  359.          //A3 = ((A1 ^ A0 & A2) ^ A1 + C33707D6 + D38 + A3) <<- 9 + A0
  360.          _asm mov edi, A1
  361.          XOR(A0);
  362.          AND(A2);
  363.          XOR(A1);
  364.          ADD(0xC33707D6);
  365.          ADDDATA(0x38);
  366.          ADDTO(A3);
  367.          ROTATE(A3, 9);
  368.          ADD2(A3, A0);
  369.  
  370.          //A2 = ((A0 ^ A3 & A1) ^ A0 + F4D50D87 + DC + A2) <<- E + A3
  371.          _asm mov edi, A0
  372.          XOR(A3);
  373.          AND(A1);
  374.          XOR(A0);
  375.          ADD(0xF4D50D87);
  376.          ADDDATA(0x0C);
  377.          ADDTO(A2);
  378.          ROTATE(A2, 0xE);
  379.          ADD2(A2, A3);
  380.  
  381.          //A1 = ((A3 ^ A2 & A0) ^ A3 + 455A14ED + D20 + A1) <<- 14 + A2
  382.          _asm mov edi, A3
  383.          XOR(A2);
  384.          AND(A0);
  385.          XOR(A3);
  386.          ADD(0x455A14ED);
  387.          ADDDATA(0x20);
  388.          ADDTO(A1);
  389.          ROTATE(A1, 0x14);
  390.          ADD2(A1, A2);
  391.  
  392.          //8
  393.          //A0 = ((A2 ^ A1 & A3) ^ A2 + A9E3E905 + D34 + A0) <<- 5 + A1
  394.          _asm mov edi, A2
  395.          XOR(A1);
  396.          AND(A3);
  397.          XOR(A2);
  398.          ADD(0xA9E3E905);
  399.          ADDDATA(0x34);
  400.          ADDTO(A0);
  401.          ROTATE(A0, 5);
  402.          ADD2(A0, A1);
  403.  
  404.          //A3 = ((A1 ^ A0 & A2) ^ A1 + FCEFA3F8 + D8 + A3) <<- 9 + A0
  405.          _asm mov edi, A1
  406.          XOR(A0);
  407.          AND(A2);
  408.          XOR(A1);
  409.          ADD(0xFCEFA3F8);
  410.          ADDDATA(0x08);
  411.          ADDTO(A3);
  412.          ROTATE(A3, 9);
  413.          ADD2(A3, A0);
  414.  
  415.          //A2 = ((A0 ^ A3 & A1) ^ A0 + 676F02D9 + D1C + A2) <<- E + A3
  416.          _asm mov edi, A0
  417.          XOR(A3);
  418.          AND(A1);
  419.          XOR(A0);
  420.          ADD(0x676F02D9);
  421.          ADDDATA(0x1C);
  422.          ADDTO(A2);
  423.          ROTATE(A2, 0xE);
  424.          ADD2(A2, A3);
  425.  
  426.          //A1 = ((A3 ^ A2 & A0) ^ A3 + 8D2A4C8A + D30 + A1) <<- 14 + A2
  427.          _asm mov edi, A3
  428.          XOR(A2);
  429.          AND(A0);
  430.          XOR(A3);
  431.          ADD(0x8D2A4C8A);
  432.          ADDDATA(0x30);
  433.          ADDTO(A1);
  434.          ROTATE(A1, 0x14);
  435.          ADD2(A1, A2);


-----
IZ.RU





Ранг: 324.3 (мудрец), 222thx
Активность: 0.480.37
Статус: Участник

Создано: 27 июля 2010 03:25
· Личное сообщение · #9

Code:
  1.          //9
  2.          //A0 = (A3 ^ A2 ^ A1 + FFFA3942 + D14 + A0) <<- 4 + A1
  3.          _asm mov edi, A3
  4.          XOR(A2);
  5.          XOR(A1);
  6.          ADD(0xFFFA3942);
  7.          ADDDATA(0x14);
  8.          ADDTO(A0);
  9.          ROTATE(A0, 4);
  10.          ADD2(A0, A1);
  11.  
  12.          //A3 = (A2 ^ A1 ^ A0 + 8771F681 + D20 + A3) <<- B + A0
  13.          _asm mov edi, A2
  14.          XOR(A1);
  15.          XOR(A0);
  16.          ADD(0x8771F681);
  17.          ADDDATA(0x20);
  18.          ADDTO(A3);
  19.          ROTATE(A3, 0xB);
  20.          ADD2(A3, A0);
  21.  
  22.          //A2 = (A1 ^ A0 ^ A3 + 6D9D6122 + D2C + A2) <<- 10 + A3
  23.          _asm mov edi, A1
  24.          XOR(A0);
  25.          XOR(A3);
  26.          ADD(0x6D9D6122);
  27.          ADDDATA(0x2C);
  28.          ADDTO(A2);
  29.          ROTATE(A2, 0x10);
  30.          ADD2(A2, A3);
  31.  
  32.          //A1 = (A0 ^ A3 ^ A2 + FDE5380C + D38 + A1) <<- 17 + A2
  33.          _asm mov edi, A0
  34.          XOR(A3);
  35.          XOR(A2);
  36.          ADD(0xFDE5380C);
  37.          ADDDATA(0x38);
  38.          ADDTO(A1);
  39.          ROTATE(A1, 0x17);
  40.          ADD2(A1, A2);
  41.  
  42.          //A
  43.          //A0 = (A3 ^ A2 ^ A1 + A4BEEA44 + D4 + A0) <<- 4 + A1
  44.          _asm mov edi, A3
  45.          XOR(A2);
  46.          XOR(A1);
  47.          ADD(0xA4BEEA44);
  48.          ADDDATA(0x04);
  49.          ADDTO(A0);
  50.          ROTATE(A0, 4);
  51.          ADD2(A0, A1);
  52.  
  53.          //A3 = (A2 ^ A1 ^ A0 + 4BDECFA9 + D10 + A3) <<- B + A0
  54.          _asm mov edi, A2
  55.          XOR(A1);
  56.          XOR(A0);
  57.          ADD(0x4BDECFA9);
  58.          ADDDATA(0x10);
  59.          ADDTO(A3);
  60.          ROTATE(A3, 0xB);
  61.          ADD2(A3, A0);
  62.  
  63.          //A2 = (A1 ^ A0 ^ A3 + F6BB4B60 + D1C + A2) <<- 10 + A3
  64.          _asm mov edi, A1
  65.          XOR(A0);
  66.          XOR(A3);
  67.          ADD(0xF6BB4B60);
  68.          ADDDATA(0x1C);
  69.          ADDTO(A2);
  70.          ROTATE(A2, 0x10);
  71.          ADD2(A2, A3);
  72.  
  73.          //A1 = (A0 ^ A3 ^ A2 + BEBFBC70 + D28 + A1) <<- 17 + A2
  74.          _asm mov edi, A0
  75.          XOR(A3);
  76.          XOR(A2);
  77.          ADD(0xBEBFBC70);
  78.          ADDDATA(0x28);
  79.          ADDTO(A1);
  80.          ROTATE(A1, 0x17);
  81.          ADD2(A1, A2);
  82.  
  83.          //B
  84.          //A0 = (A3 ^ A2 ^ A1 + 289B7EC6 + D34 + A0) <<- 4 + A1
  85.          _asm mov edi, A3
  86.          XOR(A2);
  87.          XOR(A1);
  88.          ADD(0x289B7EC6);
  89.          ADDDATA(0x34);
  90.          ADDTO(A0);
  91.          ROTATE(A0, 4);
  92.          ADD2(A0, A1);
  93.  
  94.          //A3 = (A2 ^ A1 ^ A0 + EAA127FA + D0 + A3) <<- B + A0
  95.          _asm mov edi, A2
  96.          XOR(A1);
  97.          XOR(A0);
  98.          ADD(0xEAA127FA);
  99.          ADDDATA(0x00);
  100.          ADDTO(A3);
  101.          ROTATE(A3, 0xB);
  102.          ADD2(A3, A0);
  103.  
  104.          //A2 = (A1 ^ A0 ^ A3 + D4EF3085 + DC + A2) <<- 10 + A3
  105.          _asm mov edi, A1
  106.          XOR(A0);
  107.          XOR(A3);
  108.          ADD(0xD4EF3085);
  109.          ADDDATA(0x0C);
  110.          ADDTO(A2);
  111.          ROTATE(A2, 0x10);
  112.          ADD2(A2, A3);
  113.  
  114.          //A1 = (A0 ^ A3 ^ A2 + 04881D05 + D18 + A1) <<- 17 + A2
  115.          _asm mov edi, A0
  116.          XOR(A3);
  117.          XOR(A2);
  118.          ADD(0x04881D05);
  119.          ADDDATA(0x18);
  120.          ADDTO(A1);
  121.          ROTATE(A1, 0x17);
  122.          ADD2(A1, A2);
  123.  
  124.          //C
  125.          //A0 = (A3 ^ A2 ^ A1 + D9D4D039 + D24 + A0) <<- 4 + A1
  126.          _asm mov edi, A3
  127.          XOR(A2);
  128.          XOR(A1);
  129.          ADD(0xD9D4D039);
  130.          ADDDATA(0x24);
  131.          ADDTO(A0);
  132.          ROTATE(A0, 4);
  133.          ADD2(A0, A1);
  134.  
  135.          //A3 = (A2 ^ A1 ^ A0 + E6DB99E5 + D30 + A3) <<- B + A0
  136.          _asm mov edi, A2
  137.          XOR(A1);
  138.          XOR(A0);
  139.          ADD(0xE6DB99E5);
  140.          ADDDATA(0x30);
  141.          ADDTO(A3);
  142.          ROTATE(A3, 0xB);
  143.          ADD2(A3, A0);
  144.  
  145.          //A2 = (A1 ^ A0 ^ A3 + 1FA27CF8 + D3C + A2) <<- 10 + A3
  146.          _asm mov edi, A1
  147.          XOR(A0);
  148.          XOR(A3);
  149.          ADD(0x1FA27CF8);
  150.          ADDDATA(0x3C);
  151.          ADDTO(A2);
  152.          ROTATE(A2, 0x10);
  153.          ADD2(A2, A3);
  154.  
  155.          //A1 = (A0 ^ A3 ^ A2 + C4AC5665 + D8 + A1) <<- 17 + A2
  156.          _asm mov edi, A0
  157.          XOR(A3);
  158.          XOR(A2);
  159.          ADD(0xC4AC5665);
  160.          ADDDATA(0x08);
  161.          ADDTO(A1);
  162.          ROTATE(A1, 0x17);
  163.          ADD2(A1, A2);
  164.  
  165.  
  166.          //D
  167.          //A0 = ((~A3 | A1) ^ A2 + F4292244 + D0 + A0) <<- 6 + A1
  168.          _asm mov edi, A3
  169.          XOR(-1);
  170.          OR(A1);
  171.          XOR(A2);
  172.          ADD(0xF4292244);
  173.          ADDDATA(0x00);
  174.          ADDTO(A0);
  175.          ROTATE(A0, 0x06);
  176.          ADD2(A0, A1);
  177.  
  178.          //A3 = ((~A2 | A0) ^ A1 + 432AFF97 + D1C + A3) <<- A + A0
  179.          _asm mov edi, A2
  180.          XOR(-1);
  181.          OR(A0);
  182.          XOR(A1);
  183.          ADD(0x432AFF97);
  184.          ADDDATA(0x1C);
  185.          ADDTO(A3);
  186.          ROTATE(A3, 0x0A);
  187.          ADD2(A3, A0);
  188.  
  189.          //A2 = ((~A1 | A3) ^ A0 + AB9423A7 + D38 + A2) <<- F + A3
  190.          _asm mov edi, A1
  191.          XOR(-1);
  192.          OR(A3);
  193.          XOR(A0);
  194.          ADD(0xAB9423A7);
  195.          ADDDATA(0x38);
  196.          ADDTO(A2);
  197.          ROTATE(A2, 0x0F);
  198.          ADD2(A2, A3);
  199.  
  200.          //A1 = ((~A0 | A2) ^ A3 + FC93A039 + D14 + A1) <<- 15 + A2
  201.          _asm mov edi, A0
  202.          XOR(-1);
  203.          OR(A2);
  204.          XOR(A3);
  205.          ADD(0xFC93A039);
  206.          ADDDATA(0x14);
  207.          ADDTO(A1);
  208.          ROTATE(A1, 0x15);
  209.          ADD2(A1, A2);
  210.  
  211.          //E
  212.          //A0 = ((~A3 | A1) ^ A2 + 655B59C3 + D30 + A0) <<- 6 + A1
  213.          _asm mov edi, A3
  214.          XOR(-1);
  215.          OR(A1);
  216.          XOR(A2);
  217.          ADD(0x655B59C3);
  218.          ADDDATA(0x30);
  219.          ADDTO(A0);
  220.          ROTATE(A0, 0x06);
  221.          ADD2(A0, A1);
  222.  
  223.          //A3 = ((~A2 | A0) ^ A1 + 8F0CCC92 + DC + A3) <<- A + A0
  224.          _asm mov edi, A2
  225.          XOR(-1);
  226.          OR(A0);
  227.          XOR(A1);
  228.          ADD(0x8F0CCC92);
  229.          ADDDATA(0x0C);
  230.          ADDTO(A3);
  231.          ROTATE(A3, 0x0A);
  232.          ADD2(A3, A0);
  233.  
  234.          //A2 = ((~A1 | A3) ^ A0 + FFEFF47D + D28 + A2) <<- F + A3
  235.          _asm mov edi, A1
  236.          XOR(-1);
  237.          OR(A3);
  238.          XOR(A0);
  239.          ADD(0xFFEFF47D);
  240.          ADDDATA(0x28);
  241.          ADDTO(A2);
  242.          ROTATE(A2, 0x0F);
  243.          ADD2(A2, A3);
  244.  
  245.          //A1 = ((~A0 | A2) ^ A3 + 85845DD1 + D4 + A1) <<- 15 + A2
  246.          _asm mov edi, A0
  247.          XOR(-1);
  248.          OR(A2);
  249.          XOR(A3);
  250.          ADD(0x85845DD1);
  251.          ADDDATA(0x04);
  252.          ADDTO(A1);
  253.          ROTATE(A1, 0x15);
  254.          ADD2(A1, A2);
  255.  
  256.          //F
  257.          //A0 = ((~A3 | A1) ^ A2 + 6FA87E4F + D20 + A0) <<- 6 + A1
  258.          _asm mov edi, A3
  259.          XOR(-1);
  260.          OR(A1);
  261.          XOR(A2);
  262.          ADD(0x6FA87E4F);
  263.          ADDDATA(0x20);
  264.          ADDTO(A0);
  265.          ROTATE(A0, 0x06);
  266.          ADD2(A0, A1);
  267.  
  268.          //A3 = ((~A2 | A0) ^ A1 + FE2CE6E0 + D3C + A3) <<- A + A0
  269.          _asm mov edi, A2
  270.          XOR(-1);
  271.          OR(A0);
  272.          XOR(A1);
  273.          ADD(0xFE2CE6E0);
  274.          ADDDATA(0x3C);
  275.          ADDTO(A3);
  276.          ROTATE(A3, 0x0A);
  277.          ADD2(A3, A0);
  278.  
  279.          //A2 = ((~A1 | A3) ^ A0 + A3014314 + D18 + A2) <<- F + A3
  280.          _asm mov edi, A1
  281.          XOR(-1);
  282.          OR(A3);
  283.          XOR(A0);
  284.          ADD(0xA3014314);
  285.          ADDDATA(0x18);
  286.          ADDTO(A2);
  287.          ROTATE(A2, 0x0F);
  288.          ADD2(A2, A3);
  289.  
  290.          //A1 = ((~A0 | A2) ^ A3 + 4E0811A1 + D34 + A1) <<- 15 + A2
  291.          _asm mov edi, A0
  292.          XOR(-1);
  293.          OR(A2);
  294.          XOR(A3);
  295.          ADD(0x4E0811A1);
  296.          ADDDATA(0x34);
  297.          ADDTO(A1);
  298.          ROTATE(A1, 0x15);
  299.          ADD2(A1, A2);
  300.  
  301.          //10
  302.          //A0 = ((~A3 | A1) ^ A2 + F7537E82 + D10 + A0) <<- 6 + A1
  303.          _asm mov edi, A3
  304.          XOR(-1);
  305.          OR(A1);
  306.          XOR(A2);
  307.          ADD(0xF7537E82);
  308.          ADDDATA(0x10);
  309.          ADDTO(A0);
  310.          ROTATE(A0, 0x06);
  311.          ADD2(A0, A1);
  312.  
  313.          //A3 = ((~A2 | A0) ^ A1 + BD3AF235 + D2C + A3) <<- A + A0
  314.          _asm mov edi, A2
  315.          XOR(-1);
  316.          OR(A0);
  317.          XOR(A1);
  318.          ADD(0xBD3AF235);
  319.          ADDDATA(0x2C);
  320.          ADDTO(A3);
  321.          ROTATE(A3, 0x0A);
  322.          ADD2(A3, A0);
  323.  
  324.          //A2 = ((~A1 | A3) ^ A0 + 2AD7D2BB + D8 + A2) <<- F + A3
  325.          _asm mov edi, A1
  326.          XOR(-1);
  327.          OR(A3);
  328.          XOR(A0);
  329.          ADD(0x2AD7D2BB);
  330.          ADDDATA(0x08);
  331.          ADDTO(A2);
  332.          ROTATE(A2, 0x0F);
  333.          ADD2(A2, A3);
  334.  
  335.          //A1 = ((~A0 | A2) ^ A3 + EB86D391 + D24 + A1) <<- 15 + A2
  336.          _asm mov edi, A0
  337.          XOR(-1);
  338.          OR(A2);
  339.          XOR(A3);
  340.          ADD(0xEB86D391);
  341.          ADDDATA(0x24);
  342.          ADDTO(A1);
  343.          ROTATE(A1, 0x15);
  344.          ADD2(A1, A2);
  345.  
  346.          _asm
  347.          {
  348.                  pop edi;//Md5
  349.                  //A0 += A0 начальное
  350.                  add [edi], A0
  351.                  //A4 += A1 начальное
  352.                  add [edi + 4], A1
  353.                  //A8 += A2 начальное
  354.                  add [edi + 8], A2
  355.                  //AC += A3 начальное
  356.                  add [edi + 0xC], A3
  357.          }
  358. }


-----
IZ.RU




Ранг: 47.1 (посетитель), 2thx
Активность: 0.030
Статус: Участник

Создано: 13 августа 2010 00:11 · Поправил: Vol4ok
· Личное сообщение · #10

Реализаций RWLock-ов в виде класса для С++ - сделаны по аналогии ERESOURCE в ядре.
Класс незаменим когда нужен рекурсивный доступ к разделяемому ресурсу, windows не предоставляет в user-mode таких синхрообъектов. Крайне высокой производительностью класс не отличается, особенно при высокой конкуренции потоков, но для обеспечения безопасного доступа к разделяемы объектам, при невысокой конкуренции - идеально подходит. Класс протестирован.

Code:
  1. /*
  2.  *  RWLock.hpp
  3.  *  Created by vol4ok, 12/08/2010
  4.  */
  5.  
  6. #include <windows.h>
  7. #include "stdint.h"
  8. #include <assert.h>
  9.  
  10. #define RWL_MAX_SHARED_THREADS 2048
  11.  
  12. class RWLock {
  13.  
  14.          typedef struct {
  15.                  uint32_t thread;
  16.                  uint32_t count;
  17.          } OwnerEntry;
  18.  
  19.          long         m_lock;
  20.          uint32_t                 m_flags;
  21.          uint32_t                 m_active;
  22.          uint32_t                 m_excWaiters;
  23.          uint32_t                 m_shdWaiters;
  24.          HANDLE            m_semaphore;
  25.          HANDLE            m_event;
  26.          OwnerEntry             m_owners[2];
  27.          uint32_t                 m_tableSize;
  28.          OwnerEntry*      m_ownerTable;
  29.          uint32_t                 m_ownerTableExpands;
  30.  
  31.  
  32.          enum{
  33.                  RWL_LOCK_BIT = 0,
  34.                  RWL_EXCLUSIVE_BIT = 1,
  35.          };
  36.  
  37.          enum{
  38.                  RWL_LOCK = 1,
  39.                  RWL_EXCLUSIVE = 2,
  40.          };
  41.  
  42.          void lock()
  43.          {
  44.                  while (InterlockedBitTestAndSet(&m_lock,0))
  45.                         Sleep(0);
  46.          }
  47.  
  48.          void unlock()
  49.          {
  50.                  InterlockedBitTestAndReset(&m_lock,0);
  51.          }
  52.  
  53.          void expandOwnerTable()
  54.          {
  55.                  uint32_t newSize;
  56.                  uint32_t oldSize;
  57.                  OwnerEntry* oldTable;
  58.                  OwnerEntry* ownerTable;
  59.  
  60.                  m_ownerTableExpands++;
  61.  
  62.                  oldTable = m_ownerTable;
  63.                  if (oldTable == NULL) {
  64.                         /* if m_ownerTable not has been initialized */
  65.                         oldSize = 0;
  66.                         newSize = 3;
  67.                  } else {
  68.                         /* if m_ownerTable already initialized */
  69.                         oldSize = m_tableSize;
  70.                         newSize = oldSize + 4;
  71.                  }
  72.  
  73.                  unlock();
  74.  
  75.                  ownerTable = reinterpret_cast<OwnerEntry*>(malloc(newSize * sizeof(OwnerEntry)));
  76.  
  77.                  if (!ownerTable)
  78.                         throw "Memory allocation failure!";
  79.                  else {
  80.                         ZeroMemory(ownerTable + oldSize, (newSize - oldSize) * sizeof(OwnerEntry));
  81.  
  82.                         lock();
  83.                         /* was other thread has been expand table while allocating memory? */
  84.                         if (oldTable != m_ownerTable
  85.                               || (oldTable != NULL && oldSize != m_tableSize)) {
  86.                                    /* abort expanding */
  87.                                    unlock();
  88.                                    free(ownerTable);
  89.                         } else {
  90.                               memcpy(ownerTable, oldTable, oldSize * sizeof(OwnerEntry));
  91.  
  92.                               m_tableSize = newSize;
  93.                               m_ownerTable = ownerTable;
  94.  
  95.                               unlock();
  96.                               if (oldTable)
  97.                                    free(oldTable);
  98.                         }
  99.                  }
  100.  
  101.                  lock();
  102.          }
  103.  
  104.          OwnerEntry* findEmptyEntry() {
  105.                  OwnerEntry* ownerBound;
  106.                  OwnerEntry* ownerEntry;
  107.  
  108.                  assert(m_lock != 0);
  109.                  assert(m_owners[0].thread != 0);
  110.  
  111.                  /* find free entries in m_owners first */
  112.                  if (m_owners[1].thread == 0)
  113.                         return &m_owners[1];
  114.  
  115.                  /* find free entries in owner table */
  116.                  if (m_ownerTable) {
  117.                         assert(m_tableSize > 0);
  118.                         ownerEntry = m_ownerTable;
  119.                         ownerBound = &ownerEntry[m_tableSize - 1];
  120.                         do {
  121.                               if (ownerEntry->thread == 0)
  122.                                    return ownerEntry;
  123.  
  124.                               ownerEntry += 1;
  125.                         } while (ownerEntry != ownerBound);
  126.                  }
  127.                  
  128.                  /* no free entries, then expand table */
  129.                  expandOwnerTable();
  130.                  return NULL;
  131.          }
  132.  
  133.          OwnerEntry* findCurrentThread(uint32_t currentThread, bool findFree = true) {
  134.                  OwnerEntry* freeEntry;
  135.                  OwnerEntry* ownerBound;
  136.                  OwnerEntry* ownerEntry;
  137.  
  138.                  /* find free entries in m_owners first */
  139.                  ownerEntry = &m_owners[0];
  140.                  if (ownerEntry->thread == currentThread)
  141.                         return ownerEntry;
  142.  
  143.                  ownerEntry += 1;
  144.                  if (ownerEntry->thread == currentThread)
  145.                         return ownerEntry;
  146.  
  147.                  /* remember free entry, if present */
  148.                  if (ownerEntry->thread == 0)
  149.                         freeEntry = ownerEntry;
  150.                  else
  151.                         freeEntry = NULL;
  152.  
  153.                  /* find free entries in owner table */
  154.                  if (m_ownerTable) {
  155.                         assert(m_tableSize > 0);
  156.                         ownerEntry = m_ownerTable;
  157.                         ownerBound = &ownerEntry[m_tableSize - 1];
  158.  
  159.                         do {
  160.                               if (ownerEntry->thread == currentThread)
  161.                                    return ownerEntry;
  162.  
  163.                               /* remember free entry */
  164.                               if (freeEntry == NULL && ownerEntry->thread == 0)
  165.                                    freeEntry = ownerEntry;
  166.  
  167.                               ownerEntry += 1;
  168.                         } while (ownerEntry != ownerBound);
  169.                  }
  170.  
  171.                  /* return, if free entry is doesn't needed */
  172.                  if (!findFree)
  173.                         return NULL;
  174.  
  175.                  /* return free entry, if present */
  176.                  if (freeEntry != NULL)
  177.                         return freeEntry;
  178.  
  179.                  /* no free entries, then expand table */
  180.                  expandOwnerTable();
  181.                  return NULL;
  182.  
  183.          }
  184.  
  185. public:
  186.          RWLock()
  187.                  : m_lock(0)
  188.                  , m_flags(0)
  189.                  , m_active(0)
  190.                  , m_excWaiters(0)
  191.                  , m_shdWaiters(0)
  192.                  , m_semaphore(CreateSemaphore(NULL, 0, RWL_MAX_SHARED_THREADS, NULL))
  193.                  , m_event(CreateEvent(NULL, FALSE, FALSE, NULL))
  194.                  , m_tableSize(0)
  195.                  , m_ownerTable(NULL)
  196.                  , m_ownerTableExpands(0)
  197.          {
  198.                  ZeroMemory(m_owners,sizeof(m_owners));
  199.          }
  200.  
  201.          virtual ~RWLock()
  202.          {
  203.                  acquireExclusive();
  204.  
  205.                  lock();
  206.  
  207.                  if (m_excWaiters || m_shdWaiters) {
  208.                         unlock();
  209.                         release();
  210.                         throw "Can't free RWLock, shared or exclusive waiters is present!";
  211.                  }
  212.  
  213.                  CloseHandle(m_event);
  214.                  CloseHandle(m_semaphore);
  215.  
  216.                  free(m_ownerTable);
  217.  
  218.                  unlock();
  219.          }
  220.  
  221.  
  222.          bool acquireExclusive(bool wait = true)
  223.          {
  224.                  uint32_t currentThread = GetCurrentThreadId();
  225.                  bool res = true;
  226.  
  227.                  /* enter critical section */
  228.                  lock();
  229.  
  230.                  /* already locket? */
  231.                  if (m_active != 0) {
  232.  
  233.                         /* locked by me? */
  234.                         if (m_flags & RWL_EXCLUSIVE
  235.                               && m_owners[0].thread == currentThread) {
  236.  
  237.                                    assert(m_owners[0].count > 0);
  238.  
  239.                                    m_owners[0].count++;
  240.  
  241.                         } else {
  242.  
  243.                               /* locked shared or exclusive by other thread */
  244.  
  245.                               if (!wait) {
  246.  
  247.                                    res = false;
  248.  
  249.                               } else {
  250.  
  251.                                    /* add exclusive waiter and wait for release */
  252.  
  253.                                    m_excWaiters++;
  254.                                    unlock();
  255.  
  256.                                    WaitForSingleObjectEx(m_event,INFINITE,TRUE);
  257.  
  258.                                    m_owners[0].thread = currentThread;
  259.  
  260.                                    assert(m_active == 1);
  261.  
  262.                                    return true;
  263.                               }
  264.  
  265.                         }
  266.                  } else {
  267.  
  268.                         /* unlocked - acquire it! */
  269.  
  270.                         m_flags |= RWL_EXCLUSIVE;
  271.                         m_owners[0].thread = currentThread;
  272.                         m_owners[0].count = 1;
  273.                         m_active = 1;
  274.  
  275.                  }
  276.  
  277.                  unlock();
  278.  
  279.                  return res;
  280.          }
  281.  
  282.          bool acquireShared(bool wait = true)
  283.          {
  284.                  uint32_t currentThread = GetCurrentThreadId();
  285.                  OwnerEntry* entry = NULL;
  286.  
  287.                  /* enter critical section */
  288.                  lock();
  289.  
  290. retry:
  291.                  /* if unlocked - acquire it */
  292.                  if (m_active == 0) {
  293.  
  294.                         m_owners[0].thread = currentThread;
  295.                         m_owners[0].count = 1;
  296.                         m_active = 1;
  297.                         unlock();
  298.  
  299.                         return true;
  300.                  }
  301.  
  302.                  /* locked exclusive? */
  303.                  if (m_flags & RWL_EXCLUSIVE) {
  304.  
  305.                         /* locked by me? */
  306.                         if (m_owners[0].thread == currentThread) {
  307.  
  308.                               /* acquire recursive and exit */
  309.  
  310.                               assert(m_owners[0].count > 0);
  311.  
  312.                               m_owners[0].count++;
  313.                               unlock();
  314.                               return true;
  315.                         }
  316.  
  317.                         /* else find free entry */
  318.                         entry = findEmptyEntry();
  319.                         if (!entry)
  320.                               goto retry;
  321.  
  322.                  } else {
  323.  
  324.                         /* locked shared */
  325.  
  326.                         /* find entry with current thread or free entry*/
  327.                         entry = findCurrentThread(currentThread);
  328.                         if (!entry)
  329.                               goto retry;
  330.  
  331.                         assert(entry != 0);
  332.  
  333.                         /* check, is it current thread entry? */
  334.                         if (entry->thread == currentThread) {
  335.  
  336.                               /* acquire recursive and exit */
  337.                               assert(entry->count > 0);
  338.                               entry->count++;
  339.                               unlock();
  340.                               return true;
  341.                         }
  342.  
  343.                         /* if no exclusive waiters then acquire and exit*/
  344.                         if (m_excWaiters == 0) {
  345.                               entry->thread = currentThread;
  346.                               entry->count = 1;
  347.                               m_active += 1;
  348.                               unlock();
  349.                               return true;
  350.                         }
  351.                  }
  352.  
  353.                  assert(entry != NULL);
  354.  
  355.                  if (!wait) {
  356.                         unlock();
  357.                         return false;
  358.                  }
  359.  
  360.                  /* wait for exclusive release */
  361.  
  362.                  entry->thread = currentThread;
  363.                  entry->count = 1;
  364.                  m_shdWaiters++;
  365.                  unlock();
  366.  
  367.                  WaitForSingleObject(m_semaphore,INFINITE);
  368.  
  369.                  return true;
  370.          }
  371.  
  372.          void release()
  373.          {
  374.                  uint32_t currentThread = GetCurrentThreadId();
  375.  
  376.                  /* enter critical section */
  377.                  lock();
  378.  
  379.                  /* dummy check */
  380.                  if (m_active == 0) {
  381.                         unlock();
  382.                         return;
  383.                  }
  384.  
  385.                  /* is exclusive? */
  386.                  if (m_flags & RWL_EXCLUSIVE) {
  387.  
  388.                         assert(m_owners[0].count > 0);
  389.  
  390.                         /* release recursive lock */
  391.                         if (--m_owners[0].count != 0) {
  392.                               unlock();
  393.                               return;
  394.                         }
  395.  
  396.                         assert(m_owners[0].count == 0);
  397.  
  398.                         m_owners[0].thread = 0;
  399.  
  400.                         assert(m_active == 1);
  401.  
  402.                         if (--m_active == 0) {
  403.  
  404.                               /* if shared waiter exist - start it */
  405.                               if (m_shdWaiters > 0) {
  406.  
  407.                                    uint32_t num = m_shdWaiters;
  408.                                    m_flags &= ~RWL_EXCLUSIVE;
  409.                                    m_active = num;
  410.                                    m_shdWaiters = 0;
  411.                                    unlock();
  412.  
  413.                                    ReleaseSemaphore(m_semaphore, num, NULL);
  414.  
  415.                                    return;
  416.  
  417.                               } else if (m_excWaiters > 0) {
  418.  
  419.                                    /* else if exclusive waiter exist - start it */
  420.  
  421.                                    m_owners[0].thread = 1;
  422.                                    m_owners[0].count = 1;
  423.                                    m_active = 1;
  424.                                    m_excWaiters -= 1;
  425.                                    unlock();
  426.  
  427.                                    SetEvent(m_event);
  428.  
  429.                                    return;
  430.                               }
  431.                               m_flags &= ~RWL_EXCLUSIVE;
  432.  
  433.                         }
  434.  
  435.                  } else {
  436.  
  437.                         /* release shared */
  438.  
  439.                         OwnerEntry* entry = NULL;
  440.  
  441.                         /* find entry */
  442.                         if (m_owners[1].thread == currentThread)
  443.                               entry = &m_owners[1];
  444.                         else if (m_owners[0].thread == currentThread)
  445.                               entry = &m_owners[0];
  446.                         else {
  447.                               assert(m_ownerTable != NULL);
  448.                               assert(m_tableSize > 0);
  449.  
  450.                               entry = m_ownerTable;
  451.                               OwnerEntry* ownerEnd = &entry[m_tableSize - 1];
  452.                               while (true) {
  453.                                    assert(entry <= ownerEnd);
  454.                                    if (entry->thread == currentThread)
  455.                                        break;
  456.                                    entry += 1;
  457.                               }
  458.                         }
  459.  
  460.                         assert(entry != NULL);
  461.                         assert(entry->thread == currentThread);
  462.                         assert(entry->count > 0);
  463.  
  464.                         if (--entry->count != 0) {
  465.                               /* release recursive lock */
  466.                               unlock();
  467.                               return;
  468.                         }
  469.                         entry->thread = 0;
  470.  
  471.                         assert(entry->count == 0);
  472.                         assert(m_active > 0);
  473.  
  474.                         /* if exclusive waiter exists - start it */
  475.                         if (--m_active == 0) {
  476.                               if (m_excWaiters > 0) {
  477.                                    m_flags |= RWL_EXCLUSIVE;
  478.                                    m_owners[0].thread = 1;
  479.                                    m_owners[0].count = 1;
  480.                                    m_active = 1;
  481.                                    m_excWaiters -= 1;
  482.                                    unlock();
  483.  
  484.                                    SetEvent(m_event);
  485.  
  486.                                    return;
  487.                               }
  488.                         }
  489.                  }
  490.  
  491.                  unlock();
  492.  
  493.                  return;
  494.          }
  495.  
  496.          void convertExclusiveToShared()
  497.          {
  498.                  assert(m_flags & RWL_EXCLUSIVE);
  499.                  assert(m_owners[0].thread == GetCurrentThreadId());
  500.  
  501.                  lock();
  502.  
  503.                  m_flags &= ~RWL_EXCLUSIVE;
  504.  
  505.                  /* if shared waiter exist - start it */
  506.                  if (m_shdWaiters) {
  507.                         uint32_t num = m_shdWaiters;
  508.                         m_active += num;
  509.                         m_shdWaiters = 0;
  510.                         unlock();
  511.  
  512.                         ReleaseSemaphore(m_semaphore, num, NULL);
  513.  
  514.                         return;
  515.                  }
  516.  
  517.                  unlock();
  518.                  return;
  519.          }
  520.  
  521. };



<< . 1 . 2 . 3 .
 eXeL@B —› Программирование —› Небольшие полезные коды
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати