Author Topic: MultiThreading Problem  (Read 1878 times)

0 Members and 1 Guest are viewing this topic.

Offline rain_storm

  • Here comes the Rain
  • DBF Aficionado
  • ******
  • Posts: 3088
  • Karma: 182
  • Rain never hurt nobody
    • View Profile
    • org_100h
MultiThreading Problem
« on: January 27, 2011 »
I seem to be having some trouble getting to grips with multithreading.

My idea was to spawn one thread for drawing, another for generating audio. The drawing thread works well, the problem is that I can't get Saida's synth to work in a multithreading prog.

The synth works just fine if you simply call the proc but it will not work if I launch the synth as a thread, nor will it work if I launch the draw proc as a thread then call synth directly.

It's probably something ridiculously simple but I just can't see it. Can anybody spot what I'm missing here?

stdcall
Code: [Select]
format  pe console
 entry   start
 include "windows.inc"

 RESX = 0x100
 RESY = 0x0C0

 data import
      library kernel32, "kernel32",\
              user32,   "user32",\
              gdi32,    "gdi32",\
              winmm,    "winmm.dll"
      include "api\kernel32.inc"
      include "api\user32.inc"
      include "api\gdi32.inc"
      import  winmm,\
              midiOutClose,    "midiOutClose",\
              midiOutOpen,     "midiOutOpen",\
              midiOutShortMsg, "midiOutShortMsg"
 end  data

 proc start
      ;xor     edi, edi
      ;invoke  GetModuleHandle, edi, edi
      ;invoke  CreateWindowEx, edi, edit, edi, WS_POPUP+WS_VISIBLE+WS_MAXIMIZE, edi, edi, edi, edi, edi, edi, eax, edi
      ;mov     [hWnd], eax
      ;invoke  GetDC, [hWnd]
      ;mov     [hDC], eax
      ;invoke  ShowCursor;, 0  ; <- was the second param for GetModuleHandle(0,wtf)
      ;invoke  CreateThread, 0, 0, draw, 0, 0, idDraw
      ;mov     [hDraw], eax
      ;invoke  CreateThread, 0, 0, synth, 0, 0, idSynth
      ;mov     [hSynth], eax
       call   synth
;.main:
     ;invoke  GetAsyncKeyState, VK_ESCAPE
     ;test    eax, eax
     ;jz      .main

     ;invoke  CloseHandle, [hSynth]
     ;invoke  CloseHandle, [hDraw]
     ;invoke  midiOutClose, [hMidi]
     ;invoke  ReleaseDC, [hWnd], [hDC]
     ;invoke  DestroyWindow, [hWnd]
     ;invoke  ExitProcess, 0
      ret
 endp

 proc draw
      invoke  GetClientRect, [hWnd], rc
      invoke  StretchDIBits, [hDC], 0, 0, [rc.right], [rc.bottom], 0, 0, RESX, RESY, pixel, bmi, 0, SRCCOPY
      inc     [curFrame]
      mov     edi, pixel
      mov     ecx, RESX*RESY
 .draw:
      movzx   eax, cl
      dec     al
      xor     al, ch
      add     eax, [curFrame]
      stosd
      loop    .draw
      jmp     draw
 endp

 proc synth
      xor     eax, eax
      mov     edi, hMidi
      push    eax
      push    eax
      push    eax
      dec     eax
      invoke  midiOutOpen, edi, eax

 .reset:
      mov     esi, edi
      lodsd

 .load:
      lodsb
      xchg    ah, al
      xor     ebx, ebx
      add     bl, ah
      jz      .reset
      shr     bl, 5
      and     ebx, 00000011b
      mov     bx, word [edi-16+(2*ebx)]
      mov     ecx, eax
      and     ax, 0001111100000000b
      or      eax, 00000000011111110010000010010001b
      push    eax
      push    dword [edi]
      xchg    eax, ecx
      sahf
      mov     eax, [edi-8]
      js      .done
      mov     eax, [edi-4]
 .done:
      push    eax
      push    dword [edi]
      invoke  midiOutShortMsg
      invoke  midiOutShortMsg
      invoke  Sleep, ebx
      jmp     .load
 endp

 lengths     dw 240, 1, 0, 0
 Instruments dd 12594625, 12594625
 hMidi       dd ?
 db 10000101b,10101001b,10001100b
 db 10000000b,10101001b,10001100b
 db 10000101b,10101001b,10001100b
 db 10000000b,10101001b,10001100b
 db 10000101b,10101001b,10001100b
 db 10000000b,10101001b,10001100b
 db 10000101b,10000000b,10000010b
 db 10000100b,00000000b

 edit     db "edit",0
 bmi      dd 40,RESX,RESY,0x200001,?,?,?,?,?,?,?,?,?,?
 hWnd     dd ?
 hDC      dd ?
 rc       RECT ?,?,?,?
 curFrame dd ?

 idDraw   dd ?
 hDraw    dd ?
 idSynth  dd ?
 hSynth   dd ?

 pixel    dd RESX*RESY dup ?

Multithreaded
Code: [Select]

 format  pe console
 entry   start
 include "windows.inc"

 RESX = 0x100
 RESY = 0x0C0

 data import
      library kernel32, "kernel32",\
              user32,   "user32",\
              gdi32,    "gdi32",\
              winmm,    "winmm.dll"
      include "api\kernel32.inc"
      include "api\user32.inc"
      include "api\gdi32.inc"
      import  winmm,\
              midiOutClose,    "midiOutClose",\
              midiOutOpen,     "midiOutOpen",\
              midiOutShortMsg, "midiOutShortMsg"
 end  data

 proc start
       xor     edi, edi
       invoke  GetModuleHandle, edi, edi
       invoke  CreateWindowEx, edi, edit, edi, WS_POPUP+WS_VISIBLE+WS_MAXIMIZE, edi, edi, edi, edi, edi, edi, eax, edi
       mov     [hWnd], eax
       invoke  GetDC, [hWnd]
       mov     [hDC], eax
       invoke  ShowCursor;, 0  ; <- was the second param for GetModuleHandle(0,wtf)
       invoke  CreateThread, 0, 0, draw, 0, 0, idDraw
       mov     [hDraw], eax
       invoke  CreateThread, 0, 0, synth, 0, 0, idSynth
       mov     [hSynth], eax
      ;call   synth
 .main:
      invoke  GetAsyncKeyState, VK_ESCAPE
      test    eax, eax
      jz      .main

      invoke  CloseHandle, [hSynth]
      invoke  CloseHandle, [hDraw]
      invoke  midiOutClose, [hMidi]
      invoke  ReleaseDC, [hWnd], [hDC]
      invoke  DestroyWindow, [hWnd]
      invoke  ExitProcess, 0
      ret
 endp

 proc draw
      invoke  GetClientRect, [hWnd], rc
      invoke  StretchDIBits, [hDC], 0, 0, [rc.right], [rc.bottom], 0, 0, RESX, RESY, pixel, bmi, 0, SRCCOPY
      inc     [curFrame]
      mov     edi, pixel
      mov     ecx, RESX*RESY
 .draw:
      movzx   eax, cl
      dec     al
      xor     al, ch
      add     eax, [curFrame]
      stosd
      loop    .draw
      jmp     draw
 endp

 proc synth
      xor     eax, eax
      mov     edi, hMidi
      push    eax
      push    eax
      push    eax
      dec     eax
      invoke  midiOutOpen, edi, eax

 .reset:
      mov     esi, edi
      lodsd

 .load:
      lodsb
      xchg    ah, al
      xor     ebx, ebx
      add     bl, ah
      jz      .reset
      shr     bl, 5
      and     ebx, 00000011b
      mov     bx, word [edi-16+(2*ebx)]
      mov     ecx, eax
      and     ax, 0001111100000000b
      or      eax, 00000000011111110010000010010001b
      push    eax
      push    dword [edi]
      xchg    eax, ecx
      sahf
      mov     eax, [edi-8]
      js      .done
      mov     eax, [edi-4]
 .done:
      push    eax
      push    dword [edi]
      invoke  midiOutShortMsg
      invoke  midiOutShortMsg
      invoke  Sleep, ebx
      jmp     .load
 endp

 lengths     dw 240, 1, 0, 0
 Instruments dd 12594625, 12594625
 hMidi       dd ?
 db 10000101b,10101001b,10001100b
 db 10000000b,10101001b,10001100b
 db 10000101b,10101001b,10001100b
 db 10000000b,10101001b,10001100b
 db 10000101b,10101001b,10001100b
 db 10000000b,10101001b,10001100b
 db 10000101b,10000000b,10000010b
 db 10000100b,00000000b

 edit     db "edit",0
 bmi      dd 40,RESX,RESY,0x200001,?,?,?,?,?,?,?,?,?,?
 hWnd     dd ?
 hDC      dd ?
 rc       RECT ?,?,?,?
 curFrame dd ?

 idDraw   dd ?
 hDraw    dd ?
 idSynth  dd ?
 hSynth   dd ?

 pixel    dd RESX*RESY dup ?
« Last Edit: January 27, 2011 by rain_storm »

Challenge Trophies Won:

Offline Rbz

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 2721
  • Karma: 484
    • View Profile
    • http://www.rbraz.com/
Re: MultiThreading Problem
« Reply #1 on: January 28, 2011 »
You need to set thread priority for each one, "THREAD_PRIORITY_NORMAL" should do for draw proc and "THREAD_PRIORITY_TIME_CRITICAL" for synth proc.
Challenge Trophies Won:

Offline rain_storm

  • Here comes the Rain
  • DBF Aficionado
  • ******
  • Posts: 3088
  • Karma: 182
  • Rain never hurt nobody
    • View Profile
    • org_100h
Re: MultiThreading Problem
« Reply #2 on: January 28, 2011 »
Awesome!!! Thanks rbz, K up

Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: MultiThreading Problem
« Reply #3 on: January 28, 2011 »
You may not need to fiddle with the task priorities if you make sure your threads at least yield some time back to the OS.  So if each of them called
Sleep(0) periodically it will be a lot more OS friendly and the threads may play together better.
Or you might need to do both things.

Jim
Challenge Trophies Won: