Is TFPList thread safe?

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

Is TFPList thread safe?

Xiangrong Fang
Hi,

I would like to know if TFPList is thread-safe or not? And if I make a component thread-safe by using critical sections etc. Is the performance penalty noticeable? 

Thanks.

Xiangrong



_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Is TFPList thread safe?

Michael Van Canneyt


On Thu, 2 Oct 2014, Xiangrong Fang wrote:

> Hi,
>
> I would like to know if TFPList is thread-safe or not? And if I make a component thread-safe by using critical sections etc. Is the performance penalty noticeable? 

TFPList is not thread-safe. You need to use TThreadList if you want a thread-safe list.

Critical sections use OS calls, so there is always a performance penalty.

Michael.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Is TFPList thread safe?

Michael Schnell
In reply to this post by Xiangrong Fang
On 10/02/2014 03:02 AM, Xiangrong Fang wrote:
Hi,

I would like to know if TFPList is thread-safe or not? And if I make a component thread-safe by using critical sections etc. Is the performance penalty noticeable?
For a class, Thread save" is not that easily defined.

e.g.:

It can be fully thread save (like TThreadList): you can call any function/property at any time from any thread.
It could be allowed to create multiple instances in multiple threads and use each of them with it's own thread but not with others (holds for TList)
It could be allowed to crate an instance with one thread and after that use functions/properties with a single other one. (e.g.: TList)
it could be allowed to use all instances of the class only in a one and only thread.
It could be allowed to be used only in a predefined (e.g. the main-) thread (many classes in the LCL).
...

-Michael

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Is TFPList thread safe?

Xiangrong Fang
In reply to this post by Michael Van Canneyt

2014-10-02 14:16 GMT+08:00 Michael Van Canneyt <[hidden email]>:

TFPList is not thread-safe. You need to use TThreadList if you want a thread-safe list.

Critical sections use OS calls, so there is always a performance penalty.

I think the only thread-critical operation I need is to add item to the list, so I will use critical section myself, not replace TFPList with TThreadList, for simplicity and performance reason...

Xiangrong

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Is TFPList thread safe?

Michael Schnell
In reply to this post by Michael Van Canneyt
On 10/02/2014 08:16 AM, Michael Van Canneyt wrote:
>
> Critical sections use OS calls, so there is always a performance penalty.

That is what Futex is made for.

AFAIR, in Linux, the fpc RTL calls the pthread library "mutex..."
function. This library uses Futex, if the arch supports that, and uses
the plain old MUTEX system call if the arch does not support FUTEX.

("FUTEX" = " Fast Userland MutEX" only does an OS call when necessary
(i.e. when a thread needs to wait or when another thread needs to be
woke). So in by fat most instances it just does a (atomic) userland
operation.)

-Michael

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Is TFPList thread safe?

Xiangrong Fang

2014-10-02 22:09 GMT+08:00 Michael Schnell <[hidden email]>:

AFAIR, in Linux, the fpc RTL calls the pthread library "mutex..." function. This library uses Futex, if the arch supports that, and uses the plain old MUTEX system call if the arch does not support FUTEX.

I need my program to work on both Linux and Windows, can I still use FUTEX?  For Critical Sections, FPC has the TCriticalSection object, is there a TMutex object?

Xiangrong

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Is TFPList thread safe?

Xiangrong Fang

2014-10-02 22:23 GMT+08:00 Xiangrong Fang <[hidden email]>:

2014-10-02 22:09 GMT+08:00 Michael Schnell <[hidden email]>:

AFAIR, in Linux, the fpc RTL calls the pthread library "mutex..." function. This library uses Futex, if the arch supports that, and uses the plain old MUTEX system call if the arch does not support FUTEX.

I found some quotes online:

For Windows, critical sections are lighter-weight than mutexes.
Mutexes can be shared between processes, but always result in a system call to the kernel which has some overhead. Critical sections can only be used within one process, but have the advantage that they only switch to kernel mode in the case of contention.

I only need lock WITHIN my own application, so, it seems that critical sections are better.

Xiangrong

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Is TFPList thread safe?

Jonas Maebe-2
In reply to this post by Xiangrong Fang

On 02 Oct 2014, at 15:59, Xiangrong Fang wrote:

I think the only thread-critical operation I need is to add item to the
list, so I will use critical section myself, not replace TFPList with
TThreadList, for simplicity and performance reason...

It will make your program unstable (adding an element to an fplist can cause the entire internal array to move, so if you are in the middle of a read operation at the same time, that read operation will either read invalid data or crash). Unless you are an expert at multithreaded programming, don't try to optimise existing thread-safe structures (and definitely don't perform premature optimisations).


Jonas

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Is TFPList thread safe?

Xiangrong Fang

2014-10-02 23:07 GMT+08:00 Jonas Maebe <[hidden email]>:

On 02 Oct 2014, at 15:59, Xiangrong Fang wrote:

It will make your program unstable (adding an element to an fplist can cause the entire internal array to move, so if you are in the middle of a read operation at the same time, that read operation will either read invalid data or crash). Unless you are an expert at multithreaded programming, don't try to optimise existing thread-safe structures (and definitely don't perform premature optimisations).

I don't intend to do any optimization. I just think that I need to enter a critical section, add item to the list, then leave the critical section.

I am definitely not expert in thread programming, but I am clear about the logic of my class and program.   Actually, it is a TTree object I wrote, using TFPList to store sibling nodes. There are a lot of TFPList (one per tree node).   I just need to make sure that there are no more than one thread operating on the same node at the same time.

Xiangrong



_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Is TFPList thread safe?

José Mejuto
El 03/10/2014 a las #4, Xiangrong Fang escribió:

> I don't intend to do any optimization. I just think that I need to enter
> a critical section, add item to the list, then leave the critical section.
>

Hello,

You must protect with a CriticalSection, "Add" and any other kind of
access, like indexed access. As you must protect indexed access you are
in the same penalty as using TThreadList.

Threading example to a crash (numbers are execution steps):

Thread 1
--------
1-Resolve TList data access to $00010000
2-calculate item 23 is at $00010023
3-Read $00010023
4-Crash or read from unalocated memory (content undefined).

Thread 2
--------
1-Enter "Add" function and resolve Tlist data to $00010000
2-Lock thread and find that it need to relocate data to $00020000. Move data
3-Unlock
4-Continue

--

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Is TFPList thread safe?

Michael Schnell
In reply to this post by Xiangrong Fang
On 10/02/2014 03:59 PM, Xiangrong Fang wrote:
> , not replace TFPList with TThreadList, for simplicity and performance
> reason...
I don't suppose it will be possible to beat TThreadList performance by
any home-brew Pascal code, which is same is not insecure.

-Michael
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Is TFPList thread safe?

Michael Schnell
In reply to this post by Xiangrong Fang
On 10/02/2014 04:23 PM, Xiangrong Fang wrote:



I need my program to work on both Linux and Windows, can I still use FUTEX? 
I did not recommend to use FUTEX yourself. Futex is a rather complicated thingy that needs ASM for a combination of atomic user land operations and system calls (that are done if necessary).

In Linux, the userland Futex stuff is done for you (if possible at all) in the ppthead library mutex_...() functions.

I am not sure that the fpc RTL in fact uses the pthread (standard C-language) library for TCrtitical section, but this would make sense, as in that library the dirty stuff is handled. (E.g. _not_ using FUTEX, but plain old MUTEX in case the arch does not provide FUTEX - there are several archs that don't provide FUTEX -  AFAIK, X86, X86/64 and ARM32 do provide it).

Regarding Windows, I have not much knowledge about such low-level stuff. AFAIK, all Windows system calls are done via DLLs, and so always some Microsoft code is executed in Userland, anyway.  Hence it is well possible that the Window "MUTEX" System-DLL-Call (like the pthreadlib so in Linux) automatically does a FUTEX-alike thingy.

For Critical Sections, FPC has the TCriticalSection object, is there a TMutex object?

AFAI understand, "CriticalSection" is the Delphi/fpc name for "POSIX-Mutex".

Of course you can do you own low-level implementation of a MUTEX/FUTEX  Sync-Object. Doing that directly in ASM might be slightly faster than calling the C-phtreadlib. But this definitively is hard stuff. (Unfortunately Linux does not - and supposedly will not very soon support the rather new "vdso" concept - a kind of user-land system calls - for FUTEX/MUTEX).

-Michael


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Is TFPList thread safe?

Michael Schnell
In reply to this post by Xiangrong Fang
On 10/02/2014 05:03 PM, Xiangrong Fang wrote:



For Windows, critical sections are lighter-weight than mutexes.
Mutexes can be shared between processes, but always result in a system call to the kernel which has some overhead. Critical sections can only be used within one process, but have the advantage that they only switch to kernel mode in the case of contention.

I only need lock WITHIN my own application, so, it seems that critical sections are better.

So it seems that Windows in fact does a kind of FUTEX for inter-Thread synchronizing (as does pthredlib, that as it's name says just provides  POSIX-operation within Threads, not between applications.)

Hence, provided TCrtiticalSections uses the Windows system DLL in Windows and the pthreadlib so in Linux, the resulting performance should  be very similar. 

-Michael

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Is TFPList thread safe?

Marco van de Voort
In reply to this post by Michael Schnell
In our previous episode, Michael Schnell said:

> > For Critical Sections, FPC has the TCriticalSection object, is there a
> > TMutex object?
>
> AFAI understand, "CriticalSection" is the Delphi/fpc name for
> "POSIX-Mutex".

Critical sections are bound to the owning process under Windows, while
Windows mutexes can span processes (and thus are more expensive).

So critical section is equal to posix mutex with PTHREAD_PROCESS_PRIVATE
attribute.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Is TFPList thread safe?

Michael Schnell
On 10/06/2014 12:18 PM, Marco van de Voort wrote:
> So critical section is equal to posix mutex with
> PTHREAD_PROCESS_PRIVATE attribute.
Thanks for the clearness !

(The OP of course just wants just this - synchronization between threads
of a single application.)

-Michael
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Is TFPList thread safe?

Marco van de Voort
In our previous episode, Michael Schnell said:
> > So critical section is equal to posix mutex with
> > PTHREAD_PROCESS_PRIVATE attribute.
> Thanks for the clearness !
>
> (The OP of course just wants just this - synchronization between threads
> of a single application.)

On *nix for critical section, cthreads creates a mutex of the recursive
type(_PTHREAD_MUTEX_RECURSIVE) but doesn't set that attribute, but it seems(*) that the above
attribute(PTHREAD_PROCESS_PRIVATE) is default.

(*) http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_mutexattr_getpshared.html

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Is TFPList thread safe?

Dennis Poon
In reply to this post by Michael Schnell

Michael Schnell wrote:
> On 10/02/2014 03:59 PM, Xiangrong Fang wrote:
>> , not replace TFPList with TThreadList, for simplicity and
>> performance reason...
> I don't suppose it will be possible to beat TThreadList performance by
> any home-brew Pascal code, which is same is not insecure.
>
But I looked at the source code of TThreadList,

procedure TThreadList.Add(Item: Pointer);
   begin
     LockList;
     try
       if (Duplicates=dupAccept) or
         // make sure it's not already in the list
         (FList.IndexOf(Item)=-1) then
          FList.Add(Item)
        else if (Duplicates=dupError) then
          FList.Error(SDuplicateItem,PtrUInt(Item));
     finally
       UnlockList;
     end;
   end;


where

function TThreadList.LockList: TList;
   begin
     Result:=FList;
     System.EnterCriticalSection(FLock);
   end;


There is no special optimization at all.  It simply calls
   System.EnterCriticalSection(FLock),
so performance should be JUST THE SAME as wrapping a pair of critical
section enter/leave around the code ourselves.

Dennis



_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Is TFPList thread safe?

Michael Schnell
On 10/06/2014 05:55 PM, Dennis Poon wrote:
>
>
> function TThreadList.LockList: TList;
>   begin
>     Result:=FList;
>     System.EnterCriticalSection(FLock);
>   end;
>
Yep.

System.EnterCriticalSection is a procedure variable that is set
according to the OS and arch the project is compiled for.

In Linux without  UseCThreads it is just an empty function. (OK here
creating threads is not allowed)
In Linux with  UseCThreads it is just an empty function it is a call to
pthread_mutex_lock, which is in the pthreadlib so file and calls FUTEX
or MUTEX, such as appropriate. (So don't try to "optimize" !!! )
In Windows I suppose it does a call to the Windows system DLL that
supposedly does  a FUTEX workalike.  (So don't try to "optimize" !!! )


>
> There is no special optimization at all.  It simply calls
>   System.EnterCriticalSection(FLock),
> so performance should be JUST THE SAME as wrapping a pair of critical
> section enter/leave around the code ourselves.
Yep. (So don't try to "optimize" !!! )

-Michael
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal