Join 34,000+ subscribers and receive articles from our
blog about software quality, testing, QA and security.

Thread safety


#1

Hi,

SI 3.3, Delphi 2007/2010

If I create a viewer context, eg, TSiInspectorViewerContext in a class which descends from TSiSession, will the viewer context be thread safe ?

TIA

Sue


#2

Hi,

I’ve just been for a walk and realised that the data that needs to be thread safe as well.

However any suggestions and references for this would be appreciated.

TIA

Sue


#3

Hello Sue,

a viewer context cannot be used from multiple threads at the same time. However, this is usually not necessary because if you are just creating the viewer context locally in a custom log method, the context is only available in this method and should be destroyed at the end of your custom method.

If you are using viewer contexts differently (e.g. reusing viewer context objects multiple times), it depends on the concrete scenario whether this is thread-safe or not. If you could share some additional details, I’m happy to take a look.

Hope this helps.

Regards,
Tobias


#4

Hi Tobias,

Thanks for the offer to look more closely at what I am trying to do.

I am using SmartInspect with a multi-threaded application.

I have created my own session class descended from yours, with a new method to handle a component that we have created.

type TtbsSiSession = class(TSiSession)
private
FContext: TSiInspectorViewerContext;
FrrData: TRecordRow;
public
constructor Create(const AParent: TSmartInspect;
const ASessionName: UnicodeString); overload;
destructor Destroy; override;
procedure LogRecordRow(aLevel: TSiLevel; const aTitle: UnicodeString;
TheRecordRow: TtbsThreadRecordRow);
end;

We create FContext in the Create;

Each thread has a property
property SiParent: TSmartInspect read FSiParent write FSiParent;
which is set by the unit which creates the thread.

At the start of Execute, a session is created (Providing FSiParent <> nil)
FSiSession := TtbsSiSession.Create(FSiParent, FName);
FSiSession.EnterThread(FName);

During thread processing, I call LogRecordRow in FSiSession, which, in summary, does this

FContext.StartGroup(aTitle);
iCount := TheRecordRow.GetRecordRow(FrrData);
for iIndex := 0 to iCount - 1 do
begin
  aField := FrrData.GetFieldRecordByIndex(iIndex);
  if aField.IsNull then
    FContext.AppendKeyValue(aField.Name, 'NULL')
  else
    FContext.AppendKeyValue(aField.Name, aField.AsString);

end;
tbsSiMain.LogCustomContext(aLevel, aTitle, ltText, FContext);

It seems to me that this should be thread safe. aField is a copy of the data I’m logging and is taken inside a Lock/Unlock call.

Q1. Do you agree this is thread safe ?

Q2. I also want to call some of your methods, such as LogText from within the thread. If I do it from the thread session, will it be thread safe ? (providing, of course, that the data is local to the thread).

I have been doing this assuming it was thread safe in this context, but after rereading the help and seeing these methods are not guaranteed thread safe, I want to be sure.

Hopefully I have explained this clearly.

TIA

Sue


#5

Hello Sue,

Yes, this should be thread-safe. As I understood it, you are just using the viewer context and FSiSession from within a single thread and this is thread-safe (provided, as you mentioned, that the data (FrrData etc.) in the custom method is also used in a thread-safe way). SmartInspect will take care that operations beyond the viewer context are synchronized, if needed. For example, sharing the FSiParent between threads is certainly possible (to use a shared log file for the entire application, for instance).

However, there’s one thing I would do a bit differently. I would suggest creating viewer contexts locally in the custom method instead of saving them as object fields and re-using them (and that’s also how the SmartInspect log methods are implemented, such as LogText). Creating and disposing viewer context objects is not expensive at all and this would make the code a bit cleaner and also easier to see that the code is thread-safe. In case you are using the viewer context for a reason other than avoiding creating new objects for every log call, then this wouldn’t work though.

This is also thread-safe. Every SmartInspect log method is thread-safe provided that the data the log method operates on is also thread-safe (which may not always be the case without synchronizing it explicitly). If viewer contexts are used by a specific log method, the viewer context is only created locally in this method and not shared with other threads.

Regards,
Tobias


#6

Hello Tobias,

Thanks for your reply.

<<
However, there’s one thing I would do a bit differently. I would suggest creating viewer contexts locally in the custom method instead of saving them as object fields and re-using them (and that’s also how the SmartInspect log methods are implemented, such as LogText). Creating and disposing viewer context objects is not expensive at all and this would make the code a bit cleaner and also easier to see that the code is thread-safe. In case you are using the viewer context for a reason other than avoiding creating new objects for every log call, then this wouldn’t work though.

I am creating them as object fields as I expect to add more methods which will use the same viewer context, so it saves creating objects in more than one place.

I take your point though, and will think about it. Knowing that it is not expensive is useful.

Thanks again,

Sue