Does calling of methods and functions
Asked Answered
F

1

6

I have a question regarding calling methods from different threads. Well I am using WinUSB driver to communicate with USB device. I have separate thread to read data from device. Commands to device are set within main thread. Actually I am using WinUSB_WritePipe and WinUSB_ReadPipe methods to do such operations. In thread where data is read I use asynchronus method of reading with overlapped structure and WaitForMultipleObject. My device has some features that I need to set and this is done via GUI in main thread.

I am observing some strange behaviour. My question is do I need to lock calls (eg. with mutex) to this methods so just one thread at time is accessing or calling method.

OLD WAY:

type TMyThread = TThread
   protected
      procedure Execute; override;
end;

procedure TMyThread.Execute;
begin
  while not Terminated do
  begin   
     WinUsb_ReadPipe(Pipe, Amount, Overlapped)
     ErrNo := GetLastError;                   
     if ErrNo = ERROR_IO_PENDING then 
     begin 
       wRes = WaitForMultipleObjects(2, @HndEvt, false);
       if wRes = WAIT_OBJECT_0 then
       begin 
         ResetEvent(Overlapped.hEvent);
         WinUSB_GetOVerlappedResult
         DoSomethingWithData; // Do something
       end;
     end;  
  end;
end;

MainThread:
begin
  // Set device sample rate
  WinUSB_WritePipe (Pipe, Amount, Data, ...)
end;

NEW WAY:

type TMyThread = TThread
   protected
      procedure Execute; override;

   public
     procedure Lock;
     procedure Unlock;

     constructor Create(ASuspended: boolean); override;
     destructor  Destroy; override;
end;

constructor TMyThread.Create(ASuspended: boolean); 
begin
  hMtx := CreateMutex(nil, false, nil);
end;

destructor  TMyThread.Destroy(ASuspended: boolean); 
begin
  CloseHandle(hMtx);
end;

procedure TMyThread.Lock; 
begin
  WaitForSingleObject(hMtx, 10000);
end;

procedure TMyThread.Unlock; 
begin
  ReleaseMutex(hMtx);
end;

procedure TMyThread.Execute;
begin
  while not Terminated do
  begin   

     Lock;
     WinUsb_ReadPipe(Pipe, Amount, Overlapped)
     Unlock;

     ErrNo := GetLastError;                   
     if ErrNo = ERROR_IO_PENDING then 
     begin 
       wRes = WaitForMultipleObjects(2, @HndEvt, false);
       if wRes = WAIT_OBJECT_0 then
       begin 
         ResetEvent(Overlapped.hEvent);
         Lock;
         WinUSB_GetOVerlappedResult
         Unlock;

         DoSomethingWithData; // Do something
       end;
     end;  
  end;
end;

MainThread:
begin
  // Set device sample rate
  Lock; // same mutex as in TMYThread
  WinUSB_WritePipe (Pipe, Amount, Data, ...)
  Unlock; // same mutex as in TMYThread 
end;

This is very simplified code which intension is only for description of my problem and do not reflect my programming skills. :) Of course with same mutex I lock then calling of same method in main thread.

I hope I described my problem as simple as possible... so again: Do I need to lock calls to those methods in different threads?

Thank you for your time and answers in advance. I really apppreciate it!

Br, Nix

Fefeal answered 9/5, 2012 at 17:44 Comment(4)
You don't need to lock threads, you need to protect (eg via a lock) the shared data between threads. A mutex is a bit heavy in this case, a critical section is more than enough. All GUI related routines that are called from threads outside the main thread need to be synchronized.Arango
I expect that the device has no requirements that the reads and writes are serialised, so it comes down to you. Do your read and write threads use overlapping regions of the device?Accelerometer
Provided code is just for description of my problem. I use mutexes because I am working with dlls and I need some advanced sync. All I would like to know is if I need to lock WinUSB methods before I call them. WinUSB_ReadPipe is called from two different threads. And I am reading from different pipes in different threads. Main thread is only for commands and data thread is for data so pipes are different. When reading data I use overlapped structure. When sending commands and reading results I don't use overlapped struct. Do you think driver handles concurent calls of same WinUSB method?Fefeal
If the author from this post: microchip.com/forums/m437429-print.aspx tells the thruth, you can't use winUSB from different threads. That said I still don't understand why you need 2 threads to read the data...Arango
A
3

if you download and read the winUSB white paper you will find that there is one big drawback of winUSB : it does not support multiple concurrent applications for the same USB device. IMHO this means you can't have concurrent calls for reading.

Arango answered 10/5, 2012 at 6:20 Comment(1)
Thanks I read that again and I find out that concurent reading from different pipes should not be a problem. Reading from same pipe can be a problem and needs some locking. Thanks!Fefeal

© 2022 - 2024 — McMap. All rights reserved.