Re: [Lazarus] thread safe
On 29/06/2011 16:11, Michael Schnell wrote: On 06/28/2011 08:14 PM, Hans-Peter Diettrich wrote: I just found a very nice description of some aspects of thread safety in http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap02.html#tag_22_02_09_08 titled Thread-Safety. Great. Niche background information on Posix. But it does not help regarding the issue of defining a thread-safety paradigm for classes. How is the 'thread safety for classses' different from thread safety for any other code ? L. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Lukasz Sokol schrieb: On 29/06/2011 16:11, Michael Schnell wrote: On 06/28/2011 08:14 PM, Hans-Peter Diettrich wrote: I just found a very nice description of some aspects of thread safety in http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap02.html#tag_22_02_09_08 titled Thread-Safety. Great. Niche background information on Posix. But it does not help regarding the issue of defining a thread-safety paradigm for classes. How is the 'thread safety for classses' different from thread safety for any other code ? Thread-safety has many facettes. An item may be safe in one aspect, e.g. not using global variables, but unsafe in other aspects. Objects (classes) add further topics to the list of items, that make up thread-safety in general. During the various discussions I got the impression, that thread-safety only can be a headline or keyword, that leads to a detailed description of thread-related properties or behaviour of the described item. DoDi -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 30/06/2011 11:14, Hans-Peter Diettrich wrote: Lukasz Sokol schrieb: [...] How is the 'thread safety for classses' different from thread safety for any other code ? Thread-safety has many facettes. An item may be safe in one aspect, e.g. not using global variables, but unsafe in other aspects. If it is unsafe in other aspects then it is unsafe, right? (modulo what you actually need, but AFAIR there is not much too pickchoose from, because they are related and some of them imply others ?) Objects (classes) add further topics to the list of items, that make up thread-safety in general. After compilation, it's just code, isn't it? Classes may have the 'hidden' variables but they're not 'hidden' to the OS/CPU ? During the various discussions I got the impression, that thread-safety only can be a headline or keyword, that leads to a detailed description of thread-related properties or behaviour of the described item. AFAIR, code (whatever way you write it) can either BE safe or NOT, no half measyres here - any one of the 'properties' vel 'aspects' not complied with, and you can't name your code thread-safe. It may be a headline or keyword, but it should list ALL the things one need to be aware of when writing multi-threaded code? That's my view. DoDi -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/30/2011 10:09 AM, Lukasz Sokol wrote: On 29/06/2011 16:11, Michael Schnell wrote: How is the 'thread safety for classses' different from thread safety for any other code ? This already has been discussed in this thread previously. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/30/2011 01:53 PM, Lukasz Sokol wrote: After compilation, it's just code, isn't it? Yep but the programmer that writes the code using an existing object and reading it's docs does not see the code after compilation. He is inclined to consider the functions of multiple instances of a class to be unrelated code which might or might not be appropriate, depending on the classes internals. (Or anther programmer thinks the code is related, which might in fact be too restrictive.) -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/30/2011 01:53 PM, Lukasz Sokol wrote: AFAIR, code (whatever way you write it) can either BE safe or NOT, no half measyres here - any one of the 'properties' vel 'aspects' not complied with, and you can't name your code thread-safe. A function easily can be thread safe _only_ if a parameter of same is different for each thread: var a array [0...10] of Integer; Function x(i); begin a[i] := a[i] + 1; end; A very likely case with the hidden self parameter of class instances. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Lukasz Sokol schrieb: Objects (classes) add further topics to the list of items, that make up thread-safety in general. After compilation, it's just code, isn't it? Classes may have the 'hidden' variables but they're not 'hidden' to the OS/CPU ? Objects include information, that may be subject to race conditions, deadlocks and other unwanted things. A thread-safe definition for procedures covers nothing of what applies to thread-safe objects. DoDi -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Tue, Jun 28, 2011 at 2:32 PM, Hans-Peter Diettrich drdiettri...@aol.com wrote: Andrew Brunner schrieb: In a bidirectionally linked list up to 4 pointers have to be updated together, whenever an element is inserted or removed. This leaves much room for race conditions, that cannot be cured by protecting every single pointer. Instead the entire chain must be protected, by a MUTEX or other synchronization means. And then it's only a *convention*, which object or memory block shall be protected by a MUTEX, no memory barrier prevents access without obtaining the MUTEX first. Kind of a memory barrier can be established by putting the list object (head) into a TThreadList, *provided that* no code will retain references to list elements after releasing the list object. I had a similar issue once. Above is my comment on your example ;-) The above comment has nothing to do with my example. My example was the one with 2 lines of code being executed by two different cores under the same thread protected within a criticalsection. My experience though, was shared where I happened to have a memory barrier in place, and experienced a problem with order or stale values that was solved by using InterlockedExchange calls. Why do you see a need for Interlocked updates, when only one thread can access the list at the same time? Primarily because I want to enforce core cache updates to the values. IMO Interlocked updates are fine for self-contained values, where the use of critical sections would be overkill. But when multiple variables have to be updated without interruption (synchronously, atomically), the entire data object should be protected against concurrent access. I see it as a matter of coding discipline, and how to make disobedience as impossible as possible ;-) Obedience is not germane to the topic of this particular issue of core cache and interlockedexhange. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/28/2011 08:34 PM, Hans-Peter Diettrich wrote: Another aspect seems to be the synchronization of *all* data, in *all* caches. Is this correct, or do I expect too much? Not necessary (e.g.) on detecting that a cache line resides in multiple caches doing an immediate write back and invalidating for all other caches a cache line that is written to in one cache would forces a synchronization without too much overhead. AFAIK certain processors provide a dedicated fast inter-cache bus for such operations. I suppose how exactly this is done depends on the CPU manufacturer. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/28/2011 08:14 PM, Hans-Peter Diettrich wrote: I just found a very nice description of some aspects of thread safety in http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap02.html#tag_22_02_09_08 titled Thread-Safety. Great. Niche background information on Posix. But it does not help regarding the issue of defining a thread-safety paradigm for classes. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Hello Lazarus-List, Wednesday, June 29, 2011, 5:09:22 PM, you wrote: *** This one must work Thread/core/processor 2 --- while true do begin Critical.Enter; if ab then Raise Exception.Create('KBOOM!'); Critical.Leave; end; If the second one will not work in a n-code processor, or SMP, please tell me why not. Of course the performance will be quite poor. MS Did you experience that it does not work ? IMHO that would be really ban MS news. No, exactly the opposite, I do not see how it could fail about memory order access, cache coherence, ... -- Best regards, José -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Tue, 28 Jun 2011 04:18:55 +0200 Reimar Grabowski reimg...@web.de wrote: On Mon, 27 Jun 2011 18:41:46 -0500 Andrew Brunner andrew.t.brun...@gmail.com wrote: This is relatively new theory which required low-level CPU code to perform such locks. This was never needed until the introduction of multi-core systems. Excuse my ignorance but what is different on multi-core systems compared to multi-processor systems which are around for quite some time? They used a more conservative cache system. A write automatically invalidated the cache of the other cpus. Mattias -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/27/2011 08:03 PM, Andrew Brunner wrote: entercricitalsection(); loop a:=b+c; end loop; leavecriticalsection(); thread 2 can read a and b and c at any state. If you want an accurate view of a,b,c you need to employ interlocked statements :-) Hmm. In this example, b and c are not modified so in fact any view is accurate at a certain point of time. Moreover doing the critical section outside of a lop does not make much sense. A more obvious example would be Thread 1: loop entercricitalsection(); a:=a+1; b:=b+a; leavecriticalsection(); end loop; Here another thread just fetching a and b could get inconsistent (not representing a the same loop) value of a and b. IMHO if the other thread would do entercricitalsection(); a1:=a; a2:=b+a; leavecriticalsection(); write a1 and a2 it will show consistant values. Here, it is not possible to force consistent values by interlocked instructions, as there is no interlocked instruction that does a:=a+1 and b:=b+a in a single hardware lock. So using the critical section in both threads is necessary to force consistency. An example that can be done with interlocked instructions (and thus prevents the huge overhead introduced by a critical section) is Thread 1: loop a:=a+1; end loop; Thread 2: loop a:=a-1; end loop; -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/28/2011 12:31 AM, Andrew Brunner wrote: 2.) Execution Order. As a critical section is a function call, it prevents instructions are re-ordered from being inside of the protected code sequence to being outside. And what happens inside the protected code sequence is not prone to mutual access anyway. Please do not odder any analogies but construct a decent example sowing how you think something can go wrong and why. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/28/2011 01:41 AM, Andrew Brunner wrote: 2011/6/27 Malcom Haakinsane...@gmail.com: In fact in cases this this the use of CriticalSections would be sensible and Thread 1: ... This is relatively new theory which required low-level CPU code to perform such locks. This was never needed until the introduction of multi-core systems. Of which I did extensive tests on AMD via FPC/Lazarus. We are discussing here if a critical would offer data integrity with threads or not (without additionally using low level CPU code). Your example does not say anything about this. Of course we all know that in certain cases there are better performing option than critical sections (using low level code). But this is not to be discussed right now. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/28/2011 10:48 AM, Michael Schnell wrote: ... I forgot to mention that the variables a and b need to be defined as volatile (mentioning this C-keyword) and thus need to be global/static which makes Pascal to handle them as volatile (not cashing them in CPU registers). I don't know if/how it in Pascal is possible to define stack-variables to be handled as volatile. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 28/06/11 11:13, Henry Vermaak wrote: On 27/06/11 23:31, Andrew Brunner wrote: AMD vs Intel. Kernels Linux vs Windows. The only way to make sure How does the kernel matter? Other than the cpu, compilers can also reorder instructions. You can use __asm__ __volatile__(: : :memory) in c to stop gcc from screwing around with the order, for example. This is of course if a hardware memory barrier isn't necessary. you can get code in proper order with regard to memory assignments ( specifically variables) is to use Interlocked methods. This is why they were designed. No. You have to use memory barriers for this. Atomic operations are only useful for single data elements. To add to this, on x86 the memory barrier is probably implemented with an atomic instruction. Henry -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/28/2011 12:13 PM, Henry Vermaak wrote: Other than the cpu, compilers can also reorder instructions. AFAIK modern CPUs can do on the fly instruction reordering and Register renaming, but (other than speed) this should be transparent ant not detectable when looking at what the CPU actually does. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Marco van de Voort schrieb: On Mon, Jun 27, 2011 at 03:05:36PM +0100, Hans-Peter Diettrich wrote: OOP is just a convenient abstraction, it's for people needed only :) OOP is for designers, not for hackers ;-) When some thread-safe code must never bring a program (automaton, system...) into an inconsistent state, objects are fine to break down the entire program into self-contained sub-systems. This allows to dramatically reduce the degree of freedom of the entire (flattened) problem. Whatever can be done entirely inside an object, deserves no further consideration of everything outside the object. Are you talking about monitors? How else will you force an object with only one thread in it? Or are you meaning thread+TLS+state exclusively used in the thread as object? I'm not talking specifically about threads here, instead of OOP and program design in general. An interactive program is much harder to control than a batch-style program with almost sequential control flow. When you try to create a state/transition diagram (automaton, state machine), with allowed actions and transitions for every possible state, then this will be almost impossible for an interactive program (too many possible states). When that huge automaton is broken down into sub-automatons (objects), with their own internal states and transitions, then the overall application will have to respect only a fraction of the total possible states. Every object will settle down in a limited set of allowed states, and the logic of the main program must not deal with the many *intermediate* states, that may occur inside an object. Imagine a file object, that may implement included files, an undo list and whatever you like. Such an object includes many sub-objects (lists...) and variables (file positions, undo pointers...), which can be in very many different states (values). But those states, that are of interest to the controlling program, can be restricted to simple informations like IsOpen:boolean, and all further validity checks and transitions can be encapsulated in the publicly accessible methods (actions). This model can be extended for threads, where a single test for e.g. obj.Locked will reveal whether access to *all* of the object's members is currently allowed. When such objects know about related objects, that will be accessed during some operation (method call), the number of these objects will be much lower than the number of variables, that had to be locked *individually* before the operation can start. That reduced number of dependencies will simplify the implementation of strategies for deadlock prevention and resolution. I've been following this subthread for a couple of posts yet, and the whole picture leaves an vague feeling. ACK. Using threads requires more than only TThread objects, which are useless without a reliable thread synchronization model, *and* an according implementation of this model in application specific code. DoDi -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Andrew Brunner schrieb: On Mon, Jun 27, 2011 at 2:51 PM, Hans-Peter Diettrich drdiettri...@aol.com wrote: Absolutely incorrect. Why? Two reasons. 1.) Visibility. A critical section does not particularly protect visibility as with 2 threads accessing a piece of memory. This is exactly what I wanted to say. A critical section does *not* enforce a MB (by visibility). 2.) Execution Order. A critical section does not protect or ensure that code will be executed in any particular order. Right. When execution order (race conditions) is of interest, it must be established by other means. Here is where deadlocks enter the scene. I think that you didn't understand what I wanted to say. Hard to tell, due to the snipped details you are referring to :-( DoDi -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Andrew Brunner schrieb: This is relatively new theory which required low-level CPU code to perform such locks. This is not new. String operations (CMPS...) can be interrupted since a long time, and it took some more time until even the single-core CPUs could resume such an interrupted instruction correctly. You're right that CMPXCHG and similar instructions have been missing in older instruction sets, but these would have been useful also in single-core CPUs with interrupt capabilities. Really new is the need for cache synchronization, when multiple processors or cores use their own caches, including on-chip (instruction...) caches. But wasn't this already of concern in memory-mapped I/O (graphics cards)? Cache look aside? DoDi -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Henry Vermaak wrote: On 27/06/11 23:31, Andrew Brunner wrote: 2.) Execution Order. A critical section does not protect or ensure that code will be executed in any particular order. This is where How do you know this? Unfortunately I can't read the code for the Windows critical sections and the documentation doesn't explicitly state anything, but at least pthread mutex guarantees a memory barrier. So if you're using the fpc rtl critical sections on unix (which uses pthread_mutex), your statement is false. You'll have to read the generated assembler for Windows critical sections. My hunch would be that they use memory barriers, too. On processors that support them, which I think excludes x86. My understanding is that in the general case membars are there to enforce sanity when a processor can reorder memory accesses. As such they don't guarantee anything either way when multiple threads are considered on an SMP/multicore system, they're just part of the overall picture. -- Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues] -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/28/2011 12:44 PM, Hans-Peter Diettrich wrote: This is exactly what I wanted to say. A critical section does *not* enforce a MB (by visibility). All references I read today say that pthread_mutex (on which supposedly TCriticalSection is based) and the appropriate Windows stuff does contain an MB. But there might be issues with other OSes and Archs. If they would not do so, the complete plain old threaded application paradigm would be invalid, and tons of applications would need to be trashed. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
2011/6/27 Malcom Haak insane...@gmail.com: OF WHAT? bad code? It would only look different if you are looking at different parts of memory.. or you hadn't finished writing. Are you serious? Also what the hell are you on about? You could use CriticalSections in your example and it would work fine. The fact you have one Thread doing nothing for ever is a tad silly and to me shows you have no idea what you are doing.. but that could be just because of the exceedingly limited scope of the example. You haven't a clue. Core X computes a=b+c Core X+Y computes a2 Why would you spilt this into different threads?? If it is the same thread it does not matter if it moves CPU... Your example is lacking in sanity. This code is written and compiled to execute in thread 1 as per example. Line T : Core X computes a=b+c Line T+1 : Core X+Y computes a2 T+1 most likely will be completed before line T is computed! And it is not poor practice to have threads communicating reading/writing variables. Your lack of understanding multi-threaded systems is evident. This is relatively new theory which required low-level CPU code to perform such locks. This was never needed until the introduction of multi-core systems. Of which I did extensive tests on AMD via FPC/Lazarus. Yeah your just sounding silly here. As per Reimar Grabowski's comment, whats the difference between multi-core and Multi-processor? I'll tell you... accessibility to people who don't know what they are on about. No. I speak with experience. Whether or not you are able to learn/comprehend what I am illustrating - that is a different matter. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/28/2011 12:35 PM, Hans-Peter Diettrich wrote: *and* an according implementation of this model in application specific code. Yep but the application program should not (need to) be aware of what architecture (Processor-Type, SMP,...) it is running on nor know about the underlying OS or system libraries (MUETX/FUTEX, ...). For the user program, protecting the data structures by TCriticalSection() (if necessary according to the description e.g. of the LCL objects it uses) should suffice. If this is not like that, I consider it a bug. Which might not be helpful if there is no decent way to cure it. In this case: what workaround can be used ? -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Tue, Jun 28, 2011 at 7:40 AM, Michael Schnell mschn...@lumino.de wrote: All references I read today say that pthread_mutex (on which supposedly TCriticalSection is based) and the appropriate Windows stuff does contain an MB. But there might be issues with other OSes and Archs. Yes, any object that requires atomic features will employ a memory barrier. That is to say the MB is employed in order for the spincount to be accurate across all cores. If they would not do so, the complete plain old threaded application paradigm would be invalid, and tons of applications would need to be trashed. -Michael Probably right here. My engine had worked fine on a tripple core AMD. It wasn't until I upgraded to the 6 core system did I have to start looking into what was causing random problems with pointer assignments. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 28/06/11 11:43, Michael Schnell wrote: On 06/28/2011 12:24 PM, Henry Vermaak wrote: To add to this, on x86 the memory barrier is probably implemented with an atomic instruction. Like MUTEX/FUTEX (and critical section) on the system level all this needs to be done using atomic (and with SMP bus locking / cache invalidating) instructions (with no-SMP, disabling the interrupt would be another system-level option). Different architectures have specific memory barrier instructions which must be used. For example, arm has DMB, DSB, ISB. Henry -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/28/2011 02:47 PM, Andrew Brunner wrote: Yes, any object that requires atomic features will employ a memory barrier. That is to say the MB is employed in order for the spincount to be accurate across all cores. As for a user program the only way to handle atomic operations is to protect them by a MUTEX (TCriticalSection in FPC) and same does include the memory barrier we hopefully are safe. My engine had worked fine on a tripple core AMD. It wasn't until I upgraded to the 6 core system did I have to start looking into what was causing random problems with pointer assignments. Of course it might be possible that it just was good luck that it worked on the 3-Core (because the bad timing condition did not ever occur). But there also might be some bug somewhere. As said before besides all this complicated stuff the critical variable needs to be handled as volatile by the compiler (not caching it in a register while opening or closing the critical section). I have no Idea how this can be enforced in FPC. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Tue, Jun 28, 2011 at 8:00 AM, Michael Schnell mschn...@lumino.de wrote: As said before besides all this complicated stuff the critical variable needs to be handled as volatile by the compiler (not caching it in a register while opening or closing the critical section). I have no Idea how this can be enforced in FPC. You are wrong. There is no complicated stuff. Just use interlocked assignments for high performance computing :-) -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/28/2011 03:00 PM, Andrew Brunner wrote: There is no complicated stuff. Just use interlocked assignments for high performance computing :-) This is low level stuff and not what user programs are supposed to do. User land programs only know Posix as their system interface. If the performance of Posix is not good enough you can use low level interfaces to do very dedicated non portable high performance programs. But when only using Posix the program should work correctly on all systems that provide Posix (including a million core SMP). Otherwise somewhere there is a bug. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Tue, Jun 28, 2011 at 8:27 AM, Michael Schnell mschn...@lumino.de wrote: On 06/28/2011 03:00 PM, Andrew Brunner wrote: There is no complicated stuff. Just use interlocked assignments for high performance computing :-) This is low level stuff and not what user programs are supposed to do. User land programs only know Posix as their system interface. LOL All the Interlocked / Compare and Swap statements are included in the system unit and are readily available and tested (at least on AMD). -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/28/2011 03:30 PM, Andrew Brunner wrote: LOL All the Interlocked / Compare and Swap statements are included in the system unit and are readily available and tested (at least on AMD). I don't know an IDE called AMD ;-) . I already did some research and found that on ARM there seem to be issues with those. On X64 there are hardware instructions for these operations, so I believe they will work as expected (atomic but not memory ordering). But if you need to do atomic operations that are moire complex than what a single x86 instruction provides, you still need to use MUTEX (CriticalSection). And same is bound to work on all systems (including SMP) according to the Posix specs. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Henry Vermaak schrieb: You'll have to read the generated assembler for Windows critical sections. My hunch would be that they use memory barriers, too. When a critical section object is owned, the only other threads affected are the threads that are waiting for ownership in a call to EnterCriticalSection. Threads that are not waiting are free to continue running. I don't see anything like memory barriers here. DoDi -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Michael Schnell schrieb: On 06/27/2011 07:52 PM, Hans-Peter Diettrich wrote: You forget the strength of protection. Maybe I seem to see what you mean. You think, a critical section will not prevent that the data that is accessed by both threads is duplicated in a register or in the Data cache of the two (or more) CPUs that are trying to access the resource (variable). Big Q: *which* resource? A critical section (process-local MUTEX) is not related to a specific (memory) resource, except itself, consequently it can not protect any *other* resource. It also does not block any other thread, not waiting for entering the critical section, so that all resources are accessible by all threads, except the critical section (or mutex...) itself. Thus a concurrent access might erroneously offer a not updated state to the other CPU. Right. All threads keep running, except those waiting for a critical section in use, so that concurrent access can occur in all threads. Regarding Data Cache, AFAIK, the hardware prevents this. If one CPU writes a value, an invalidate signal for the addresses in that cache line is sent to all caches, and so all other CPUs will reread the data from the main memory, which in turn will force a preliminary write from cache to main memory for the cache line of the first CPU. An invalidated cache line does not cause a reload from RAM. A reload only occurs when the next read will result in an cache miss. Thus Locked instructions (that force this mechanism, guaranteeing proper read-modify-write access even if multiple instructions access the same data are issued at the same time overlapping execution ) only are necessary outside a critical section protecting the data in question. That's wrong, since a critical section does not protect any range of memory addresses. A locking instruction most probably will invalidate the address in all caches, before reading from or writing to the specified address. Since the RAM is locked during the instruction, all other cores or processors have to wait until the end of the instruction cycle, before they can access the same address. My conclusion is, that the said problem with linked lists results from the pointers not being defined as volatile. No. In a bidirectionally linked list up to 4 pointers have to be updated together, whenever an element is inserted or removed. This leaves much room for race conditions, that cannot be cured by protecting every single pointer. Instead the entire chain must be protected, by a MUTEX or other synchronization means. And then it's only a *convention*, which object or memory block shall be protected by a MUTEX, no memory barrier prevents access without obtaining the MUTEX first. Kind of a memory barrier can be established by putting the list object (head) into a TThreadList, *provided that* no code will retain references to list elements after releasing the list object. And I really don't know how this could be cured in Pascal other than doing ASM. (I was not aware of this problem and I feel it should be discussed in the FPC mailing list.) It's not a matter of the language, when a thread does *not* aquire a lock before accessing the related resource. It's simply a design flaw, when some piece of code does not obey the established rules. DoDi -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Tue, Jun 28, 2011 at 9:47 AM, Hans-Peter Diettrich drdiettri...@aol.com wrote: I don't see anything like memory barriers here. Compare and swap mechanisms aren't quite like memory barriers but they to get the CPU to send a fresh copy of a variable to all cores' cache... -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/28/2011 05:33 PM, Hans-Peter Diettrich wrote: A critical section (process-local MUTEX) is not related to a specific (memory) resource, except itself, consequently it can not protect any *other* resource. It also does not block any other thread, not waiting for entering the critical section, so that all resources are accessible by all threads, except the critical section (or mutex...) itself. I understand that you are supposed to do CriticalSection.Enter; do something with the variables that are protected CriticalSection.leave; What did you think how to use them ? Of course a MUTEX can do other things, too, but here we are discussing normal CriticalSection use. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 28/06/11 15:47, Hans-Peter Diettrich wrote: Henry Vermaak schrieb: You'll have to read the generated assembler for Windows critical sections. My hunch would be that they use memory barriers, too. When a critical section object is owned, the only other threads affected are the threads that are waiting for ownership in a call to EnterCriticalSection. Threads that are not waiting are free to continue running. I don't see anything like memory barriers here. Quoting from http://msdn.microsoft.com/en-us/library/ms686355%28v=VS.85%29.aspx The following synchronization functions use the appropriate barriers to ensure memory ordering: Functions that enter or leave critical sections Functions that signal synchronization objects Wait functions Interlocked functions Henry -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/28/2011 05:33 PM, Hans-Peter Diettrich wrote: No. In a bidirectionally linked list up to 4 pointers have to be updated together, whenever an element is inserted or removed. This leaves much room for race conditions, that cannot be cured by protecting every single pointer. Instead the entire chain must be protected, by a MUTEX or other synchronization means. And then it's only a *convention*, which object or memory block shall be protected by a MUTEX, no memory barrier prevents access without obtaining the MUTEX first. Kind of a memory barrier can be established by putting the list object (head) into a TThreadList, *provided that* no code will retain references to list elements after releasing the list object. I fully agree. With the RTL/LCL, the MUTEX is encapsulated in the TCtriticalSection Object (one MUTEX per instance. And of course, here, a single instance is necessary to be used for all accesses to the pointers). And as the Mutex already contains the Full Fence memory barrier and (as discussed over in the fpc list) the function calls to Enter and Leave prevents the compiler from caching any of the intermediate pointer values in registers at a wrong point in time, I don't see why CriticalSection would not be the correct way to go and work as expected. (OTOH using atomic interlocked ASM instructions does not help as all pointers need to be updated in a single atomic operation). But the original claim was that the implementation with Critical sections failed on a multi core engine and interlocked instructions helped. This is why I suggested that there is some kind of bug. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Tue, Jun 28, 2011 at 10:33 AM, Hans-Peter Diettrich drdiettri...@aol.com wrote: Big Q: *which* resource? A critical section (process-local MUTEX) is not related to a specific (memory) resource, except itself, consequently it can not protect any *other* resource. It also does not block any other thread, not waiting for entering the critical section, so that all resources are accessible by all threads, except the critical section (or mutex...) itself. 100% correct. That's what I've been saying. I think some think that its some magical solution that protects everything under the sun. Thus a concurrent access might erroneously offer a not updated state to the other CPU. Right. All threads keep running, except those waiting for a critical section in use, so that concurrent access can occur in all threads. Simple semantics. Regarding Data Cache, AFAIK, the hardware prevents this. If one CPU writes a value, an invalidate signal for the addresses in that cache line is sent to all caches, and so all other CPUs will reread the data from the main memory, which in turn will force a preliminary write from cache to main memory for the cache line of the first CPU. An invalidated cache line does not cause a reload from RAM. A reload only occurs when the next read will result in an cache miss. OK folks. Can we please focus around this comment ??? This is what makes a piece of memory volatile with respect to threading/cores. CAS / Interlocked mechanisms are the solution to this issue. But are there others? Thus Locked instructions (that force this mechanism, guaranteeing proper read-modify-write access even if multiple instructions access the same data are issued at the same time overlapping execution ) only are necessary outside a critical section protecting the data in question. That's wrong, since a critical section does not protect any range of memory addresses. Ok another focus here. Lets make the distinction between Thread Locks and Interlocked/Compare and Swaps here. Anyone else got anything to add here? A locking instruction most probably will invalidate the address in all caches, before reading from or writing to the specified address. Since the RAM is locked during the instruction, all other cores or processors have to wait until the end of the instruction cycle, before they can access the same address. This is good info. This is exactly what I observed on my AMD 1075Ts My conclusion is, that the said problem with linked lists results from the pointers not being defined as volatile. No. In a bidirectionally linked list up to 4 pointers have to be updated together, whenever an element is inserted or removed. This leaves much room for race conditions, that cannot be cured by protecting every single pointer. Instead the entire chain must be protected, by a MUTEX or other synchronization means. And then it's only a *convention*, which object or memory block shall be protected by a MUTEX, no memory barrier prevents access without obtaining the MUTEX first. Kind of a memory barrier can be established by putting the list object (head) into a TThreadList, *provided that* no code will retain references to list elements after releasing the list object. I had a similar issue once. And it was solved with bringing the list under my manager/worker system so that there was only one thread accessing the linkedlist, and I used InterlockedExchange for First,Last,Next,Previous. And I really don't know how this could be cured in Pascal other than doing ASM. (I was not aware of this problem and I feel it should be discussed in the FPC mailing list.) It's not a matter of the language, when a thread does *not* aquire a lock before accessing the related resource. It's simply a design flaw, when some piece of code does not obey the established rules. I don't see how this is an issue of obedience. It's more of a phenomenon. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Tue, Jun 28, 2011 at 9:59 AM, Michael Schnell mschn...@lumino.de wrote: But the original claim was that the implementation with Critical sections failed on a multi core engine and interlocked instructions helped. This is why I suggested that there is some kind of bug. LOL I don't recall you ever asking specifics on my implementation. You have indeed made gross assumptions regardless of design. The Engine doesn't have cores. It's an application written in Lazarus and proudly compiled with FPC and worked flawlessly on Windows/Ubuntu32/64 untill I upgraded from a 3 core to a 6 core. During stress tests - I watched graphically under each core, using AWN widgets (1 display per core) code execution went from core to core instead of staying locked. While my linked list was headed by a critical section, that head was there only by design for general use and as vestigial for my particular instance. Keep in mind, there was no re-entrancy with this particular link-list instance. I had headed it with critical sections there for two reasons. 1) it was vestige from a non-adapted - general purpose link list - and were always allowed access b/c the same thread was accessing. 2) if I ever wanted to re-use the component, I would still need that thread barrier to block re-entrance. So to bring this to a conclusion, the Critical section did not ensure code order of execution when run on the multi-core system. And by using InterlockedExhchange we can be assured that variables are valid to other cores when the event of a core switch occurred - which resolved the stale values problem I was experiencing. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/23/2011 12:37 AM, Malcom Haak wrote: Correct me if I'm wrong, But can't you technically make any code 'thread-safe' by using Critical Sections before doing work. Of course you are correct. But this is not a decent way to go. 1) the calls of CriticalSection themselves can slow down the code, as they need library and (unless the Library and the Arch decently implements FUTEX) System API calls. And even with FUTEX, hardware-locked instructions need to be use that might count for hundreds of normal instructions with modern processors due to necessary cache syncing. 2) if the CriticalSection in fact requires waiting the increase in latency is huge. So the calls should be placed only there where they are really necessary and the code should be optimized to run as little within CriticalSections as possible. In some code I have seen before a critical section was entered before calling TList.Add Now provided that you don't need a specific order, does this not then make it thread safe? Yes, but in General it's not a decent way to go. That is why I state that TList (supposedly) already is per-instance thread safe and does not need further ado if no concurrent thread accesses the same instance. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/23/2011 07:50 AM, Hans-Peter Diettrich wrote: I may be wrong here, because I used threads only on realtime systems, never in Delphi or Lazarus... Threads can help to greatly improve the soft realtime behavior of a Delphi/Lazarus program. We do this a lit. BTW, I just got my copy of RAD Studio XE, where e.g. thread.suspend is deprecated, and other means for thread synchronization are added. But these have to be implemented in FPC first, before SpinLock or other procedures or methods can be used. IMHO TThread.Suspend and friends is a very queer way of doing thread synchronizing. The Delphi developers seem to have been drunk when inventing this (in vain trying to create something idiot-friendly). I never used this stuff. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Thu, Jun 23, 2011 at 06:50:14AM +0100, Hans-Peter Diettrich wrote: BTW, I just got my copy of RAD Studio XE, where e.g. thread.suspend is deprecated, So is FPC 2.4.4. and other means for thread synchronization are added. Afaik they only added start as a replacements for deprecated .resume. But these have to be implemented in FPC first, before SpinLock or other procedures or methods can be used. These are afaik unrelated to the above change, and related to the addition of monitors. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Mon, 27 Jun 2011, Michael Schnell wrote: On 06/23/2011 07:50 AM, Hans-Peter Diettrich wrote: I may be wrong here, because I used threads only on realtime systems, never in Delphi or Lazarus... Threads can help to greatly improve the soft realtime behavior of a Delphi/Lazarus program. We do this a lit. BTW, I just got my copy of RAD Studio XE, where e.g. thread.suspend is deprecated, and other means for thread synchronization are added. But these have to be implemented in FPC first, before SpinLock or other procedures or methods can be used. IMHO TThread.Suspend and friends is a very queer way of doing thread synchronizing. The Delphi developers seem to have been drunk when inventing this (in vain trying to create something idiot-friendly). I never used this stuff. These calls are simply wrappers around the Microsoft threading API. So it's the MS engineers who were drunk, I suppose. Michael. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/23/2011 02:02 PM, Andrew Brunner wrote: With multi-core systems simply adding a mutex/lock is not enough. A MUTEX or FUTEX (or CriticalSection) is supposed to work as expected on multi-Core systems as well. User code is not supposed to need to bother about running on a multi-core system. If MUTEX/FUTEX does not work correctly this is a bug of the OS / SystemLibrary. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/27/2011 11:29 AM, michael.vancann...@wisa.be wrote: So it's the MS engineers who were drunk, I suppose. I don't doubt this :-) :-) :-) . -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 22/06/2011 23:37, Malcom Haak wrote: Correct me if I'm wrong, But can't you technically make any code 'thread-safe' by using Critical Sections before doing work. I don't think so. If the function, for example stores some important data in a thread local variable, but flags (thread global) the availability of the data, then no Critical section will fix it. Admittedly this is a constructed case, and sounds like an extremely poor implementation... But it shows that thread-safety is more than just a Critical Section. After execution of a thread-save function the overall state of your app (and the entire system) must still be valid (and it must be so, for each thread). Martin -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe [ot]
On 27/06/2011 10:31, Michael Schnell wrote: On 06/27/2011 11:29 AM, michael.vancann...@wisa.be wrote: So it's the MS engineers who were drunk, I suppose. I don't doubt this :-) :-) :-) . -Michael Must have been something to do with the Ballmer Peak http://xkcd.com/323/ :) L. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/27/2011 11:37 AM, Martin wrote: If the function, for example stores some important data in a thread local variable, but flags (thread global) the availability of the data, then no Critical section will fix it. Yep ! As stated in my former messages in this thread, IMHO, the official definition of thread-safe-ness does not make much sense with objects, but a more complex definition covering several cases of use is necessary. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 27/06/2011 11:19, Michael Schnell wrote: On 06/27/2011 11:37 AM, Martin wrote: If the function, for example stores some important data in a thread local variable, but flags (thread global) the availability of the data, then no Critical section will fix it. Yep ! As stated in my former messages in this thread, IMHO, the official definition of thread-safe-ness does not make much sense with objects, but a more complex definition covering several cases of use is necessary. Why? Where does the definition conflict with the above? A piece of code is *thread-safe* if it can be safely invoked by multiple threads at the same time Save invocation includes that the function returns a correct result(output) for any input. Where input: - is not limited to the parameters passed in the parameter list, not even to limited to parameters passed implicitly (such as the object instance) - input includes the entire state of the system (that can be global vars, available and unavailable resources of any kind, and much more) The same applies to result, or output. This part of Save invocation is not limited to thread safeness. It applies to any piece of code. For example, a piece of code involving memory allocation, must examine the result of the actual AllocMem call for errors. Otherwhise it is not save to be executed, as it may fail with an undefined result, if no mem is available. So as far as I can see, my example, (as well as objects) are very well covered by the definition. Martin -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 27/06/2011 11:58, Martin wrote: On 27/06/2011 11:19, Michael Schnell wrote: On 06/27/2011 11:37 AM, Martin wrote: If the function, for example stores some important data in a thread local variable, but flags (thread global) the availability of the data, then no Critical section will fix it. Yep ! As stated in my former messages in this thread, IMHO, the official definition of thread-safe-ness does not make much sense with objects, but a more complex definition covering several cases of use is necessary. Why? Where does the definition conflict with the above? A piece of code is *thread-safe* if it can be safely invoked by multiple threads at the same time Save invocation includes that the function returns a correct result(output) for any input. Make that any defined/allowed input Obviously if you pass in a pointer to random memory as object instance no function will be ave to call. Where input: - is not limited to the parameters passed in the parameter list, not even to limited to parameters passed implicitly (such as the object instance) - input includes the entire state of the system (that can be global vars, available and unavailable resources of any kind, and much more) The same applies to result, or output. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 27/06/2011 11:19, Michael Schnell wrote: On 06/27/2011 11:37 AM, Martin wrote: If the function, for example stores some important data in a thread local variable, but flags (thread global) the availability of the data, then no Critical section will fix it. Yep ! As stated in my former messages in this thread, IMHO, the official definition of thread-safe-ness does not make much sense with objects, but a more complex definition covering several cases of use is necessary. -Michael The computer/OS/system has no clue of anything you may call 'an object'... when compiled, it is just 'code'. OOP is just a convenient abstraction, it's for people needed only :) L. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/27/2011 12:51 PM, Martin wrote: Why? Where does the definition conflict with the above? A piece of code is *thread-safe* if it can be safely invoked by multiple threads at the same time It does not *conflict* it is just not useful. The problem is not safe invocation the problem is *a* piece of code. An object is invocated with a hidden self pointer. So for the user this self is not an input as normal parameters are. By definition, an object is a combination of a data store and a pool of functions. Thus (when looking at your definition above) you either can define that (A) the the code is *different* for multiple instances of the object (even though it only exists once in memory and in the source code), or you can define or you can define that (B) it's *the same piece of code* for all instances. From the point of view of the user both does make sense (if you get him to be aware of that at all). Obviously as an example, the (non-thread-safe) TList.add (supposedly) can happily be used with multiple threads if each thread uses it's own instance and thus different code (regarding definition (A), while TThreadList is thread safe (regarding both definitions) and the same instance can be used by multiple threads. The reason is, that TList just uses (stack and) class variables (and decently protected global variables), While with TThreadList additionally the class variables are decently protected. OTOH, e.g. TForm is not thread save at all: you can't do multiple instances and use each of them from it's dedicated thread, because implicitly TForm uses unprotected global variables. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 27/06/2011 12:23, Michael Schnell wrote: On 06/27/2011 12:51 PM, Martin wrote: Why? Where does the definition conflict with the above? A piece of code is *thread-safe* if it can be safely invoked by multiple threads at the same time It does not *conflict* it is just not useful. The problem is not safe invocation the problem is *a* piece of code. An object is invocated with a hidden self pointer. So for the user this self is not an input as normal parameters are. Unfortunately you left out the real important part of my last msg. If you choose to ignore the full meaning of safely invoked (even WITHOUT threads), then I agree the definition is not useful. But then which definition is useful if you ignore parts of it? Ask yourself: WITHOUT threads, when can a piece of code be safely invoked? Answer: It can be safely invoked, if it will return a correct result for any input, within the range of input for which it is defined. See my example about memory alloc in my other mail. It shows, that a piece of code (and it's ability to be safely invoked ) does not solely depend on the parameters passed, but also on (selected parts of) the state of the application or system. By definition, an object is a combination of a data store and a pool of functions. The data part can be seen as input, for the above definition That this input is made available in a specific way does not matter. But yes, It's your choice. You can have an indefinite amount of definitions for each possible special case . Or you can have one definition, using the most abstract common part of them all. For the above it is enough to see an object as a piece of code (or several pieces of code), for (each of) which the data is a part of the input. It does not matter by which means this input is made available. It does not matter that the programmer does not need to explicitly specify this input. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe (concurrently versus subsequently)
On 10/06/2011 12:26, Henry Vermaak wrote: On 10/06/11 02:09, Hans-Peter Diettrich wrote: What is thread safe? The definition is very clear here: http://en.wikipedia.org/wiki/Thread_safety A piece of code is *thread-safe* if it can be safely invoked by multiple threads at the same time Just to point out first, I am aware of the discussion this has already sparked, and in the light of any argument of that discussion, in my opinion this definition is correct. Yet I came to think of a case, for which I wonder, and would like to hear opinions, if indeed the above statement is complete. My query is about the part: at the same time Now a piece of code could for example mix up thread local and thread global data: - cache access to thread local data in a thread global way. Subsequent calls from another thread may fail. - create an initialize some data, and store it thread-local, while flagging it's existence thread global. Subsequent calls from another thread may fail. Even if such code was using some sort of locking (mutex, criticalsection, ...) it would fail. It would not need to be executed from several threads at the same time, it fails if executed by several threads subsequently. However so far of course each of those would also fail, if called at the same time. So all my examples are indeed covered by the original definition. The question is, is it prooven, or can it be prooven, that no code can be constructed, that would not fail if called at the same time, but that would fail if called subsequently That would be code, for which *during* its execution the application would be in a state valid to enter the code in another thread, but *after* it's execution, this validity would no longer be given. If such code can be constructed, then would the above statement have to be extended to subsequent calls of the piece of code ? Martin -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
There is no question that we all agree about the technical background of all this. The discussion I started was just about what (new) definitions makes sense to be provided in the docs to the user of an Object language to allow him to decide which object (e.g. TList vs. TThreadList) he needs to use where in his threaded application and what is allowed (e.g. accessing multiple TList instances from multiple threads with each thread only accessing one of them, or accessing any TThreadList instance from any thread) and what is forbidden (e.g accessing a single TList instance from multiple threads or accessing a TForm instance from any thread but the MainThread.) -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 27/06/2011 13:57, Michael Schnell wrote: There is no question that we all agree about the technical background of all this. The discussion I started was just about what (new) definitions makes sense to be provided in the docs to the user of an Object language to allow him to decide which object (e.g. TList vs. TThreadList) he needs to use where in his threaded application and what is allowed (e.g. accessing multiple TList instances from multiple threads with each thread only accessing one of them, or accessing any TThreadList instance from any thread) and what is forbidden (e.g accessing a single TList instance from multiple threads or accessing a TForm instance from any thread but the MainThread.) Well, that is something, I can agree with. *IF* a definition is supplied (with FPC/Lazarus), and in the light that the users come with all levels of experience, then it would be nice, if (in addition) an explanation would be given, rather than just a short abstract form. In this case your wording may be misleading just about what (new) definitions . There would be no new definition, only an explanation, of the existing definition. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe (concurrently versus subsequently)
Martin laza...@mfriebe.de hat am 27. Juni 2011 um 14:47 geschrieben: On 10/06/2011 12:26, Henry Vermaak wrote: On 10/06/11 02:09, Hans-Peter Diettrich wrote: What is thread safe? The definition is very clear here: http://en.wikipedia.org/wiki/Thread_safety A piece of code is thread-safe if it can be safely invoked by multiple threads at the same time Just to point out first, I am aware of the discussion this has already sparked, and in the light of any argument of that discussion, in my opinion this definition is correct. Yet I came to think of a case, for which I wonder, and would like to hear opinions, if indeed the above statement is complete. My query is about the part: at the same time Think about safely invoked as no need for extra precautions to call it multi threaded, like e.g. critical sections or check which thread is running. Obviously thread-safe does not extend the safety nor does it fix any kind of flaw that is already there when called single threaded. And thread safe does not mean that calling a function multi threaded will give the same results as called single threaded. Although typically it does. And look up the definition of function. A function is defined by the input, output and task. Failing means for some input the wrong output is returned. Input/Output are not only parameters. Now a piece of code could for example mix up thread local and thread global data: - cache access to thread local data in a thread global way. Subsequent calls from another thread may fail. - create an initialize some data, and store it thread-local, while flagging it's existence thread global. Subsequent calls from another thread may fail. The fail depends on how you define the task of the function. I guess with fail you mean the function can fail its tasks when called multi threaded. Then it is by definition not thread safe. Even if such code was using some sort of locking (mutex, criticalsection, ...) it would fail. It would not need to be executed from several threads at the same time, it fails if executed by several threads subsequently. However so far of course each of those would also fail, if called at the same time. So all my examples are indeed covered by the original definition. The question is, is it prooven, or can it be prooven, that no code can be constructed, that would not fail if called at the same time, but that would fail if called subsequently At the same time includes subsequently, for the simple reason that critical sections are allowed, which simply turns a parallel (at the same time) into a sequential one. That would be code, for which *during* its execution the application would be in a state valid to enter the code in another thread, but *after* it's execution, this validity would no longer be given. If such code can be constructed, then would the above statement have to be extended to subsequent calls of the piece of code ? Mattias-- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Mon, Jun 27, 2011 at 7:57 AM, Michael Schnell mschn...@lumino.de wrote: There is no question that we all agree about the technical background of all this. Actually, There was no mention of memory barriers other than the content in my post. So if you want to understand what that is here is a link... http://en.wikipedia.org/wiki/Memory_barrier Simply protecting a loop with a futex is not sufficient. Assigning variables in a multi-threaded environment is not sufficient. Interlocked/Exchange/ExchangeAdd/Increment features must be used whenever dealing with variables (with at least one exception) In my experience arrays of boolean are atomic. I ran tests on a HexCore AMD system which had unexplained anomalies with pointers in an bidirectional linked list. I replaced all the pointer assignments with InterlockedExchange and the system worked flawlessly. Some of the assignments were taking place in a criticalsection (btw). -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Michael Schnell mschn...@lumino.de hat am 27. Juni 2011 um 14:57 geschrieben: There is no question that we all agree about the technical background of all this. The discussion I started was just about what (new) definitions makes sense to be provided in the docs to the user of an Object language to allow him to decide which object (e.g. TList vs. TThreadList) he needs to use where in his threaded application and what is allowed (e.g. accessing multiple TList instances from multiple threads with each thread only accessing one of them, or accessing any TThreadList instance from any thread) and what is forbidden (e.g accessing a single TList instance from multiple threads or accessing a TForm instance from any thread but the MainThread.) The documentation can simply say about TList: Thread safe: no Used non thread safe global variables: none About TAVLTree: Thread safe: no Used non thread safe global variables: NodeMemManager, unless overriden by SetNodeManager No need for new terms. And everyone knows what to do to use the class in a specific thread. Mattias-- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Martin schrieb: As stated in my former messages in this thread, IMHO, the official definition of thread-safe-ness does not make much sense with objects, but a more complex definition covering several cases of use is necessary. Why? Where does the definition conflict with the above? A piece of code is *thread-safe* if it can be safely invoked by multiple threads at the same time That's the definition of reentrant subroutines only. Save invocation includes that the function returns a correct result(output) for any input. Where input: - is not limited to the parameters passed in the parameter list, not even to limited to parameters passed implicitly (such as the object instance) - input includes the entire state of the system (that can be global vars, available and unavailable resources of any kind, and much more) The same applies to result, or output. This would mean that a thread-safe procedure has to lock *all* input that it - or one of its called procedures - wants to read or update, before starting at all. The best scenario for an unrecoverable deadlock :-( This part of Save invocation is not limited to thread safeness. It applies to any piece of code. Your attempt to re-interpret above definition is of no use :-( DoDi -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Lukasz Sokol schrieb: The computer/OS/system has no clue of anything you may call 'an object'... when compiled, it is just 'code'. Right. OOP is just a convenient abstraction, it's for people needed only :) OOP is for designers, not for hackers ;-) When some thread-safe code must never bring a program (automaton, system...) into an inconsistent state, objects are fine to break down the entire program into self-contained sub-systems. This allows to dramatically reduce the degree of freedom of the entire (flattened) problem. Whatever can be done entirely inside an object, deserves no further consideration of everything outside the object. DoDi -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/27/2011 03:31 PM, Andrew Brunner wrote: Simply protecting a loop with a futex is not sufficient. Assigning variables in a multi-threaded environment is not sufficient. While I don't think we should this discuss in this context, I suggest that in the docs for the user of the object library (that was the starting point of the discussion), any type of thread-safety should include threads running on multiple processors. Interlocked/Exchange/ExchangeAdd/Increment features must be used whenever dealing with variables (with at least one exception) In my experience arrays of boolean are atomic. Yep. But this is only relevant if you don't protect them by a critical section, as this excludes concurrent exchange before the critical instructions are executed. Of course (when possible) using the interlocked instruction results in a lot less overhead than simply using a critical section. I ran tests on a HexCore AMD system which had unexplained anomalies with pointers in an bidirectional linked list. I replaced all the pointer assignments with InterlockedExchange and the system worked flawlessly. This is clear. You also would have been able to avoid the problem by using critical sections around *all *the appropriate instructions, but supposedly this would have slowed done the application greatly. Some of the assignments were taking place in a criticalsection (btw). I believe that the some were not enough. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/27/2011 03:34 PM, Mattias Gaertner wrote: The documentation can simply say about TList: Thread safe: no Used non thread safe global variables: none Poor user ! If he just reads Thread safe: no, he supposedly will believe he needs to use TThreadList in all threads and do very inefficient code. How is he supposed to know that accessing a TList instance with just a single thread while accessing another instance only with another thread is safe ? A new term (decently explained on a central location) that can be used in a Feature grid would be much more readable. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe (concurrently versus subsequently)
On 27/06/2011 14:23, Mattias Gaertner wrote: What is thread safe? The definition is very clear here: http://en.wikipedia.org/wiki/Thread_safety A piece of code is *thread-safe* if it can be safely invoked by multiple threads at the same time Just to point out first, I am aware of the discussion this has already sparked, and in the light of any argument of that discussion, in my opinion this definition is correct. Yet I came to think of a case, for which I wonder, and would like to hear opinions, if indeed the above statement is complete. My query is about the part: at the same time Think about safely invoked as no need for extra precautions to call it multi threaded, like e.g. critical sections or check which thread is running. Obviously thread-safe does not extend the safety nor does it fix any kind of flaw that is already there when called single threaded. And thread safe does not mean that calling a function multi threaded will give the same results as called single threaded. Although typically it does. And look up the definition of function. A function is defined by the input, output and task. Failing means for some input the wrong output is returned. Input/Output are not only parameters. Yes, but if I am correct, input for example can not (always) be limited to the list of param (not even including hidden param, like self) eg, a constructor, includes the task of allocating memory. If that fails a defined behaviour should be expected (return nil, throw exception, ...). That implies, that available memory in this case is part of the input. Sure, similar flaws (with invalid data) can be constructed outside threads. But the ability to store data in either a variable local to one thread, or global to all threads does not exists without threads. Yes the aim of the definition, is solely to extend the concept of being called safely to being called safely from several threads. But the above definition *limits* this requirement to called at the same time Now a piece of code could for example mix up thread local and thread global data: - cache access to thread local data in a thread global way. Subsequent calls from another thread may fail. - create an initialize some data, and store it thread-local, while flagging it's existence thread global. Subsequent calls from another thread may fail. The fail depends on how you define the task of the function. I guess with fail you mean the function can fail its tasks when called multi threaded. Then it is by definition not thread safe. As I said, those examples, are not actually correct (for what I am questioning) They only point into a direction. fail = not the result that is expected according to the definition of the function (that could be: not return at all, crash, or return an incorrect value as result...) The example is merely to indicate, that thread related problems can occur, even if calls are not at the same time. Yes similar issues can be constructed without threads. But without threads you do not have a differentiation between data accessible to just one thread, and data accessible to all threads. So problems arising from this, are thread related. Even if such code was using some sort of locking (mutex, criticalsection, ...) it would fail. It would not need to be executed from several threads at the same time, it fails if executed by several threads subsequently. However so far of course each of those would also fail, if called at the same time. So all my examples are indeed covered by the original definition. The question is, is it prooven, or can it be prooven, that no code can be constructed, that would not fail if called at the same time, but that would fail if called subsequently At the same time includes subsequently, for the simple reason that critical sections are allowed, which simply turns a parallel (at the same time) into a sequential one. There is a difference between called/invoked at the same time, and executed at the same time. The original defintion says invoked they are still invoked at the same time, even though *if* a critical section is used, the part inside it (and only this part, not the whole piece of code, which includes the critical section) is executed deferred. at the same time does not necessarily mean a critical section has to exist, there are other means that allow for more parallel execution: 2 read only calls, may not need to block each other at all. Yet a read-only call may fail due to something thread related, that happened long before (in an other thread, and only because it happened in an other thread). -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe (concurrently versus subsequently)
Martin laza...@mfriebe.de hat am 27. Juni 2011 um 16:01 geschrieben: [...] Think about safely invoked as no need for extra precautions to call it multi threaded, like e.g. critical sections or check which thread is running. Obviously thread-safe does not extend the safety nor does it fix any kind of flaw that is already there when called single threaded. And thread safe does not mean that calling a function multi threaded will give the same results as called single threaded. Although typically it does. And look up the definition of function. A function is defined by the input, output and task. Failing means for some input the wrong output is returned. Input/Output are not only parameters. Yes, but if I am correct, input for example can not (always) be limited to the list of param (not even including hidden param, like self) eg, a constructor, includes the task of allocating memory. If that fails a defined behaviour should be expected (return nil, throw exception, ...). That implies, that available memory in this case is part of the input. In fact a function's input can even be a file on disk. The memory manager is thread safe, so there is not much difference between single threaded and multi threaded here. Sure, similar flaws (with invalid data) can be constructed outside threads. But the ability to store data in either a variable local to one thread, or global to all threads does not exists without threads. Well, this depends on pov. So this is more a philosophical question. Yes the aim of the definition, is solely to extend the concept of being called safely to being called safely from several threads. But the above definition *limits* this requirement to called at the same time English lacks the exactness of mathematical expressions. You are right, that the definition is not exact and the wikipedia page contains a few remarks about that. The nice thing about this definition is that everyone I knew instantly understands the idea and was able to apply it to most cases without much thinking, including methods and classes. Everyone - until I read this thread. Apparently some people have problems with it. Well, life is learning. The fail depends on how you define the task of the function. I guess with fail you mean the function can fail its tasks when called multi threaded. Then it is by definition not thread safe. As I said, those examples, are not actually correct (for what I am questioning) They only point into a direction. fail = not the result that is expected according to the definition of the function (that could be: not return at all, crash, or return an incorrect value as result...) Then the function is not thread safe. The example is merely to indicate, that thread related problems can occur, even if calls are not at the same time. True. And I would like to discuss this, but I'm not sure if this topic is Lazarus related. [...] At the same time includes subsequently, for the simple reason that critical sections are allowed, which simply turns a parallel (at the same time) into a sequential one. There is a difference between called/invoked at the same time, and executed at the same time. For thread safe it is the same. The original defintion says invoked they are still invoked at the same time, even though *if* a critical section is used, the part inside it (and only this part, not the whole piece of code, which includes the critical section) is executed deferred. at the same time does not necessarily mean a critical section has to exist, there are other means that allow for more parallel execution: 2 read only calls, may not need to block each other at all. Yet a read-only call may fail due to something thread related, that happened long before (in an other thread, and only because it happened in an other thread). Yes. But then again it is a question of how you define the task of the code. Maybe you want this behavior, maybe you don't care. Mattias -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/27/2011 04:17 PM, Andrew Brunner wrote: See the link at wikipedia. I don't think Wikipedia can explain implementation details of the LCL/RTL.. But if TCriticalSection uses a MUTEX (which in fact is a FUTEX as (on Linux) it uses pthreadlib mutex function from LibC, which automatically uses FUTEX if available in the underlying arch, otherwise fallback to MUTEX) (and I believe it is implemented this way) same blocks all at the start of the section independently from the core they run on, and thus no concurrent access can happen. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Martin schrieb: See my example about memory alloc in my other mail. It shows, that a piece of code (and it's ability to be safely invoked ) does not solely depend on the parameters passed, but also on (selected parts of) the state of the application or system. What when some code does not return anything, *and* cannot work at all due to some problem (out-of-memory, file deleted, object destroyed...)? When e.g. a file search cannot proceed due to missing access rights? It cannot return an boolean value (succ/fail), because it's simply unknown whether the file exists. When in case of an unexpected error the called procedure throws an exception? Can this procedure *ever* be safely invoked, when it may return to some other place in code (exception handler)? DoDi -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Andrew Brunner schrieb: I ran tests on a HexCore AMD system which had unexplained anomalies with pointers in an bidirectional linked list. I replaced all the pointer assignments with InterlockedExchange and the system worked flawlessly. Some of the assignments were taking place in a criticalsection (btw). Here I feel a need for clarification of CriticalSection in general. Can multiple critical sections be used in a program, to protect *specific* resources? Is it wise to do so? How can critical sections prevent concurrent access to a resource, when *not* entered as required? Your observation suggests to me that there existed some other code, accessing the list *without* entering the (related) critical section. This would mean that *no* code can be thread-safe by itself, instead it requires *also* that all other code respects resource protection (aquire/release locks). AFAIR TThreadList is thread-safe, because it requires to obtain (and lock) an object, before it becomes accessible at all. This definitely prevents all other code from accessing the protected object - provided there exist no other references to such an object outside the list. But this is no guarantee that the object itself will be protected against concurrent access to *further* resources. My conclusion: thread-safety can be achieved only for items (procedures, objects) which do not use non-local data at all. Otherwise thread-safety can be achieved only by sequentializing *all* critical operations in an process - but then we effectively are back to single-threaded code, with only a bit more of noise in switching the active thread in random sequence :-( When consequently thread-safe code is entirely up to the proper use of synchronization means, what's the use of sticking an thread-safe attribute to anything but an entire program? DoDi -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
You're totally underestimating the need for a memory barrier : Multithreaded programming and memory visibility See also: Memory model (computing) Multithreaded programs usually use synchronization primitives provided by a high-level programming environment, such as Java and .NET Framework, or an application programming interface (API) such as POSIX Threads or Windows API. Primitives such as mutexes and semaphores are provided to synchronize access to resources from parallel threads of execution. These primitives are usually implemented with the memory barriers required to provide the expected memory visibility semantics. In such environments explicit use of memory barriers is not generally necessary. Focus on the These primitives are usually implemented with the memory barriers required to provide the expected memory visibility semantics. These primitives include TCrticialSection. It's not enough to ensure that someone from another thread is reading a variable at will. And it would safe to assume that CPU management systems can switch code execution on any core at any time. On Mon, Jun 27, 2011 at 9:47 AM, Michael Schnell mschn...@lumino.de wrote: On 06/27/2011 04:17 PM, Andrew Brunner wrote: See the link at wikipedia. I don't think Wikipedia can explain implementation details of the LCL/RTL.. But if TCriticalSection uses a MUTEX (which in fact is a FUTEX as (on Linux) it uses pthreadlib mutex function from LibC, which automatically uses FUTEX if available in the underlying arch, otherwise fallback to MUTEX) (and I believe it is implemented this way) same blocks all at the start of the section independently from the core they run on, and thus no concurrent access can happen. Semantically Ok. Poor code performance though.. If you had 1 CriticalSection per instance of a variable you possibly could make this argument... But it's just easier and FAAASTER to use interlocked statements ;-) Locking a thread is poor practice. Just design it well and you won't have to worry about locking much. And wherever possible use interlocked features - they were designed for this issue alone. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/27/2011 04:15 PM, Mattias Gaertner wrote: A new term would need explanation too. Yep. In a central location, so the feature lists for the objects is not polluted. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 27/06/2011 15:58, Hans-Peter Diettrich wrote: Martin schrieb: See my example about memory alloc in my other mail. It shows, that a piece of code (and it's ability to be safely invoked ) does not solely depend on the parameters passed, but also on (selected parts of) the state of the application or system. What when some code does not return anything, *and* cannot work at all due to some problem (out-of-memory, file deleted, object destroyed...)? When e.g. a file search cannot proceed due to missing access rights? It cannot return an boolean value (succ/fail), because it's simply unknown whether the file exists. When in case of an unexpected error the called procedure throws an exception? Can this procedure *ever* be safely invoked, when it may return to some other place in code (exception handler)? Yes, why not. IF this is the defined behaviour. Exceptions can be caught. To safely call such a function one would need to define an exception handler. But it can be safely called. That a function can be safely called does not mean that there is no way to call it unsafely. A function expecting a pointer to some specific data, may be able to check if the pointer is nil, but it can not necessarily check if the pointer is otherwise valid. Hence input range for which the function is defined, is a pointer that is nil, or pointing to the correct type of data. Within this range of input the function may be called and will be safe, with other input the result of calling the function is not defined, hence it is not safe. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/27/2011 04:58 PM, Andrew Brunner wrote: You're totally underestimating the need for a memory barrier : While I do know that memory barriers are the way to go to avoid the expensive use of Mutex and friends, I am positive that an MB is not necessary if all accesses to something are protected by a Mutex, as same is designed to block any thread independently from the CPU it is running on. so no other thread can even try to access that memory location. (we are not discussing how to construct a Mutex/FUTEX internally). Focus on the These primitives are usually implemented with the memory barriers ... Yep, usually as critical sections are much more expensive. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Hans-Peter Diettrich drdiettri...@aol.com hat am 27. Juni 2011 um 16:58 geschrieben: Martin schrieb: See my example about memory alloc in my other mail. It shows, that a piece of code (and it's ability to be safely invoked ) does not solely depend on the parameters passed, but also on (selected parts of) the state of the application or system. What when some code does not return anything, *and* cannot work at all due to some problem (out-of-memory, file deleted, object destroyed...)? When e.g. a file search cannot proceed due to missing access rights? It cannot return an boolean value (succ/fail), because it's simply unknown whether the file exists. When in case of an unexpected error the called procedure throws an exception? Can this procedure *ever* be safely invoked, when it may return to some other place in code (exception handler)? Yes, if raising an IO exception is a valid output. Mattias -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 27/06/2011 15:05, Hans-Peter Diettrich wrote: Lukasz Sokol schrieb: The computer/OS/system has no clue of anything you may call 'an object'... when compiled, it is just 'code'. Right. OOP is just a convenient abstraction, it's for people needed only :) OOP is for designers, not for hackers ;-) When some thread-safe code must never bring a program (automaton, system...) into an inconsistent state, objects are fine to break down the entire program into self-contained sub-systems. This allows to dramatically reduce the degree of freedom of the entire (flattened) problem. Whatever can be done entirely inside an object, deserves no further consideration of everything outside the object. What I meant (and I think) it is, is that whatever thread-safe *is*, is completely orthogonal i.e. not dependent on your programming paradigm, it is completely about the resulting code. Therefore, *result* code can either be thread safe, or it can not be, there is no shades of gray here, whatever complex paradigms you apply to your language :) (somebody correct me if I'm not correct ;) L. DoDi -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Mon, Jun 27, 2011 at 12:52 PM, Hans-Peter Diettrich drdiettri...@aol.com wrote: You forget the strength of protection. A MB will disallow immediately any concurrent access to the memory area - no way around. Protection by other means only can work in *perfect* cooperation, a very weak model. Absolutely incorrect. entercricitalsection(); loop a:=b+c; end loop; leavecriticalsection(); thread 2 can read a and b and c at any state. If you want an accurate view of a,b,c you need to employ interlocked statements :-) -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Andrew Brunner schrieb: On Mon, Jun 27, 2011 at 12:52 PM, Hans-Peter Diettrich drdiettri...@aol.com wrote: You forget the strength of protection. A MB will disallow immediately any concurrent access to the memory area - no way around. Protection by other means only can work in *perfect* cooperation, a very weak model. Absolutely incorrect. Why? entercricitalsection(); Where do you see a memory barriere here? DoDi -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Mon, Jun 27, 2011 at 03:05:36PM +0100, Hans-Peter Diettrich wrote: OOP is just a convenient abstraction, it's for people needed only :) OOP is for designers, not for hackers ;-) When some thread-safe code must never bring a program (automaton, system...) into an inconsistent state, objects are fine to break down the entire program into self-contained sub-systems. This allows to dramatically reduce the degree of freedom of the entire (flattened) problem. Whatever can be done entirely inside an object, deserves no further consideration of everything outside the object. Are you talking about monitors? How else will you force an object with only one thread in it? Or are you meaning thread+TLS+state exclusively used in the thread as object? I've been following this subthread for a couple of posts yet, and the whole picture leaves an vague feeling. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Mon, 27 Jun 2011 18:41:46 -0500 Andrew Brunner andrew.t.brun...@gmail.com wrote: This is relatively new theory which required low-level CPU code to perform such locks. This was never needed until the introduction of multi-core systems. Excuse my ignorance but what is different on multi-core systems compared to multi-processor systems which are around for quite some time? R. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Tue, Jun 28, 2011 at 9:41 AM, Andrew Brunner andrew.t.brun...@gmail.comwrote: 2011/6/27 Malcom Haak insane...@gmail.com: Tell me then why any of what you have said is relevant. In fact in cases this this the use of CriticalSections would be sensible and would not cause 'tons of wait' as you have all your worker threads off doing things 99% of the time. Firstly, I was referring to my example Thread 1: a=b+c a2=a+c2 SignalEvent(E1) This will run in 1 thread.. if you use local variables this is fine. if you were using global variables you are an idiot. Thread 2: repeat WaitForEvent(E1,120); We can read anything now until terminated or complete This the prime example. On a 6 core system a looks like one value to one core than it does to another core. It's that simple. No getting around this issue. OF WHAT? bad code? It would only look different if you are looking at different parts of memory.. or you hadn't finished writing. While spinlocks can block a entrance - it cannot guarantee memory order / code execution order. Therefore it is good practice to adopt interlocked assignments to guarantee memory is what it is. Also what the hell are you on about? You could use CriticalSections in your example and it would work fine. The fact you have one Thread doing nothing for ever is a tad silly and to me shows you have no idea what you are doing.. but that could be just because of the exceedingly limited scope of the example. Core X computes a=b+c Core X+Y computes a2 Why would you spilt this into different threads?? If it is the same thread it does not matter if it moves CPU... Your example is lacking in sanity. This is relatively new theory which required low-level CPU code to perform such locks. This was never needed until the introduction of multi-core systems. Of which I did extensive tests on AMD via FPC/Lazarus. Yeah your just sounding silly here. As per Reimar Grabowski's comment, whats the difference between multi-core and Multi-processor? I'll tell you... accessibility to people who don't know what they are on about. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
2011/6/22 Malcom Haak insane...@gmail.com: Correct me if I'm wrong, But can't you technically make any code 'thread-safe' by using Critical Sections before doing work. In some code I have seen before a critical section was entered before calling TList.Add Now provided that you don't need a specific order, does this not then make it thread safe? Partially. Read barriers may not be necessary. It depends on the implementation. By having barriers placed at strategic locations in the code, you can make an implementation thread safe. Add, Delete, and Clear would be some. List iterations would be difficult if not unsafe outside a lock but if accessed under a manager thread you can schedule and operation and it will wait done until conditions are safe to perform. Getting an item from the list rather than locking the entire list and having an inUse boolean set to true for that item, would allow for any deletion to be blocked until another time (by a manager thread). With multi-core systems simply adding a mutex/lock is not enough. A manager is needed to be in place to safely provision, delegate, and use items. IMO, this forces efficiency in a system design. The basic logic for a manager thread is that the manager thread is accepting commands, and scheduled execution happens automatically. Further, you could create a command system for each list so when you add/remove an item from the list you are merely scheduling that item for deletion. I would avoid polling for large lists. The command should have a completion routine like Item.onComplete(Item) where the item is passed for use in the application. This way there would be absolutely no waiting for data in code and the system in general at rest until needed. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Malcom Haak schrieb: Correct me if I'm wrong, But can't you technically make any code 'thread-safe' by using Critical Sections before doing work. In some code I have seen before a critical section was entered before calling TList.Add IMO this won't help, because any other thread that does *not* use the critical section still can trash the list. It might help when TList.Add would use a critical section internally, but then *all* lists are blocked at once, unless a critical section is connected to *every* single TList instance - what may run into out-of-resources. Otherwise a global TList.Add lock may lock up an entire application, when an OnAdd handler tries to use another (temporary...) TList. IMO. I may be wrong here, because I used threads only on realtime systems, never in Delphi or Lazarus... BTW, I just got my copy of RAD Studio XE, where e.g. thread.suspend is deprecated, and other means for thread synchronization are added. But these have to be implemented in FPC first, before SpinLock or other procedures or methods can be used. DoDi -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Tue, 14 Jun 2011 11:53:14 +0200 Michael Schnell mschn...@lumino.de wrote: On 06/10/2011 06:09 PM, Mattias Gaertner wrote: Sigh. It already does. See my TThreadList.Add example. This example shows that it does not make sense. (Supposedly) TThreadList.Add is separate-instance-thread safe (each thread can create an instance and use the Add procedure without risking a conflict). TThreadList.Add is not cross-instance-thread safe (multiple threads using the same instance's Add procedure will result in erroneous behavior). Why do you think so? Simply stating that TThreadList.Add is not thread save (which of course is perfectly correct) would prevent using a TThreadList as a data store e.g. in a thread class that itself is instantiated multiple times. There using TThreadList would be overkill. Mattias -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 14/06/11 10:53, Michael Schnell wrote: On 06/10/2011 06:09 PM, Mattias Gaertner wrote: Sigh. It already does. See my TThreadList.Add example. This example shows that it does not make sense. (Supposedly) TThreadList.Add is separate-instance-thread safe (each thread can create an instance and use the Add procedure without risking a conflict). Everything is separate-instance-thread safe. How can something be unsafe if only one thread is accessing it? TThreadList.Add is not cross-instance-thread safe (multiple threads using the same instance's Add procedure will result in erroneous behavior). No, it won't. All the operations lock the list, so you can use the same instance from multiple threads. Just read the source before you make misguided comments like this. Henry -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/14/2011 12:02 PM, Mattias Gaertner wrote: Why do you think so? Sorry I have been typing much faster than thinking here (again). I had meant to be talking about TTlist. :-[ :-[ :-[ So once again: (Supposedly) TList.Add is separate-instance-thread safe (each thread can create an instance and use the Add procedure without risking a conflict). TList.Add is not cross-instance-thread safe (multiple threads using the same instance's Add procedure will result in erroneous behavior). Simply stating that TList.Add is not thread save (which of course is perfectly correct) would prevent using a TList instance as a data store e.g. in a thread class that itself is instantiated multiple times. There using TThreadList would be overkill. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
Everything is separate-instance-thread safe. How can something be unsafe if only one thread is accessing it? As soon as you use global variables. E.G. Application uses global variables, as well internally, as implicitly by doing calls to an external Widget set. That is why the LCL is known to be not thread safe. TThreadList.Add is not cross-instance-thread safe (multiple threads using the same instance's Add procedure will result in erroneous behavior). No, it won't. Right you are. I meant to write TList. Sorry. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Tue, 14 Jun 2011 13:26:07 +0200 Michael Schnell mschn...@lumino.de wrote: On 06/14/2011 12:02 PM, Mattias Gaertner wrote: Why do you think so? Sorry I have been typing much faster than thinking here (again). I had meant to be talking about TTlist. :-[ :-[ :-[ Your mails contain so many confusions - TThread.Add, completely thread safe, separate-instance-thread safe, TList with TThreadList and now TTlist. You are a very confused troll. This thread started about thread safe LCL functions. If you want that FCL functions/methods be documented whether they are thread safe or not you can ask on the fpc lists or create a feature request. [...] Simply stating that TList.Add is not thread save (which of course is perfectly correct) would prevent using a TList instance as a data store e.g. in a thread class that itself is instantiated multiple times. There using TThreadList would be overkill. Mattias -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
The fact that I am a paranoiac does not mean that they are not after me ;-) :-P :-D . -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/14/2011 04:57 PM, Hans-Peter Diettrich wrote: How would you expect a thread-safe version to work? A TList doesn't serialize requests, this would have to be added separately. It does not need to, as separate-instance-thread safe means that each thread handles only it's own instance. Add only needs to use stack variables and instance variables. Both are dedicated to the thread and thus don't need a protection (OK it if needs to allocate memory the heap allocation procedure does need protection mechanism, but this is provided by the infrastructure anyway. ) -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Sat, Jun 11, 2011 at 02:41:03AM +0100, Hans-Peter Diettrich wrote: threads at the same time. Which piece of code can *not* be safely invoked? Instead I'd define thread safety as the *absence* of possible data or state inconsistencies in concurrent execution [of threads]. The FileExistsUTF8() definition even adheres to that. The possible inconsistency is in a different layer, the OS layer outside the runtime and language's reach. In short, then you must simply open the file for exclusive access and abort on failure to open, instead of checking for existance. -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe (was: How to PostMessage to object?)
On Fri, 10 Jun 2011 03:09:07 +0200 Hans-Peter Diettrich drdiettri...@aol.com wrote: Mattias Gaertner schrieb: Only if the documentation explicitly says a method is thread safe it is. Maybe this needs to be made more clear. Any ideas, where? What is thread safe? http://lmgtfy.com/?q=thread+safel=1 A piece of code is thread safe if it can be safely invoked by multiple threads at the same time. [...] After all: how/where can I find thread-related Lazarus/FPC documentation? My wiki search was not really successful :-( What words did you search? I got results on Thread, Threads and Multithreading. Mattias -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/10/2011 03:09 AM, Hans-Peter Diettrich wrote: What is thread safe? IMHO, quite often, this needs further explanation in the docs. e.g. if the code in question defines a class the diversification is generated by the potential use of class variables and global variables: - Are you allowed to create in in another thread but the main thread (e.g. forbidden for GUI-aware objects) ? - Can you create the class in one thread and call it's functions and properties from another one (e.g. forbidden for GUI-aware objects) ? - Are the functions and properties of a single project reentry-safe (is it allowed to use the same function of the same instance with multiple threads). - Is it allowed to use multiple instances of the object with multiple threads (each thread uses an instance; is it allowed to use the same function of a different instance with multiple threads). - Does an instance internally create threads and are events thrown in the context of such a thread instead in the context of the thread that created the object ? - ... -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 10/06/11 02:09, Hans-Peter Diettrich wrote: What is thread safe? The definition is very clear here: http://en.wikipedia.org/wiki/Thread_safety In how far is just FileExistsUTF8 thread safe? Even if the file existed at function return, it can have been killed by somebody else immediately after, even from outside the application. This example is here: http://en.wikipedia.org/wiki/Thread_safety#Concurrent_programing It has nothing to do with thread safety. Henry -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Fri, 10 Jun 2011 12:49:59 +0200 Hans-Peter Diettrich drdiettri...@aol.com wrote: Mattias Gaertner schrieb: Only if the documentation explicitly says a method is thread safe it is. Maybe this needs to be made more clear. Any ideas, where? What is thread safe? http://lmgtfy.com/?q=thread+safel=1 A piece of code is thread safe if it can be safely invoked by multiple threads at the same time. As already explained, I'm not comfortable with that definition. Welcome to earth. How do you define it on your planet? Which aspect would cover access to shared objects by different pieces of code? What did you not understand on the link I gave? [...] After all: how/where can I find thread-related Lazarus/FPC documentation? My wiki search was not really successful :-( What words did you search? I got results on Thread, Threads and Multithreading. Yes, hundreds of results per search - this is not really helpful :-( I'm always amazed how spoiled Lazarus users are. I think this is a compliment for Lazarus. :) It would help, to some degree, if a language could be specified, so that the results are not crowded with any number of translated pages. +1 Although I must admit I would not use that feature, because I often want to know where a word is used. Mattias -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/10/2011 01:26 PM, Henry Vermaak wrote: On 10/06/11 02:09, Hans-Peter Diettrich wrote: What is thread safe? The definition is very clear here: http://en.wikipedia.org/wiki/Thread_safety clear does not imply useful :) . With piece of code they obviously mean a single function (or part of it), with the implication that no other functions are called during this test by any of those threads. E.g. Regarding Objects this is not enough. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Fri, 10 Jun 2011 13:52:35 +0200 Michael Schnell mschn...@lumino.de wrote: On 06/10/2011 01:26 PM, Henry Vermaak wrote: On 10/06/11 02:09, Hans-Peter Diettrich wrote: What is thread safe? The definition is very clear here: http://en.wikipedia.org/wiki/Thread_safety clear does not imply useful :) . With piece of code they obviously mean a single function (or part of it), with the implication that no other functions are called during this test by any of those threads. ? Of course a threads safe function can call other thread safe functions. E.g. Regarding Objects this is not enough. Prove? Mattias -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/10/2011 02:18 PM, Mattias Gaertner wrote: E.g. Regarding Objects this is not enough. Prove? Theory: with multiple instances, the same piece of code behaves differently, according to to the states that are stored internally in an instance. It's not practical to just ignore this as a specification: you now would need to say that Objects never are thread safe and by this make any object language totally unsuited for threaded application. It's a lot more helpful to do a more sophisticated definition of thread-safety for objects. Example: Imagine you create an instance of an object for each thread. So the same piece of code (a function procedure or property of the object) can behave differently regarding which instance is used (here which thread is calling it). e.g. the function accesses just class variables (and local variables). Now it is thread safe if in fact each thread uses it's instance; but it's not thread safe, if a thread uses another thread's instance. If it uses global variables it is not thread safe at all. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Fri, 10 Jun 2011 14:36:36 +0200 Michael Schnell mschn...@lumino.de wrote: On 06/10/2011 02:18 PM, Mattias Gaertner wrote: E.g. Regarding Objects this is not enough. Prove? Theory: with multiple instances, the same piece of code behaves differently, according to to the states that are stored internally in an instance. Not only theory. It's common practical thing. For example TThreadList.Add is thread safe and each call changes the object. It's not practical to just ignore this as a specification: you now would need to say that Objects never are thread safe and by this make any object language totally unsuited for threaded application. I can't follow you here. It's a lot more helpful to do a more sophisticated definition of thread-safety for objects. Example: Imagine you create an instance of an object for each thread. So the same piece of code (a function procedure or property of the object) can behave differently regarding which instance is used (here which thread is calling it). e.g. the function accesses just class variables (and local variables). Now it is thread safe if in fact each thread uses it's instance; but it's not thread safe, if a thread uses another thread's instance. I got the feeling you are not familiar with mathematical definitions. If the definition says it can be safely invoked by multiple threads at the same time then it means it can be invoked by any thread in any order at any time and the code still performs its task. For example: TThreadList.Add is thread safe because the task is to add an element to the list. If you define the task that after calling the element is in the list, then it would not be thread safe. If it uses global variables it is not thread safe at all. No. For example the heap manager uses global variables and it is thread safe. Mattias -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On 06/10/2011 03:32 PM, Mattias Gaertner wrote: If the definition says it can be safely invoked by multiple threads at the same time then it means it can be invoked by any thread in any order at any time and the code still performs its task. But what is it. The wiki says: piece of code. With Objects this would need to be piece of code of a particular instance, as the same piece of code of another instance c an behave totally different, as the states that are stored in the instance can behave totally different. Of course (only with less practical value) this is also true in a not-object languages: The piece of code can be a function that is called with a parameter. It can be thread safe if each thread calls it with a different parameter value (say a number denoting the thread) and not thread safe if some threads call it with the same parameter. e.g.: void a(n) { array[n] ++; } -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] thread safe
On Fri, 10 Jun 2011 15:45:35 +0200 Michael Schnell mschn...@lumino.de wrote: On 06/10/2011 03:32 PM, Mattias Gaertner wrote: If the definition says it can be safely invoked by multiple threads at the same time then it means it can be invoked by any thread in any order at any time and the code still performs its task. But what is it. The wiki says: piece of code. correct With Objects this would need to be piece of code of a particular instance, No. as the same piece of code of another instance c an behave totally different, as the states that are stored in the instance can behave totally different. Doesn't matter as long the code does its task. [...] Mattias -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus