Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2014-06

Thread Safety of String

21 messages · 9 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Unknown author

Hello:

Is a string[30] declaration under Linux thread safe?

I am not worried about atomicity, just that the memory for a string[30] if thread safe.

For UTF8String, it is not.

I have 2 threads which are comparing/changing memory and I do not want criticalsections wrapping the memory accesses for speed reasons.

Type
  Class TTest(TObject)
  public
    nflag : integer ;
    sflag : string[30]
  end;

Gui Thread

gtest := TTest.Create ;

Thread #1 - Constantly changing values

while true do
begin
 gtest.nflag := Random($FFFFFFFF) ;
 gtest.sflag := inttostr(gtest.nflag) ;
end;

Thread #2 - Constantly Comparing values

While true do
begin
  if gtest.nflag = 777888 then
  begin
    break ;
  end;
  //Test string matching instead of integer matching
  if gtest.sflag = '123456' then
  begin
    LaunchSpaceShuttle(gtest) ;
  end;
end;

Thanks for any replies,

marco

Unknown author
to Michael Van Canneyt

Just as I suspected.

So every time a new value is assigned to a string[30] variable, memory is allocated and changed by the compiler, so the internal string pointer changes as well.

And the only recourse is critical sections for memory access.

Correct?

CHeers,

marco

Michael Van Canneyt wrote 15 lines
On Wed, 4 Jun 2014, wrote: > Hello: > > Is a string[30] declaration under Linux thread safe? No. Michael. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Unknown author
to Michael Van Canneyt: No. Michael.

I guess what I was really asking is:

Is there a way to treat an array of chars as a string.

I like the string handling patterns of freepascal but I want the memory stability of a static array of chars
so I can be used in multi-thread operations without a lot a critical section considerations.

Cheers,

marco

Michael Van Canneyt wrote 15 lines
On Wed, 4 Jun 2014, wrote: > Hello: > > Is a string[30] declaration under Linux thread safe? No. Michael. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Craig Peterson
to Unknown author
I like the string handling patterns of freepascal but I want the memory stability of a static array of chars so I can be used in multi-thread operations without a lot a critical section considerations.

Have you actually verified that adding a critical section makes things noticeably slower? You're better off starting with something that you know is correct and optimizing it with questionable changes when you're sure you need it.

Craig Peterson Scooter Software
Unknown author
to Unknown author: Just as I suspected. So every time a new value is assigned to a string[30] variable,…
Show quoted text 26 lines
On 6/4/2014 1:16 PM, Michael Van Canneyt wrote: > > > On Wed, 4 Jun 2014, wrote: > >> Hello: >> >> Is a string[30] declaration under Linux thread safe? > > No. > > Michael. Just as I suspected. So every time a new value is assigned to a string[30] variable, memory is allocated and changed by the compiler, so the internal string pointer changes as well. And the only recourse is critical sections for memory access. Correct? CHeers, marco

I still program in Turbo Pascal so I am more of a
spectator than a user of Free Pascal. As I understand it the shortstring type is the same as string type in Turbo Pascal. This would make index 0 of variable typed as shortstring[SIZE] an internal length byte and index positions 1 through SIZE the data value of the string. Since, unlike a newer string type, a shortstring is not an object and not a managed string at all, but a simple type like an integer, I would expect shortstring might be thread safe.

Is this the case?

Saunders, Rich
to Unknown author: I guess what I was really asking is: Is there a way to treat an array of chars as a…
Show quoted text 8 lines
I guess what I was really asking is: Is there a way to treat an array of chars as a string. I like the string handling patterns of freepascal but I want the memory stability of a static array of chars so I can be used in multi-thread operations without a lot a critical section considerations.

Short strings (those declared with a defined length) are not as dynamic as you fear. They should stay in place while you change their values.

The String type (declared without defined length) is the one that is dynamic and reference counted.

Cheers! Rich Saunders
Michael Van Canneyt
to Unknown author: I still program in Turbo Pascal so I am more of a spectator than a user of Free Pascal. …
Show quoted text 37 lines
On Wed, Jun 04, 2014 at 01:19:33PM -0400, wrote: > On 6/4/2014 1:16 PM, Michael Van Canneyt wrote: >> >> >> On Wed, 4 Jun 2014, wrote: >> >>> Hello: >>> >>> Is a string[30] declaration under Linux thread safe? >> >> No. >> >> Michael. > > Just as I suspected. > > So every time a new value is assigned to a string[30] variable, memory > is allocated and changed by the compiler, so the internal string pointer > changes as well. > > And the only recourse is critical sections for memory access. > > Correct? > > CHeers, > > marco I still program in Turbo Pascal so I am more of a spectator than a user of Free Pascal. As I understand it the shortstring type is the same as string type in Turbo Pascal. This would make index 0 of variable typed as shortstring[SIZE] an internal length byte and index positions 1 through SIZE the data value of the string. Since, unlike a newer string type, a shortstring is not an object and not a managed string at all, but a simple type like an integer, I would expect shortstring might be thread safe. Is this the case?

No, exactly the opposite.

Michael.

Unknown author
to Saunders, Rich: Short strings (those declared with a defined length) are not as dynamic as you fear. They…

For anybody who has followed this thread, there is some disagreement over the thread safety of shortstrings. And in this case, a shortstring with a clearly defined maximum length.

Some have clearly said string[30] is NOT thread safe.

Rich indicated below he feels they ARE SAFE.

Hmmm. Time for DOUBLE jeopardy.

Alex Trebeck says, "I am the son of Ansistring but I don't move around much. My pointer is me and I am my pointer."

Answer: What is a shortstring in Freepascal?

I am going to err on the side of caution and take Michael Van Canneyt's version and implement it that way.

I have to implement the same thread code in C++ a little later, so there are no shortstrings in C++, just QStrings. (oops, yeah, I use Qt also)

Cheers,

Marco

Rich wrote 16 lines
On 2014-06-04 13:22, wrote: > I guess what I was really asking is: > > Is there a way to treat an array of chars as a string. > > I like the string handling patterns of freepascal but I want > the memory stability of a static array of chars > so I can be used in multi-thread operations without > a lot a critical section considerations. Short strings (those declared with a defined length) are not as dynamic as you fear. They should stay in place while you change their values. The String type (declared without defined length) is the one that is dynamic and reference counted.
Ewald
to Unknown author
Show quoted text 8 lines
For anybody who has followed this thread, there is some disagreement over the thread safety of shortstrings. And in this case, a shortstring with a clearly defined maximum length. Some have clearly said string[30] is NOT thread safe. Rich indicated below he feels they ARE SAFE.

Actually, the question is: what do you mean by `thread safe`? So you mean it like: `the variable stays at the same place in memory (but not always, the variable can reside in a register for some time)`, like `accesses to this variable are atomic`, like `this variable will *always* be in memory at the same location (no prolonged life in registers for this bugger)`, or ...?

Show quoted text 5 lines
Hmmm. Time for DOUBLE jeopardy. Alex Trebeck says, "I am the son of Ansistring but I don't move around much. My pointer is me and I am my pointer."

Hmmm, JuniorString must be a cripple philosopher then ;-)

Anyway, I would be interested in the answer, as do you I suppose.

I have to implement the same thread code in C++ a little later, so there are no shortstrings in C++, just QStrings. (oops, yeah, I use Qt also)
Time for some nitpicking..Yay! How about:
	char YourString[SIZE];

It's kind of a drudgery to handle those though, so I see why you like QStrings better :-)

Ewald
Saunders, Rich
to Unknown author: For anybody who has followed this thread, there is some disagreement over the thread…
Show quoted text 8 lines
For anybody who has followed this thread, there is some disagreement over the thread safety of shortstrings. And in this case, a shortstring with a clearly defined maximum length. Some have clearly said string[30] is NOT thread safe. Rich indicated below he feels they ARE SAFE.

You have misinterpreted by comment. I was pointing out that short strings are more static than the String type and not the as dynamic as the earlier message indicated. When you assign a new value it is placed in the same memory location as the previous value. This is not always the case with the String type.

Whether static variables are more or less thread safe is for you to decide since you know what you are doing with them. I don't think either short strings or Strings are inherently more or less thread safe. It depends on what you do with them.

Cheers! Rich Saunders
Mattias Gaertner
to Saunders, Rich
Rich" wrote 5 lines
[...] Whether static variables are more or less thread safe is for you to decide since you know what you are doing with them. I don't think either short strings or Strings are inherently more or less thread safe. It depends on what you do with them.

No data is "thread safe". Only code can be thread safe.

Mattias

Unknown author
to Mattias Gaertner

I thought I had publicly declared what I wanted to do.

Here is the example code again for ease of reference:

Type
  Class TTest(TObject)
  public
    nflag : integer ;
    sflag : string[30]
  end;

Gui Thread

gtest := TTest.Create ;

Thread #1 - Constantly changing values

while true do
begin
 gtest.nflag := Random($FFFFFFFF) ;
 gtest.sflag := inttostr(gtest.nflag) ;
end;

Thread #2 - Constantly Comparing values

While true do
begin
  if gtest.nflag = 777888 then
  begin
    break ;
  end;
  //Test string matching instead of integer matching
  if gtest.sflag = '123456' then
  begin
    LaunchSpaceShuttle(gtest) ;
  end;
end;

Will this code be thread safe in terms of the gtest.sflag = '123456' line never throw an exception because it is referring to stable memory that is always less than 31 bytes.

Cheers,

marco

Mattias Gaertner wrote 16 lines
On Wed, 04 Jun 2014 15:03:31 -0400 "Saunders, Rich" wrote: > [...] > Whether static variables are more or less thread safe is for you to > decide since you know what you are doing with them. I don't think either > short strings or Strings are inherently more or less thread safe. It > depends on what you do with them. No data is "thread safe". Only code can be thread safe. Mattias _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Jeppe Græsdal Johansen
to Unknown author

It will never throw an exception, but it will never be thread safe either.

Unless you are using the Interlocked* functions no datatype is threadsafe on a modern processor(except for reference counting of ansistrings, dynamic arrays, and interfaces; and all those use Interlocked* functions under the hood).

Use semaphores or events instead if you need something fast, thread safe, and responsive.

Show quoted text 72 lines
I thought I had publicly declared what I wanted to do. Here is the example code again for ease of reference: Type Class TTest(TObject) public nflag : integer ; sflag : string[30] end; Gui Thread gtest := TTest.Create ; Thread #1 - Constantly changing values while true do begin gtest.nflag := Random($FFFFFFFF) ; gtest.sflag := inttostr(gtest.nflag) ; end; Thread #2 - Constantly Comparing values While true do begin if gtest.nflag = 777888 then begin break ; end; //Test string matching instead of integer matching if gtest.sflag = '123456' then begin LaunchSpaceShuttle(gtest) ; end; end; Will this code be thread safe in terms of the gtest.sflag = '123456' line never throw an exception because it is referring to stable memory that is always less than 31 bytes. Cheers, marco On 6/4/2014 3:27 PM, Mattias Gaertner wrote: > On Wed, 04 Jun 2014 15:03:31 -0400 > "Saunders, Rich" wrote: > >> [...] >> Whether static variables are more or less thread safe is for you to >> decide since you know what you are doing with them. I don't think either >> short strings or Strings are inherently more or less thread safe. It >> depends on what you do with them. > No data is "thread safe". Only code can be thread safe. > > Mattias > _______________________________________________ > fpc-pascal maillist - > http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal > _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Michael Schnell
to Unknown author: I still program in Turbo Pascal so I am more of a spectator than a user of Free Pascal. …
I would expect shortstring might be thread safe.

Only a simple write (not a modification) of processor-native types is inherently atomic and thus really thread save.

So I suspect that even Int64 is not thread save (in this sense) on 32 bit CPUs: a simple write to a memory based variable is doner in two steps and so could be preempted by the other thread, but is on a 64 bit CPU.

A modification of course is even worse (here you can use "atomic" functions provided by the RTL).

Obviously a short string can't be re-written in a single instruction.

-Michael

Michael Schnell
to Mattias Gaertner
Mattias Gaertner wrote
> Only a simple write (not a modification) of processor-native types is > inherently atomic and thus really thread save. No.

What do you want to say by "No" ?
- even a simple write might be not thread save or
- also more complex writes are thread save
("thread save" in the sense that a write of the value can't be interrupted by another thread and hence the other thread always reads the coherent value - either the one before the writing or the one after writing)

I understand that the implementation of memory barriers is architecture specific and in a portable code you can't rely on a desired behavior.

-Michael

Michael Schnell
to Mattias Gaertner
Mattias Gaertner wrote
> - even a simple write might be not thread save or

OK. I do see that with multi-processor archs with lacking automatic memory barriers this in fact might be violated for misaligned variables. (I don't doubt that such archs do exist.)
("thread save" in the sense that a write of the value can't be interrupted by another thread and hence the other thread always reads the coherent value - either the one before the writing or the one after writing) .

Thanks for clearness.
-Michael

Bruno Krayenbuhl
to Mattias Gaertner: On Thu, 05 Jun 2014 09:51:05 +0200 this: Mattias

My point of view after looking at the code.

This code is not thread safe.

Discussion

    gtest.sflag := inttostr(gtest.nflag) ; -> will call
fpc_AnsiStr_To_ShortStr

fpc_AnsiStr_To_ShortStr is programmed as :

procedure fpc_AnsiStr_To_ShortStr (out res: shortstring; const S2 :
Ansistring);[Public, alias: 'FPC_ANSISTR_TO_SHORTSTR'];  compilerproc;

{

  Converts a AnsiString to a ShortString;

}

Var
  Size : SizeInt;
begin
  if S2='' then
   res:=''
  else
   begin
     Size:=Length(S2);
     If Size>high(res) then
      Size:=high(res);
     Move (S2[1],res[1],Size); // 1° ~bk Copy the string
     byte(res[0]):=byte(Size);  // 2° ~bk patch the length
   end;
end;

1° and 2° (the processor instructions generated for the task) can not be guaranteed to be executed in order on most processors.

+

As far as I know, or at least that would be something that I would consider as true, pre-emptive multitasking may switch the threads during 1° or between and 1° and 2°.

+

Thread doing

if gtest.sflag = '123456' then begin // 3° ~bk unfinished AnsiStr_To_ShortStr ?

      // gtest.sflag is equal to '123456'

3° ~bk unfinished AnsiStr_To_ShortStr : res might contain '1234567' with length 6 because if contained a length of 6 before step 2°, but the length=6 would be, for example, the residue length of the previous res= '263456' .

And so on.

My experience is that for these things one must use a CriticalSection or similar thread protection.

Regards, Bruno