I've got a singleton that can be called by multiple threads.
I do some lookup of data pretty often and I what to cache the data so that I don't have to repeat the same lookup again and again.
I'd like to do something akin to using static local variables, but in a thread-safe way. I suspect the code below is watertight. Is this correct?
type
TPrevious = record
public
Fontname: string;
FontSize: integer;
Canvas: pointer;
Width: integer;
end;
threadvar Previous: TPrevious;
function TEditorOptions.GetEditorFontWidth(const Canvas: TCanvas): integer;
var
Font: TFont;
//var //static vars <<-- static var != threadsafe
// PreviousFontName: string = '';
// PreviousFontSize: integer = 0;
// PreviousCanvas: pointer = nil;
// PreviousWidth: integer = 0;
begin
{1: I'm assuming a managed threadvar is always initialized to Default(T)}
if (Previous.Fontname <> '') then begin
//Cache the values, so we don't recalculate all the time.
//Caching is per thread, but that's fine.
if (SameText(Previous.FontName, FFontName)) and (Previous.FontSize = FFontSize)
and (pointer(Canvas) = Previous.Canvas) then Exit(Previous.Width);
end;
Previous.Canvas := pointer(Canvas);
Previous.FontName := FFontName;
Previous.FontSize := FFontSize;
Result:= SomeCalculation(Canvas, FFontName, FFontSize);
....
Previous.Width:= Result;
....
end;
I have 2 questions:
A: Am I correct in assuming that managed threadvars like the string FontName are always initialized to Default(T) (i.e. '')
B: Is this code fully threadsafe/ re-entrant?