On Wed, 06 Jan 2010, Xavi wrote:

Hi,

> Only activating HB_TRACE() with any example of /test/mt and adding
> wapi_SetLastError() you can see that this is not true.
> Just store only a single ID/lasterror pairs by thread and these pairs
> can be made easily accessible from another thread.
> I think that C don't have the problems of spoken language such as English.
> But sorry, I use my code resources made before and It's maybe the reason
> for not having seen another solution for Harbour.

Please note that the code you sent creates an array of thread IDs.
Each unique thread ID ever given by the system to thread needs separate
entry. It's not guarantied that OS tries to use as small pool of thread
IDs as possible. Usually not because such condition needs additional
operation and creates potential problems for programmers so this is
rather range of numbers cyclically reused when free.
It means that in long running programs creating a lot of (even very short
life) threads this array is systematically growing up until it reach the
size of thread IDs range used by OS.
Then for each StoreLastError() operation this code makes covered by
mutex linear scan of this array to locate calling thread entry.
Because the array is big (probably few thousands of entries for each thread
which existed before and called at least once StoreLastError()) then it's
strongly time consuming operation which usually cost much more then the
whole operation setting it. It will kill the performance. Additionally
it strongly reduce scalability because this expensive and quite frequently
used in all WIN API functions which needs to store LastError scan operation
is covered by mutex.
Current code committed by Viktor use TLS on HVM stack what resolve such
problems. Anyhow such code used even without HVM should be fixed and it
can be easy done. Just simply call:

   static DWORD s_dwTlsIndex = TLS_OUT_OF_INDEXES;

   [...]

   void StoreLastError( DWORD dwError )
   {
      if( s_dwTlsIndex == TLS_OUT_OF_INDEXES )
      {
         /* call it at least once before the 1-st thread is created to
            avoid race condition and potential resource leak */
         s_dwTlsIndex = TlsAlloc();
      }
      TlsSetValue( s_dwTlsIndex, ( LPVOID ) dwError );
   }

   DWORD RetrieveLastError( void )
   {
      return ( DWORD ) TlsGetValue( s_dwTlsIndex );
   }

Please remember that size of TLS data is limited. In bigger programs
I suggest to make s_dwTlsIndex global variable initialized at startup
and then store inside pointer to dynamically allocated structure. In
such case your code will use only one TLS item just like Harbour for
HVM stack.
If it's necessary to access such structure also by other threads then
they should be additionally linked in some public list. This is also
done by HVM which keeps list of all HVM stacks.

HTH

best regards,
Przemek
_______________________________________________
Harbour mailing list (attachment size limit: 40KB)
Harbour@harbour-project.org
http://lists.harbour-project.org/mailman/listinfo/harbour

Reply via email to