Strings & thread safety

Hi,

I used to believe that string handling was thread-safe in Delphi, I even remember when people were nagging about string handling getting slower in a past Delphi release (a long time ago), when they got thread-safe. Lots of internet resources even seem to claim that strings are thread-safe.
...but they're not, and we've been told that they're not supposed to be.

So my questions are:

-Is there an official statement about strings & thread-safety?

-Is there any known function that can swap/copy strings safely with minimal locking? That is, only using locks (I'd like to avoid a critical section).
I've tested "s1:=Copy(s2,1,MaxInt)" and it really seems to be thread-safe in practice, but in theory I have no idea, is it designed to be or it's just luck?

-Why is the string-related compiler magic in System.pas full of thread-safety code & hints for string reference counting, if they're not supposed to be thread-safe?
I of course don't expect custom string manipulation (like working on the buffer directly) to be thread-safe, but considering that "s1:=s2" is purely compiler magic for strings, & that the compiler magic (I suppose it calls _LStrAsg or something) behind tells about thread-safety, it was tempting to assume that the assignments was thread-safe.



Thanks
0
Didier
3/3/2010 9:28:20 AM
embarcadero.delphi.general 4258 articles. 0 followers. Follow

24 Replies
1569 Views

Similar Articles

[PageSpeed] 16

Didier Dambrin wrote:

> I used to believe that string handling was thread-safe in Delphi, I
> even remember when people were nagging about string handling getting
> slower in a past Delphi release (a long time ago), when they got
> thread-safe. Lots of internet resources even seem to claim that
> strings are thread-safe.

	This was to make them thread-safe to *read* (and assign references),
not to write. The reference count has to be thread-safe, but the string
itself is not.

-- 
Craig Stuntz · Vertex Systems Corp. · Columbus, OH
Delphi/InterBase Weblog : http://blogs.teamb.com/craigstuntz/
0
Craig
3/3/2010 3:51:53 PM
> 	This was to make them thread-safe to *read* (and assign references),
> not to write. 


mmh, why would it even need anything for reading alone to be thread-safe? Doesn't make much sense. 

By assigning references, do you mean that "s1:=s2" should be thread-safe? Because it's definitely not (& I think a lot of people like me were assuming it was).

Again, I don't want to "write" to a string if you mean custom manipulation. I'm just looking for the equivalent of InterlockedXXX, but to copy or swap a string. Copy() seems to do it but I'm not sure at all, and I wouldn't know how to write it properly without fully understanding the strings internal management.
If someone knows strings in depth & could tell if it even is possible technically to write a thread-safe string assignment that would only use LOCK, & not a critical section or anything that can block threads for too long.
0
Didier
3/3/2010 8:58:06 PM
Didier Dambrin wrote:

> By assigning references, do you mean that "s1:=s2" should be
> thread-safe? 

	Yes, presuming that s1 is thread-local and s2 might be global but not
mutated.

> Because it's definitely not 

	Please elaborate. A minimal test case would be helpful.

-- 
Craig Stuntz · Vertex Systems Corp. · Columbus, OH
Delphi/InterBase Weblog : http://blogs.teamb.com/craigstuntz/
0
Craig
3/3/2010 10:14:31 PM
> > Because it's definitely not 
> 
> 	Please elaborate. A minimal test case would be helpful.
> 


Here's the string stressing app that we've posted to the bug repository (to be told that it's not supposed to work anyway).

Basically, a thread assigns (using a simple assignment, GlobalString:=s) random stuff to a global string. Meanwhile, a timer in the GUI thread does TempString:=GlobalString.

Once TempString:=GlobalString has been performed, I see no reason for a change in GlobalString to reflect in TempString, if the assignment had been thread-safe. However, the length of TempString does change, only because GlobalString has been changed. 
If "TempString:=GlobalString" was thread-safe, it would increase the string's ref counter, and further assignments to GlobalString (in the thread) wouldn't mess with TempString's content.

If you lock "TempString:=GlobalString" & "GlobalString:=s" using a critical section, everything works, thus it's the assignment that's not thread-safe. 

TempString:=Copy(GlobalString,1,MaxInt) seems to work, but maybe that's just luck, I don't know if it's supposed to be thread-safe.

The test fails whether TempString is a global var, a threadvar, or a function-local variable.



----
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;

type
    TTestThread = class(TThread)
    public
      procedure Execute; override;
    end;

type
  TForm1 = class(TForm)
    Timer: TTimer;
    Label1: TLabel;
    procedure TimerTimer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    Counter:Integer;
  public
    Thread     : TTestThread;
  end;

var
  Form1:TForm1;
  GlobalString:String;
  TempString:String;


implementation

{$R *.dfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  Thread := TTestThread.Create(FALSE);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Thread.Terminate;
  FreeAndNil(Thread);
end;

procedure TForm1.TimerTimer(Sender: TObject);
var  i,j,l:Integer;
//     TempString:String;
begin
//TempString:=Copy(GlobalString,1,MaxInt);  // works
TempString:=GlobalString;

l:=Length(TempString);
for j := 0 to 100000 do if l<>Length(TempString) then
  Begin
  inc(Counter);
  Label1.Caption:=IntToStr(Counter);
  End;
end;

{ TTestThread }

procedure TTestThread.Execute;
var
   s: string;
   n,m:integer;
begin
while not Terminated do
  begin
   for n:=0 to 100000 do
     Begin
     if random(2)=0 then s:=''
                    else s:=inttostr(random(10000000))+' '+inttostr(random(10000000))+'v'+inttostr(random(10000000))+inttostr(random(10000000));
     GlobalString:=s;               
     End;
  end;
end;

end.
0
Didier
3/4/2010 6:50:50 AM
Before I analyze the test case you showed, let me point out that the
point of the lock on the reference count is *not* to automatically make
your app consistent. Rather, it's to prevent your app from crashing and
burning due to an assignment. Your app does not crash, so it's doing
its job.

	But why does it behave the way it does? Let's look.

Didier Dambrin wrote:

> Once TempString:=GlobalString has been performed, I see no reason for
> a change in GlobalString to reflect in TempString, if the assignment
> had been thread-safe. However, the length of TempString does change,
> only because GlobalString has been changed.  

	Your app has an order of operations somewhat like this:

1) Create form
2) Create thread and timer
3) Seems likely to me that the thread would execute before the timer
fires, although this may not be deterministic.
4) Assign GlobalString contents in thread.
5) Assign TempString reference in main thread.
6) Repeat steps 4-5 in non-deterministic order

	Agree?

> If
> "TempString:=GlobalString" was thread-safe, it would increase the
> string's ref counter, and further assignments to GlobalString (in the
> thread) wouldn't mess with TempString's content.

	Except that TempString's reference is re-assigned every time the timer
fires, and, as you point out, the *location* of GlobalString can change
when its contents are mutated, due to a non-zero reference count.

	My suggestion for getting to the bottom of the test case is to print
the *address* of TempString as well as the length. That should make
things clearer.

> TempString:=Copy(GlobalString,1,MaxInt) seems to work, but maybe
> that's just luck, I don't know if it's supposed to be thread-safe.

	It behaves differently, because it guarantees the reference count of
GlobalString will always be 1, since you're not copying a refrence.

-- 
Craig Stuntz · Vertex Systems Corp. · Columbus, OH
Delphi/InterBase Weblog : http://blogs.teamb.com/craigstuntz/
0
Craig
3/4/2010 1:12:32 PM
>Your app does not crash, so it's doing its job.

Wrong, it does eventually crash (that's how we discovered it), but it takes time since it's a simple app, hence the counter I added. But eventually you get an invalid pointer operation (try it).


>Except that TempString's reference is re-assigned every time the timer
>fires, and, as you point out, the location of GlobalString can change
>when its contents are mutated, due to a non-zero reference count.

Yes, I of course expect the location of GlobalString to change. However, because TempString has been assigned to its content previously, its ref count should tell "GlobalString:=s" NOT to discard the memory, and instead to allocate new memory. If that was the case & that was thread-safe, then TempString shouldn't change even if GlobalString does.


>My suggestion for getting to the bottom of the test case is to print
>the address of TempString as well as the length. That should make
>things clearer.

They both fluctuate of course, since they're assigned to strings that change. 
What's sure is that the problem occurs in TempString:=GlobalString & GlobalString:=s, because locking these stops crashing. So the problem is not that something goes wrong in the loop where TempString's length is being checked, the problem is that something has gone wrong during TempString:=GlobalString.
What I believe is that the ref count management is not thread-safe, and that at one point GlobalString:=s thinks that the string isn't used anymore & discards the content, while TempString still points to it.

Edited by: Didier Dambrin on Mar 4, 2010 6:10 AM
0
Didier
3/4/2010 2:10:28 PM
Didier Dambrin wrote:

> Wrong, it does eventually crash (that's how we discovered it), but it
> takes time since it's a simple app, hence the counter I added. But
> eventually you get an invalid pointer operation (try it).

	A crash is the only thing which would be interesting in this
discussion, since avoiding it is the *sole* purpose of the lock. The
notion of the changing length looks to me like inconsistency in the
app. At any rate, that's not what the lock is for.

	My suggestion: Ignore your expectations on how the assignment should
*behave* -- you have no cause to expect a certain value when you mutate
the reference in another thread. Instead, try to isolate the crash.

	In other words, the reference count should be equal to the actual
number of references, rather than your expectation of what the number
of references is. This is a *very* tricky thing to prove in a
concurrent environment, so focusing on the crash will be the best route.

-- 
Craig Stuntz · Vertex Systems Corp. · Columbus, OH
Delphi/InterBase Weblog : http://blogs.teamb.com/craigstuntz/
0
Craig
3/4/2010 2:22:28 PM
I usually avoid relying on crashes, because while a crash means that something went wrong, no crash doesn't mean that nothing went wrong.

Anyway, if you really want a crash, here's the app, let it run for several seconds, you will get an invalid pointer operation.
All I'm seeing in this code are string assignments, so if it's true that the assignment should be thread-safe (but isn't there any official statement about this?), then it's buggy.

And really, I know that Copy() doesn't crash, all I'm asking is if it's only luck or if Copy really behaves like an InterlockedXXX but for strings.





unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;

type
    TTestThread = class(TThread)
    public
      procedure Execute; override;
    end;

type
  TForm1 = class(TForm)
    Timer: TTimer;
    Label1: TLabel;
    procedure TimerTimer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    Counter:Integer;
  public
    Thread     : TTestThread;
  end;

var
  Form1:TForm1;
  GlobalString:String;
  TempString:String;


implementation

{$R *.dfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  Thread := TTestThread.Create(FALSE);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Thread.Terminate;
  FreeAndNil(Thread);
end;

procedure TForm1.TimerTimer(Sender: TObject);
begin
TempString:=GlobalString;
end;

{ TTestThread }

procedure TTestThread.Execute;
var
   s: string;
   n,m:integer;
begin
while not Terminated do
  begin
   for n:=0 to 100000 do
     Begin
     if random(2)=0 then GlobalString:=''
                    else GlobalString:=inttostr(random(10000000))+' '+inttostr(random(10000000))+'v'+inttostr(random(10000000))+inttostr(random(10000000));
     End;
  end;
end;

end.
0
Didier
3/4/2010 3:39:28 PM
<div id="jive-html-wrapper-div">
<br />
<DIV><FONT size="2" face="Courier New"></FONT>&nbsp;</DIV>
<DIV><FONT size="2" face="Courier New">"Craig Stuntz" wrote</FONT></DIV>
<DIV><FONT size="2" face="Courier New">&gt; ...&nbsp;let me point out that <br />
the&nbsp;point of the lock on the </FONT></DIV>
<DIV><FONT size="2" face="Courier New">&gt; reference count is <b>not</b> to <br />
automatically make your app</FONT></DIV>
<DIV><FONT size="2" face="Courier New">&gt; consistent. Rather, it's <br />
to&nbsp;prevent your app from crashing</FONT></DIV>
<DIV><FONT size="2" face="Courier New">&gt; and burning due to an <br />
assignment.&nbsp;Your app does not crash,</FONT></DIV>
<DIV><FONT size="2" face="Courier New">&gt;&nbsp;so it's doing its <br />
job.&nbsp;&nbsp; ... </FONT></DIV>
<DIV><FONT size="2" face="Courier New"></FONT>&nbsp;</DIV>
<DIV><FONT size="2" face="Courier New">Craig, et. al,</FONT></DIV>
<DIV><FONT size="2" face="Courier New"></FONT>&nbsp;</DIV>
<DIV><FONT size="2" face="Courier New">There have been&nbsp;many comments in these <br />
forums using the </FONT></DIV>
<DIV><FONT size="2" face="Courier New">phrase "thread safe" without any further <br />
explanation of </FONT></DIV>
<DIV><FONT size="2" face="Courier New">what it means in the writer's <br />
context.&nbsp; I would like to</FONT></DIV>
<DIV><FONT size="2" face="Courier New">see in the Delphi help as well as in these <br />
forums, an</FONT></DIV>
<DIV><FONT size="2" face="Courier New">explanation of exactly what is meant by <br />
"thread safe"</FONT></DIV>
<DIV><FONT size="2" face="Courier New">whenever it is used in the context of the <br />
topic being </FONT></DIV>
<DIV><FONT size="2" face="Courier New">referred to.</FONT></DIV>
<DIV><FONT size="2" face="Courier New"></FONT>&nbsp;</DIV>
<DIV><FONT size="2" face="Courier New">Regard, JohnH</FONT></DIV>
</div>
0
John
3/4/2010 4:11:29 PM
Personally, my lowest requirement for strings to be claimed "thread-safe" (which may never have been an official claim [hard to know, since Delphi's help changed a long time ago, it has been way easier to find Visual Basic-related stuff than Delphi-related stuff in Delphi's own help]), would be the assignment alone. I can't even think of anything simpler than assignment that could be performed on strings.  And I also cannot think of any other reason than thread safety behind the LOCK in _LStrAsg & other s
tring-related compiler magic functions.

Craig's claim that the lock is only there to avoid crashing (it does crash anyway) but not to safely assign strings is doubtful. If it fails assigning, crash or not, it failed. A crash is not an error in my book, it's only the result of an error.
0
Didier
3/4/2010 4:44:22 PM
Didier Dambrin wrote:

> Anyway, if you really want a crash, here's the app, let it run for
> several seconds, you will get an invalid pointer operation.  

	You're mutating the reference in one thread and assigning it in
another. I wouldn't expect that to be safe.

	The lock on the reference count is for a *very narrow* case which
should always be safe. Consider a global var which is assigned a value
at startup and is *never* changed. Now consider two or more additional
threads which do:


TMyThread.Execute;
var 
  local: string;
begin
  local := GlobalString;
  DoSomething(local);
end;

	Before the lock, this could crash. Now it will not.

> And really, I know that Copy() doesn't crash, all I'm asking is if
> it's only luck or if Copy really behaves like an InterlockedXXX but
> for strings.

	Copy is not interlocked, no. But it returns an entirely new string, so
it's an unrelated case. I would not bank on it as a thread-safety tool.

-- 
Craig Stuntz · Vertex Systems Corp. · Columbus, OH
Delphi/InterBase Weblog : http://blogs.teamb.com/craigstuntz/
0
Craig
3/4/2010 4:50:02 PM
Didier Dambrin wrote:

> Craig's claim that the lock is only there to avoid crashing (it does
> crash anyway) but not to safely assign strings is doubtful. If it
> fails assigning, crash or not, it failed.

	Not when you are concurrently mutating the reference in another
thread, no.

-- 
Craig Stuntz · Vertex Systems Corp. · Columbus, OH
Delphi/InterBase Weblog : http://blogs.teamb.com/craigstuntz/
0
Craig
3/4/2010 4:50:35 PM
If I wasn't changing the string in any of the threads, it would be a constant, and there would then be no concept of multithreading. 

What you're basically saying is, string assignment is thread safe as long as you never touched any of the strings, ever.
0
Didier
3/4/2010 5:09:42 PM
Didier Dambrin wrote:

> If I wasn't changing the string in any of the threads, it would be a
> constant, and there would then be no concept of multithreading.

	That's simply wrong. But it's a very common misunderstanding from the
vast majority of Delphi developers who do not read the ASM code which
the compiler injects on string assignments. Indeed, it is precisely
this expectation which caused the Delphi team to decide that the
performance penalty of the lock was worth the benefit.

	Consider what happens:

1) String is created on main thread. Reference count is 1.
2) Another thread assigns a local variable to the global string. The
global string is *mutated* to change its refererence count to 2.
3) The thread in (2) lets its local var go out of scope again. Once
more, the global string is mutated to change its reference count back
to 1.
4) Now consider what happens when two threads do 2-3 concurrently.

	*This* is the bug that the lock fixes. Nothing more.

> What you're basically saying is, string assignment is thread safe as
> long as you never touched any of the strings, ever.

	Why should this be surprising? If you mutate a variable, you should
not expect two concurrent threads to work without a lock. That's true
of essentially every type. The "embarassing" bug the lock fixed was
that the app would crash even with *no* mutation of the string's
contents.

-- 
Craig Stuntz · Vertex Systems Corp. · Columbus, OH
Delphi/InterBase Weblog : http://blogs.teamb.com/craigstuntz/
0
Craig
3/4/2010 5:23:03 PM
>Consider what happens:
>1) String is created on main thread. Reference count is 1.
>2) Another thread assigns a local variable to the global string. The
>global string is mutated to change its refererence count to 2.
>3) The thread in (2) lets its local var go out of scope again. Once
>more, the global string is mutated to change its reference count back
>to 1.
>4) Now consider what happens when two threads do 2-3 concurrently.


Ok so basically string assignments are not thread-safe at all & the locks are only there for the strings garbage collector (thus the LOCKS are of no use for this case where all strings are global).

Now, I suppose it'd be safe to copy the string (still trying to avoid critical sections) by
-incrementing the ref count using a LOCK
-reading the string's length, allocating memory & copying the string data
-decrementing the ref count using a LOCK
...problem here is the special case where the string is empty, thus NIL.  If you check if the string is empty, by the time you get to the instruction that increments the ref count, the string may now be empty. Seeing that _LStrCopy doesn't deal with this, I assume that it's not a valid thread-safe assignment method either :(



>Why should this be surprising? If you mutate a variable, you should
>not expect two concurrent threads to work without a lock. That's true
>of essentially every type. 

not really, for most types you either know when assignments are atomic, or you have InterlockedXXX functions to avoid more expensive locking. By the lack of a function to thread-safely assign strings, I was assuming that they were by default.

Edited by: Didier Dambrin on Mar 4, 2010 9:56 AM
0
Didier
3/4/2010 5:59:12 PM
Didier Dambrin wrote:

> Now, I suppose it'd be safe to copy the string (still trying to avoid
> critical sections) by

	I could probably give more intelligent feedback on the way to solve
this if I understood what problem you are trying to solve by passing
the string. In general, manipulating ref counts directly is a mistake.
But I don't know what you're trying to do.

-- 
Craig Stuntz · Vertex Systems Corp. · Columbus, OH
Delphi/InterBase Weblog : http://blogs.teamb.com/craigstuntz/
0
Craig
3/4/2010 6:02:26 PM
I'm just trying to pass a string from a side thread to the GUI thread, it's that simple.
I suppose I could use a lock-free list, allocate the string in the writer thread, and unallocate it in the reader thread.

Edited by: Didier Dambrin on Mar 4, 2010 10:11 AM
0
Didier
3/4/2010 6:11:49 PM
Didier Dambrin wrote:

> I'm just trying to pass a string from a side thread to the GUI
> thread, it's that simple.

	What about WM_COPYDATA, then? Or a custom message? I generally use
messages for communicating with the UI.

-- 
Craig Stuntz · Vertex Systems Corp. · Columbus, OH
Delphi/InterBase Weblog : http://blogs.teamb.com/craigstuntz/
0
Craig
3/4/2010 6:17:30 PM
I'm actually passing a message already, but of course it only has 2 32bit params. 
WM_CopyData requires a SendMessage (not post), so the overhead is most likely a lot higher than using a critical section.

Anyway I'll use a critical section, they're not evil, and on a multiprocessor the default spincount will probably be enough for a simple string assignment. But I avoid them when I can, as I'm dealing with audio.
0
Didier
3/4/2010 6:29:11 PM
IMHO if you're passing strings so frequently that a CS overhead is
measurable *at all*, then you need to use a different means of passing
data (e.g., memory mapped file).

-- 
Craig Stuntz · Vertex Systems Corp. · Columbus, OH
Delphi/InterBase Weblog : http://blogs.teamb.com/craigstuntz/
0
Craig
3/4/2010 6:35:37 PM
Statistically it's neglectable overhead, and for this case alone I'm not worried, it's just a bad practice to do this while dealing with audio & very short processing buffers. I do it when I have a good reason, but just to pass a string..  
A CS is statistically good, but in the worst case it means waiting for an event, & this is bad when audio has to be processing buffers of a couple of milliseconds. Especially since it's communicating with the GUI thread that has a lower priority, here I can only hope that priority inversion works.

Most programmers dealing with audio just ban critical sections, IMHO they're not the evil they think, but I woulnd't abuse them either, especially when there's an easy lock-free alternative.

Edited by: Didier Dambrin on Mar 4, 2010 10:47 AM
0
Didier
3/4/2010 6:49:58 PM
Didier Dambrin wrote:

> A CS is statistically good, but in the worst case it means waiting
> for an event, & this is bad when audio has to be processing buffers
> of a couple of milliseconds. Especially since it's communicating with
> the GUI thread that has a lower priority, here I can only hope that
> priority inversion works.

	Whether you make a CS block on an event is of course up to you.
Obviously, I wouldn't recommend it!

-- 
Craig Stuntz · Vertex Systems Corp. · Columbus, OH
Delphi/InterBase Weblog : http://blogs.teamb.com/craigstuntz/
0
Craig
3/4/2010 7:06:38 PM
Well you don't have the choice, a critical section USES an event in the worst case.  But as I wrote, thankfully there's a spincount so most likely it will never have to revert to an event if I'm only assigning a string.
0
Didier
3/4/2010 7:13:21 PM
Didier Dambrin wrote:

> Well you don't have the choice, a critical section USES an event in
> the worst case.

	To be clear, I was referring to a Delphi event (a Windows message),
not a Windows event.

-- 
Craig Stuntz · Vertex Systems Corp. · Columbus, OH
Delphi/InterBase Weblog : http://blogs.teamb.com/craigstuntz/
0
Craig
3/4/2010 7:18:44 PM
Reply:

Similar Artilces:

threads & threads::shared & Threads::Semaphore
Hi, All, Hope everyone's new year is starting out very well. I'm having to adjust a perl program I wrote to manipulate some genetics data. Originally, the program had no memory problems but now that I've added a couple more hashes, I'm having memory issues. It now runs out of memory when it's about half way through processing the data. Unfortunately, the data is very interconnected and the statistics I need to execute involves data from several of the hashes. I'm thinking of using threads & threads::shared in order to be able to proces...

Messaging thread pools & thread safety
I was wondering about the lifecycle of messaging components [CTS::MessageListener, Java implementation] 1. Java/CORBA components require a no argument constructor. This constructor is invoked only _once_ ? [a single invokcation for the pool, not a constructor per instance] 2. Are non-static class fields permitted? Are they isolated on a Message by Message invocation? [I would prefer using ordinary class members rather than local variables in the onMessage method - it would simplifiy my abstract base class design] 3. When the onMessage method returns, what does the Jaguar jvm do ...

Strings and Thread Safety
I have seen some conflicting information regarding this topic, and I was hoping to get some help. My current understanding is (please correct me if this is wrong): 1) string variable read by multiple threads = safe 2) string variable written by multiple threads = not safe but what about: 3) string variable written by one thread, read by multiple threads = ??? The reason I ask is because I have a class derived from TThread with an FComError string member. That thread will be the only one writing to it, and other threads will only read it. (BTW, using Delphi 7) Thanks, Wa...

Thread safety and mutable strings
FinishSharingTitle only calls js_MakeStringImmutable() for strings referenced by the slots of TITLE_TO_SCOPE(title)->object. But that scope could be shared by many objects. Is this a bug? -j On Jul 10, 3:58=A0pm, Jason Orendorff <jorendo...@mozilla.com> wrote: > FinishSharingTitle only calls js_MakeStringImmutable() for strings > referenced by the slots of TITLE_TO_SCOPE(title)->object. > > But that scope could be shared by many objects. Is this a bug? Not objects that have to have their own scope in order to have string- valued properties. Objects ...

Session & Application Thread Safety
OK, so all the books I have read say that Session variables are thread safe and that application variables are not thread safe because they can be accessed by multiple pages at the same time.However as far as I can tell it would seem to be possible to have the same session being used on multiple browsers. e.g. if I have a site open in IE and I press ctrl-N I open a new window and remain logged in - which to me suggests I am participating in the same session in 2 different browsers.So my question is, are the Session variables thread safe given that it seems you can have multiple pages op...

iThreads & thread safety + ITRPC
Hello, Sorry I'm a bit more of a lurker than a contributor, but I saw an idea a while back in the "our :shared $foo / iThreads" thread that I thought made an aweful lot of sense but went unnoticed (I couldn't find the message right off hand). What about implementing an inter-thread RPC of some sort for those nasty non-reentrant functions? For instance, if I'm doing a bunch of work in Thread B and need to call foo(), an unsafe function, I would be safe and simply do my $bar = iThread->{thread_a}->foo(); # I know threads aren't named... Since...

Concatenate date string & time string & convert to UK DateTime Problem
Hi, I have a date string (from textbox) & a time string (eg "09:00:00") which i want to concatenate together to form a full date time value which is passed into my sql server table. However, after i concatenate the strings & use the convert.toDateTime i always get the US date format (which causes problems with my date comparisons). i want it showing the UK date/time format. I tried inserting the following line in my web.config file on my LOCAL machine but with no luck:<globalization culture="en-GB" uiCulture="en-GB" requestEncoding="...

Threads && PipeLines.
Hi everyone, I have two questions of which I have never implemented/used in powerbuilder before. 1.) Does power builder allow multiple concurrent threads(I know java does)? I am trying to start a separate thread besides the application -- need to do some concurrent stuff aswell have application trying to connect to the database or any other processing that is. I am trying to have some animation while my application is trying to connect to my database. 2.) Where can I find info on pipelines? I have tried the documentaion but it does offer much. Thanks in advance! ...

Delphi 7 & SOAP & WSDL Import & SSRS
Hi I am struggling with a web service I consumed (ReportService2010.asmx). I am not sure if I consumed it with the in-corrections options or if I am not setting THTTPRIO settings correctly or both ! I am really new to webservice & SOAP. I update the Delphi SOAP Runtime and Importer Update (http://cc.embarcadero.com/Item/24535). Thank you Jean-Marie Babet. I imported the WSDL with the following options [wfDebug,wfUnwindLiteralParameters,wfUseSerializerClassForAttrs]. I had to make a few changes to the pas file to get it to compile. I changed {code} SensitivityEnum = (True, Fals...

delphi 2010 RTTI & create component by class type string
i need to create components in runtime by class type string . it seems delphi 2010 can help me to avoid using Registerclass : from : [http://robstechcorner.blogspot.com/2009/09/delphi-2010-rtti-basics.html] program Project11; {$APPTYPE CONSOLE} uses StdCtrls, TypInfo, Classes, Rtti; var c : TRttiContext; m : TRttiMethod; t : TRttiInstanceType; SL : TValue; Lines : TValue; begin c := TRttiContext.Create; t := (c.FindType('Classes.TStringList') as TRttiInstanceType); SL := t.GetMethod('Create').Invoke(t.MetaclassType,[]); t.GetMethod(...

search & extract string from a string.
I have a string  string str = "XR=XG(TABLE1,ITEM1,DATE)+SUM(A1:B4)+B5+AVERAGE(C1:C4)+IF(XG(TABLE2,ITEM1,DATE)-XG(TABLE3,ITEM1,DATE)>0,XG(TABLE4,ITEM1,DATE),B5)" I want to know if i can extract: -XG(TABLE1,ITEM1,DATE)-XG(TABLE2,ITEM1,DATE)-XG(TABLE3,ITEM1,DATE)-XG(TABLE4,ITEM1,DATE) basically, I need to write a function that would search and get all value within "(" and ")" right after each XG, and save it as XG(*****), anyone know what function should I be using?  The best way is to use a regular expression, there's a really good reference ...

threads & threads::shared status
//depot/perlio/... as now achieved my original short term goals: - No segfaults on Win32 and Win32/Linux behaving the same Linux: nick@bactrian 510$ ./perl harness ../ext/threads/t/*.t ../ext/threads/shared/t/*.t ..../ext/threads/t/basic...............ok ..../ext/threads/t/stress_cv...........ok ..../ext/threads/t/stress_re...........ok ..../ext/threads/t/stress_string.......ok ..../ext/threads/shared/t/0nothread....ok ..../ext/threads/shared/t/av_simple....ok ..../ext/threads/shared/t/hv_refs......FAILED test 12 Failed 1/17 tests, 94.12% okay (-4 skipped tests: 12 okay, ...

&& In Generated Javascript Becomes &amp;&amp;
I am trying to write client side scripts in c#, asp.net V 1.4. The && operator is generated in the javascript as &amp;amp;, which causes errors.  How can I avoid this? (Code below)  Thanks in advance.   script = "<script language='javascript' type='text/javascript'>\n"; script += "if (Form1." + tbxA.ClientID + ".value == '' && "; script += "Form1." + tbxB.ClientID + ".value == '') {"; script += "Form1." + cbxC.ClientID + ".Checked = false;}"; ...

How Can I Delphi 2009 & Indy 10 TCPServer & TCPClient & Stream ? [Edit]
How can i send simple XML data from TCPClient to TCPServer and opposite. The Indy Version is the Delphi 2009 shipped version (v10). I have some XML data (you can think it as TStrings). I Can not convert the xml string to stream and send it to server then can't convert from stream sent to server to TStrings (or string) again in server (or client) side... Thanks for code snippets & answers... Edited by: Huseyin Melih Kara on Apr 27, 2009 7:59 AM Edited by: Huseyin Melih Kara on Apr 28, 2009 5:24 AM > {quote:title=Huseyin Melih Kara wrote:}{quote} > How can i send simp...

Web resources about - Strings & thread safety - embarcadero.delphi.general

Kubo and the Two Strings - Wikipedia, the free encyclopedia
Kubo and the Two Strings is an upcoming American 3D stop motion film produced by Laika for Focus Features . It is being directed by Travis Knight ...

Facebook + Twitter + Klout + Pinterest = No-Strings-Attached Dates? April Fool’s!
... Twitter, and Klout, and then brings it into Pinterest and uses a “secret algorithm” to match up “like-minded Pinterest users” for “no-strings ...

Query Strings - Quora
Quora is your best source for knowledge.

Strings... on the App Store on iTunes
Get Strings... on the App Store. See screenshots and ratings, and read customer reviews.

12 Windows Apps Behind the Strings - YouTube
Adam and Shaun Lee, founders of Bohemian Guitars, are fueled by Windows apps and their own ingenuity. Discover how they continue to change what ...

Pakistani band Strings battles it out with Indian band Euphoria at Red Bull Soundclash - The National ...
Everyone's a winner at battle of the bands as musicians from both bands declare a draw, delighting the crowd at Dubai World Trade Centre.

Home help has strings attached
Home help has strings attached

A bad time for households to tighten the purse strings
Growth continues to be driven largely by resource exports, leaving the economy vulnerable to the whims of China. Household consumption is needed ...

De Castella queries wisdom of AIS handing over purse strings
Marathon legend Robert de Castella has urged the Australian Institute of Sport to employ ''strict accountability and performance expectations'' ...

Strings attached as guitar store goes under
JACKSONS RARE GUITARS sold instruments to the stars: George Harrison, Metallica, Slash and Keith Urban. The walls were adorned with rock'n'roll ...

Resources last updated: 2/5/2016 4:35:37 PM