Using multithreading

Top  Previous  Next

As a short example of how to use multithreading, we will look into a VPL program that monitors two digital inputs that will generate an SMS message on each rising edge. That could provide the basis for a simple alarm system with two door switches.

 

First we take a look at how the somewhat simplified program will look without multithreading:

 

INCLUDE rtcu.inc
 
VAR_INPUT
  al_1 : BOOL R_EDGE;
  al_2 : BOOL R_EDGE;
END_VAR;
 
PROGRAM test;
gsmPower(power := TRUE);
BEGIN
  IF al_1 THEN
    //Alarm!
    gsmSendSMS(phonenumber := "22448899", message := "Alarm. Door 1");
  END_IF;
  IF al_2 THEN
    //Alarm!
    gsmSendSMS(phonenumber := "22448899", message := "Alarm. Door 2");
  END_IF;
END;
 
END_PROGRAM;

 

This is a very simple program with one serious problem. If the "al_1" input goes high, it will send out an SMS message. That will take maybe 5..6 seconds before the call to gsmSendSMS() returns. If during this period the "al_2" (or the "al_1" once more) input goes high and low, it will never be detected by the program. This is serious as another thief could just have broken in.

 

Here is how we can improve these shortcomings with multithreading:

 

INCLUDE rtcu.inc
 
 
VAR_INPUT
  al_1 : BOOL R_EDGE;
  al_2 : BOOL R_EDGE;
END_VAR;
 
VAR
  chalarm : CHANNEL;
END_VAR;
 
//SMS thread
THREAD_BLOCK smsalarm;
VAR
  alarmno : SINT;
END_VAR;
 
WHILE TRUE DO
  chRead(ch:=chalarm,msg:=ADDR(alarmno),lenmax:=SIZEOF(alarmno));
  gsmSendSMS(phonenumber := "22448899",message := strFormat(format:="Alarm. Door \1", v1:=alarmno));
END_WHILE;
 
END_THREAD_BLOCK;
 
 
PROGRAM test;
VAR
  smshandler : smsalarm;
  alarm : sint;
END_VAR;
 
//main thread
chalarm := chInit(msgMax:=10);
smshandler();
gsmPower(power := TRUE);
BEGIN
  IF al_1 THEN
     alarm:=1;
     chWrite(ch:=chalarm,msg:=ADDR(alarm),len:=SIZEOF(alarm));
  END_IF;
  IF al_2 THEN
     alarm:=2;
     chWrite(ch:=chalarm,msg:=ADDR(alarm),len:=SIZEOF(alarm));
  END_IF;
END;
 
END_PROGRAM;

 

 

This program is a bit longer than the single threaded version, but it will address all the shortcomings previously mentioned.

We realize that both the responsiveness and correctness of the application have been improved. The program structure can also be said to have improved, but this will be more visible in larger and more complex programs.

 

The program uses the Channel mechanism for passing the alarm as a number to the SMS thread. The chWrite() function call is non-blocking which means that the main thread will very quickly send the message and continue its operation. The SMS thread will automatically be blocked in the chRead() function call as it waits for messages from the main thread. When a message arrives, it will send the actual SMS message by using the gsmSendSMS() function. The speed of sending the SMS message is not important, because when new alarms do occur, they will simply be queued in the Channel mechanism and processed in the order they were inserted into the channel.

 

Please continue reading the section Thread syncronization.