Active Sleep procedure - Aftermath

by Iztok Kacin in Coding

Last time I wrote about an Active Sleep procedure that allows better blocking wait function than classic combination of “Sleep” and “Application.ProcessMessages”. I had some interesting discussions about that with my coworker and a fellow Delphi programmer (gabr). They had three valid arguments about my approach:

  1. There could be reentrancy problems if message was posted after the event was fired, but before the MsgWaitForMultipleObjects was called.
  2. There could be reentrancy problems if in internal message loop some code is called, that should not be called while wait was active.
  3. This approach is inferior to a queue of “blocking” requests that wait there to be processed.

All three arguments seemed valid, so I decided to look into them and find out what can be done about them.

I will start by 3. argument. I agree that approach with a queue is better in theory. You pool the requests in a queue, processing them one by one and in the meantime you do not process anything that should wait for those requests to finish. You can process any other code that is not bound to them. While waiting, no actual blocking is happening anywhere. It is all about structuring your code correctly.

This sound as a sound approach and it is, but it takes a lot of work to set up such a framework. Now in two situations I cannot justify such an approach (note that gabr wrote a threading library that makes this actually very simple):

  1. Your “blocking” problem is simple and isolated to that small code area.
  2. Your application is not written in a way that could easily adopt the queue approach.

It seems to me that in such cases the queue approach is overkill. But I would absolutely prefer it if you have an application that relies heavily on blocking or non-blocking actions that take place during some code execution.

Now to the other two arguments. The 1. one is not actually a problem as the study showed. If a message (action is completed) arrived after the action was started and before the MsgWaitForMultipleObjects is called, the MsgWaitForMultipleObjects will exit right away, because it has an “unflaged” message in the queue. The only possible problem here is if some code elsewhere would call PeekMessage with PM_NOREMOVE flag. This would flag the message as read and block the wait code.

Raymond Chen had a blog post about that issue some time ago.

Even if you worry about that, you still have two possible solutions to the problem:

  1. You can use an external Event passed to the ActiveSleep Function
  2. You can call MsgWaitForMultipleObjectsEx with MWMO_INPUTAVAILABLE flag.

The first would enable that the wait object is handled from outside the function and could be signaled before the MsgWaitForMultipleObject is called. The second approach will exit right away if a message if in the queue, even if it is flaged as read.

The first approach would look like this. First the action code and the action calling code.

procedure TQMLAction.Execute;
begin
  // set flags and run
  FSuccessful := False;
  FIsRunning := True;
  FStartTime := Now;
  Inc(FExecuteCount);
 
  FActionEvent := CreateEvent(nil, False, False, nil);
  // execute the basic action code
  FThread := TQMLBasicAction.Create(FActionEvent);
 
  // if wait then cycle
  if FAction.Wait then
  begin
    while FIsRunning do
    begin
      if FAction.Timeout > 0 then
       if (MilliSecondsBetween(Now, FStartTime) > (FAction.Timeout * 1000)) then
       begin
         FSuccessful := TActionThread(FThread).SuccessStatus;
         FThread := 0;
         Exit;
       end;
 
      case FAction.Timeout > 0 of
        True: ActiveSleep(FAction.Timeout * 1000, QS_SENDMESSAGE, FActionEvent);
        False: ActiveSleep(INFINITE, QS_SENDMESSAGE, FActionEvent);
      end;
    end;
  end;
end;
procedure TQMLBasicAction.Execute;
begin
  // process the action event code
  // set the event as finished
  SetEvent(ActionEvent);
end;

An then the modified ActiveSleep procedure.

procedure TQMLAction.ActiveSleep(const Timeout, WakeMask: Cardinal; const Handle: Cardinal);
var
  Msg: TMsg;
  Result: DWORD;
begin
  Result := MsgWaitForMultipleObjects(1,              { 1 handle to wait on }
                                      Handle,         { the handle }
                                      False,          { wake on any event }
                                      Timeout ,       { wait with timeout }
                                      WakeMask        { wake on sendmessage }
                                      );
 
  if Result <> WAIT_TIMEOUT then
  begin
    while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
    begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
  end;
end;

The second approach is actually wery similar to the original:

procedure TQMLAction.ActiveSleep(const Timeout, WakeMask: Cardinal);
var
  Msg: TMsg;
  Handle: THandle;
  Result: DWORD;
begin
  Handle := OpenThread(SYNCHRONIZE, False, GetCurrentThreadID);
 
  Result := MsgWaitForMultipleObjectsEx(1,              { 1 handle to wait on }
                                        Handle,         { the handle }
                                        False,          { wake on any event }
                                        Timeout ,       { wait with timeout }
                                        WakeMask        { wake on sendmessage }
                                        MWMO_INPUTAVAILABLE { wake if message in queue});
 
  if Result <> WAIT_TIMEOUT then
  begin
    while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
    begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
  end;
end;

So we have dealt with the two problems at hand. Now the problem number 2. Yes potentially this could cause problems but only if the code is poorly written and we are not aware of the workings of such a wait loop. As long as you know what you are doing, you should be fine.

I have showed that such an approach is completely reasonable in certain situations. And if nothing else, I see so many poorly written “Sleep” / “Application.ProcessMessages” loops that this post should help at least in some of those cases.

Active Sleep procedure

by Iztok Kacin in Coding

Recently I have stumbled upon an interesting problem. I had a thread that was executing some actions. This actions could be blocking or non-blocking and were executed in background threads, each actions was running in it’s own thread. The parent thread recieved the results via the SendMessage function. Now as long as I only supported non-blocking actions everything was fine, the parent thread kept running and executing actions while it recieved the results inside its own message loop.

But then I introduced blocking actions, because somethimes I had to wait for the result before moving on. Now the problem was how to efficiently wait for the result while still being able to process messages. So to sumarize the problem:

  • blocking or non-blocking actions are executed from parent thread
  • parent thread is executing actions and waits for the results
  • parent thread must process messages at all times

Windows OS has a number of functions designed for thread synchronization, probably the most famous among them being the WaitForSingleObject. In most cases the WaitForSingleObject works just fine puting the thread in deep sleep while waiting for a certain event, but in my case this just would not cut it. Why? Because I had to process messages while trying to wait (sleep) as efficiently as possible. The most obvious and working solution would be the following:

  if FAction.Wait then
  begin
    while FIsRunning do
    begin
       if (MilliSecondsBetween(Now, FStartTime) > (FAction.Timeout * 1000)) then
       begin
         FSuccessful := TActionThread(FThread).SuccessStatus;
         FThread := 0;
         Exit;
       end;
 
       Sleep(10);
       Application.ProcessMessages
    end;
  end;

A simple combination of Sleep and ProcessMessages. But this aproach while working fine has two flaws:

  • The Sleep interval must be short to catch the timeout on time. This way it causes a loot of thread switching and a lot of message processing with no gain.
  • It uses Application object which means we must use Forms.pas. This is overkill and Forms.pas is not thread safe (ok VCL is not but I do not like to take any chances).

So is there anything better we can do about that. As I said WaitForSingleObject is out of the question because we would miss the SendMessage call. I went looking which other synchronization functions are available. At first I did not see anything useful, but then I read some neewsgroup post from Peter Bellow. He used MsgWaitForMultipleObjects. Briliant, this is exactely what I needed. WaitForMultipleObjects waits for number of objects and additionally wakes when certain messages are recieved. Which are those messages, can be set with the dwWakeMask parameter. His solution still had a few flaws (he used Application object for one), so I made some improvements and came out with this:

  procedure TQMLAction.ActiveSleep(const Timeout, WakeMask: Cardinal);
  var
    Msg: TMsg;
    Handle: THandle;
    Result: DWORD;
  begin
    Handle := OpenThread(SYNCHRONIZE, False, GetCurrentThreadID);
 
    Result := MsgWaitForMultipleObjects(1,              { 1 handle to wait on }
                                        Handle,         { the handle }
                                        False,          { wake on any event }
                                        Timeout ,       { wait with timeout }
                                        WakeMask        { wake on sendmessage }
                                        );
 
    if Result <> WAIT_TIMEOUT then
    begin
      while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
      begin
        TranslateMessage(Msg);
        DispatchMessage(Msg);
      end;
    end;
  end;

For the object to wait upon I chose the current thread. This ensures that the object will never become signaled and we wake only upon special messages or when the timeout is trigered. And instead of using the Application object I just wrote a small message pump that uses PeekMessage. If I used GetMessage then i would get blocked when all messages were processed as GetMessage waits for the next message to be processed. PeekMessage ensures that I only process the waiting messages and then exit the Sleep function. The final result would look like this:

  if FAction.Wait then
  begin
    while FIsRunning do
    begin
       if (MilliSecondsBetween(Now, FStartTime) > (FAction.Timeout * 1000)) then
       begin
         FSuccessful := TActionThread(FThread).SuccessStatus;
         FThread := 0;
         Exit;
       end;
 
       ActiveSleep(FAction.Timeout * 1000, QS_SENDMESSAGE);
    end;

Because I only wait for SendMessage calls the thread sleeps the entire Timeout period and is not waking every 10ms. When the SendMessage is recieved it wakes and processes the message so the cycle is broken.

The solution work perfectly for now, but if someone sees some issues with this aproach please explain me why this is a bad idea :)

Simple XML based storage - Part II.

by Iztok Kacin in Coding

Last time I showed some basic data manipulation with the storage and explained the very basics of its workings. Ok it was maybe interesting, but it was nothing to be excited about. So this time I am going to show you some advanced data manipulation tehniques and explain some other things about SimpleStorage.

First of all we have three ways of creating the storage.

1
2
3
4
5
  function CreateStorage(const RootNode: XmlString = ''): ISimpleStorage;
  function StorageFromXML(const XML: XmlString): ISimpleStorage;
  function StorageFromFile(const FileName: XmlString): ISimpleStorage;
  function StorageFromStream(const Stream: TStream): ISimpleStorage;
  function StorageFromElement(const Element: IElement): ISimpleStorage;

The idea behind these is that it lets us create the storage in one step. We do not need to create the storage and load it from file (yes we can do that if we want to) if we already know that we want to create a storage based on existing XML file (like conf file for instance). Same goes for XML as WideString, or for new in memory storage that lets us declare the root element right in the constructor.

Now let me show you some examples of getting the values from the storage.

1
2
3
4
  SourceStorage.Get('English/Science/Mathematics').AsInteger;
  SourceStorage.Get('English/Science/DoesNotExist').AsInteger;
  SourceStorage.Get('English/Science/DoesNotExist').AsIntegerDef;
  SourceStorage.Get('English/Science/DoesNotExist').AsIntegerDef(10);

Here we have four ways of getting the values. The first one we already saw last time and it gets us the number of Mathematical books as integer. Get always tries to get the node, but if the node is not there it stil returns a valid interface. But the interface has an internal pointer to actual XML node which is nil.So the second example will stil generate AV. This is welcome in certain conditions, when we want to be aware of missing values, but most of the time, we want the code to always succed. So the last two examples do not generate AV. Instead they return the default value, which is “0″ as default for integer and “10″ in the last example. Here we explicitly demanded “10″ if the value is not found.

We can also use the power of XPath in our searches.

1
2
3
4
  SourceStorage.Get('English/Science/*[@Difficulty="Medium"]').AsInteger;
  SourceStorage.Get('English/Science/[@Difficulty]').AsInteger;
 
  SourceStorage.Ensure('English/Science/Astronomy[@Difficulty="High"]').AsInteger;

The first example will return the first value under the science books that has attribute Difficulty=”Medium” and the second one will return the first value that has attribute Difficulty present. The third example is more interesting because it check if an element with name Astronomy and attribut Difficulty=”High” exists. And if it does not then it created such element (attribute included).

And we can read or write the values in many different formats (types). Here is the IValue interface that shows all the possibilities.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  IValue = Interface(IInterface)
  ['{3D25DFB7-CC19-4598-9010-8FA55322F126}']
    // getters and setters
    function _GetName: XmlString;
    function _GetAsFloat: Real;
    function _GetAsBinary: IBinary;
    function _GetAsString: XmlString;
    function _GetAsInteger: Integer;
    function _GetAsBoolean: Boolean;
    function _GetAsDateTime: TDateTime;
    procedure _SetAsFloat(Value: Real);
    procedure _SetAsString(Value: XmlString);
    procedure _SetAsInteger(Value: Integer);
    procedure _SetAsBoolean(Value: Boolean);
    procedure _SetAsDateTime(Value: TDateTime);
    // value properties that get/set value in different formats
    function AsFloatDef(const DefValue: Real = 0): Real;
    function AsStringDef(const DefValue: XmlString = ''): XmlString;
    function AsIntegerDef(const DefValue: Integer = 0): Integer;
    function AsBooleanDef(const DefValue: Boolean = False): Boolean;
    function AsDateTimeDef(const DefValue: TDateTime = 0): TDateTime;
    property AsDateTime: TDateTime read _GetAsDateTime write _SetAsDateTime;
    property AsBoolean: Boolean read _GetAsBoolean write _SetAsBoolean;
    property AsInteger: Integer read _GetAsInteger write _SetAsInteger;
    property AsString: XmlString read _GetAsString write _SetAsString;
    property AsFloat: Real read _GetAsFloat write _SetAsFloat;
    property AsBinary: IBinary read _GetAsBinary;
    property Name: XmlString read _GetName;
  end;

Ok now let me show how we can enumerate certain values or nodes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  for Element in SourceStorage.Get('English/Science').Values do
    mmResultsData.Lines.Add(Format('%s : %s', [Element.Name, Element.AsString]));
 
  for Element in SourceStorage.Get('English/Science').Nodes do
    mmResultsData.Lines.Add(Format('%s', [Element.Name]));
 
  for Element in SourceStorage.Get('English/Science').Values('*[@Difficulty="High"]') do
    mmResultsData.Lines.Add(Format('%s : %s', [Element.Name, Element.AsString]));
 
  for Element in SourceStorage.Values('English/Science/*[@Difficulty="High"]') do
    mmResultsData.Lines.Add(Format('%s : %s', [Element.Name, Element.AsString]));
 
  for Element in SourceStorage.Get('English/Science').Values('Engineering') do
    mmResultsData.Lines.Add(Format('%s : %s', [Element.Name, Element.AsString]));

I will not talk to much about this as you probably see what the results will be by now. I will only explain the last one. The last example enumerates all values which are named ‘Engineering’ under the ‘English/Science’ node.

Maybe it is also worth noting that the first example iterates on all values (elements that have no children) of a single node and the secod example iterated on all nodes (elements that have childred). It is similar to folders and files if we use filesystem as comparison.

Probably one of the strongest features is data merging. You can merge data from different storages with almost no code at all, or you can even copy data inside the same storage with ease. Two examples to demostrate this. We have two different XML samples. The Target storage.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  <Books>
    <English>
      <Science>
        <Mathematics Difficulty="High">5</Mathematics>
        <Physics Difficulty="Low">0</Physics>
        <Computers Difficulty="Medium">8</Computers>
        <Engineering Difficulty="Low">4</Engineering>
        <Electoronics Difficulty="High">8</Electoronics>
      </Science>
      <Musical>
        <Classic>2</Classic>
        <Etno>2</Etno>
        <Pop>8</Pop>
      </Musical>
    </English>
  </Books>

And the source storage.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  <Demografija>
    <Males>
      <Janez>Novak</Janez>
      <Darko>Gazvoda</Darko>
      <Mitja>Dežela</Mitja>
      <Tilen>Medved</Tilen>
    </Males>
    <Females>
      <Person Name="Marija">Gorenjska</Person>
      <Person Name="Tanja">Notranjska</Person>
      <Person Name="Maja">Primorska</Person>
      <Person Name="Tadeja">Pomurje</Person>
      <Person Name="Irma">Posočje</Person>
      <Person Name="Marija">Notranjska</Person>
    </Females> 
  </Demografija>

Now we have these lines of code.

1
2
3
4
5
  SourceStorage := CreateStorageFile(FRootDir + DIR_DATA + FILE_DATA_TWO);
  TargetStorage := CreateStorageFile(FRootDir + DIR_DATA + FILE_DATA_ONE);
 
  TargetStorage.Get('English').Append(SourceStorage, True);
  TargetStorage.Get('English/Musical').Append(SourceStorage.Get('Females').Values);

And the result of these four lines of code (of which only two line actually manipulate the data) is shown bellow. The first merge appended the whole source storage to the single target node (‘English’) in the target storage. And the second merge appended all values that were result of a single iteration to another target single node (‘English/Musical’).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  <Books>
    <English>
      <Science>
        <Mathematics Difficulty="High">5</Mathematics>
        <Physics Difficulty="Low">0</Physics>
        <Computers Difficulty="Medium">8</Computers>
        <Engineering Difficulty="Low">4</Engineering>
        <Electoronics Difficulty="High">8</Electoronics>
      </Science>
      <Musical>
        <Classic>2</Classic>
        <Etno>2</Etno>
        <Pop>8</Pop>
        <Person Name="Marija">Gorenjska</Person>
        <Person Name="Tanja">Notranjska</Person>
        <Person Name="Maja">Primorska</Person>
        <Person Name="Tadeja">Pomurje</Person>
        <Person Name="Irma">Posočje</Person>
        <Person Name="Marija">Notranjska</Person>
      </Musical>
      <Demografija>
        <Males>
          <Janez>Novak</Janez>
          <Darko>Gazvoda</Darko>
          <Mitja>Dežela</Mitja>
          <Tilen>Medved</Tilen>
        </Males>
        <Females>
          <Person Name="Marija">Gorenjska</Person>
          <Person Name="Tanja">Notranjska</Person>
          <Person Name="Maja">Primorska</Person>
          <Person Name="Tadeja">Pomurje</Person>
          <Person Name="Irma">Posočje</Person>
          <Person Name="Marija">Notranjska</Person>
        </Females>
      </Demografija>
    </English>
  </Books>

I hope you see how powerfull this data manipulation was :)

Ok that is all in the second part of the series about the SimpleStorage. Next time I will conclude it with some final thoughts and some more ways of using it.

The code is considered to be stable. But there may still be some bugs in it. To download the code with the demo get it here - SimpleStorage

Simple XML based storage - Part I.

by Iztok Kacin in Coding

For quite some time now, I was being bothered by the fact that every time I use XML as a data transmitting media, I write a lot of code just to read and write from / to XML. I use XML to maintain config files for quite a few project. Furthermore I use it in a few projects as means of transferring data. For instance here is an event handler that is used in a rendering engine when the engine requests some external data to process.

  procedure OnRenderEngineCustomTag(const TagName: TUTF8String;
                                    const TagParams: TStrings;
                                    var TagData: ISimpleStorage);

So I looked for means that would allow me to transfer any kind of data over and do that with as little code as possible. Needed qualities were (not in any particular order):

  • flexibility,
  • ease of use,
  • structured type of storage.

As a cherry on the pie, it would be nice if I could use this to parse my config files and to use it as a method of serialization in SOAP data transfers. This way I could read / write SOAP data with ease.

I realized that even if it is not the fastest technology out there, XML would be perfect for this.

  • It is Flexible and can hold almost any kind of data. It even can hold attributes to describe the data.
  • It is well accepted, so the tools are numerous and almost everyone can read it.
  • It can be manipulated by hand if need arises.
  • It is well structured by nature.

I already use XML a lot in my day to day work. OmniXML is a wonderful Delphi XML library that is flexible and powerful. It also already has a lot of supporting code and tools build around it. So I decided to build on top of OmniXML. Actually it was a no brainier :).

The whole idea of the storage I had, was build around nodes and values. They are both elements. The storage has a root element and any number of elements further down the tree structure. An element is a node if it has at least one child. And all the elements without any children are values. Both can have attributes that describe them even better, but only values can hold actual data. So a typical storage would look like this. You can map this logic to lets say some of the tree data structures.

<Books>
    <English>
      <Science>
        <Mathematics Difficulty="High">5</Mathematics>
        <Physics Difficulty="Low">0</Physics>
        <Computers Difficulty="Medium">8</Computers>
        <Engineering Difficulty="Low">4</Engineering>
        <Electronics Difficulty="High">8</Electronics>
      </Science>
      <Musical>
        <Classic>2</Classic>
        <Etno>2</Etno>
        <Pop>8</Pop>
      </Musical>
    </English> 
  </Books>

Here we have a book storage, which holds two type of books. Science books and Musical books. These are further divided by the category to which they belong. Here we can see that “Science” and “Musical” elements are typical nodes that have values. “Mathemathics” and “Physics” are values under the “Science” node and “Etno” is a value under the “Musical” node. They all hold actual data. We can see that we have 5 “Mathemathical” books and 0 “Physics” books. And all “Science” books have and attribute “Difficulty” that further divides them into groups.

Now you probably already have the idea how the things are meant to work. So I am just going to demonstrate a little sample of how easy it is to write or read using the SimpleStorage.

  SourceStorage := StorageFromFile('BookStorage.xml');
 
  SourceStorage.Get('English/Science/Mathematics').AsInteger;
  SourceStorage.Get('English/Science/Computers').AsString;
 
  SourceStorage.Ensure('English/Science/Arheology').AsInteger := 3;
  SourceStorage.Ensure('English/Science/Geology').AsInteger := 15;

In the first two lines we read the “Mathematics” and “Computers” values as integer and as string. It is really easy to access any node in the tree and also read it in a needed value type. The second two lines demonstrate how easy it is to write two new values (“Arheology” and “Geology”) to the storage. As you can see you can use simplified XPath to access the nodes which gives you great flexibility.

For now this will be all. Next time I will go further and show advanced methods of data manipulation.

The code is considered to be stable. But there may still be some bugs in it. To download the code with the demo get it here - SimpleStorage