If the record contained only simple types (like integers) this should
(unless I have missed something major) be fool-proof (provided the actions
taken by B are safe of course), since the data that goes out of scope when A
and B continues processing is in no way shared. But with the dynamically
allocated types, the reference counts are shared, and things will happen
behind the scenes when data goes out of scope. I thought that these
behind-the-scenes things were thread safe, but as mentioned we have seen
some problems. Case I (which is the most common) has appeared to work well
from a functionality point of view, but we have observed memory leakage, and
the only indications from the testing software (AQTime) pointed at this
record handling (occasional memory leaks originating from New, NewAnsString
and ReallocateMem (the dynamic array I think) in System.pas). Case II gave a
nasty error the next time you accessed a seamingly totally unrelated object
(through an Interface), and this error disappeared if A did not dispose the
record in 4 but instead "recycled" it for use the next time. Can anyone shed
some light on this?
Regards
Magnus Oskarsson
Marc
New/Dispose (on pointer variables of the appropriate type, e.g. PMyRec =
^TMyRec).
Magnus
However, if you have a loop like:
for i := 1 to length(strVar) do
strVar[i1] := '1';
while another thread does this:
strVar := '';
Then you have a problem. In that case you should synchronize access to
the string variable by using e.g. a critical section.
--
www.madshi.net
quality low level Delphi components
extended exception handling
API hooking, DLL injection
undocumented functionality
> String assignments are thread safe
Reading a string is thread safe; assigning to one requires
synchronization. I think this is what you meant, but it's not how your
syntax comes across here.
-Craig
--
Craig Stuntz [TeamB] . Vertex Systems Corp. . Columbus, OH
Delphi/InterBase Weblog : http://delphi.weblogs.com
InterBase PLANalyzer 1.1 -- Free InterBase query optimization
tool: http://delphi.weblogs.com/IBPLANalyzer
Actually that was not what I meant.
Are you sure that assigning requires synchronization? How do you define
"require"? Does assigning to an integer variable require
synchronization? As far as I can see, Delphi string variables seem to be
as thread safe as e.g. integer variables - apart from the length related
problems I talked about in my previous comment.
Please try the following code. It doesn't crash, nor do you get any
memory leaks:
var strVar : string;
stop : boolean = false;
function AssignStr(dummy: integer) : integer; stdcall;
begin
while not stop do
strVar := IntToHex(GetTickCount, 1);
result := 0;
end;
var tid, th1, th2 : dword;
mem : integer;
initialization
IsMultiThread := true;
mem := AllocMemSize;
th1 := CreateThread(nil, 0, @AssignStr, nil, 0, tid);
th2 := CreateThread(nil, 0, @AssignStr, nil, 0, tid);
MessageBox(0, 'test', 'test', 0);
stop := true;
WaitForSingleObject(th1, INFINITE);
WaitForSingleObject(th2, INFINITE);
CloseHandle(th1);
CloseHandle(th2);
strVar := '';
mem := AllocMemSize - mem;
MessageBox(0, pchar('mem leak: ' + IntToStr(mem)), 'info', 0);
> Are you sure that assigning requires synchronization? How do you
> define "require"? Does assigning to an integer variable require
> synchronization?
It's hardware dependent. AFAIK, it is safe on Intel CPUs in most
conditions, but I wouldn't want to make that presumption unless I was
confident I knew exactly which CPUs someone running my app would be
using and had checked the developer documentation for each of them.
> As far as I can see, Delphi string variables seem to
> be as thread safe as e.g. integer variables - apart from the length
> related problems I talked about in my previous comment.
I agree there's little difference between assigning to a string
variable and any other reference counted pointer, and that the refrence
counting issues were addressed in, what was it, D5?
> Are you sure about that it's hardware dependent?
Reading and writing a particular value is thread safe as long as the
read/write is an atomic operation on the CPU. This varies with CPU and
data type. Also, some operations are effectively atomic on a single
processor system but are not truly atomic on a SMP system.
AFAIK, a 32 bit integer read/write will always be atomic, but this is
an implementation detail of current processors, rather than a rule or
policy.
> There are
> only few asm instructions on Intel CPUs which are not
> supported by AMD, and IIRC none of them has to do with
> thread switching or synchronization.
Right, it doesn't have anything to do with *which* instructions are
supported, just how they're implemented.
-Craig
--
Craig Stuntz [TeamB] . Vertex Systems Corp. . Columbus, OH
Delphi/InterBase Weblog : http://delphi.weblogs.com
InterBase Performance Monitor -- Analyze and control your IB7
server: http://delphi.weblogs.com/IBPerformanceMonitor
Are you sure about that it's hardware dependent? There are
only few asm instructions on Intel CPUs which are not
supported by AMD, and IIRC none of them has to do with
thread switching or synchronization.
> I agree there's little difference between assigning to a
> string variable and any other reference counted pointer,
> and that the refrence counting issues were addressed in,
> what was it, D5?
Yeah, I think it was D5.
Well, we have the "lock" prefix to make some specific asm
instructions multi CPU safe.
> Right, it doesn't have anything to do with *which* instructions
> are supported, just how they're implemented.
Hmmm... Do you have a link about that? I mean I really doubt that there
are significant differences to which instructions are atomic or not
between Intel and AMD CPUs. IIRC, the Intel instruction reference it
pretty clear on what is atomic and what not. AMD would be silly to not
follow this specification. AMD CPUs would not be 100% x86 compatible in
that case.
> Well, we have the "lock" prefix to make some specific asm
> instructions multi CPU safe.
Yes, but I thought we were discussing stuff outside of an explicit
lock. Obviously, anything you lock is safe.
> > Right, it doesn't have anything to do with which instructions
> > are supported, just how they're implemented.
>
> Hmmm... Do you have a link about that? I mean I really doubt that
> there are significant differences to which instructions are atomic or
> not between Intel and AMD CPUs. IIRC, the Intel instruction reference
> it pretty clear on what is atomic and what not. AMD would be silly to
> not follow this specification. AMD CPUs would not be 100% x86
> compatible in that case.
Maybe I wasn't clear; I wasn't saying that AMD was different (you
brought up AMD, not me!). Only that Intel is free to change which reads
and writes are atomic in any CPU they introduce, and nobody can really
complain if they do. You have to presume that anything which happens
to be thread-safe outside the context of an explicit lock is an
implementation detail.