Subroutines and Flag Lock

I have a queue that is being read by a single chart using FIFO and after each read it shifts the queue by -1 to remove the top item.

I also have subroutine that writes to this queue and this subroutine can be called from multiple charts.

I want to:

  • Pass a Flag variable to the subroutine (or really a pointer to a Flag variable because I’m afraid the subroutine wont lock the flag otherwise)
  • Then lock the Flag using blocking (-1)
  • Write to end of queue
  • Then unlock the Flag

Do charts that call a subroutine pause until the subroutine finishes?

If the subroutine tries to lock the Flag but finds it already locked, will it immediately delay the subroutine to try again in XX ms? or will it spike the CPU trying over and over to lock the Flag for up to 1ms before its forced to move on to the next chart?

I can’t find any reference to how often the FlagLock() command will attempt to lock a locked Flag and if FlagLock() only tries once before delaying the current chart/subroutine.

Thanks

(Passing direct as an Integer variable works fine)

Yes they do.

Not sure on this, but I believe the chart doesn’t get the time slice again until the flag is unlocked - much like a Delay command - I haven’t noticed any unusual performance issues when using semaphores - and I wouldn’t expect there to be. However, I usually don’t have code holding the semaphore for too long.

Thank you for all the great answers. I’ll think about using a timeout instead of blocking to make sure I don’t hold the flag too long.

Blocking is fine, just make sure that there is no way for the code between the lock and unlock to stop. Don’t stop or pause charts with semaphores, and make sure your unlock will always get called - no condition statements that could skip over it.

This question is out of my wheelhouse, but interesting… so, I reached out to a few of the software engineers that write the code that runs your code for their input…Here is a summery of their feedback.


He can go ahead and pass the flag lock variable; when you pass in a variable, the subroutine operates on the actual variable, not a copy.

Charts enter a loop while they’re waiting for the flag lock variable, but there’s a 1 msec delay at the top of the loop; the only thing the chart does while in that state is to check for messages, (like STOP or QUIT), and delay. CPU usage during that time will be negligible.

Perhaps they are thinking that a subroutine is like a Call Chart; it’s not. Charts that call a subroutine don’t pause; their execution branches to the subroutine, which means the chart’s other instructions can’t be executed until the subroutine completes and returns execution back to the chart.

The very high level sequence of events for locking the flag looks like this:

Do

  Attempt lock

  If failed

    Check for messages (Like stop or quit)

    Delay 1 msec

  Endif

While failed and not (stop or quit)

I hope that between @philip typically excellent information / experience and this insight you can go forth and code in confidence.

3 Likes