Does that work on a nil variable?
The point is, a static variable must be thread safe.
Does that work on a nil variable?
it’d be locked on “self”
I don’t like that.
That means that every static variable is locked as soon as one of them is locked.
Might give a performance problem with multithreading.
We could also just create a custom lock object for each var, but still only the “locked” is specified. and alternatively allow “locked on x;” as well.
That is a good solution.
Race conditions are still possible with this (if you use the variable within the method) - but that is the same as I am used to with VB. To prevent that, the only option is to lock the complete method.
But that depends on how you use the static variable, so this is an implementation detail for the programmer.
Be maybe something to describe in the docs.
TBH, the more I think about it, I don’t see why these should behave any different that regular fields (except for being limited to a single function). If your method ac ceases fields on the class, its up to you to do the locking, if races can occur; the same could be argued should be needed here.
All this feature should do is move the field declaration into the method, and limit the visibility of the field to the method.
That is indeed the simplest solution and should be sufficient for most cases.
But if you implement it as a lazy property instead as a field, we will at least get the functionality that the local static field is only initialized when it is used during program execution.
I would be happy with that solution too.
wouldn’t even have too be a lazy property, could be more like
method Foo; begin var x := "Hello"; static; writeLn(x); x := "again"; end;
method Foo; begin if not x_Was_Initialized then begin x := "Hello"; x_Was_Initialized := true; end; writeLn(x); x := "again"; end; var x: String; var @x_Was_Initialized: Boolean;
method Foo; begin locking x_Was_Initialized do begin if not x_Was_Initialized then begin x := "Hello"; x_Was_Initialized := true; end; end; writeLn(x); x := "again"; end; var x: String; var @x_Was_Initialized: Boolean;
It should be the locked version to prevent multiple threads to initialize the field.
probably, yes. Think is, on Island, locking will require a Monitor instance (On .NET and Java, we can lock on anything, so locking on the boolean instance will probably be safe, not sure if changing a boolean, being a value type, affects its identity for locking purposes (if so, we might need an extra lock object even there :().
And the name should be mangled; I should be able to use var x: String: static in every method.
And monitor is also available in .Net (also used by VB for this).
of course, yes
Yes, I’m merely thinking if we can somehow get away without needing an explicit Monitor (or Object) for locking for each static var, as they’d all add to the class size and memory footprint ofc…
If the locking is only for the initialization, I have no problems with locking on self.
To prevent lots of locking on self, the following (not really nice) solution:
method Foo; begin if not x_Was_Initialized then begin locking self do begin if not x_Was_Initialized then begin x := "Hello"; x_Was_Initialized := true; end; end; end; writeLn(x); x := "again"; end; var x: String; var @x_Was_Initialized: Boolean;
So, first check if it was already initialized, then lock and when you get the lock, check again.
Wait a minute: Locking on self only works with instances …
So a separate lock object is needed.
I would suggest one class lock object per class that is used by all local static variables for initialization.
Good idea. I use that pattern myself often.
Locking on self also works for class methods, it’ll lock on the class, so it does exactly the right thing.
Ok, did not know that. I thought self was the instance and a class method has no instance.
Just making sure this one is not forgotten (as I can not do this with an aspect, I depend on you )
Thanks, logged as bugs://83118