1 of 18

Untangle Your Threads

Vlad Patryshev

(this is not me!!!)

© 2020 Vlad Patryshev

2 of 18

Some History

Many years ago Edsger Dijkstra invented semaphores and wrote "Structured Programming". Then C.A.R. Hoare wrote a book, "Communicating Sequential Processes". 

Ideas of these two became the foundation of all later books on how processes should communicate.

We find code samples in such books, translated into C, Java, Python, Perl, Ruby, and use them to solve all our problems. Thanks to these guys, all our problems look like a nail now.

This is called Cargo Cult. 

3 of 18

Cargo Cult

During WWII, somewhere on Pacific, large amounts of materials were brought in by the  combatants, and this was observed by the residents. When the war ended, the flow of goods and materials ceased. 

To attract further deliveries of goods, the residents started building imitation landing strips and aircrafts, to attract other aircrafts. /from Wikipedia/

4 of 18

The Problem

  • Every M minutes start GPS, get N fixes, send them to server
  • M and N may change on demand
  • GPS may need restart now and then
  • Turn it off after getting N fixes
  • May skip invalid fixes or when we are not moving
  • Save power

5 of 18

Before Refactoring

  

Recorder Thread

Reader Thread

Reporter Thread

Device Thread

Policy Thread

  • kicks reader
  • wake up when it has N or on timeout
  • stop reader
  • retrieve N fixes from reader
  • pass fixes to Reporter queue
  • sleep for M minutes
  • repeat
  • pause
  • when kicked, turn on GPS
  • start receiving fixes, filling the circular buffer
  • when requested, return N fixes, or as many as we have
  • when told to stop, stop GPS
  • repeat
  • check the queue
  • send all fixes from the queue to server via UDP
  • sleep for a while
  • repeat
  • call listener passing new fix
  • repeat
  • wait for K minutes
  • check if there's new policy
  • if yes, reconfigure recorder (N,M, conditions)
  • repeat

6 of 18

Look Closer

  

Recorder Thread

Reader Thread

Reporter Thread

Device Thread

Policy Thread

  • kicks reader
  • wake up when it has N or on timeout
  • stop reader
  • retrieve N fixes from reader
  • pass fixes to Reporter queue
  • sleep for M minutes
  • repeat
  • pause
  • when kicked, turn on GPS
  • start receiving fixes, filling the circular buffer
  • when requested, return N fixes, or as many as we have
  • when told to stop, stop GPS
  • repeat
  • check the queue
  • send all fixes from the queue to server via UDP
  • sleep for a while
  • repeat
  • call listener passing new fix
  • repeat
  • wait for K minutes
  • check if there's new policy
  • if yes, reconfigure recorder (N,M, conditions)
  • repeat

7 of 18

Look Closer

Recorder Thread

Reader Thread

Reporter Thread

Device Thread

Policy Thread

  • kicks reader
  • wake up when it has N or on timeout
  • stop reader
  • retrieve N fixes from reader
  • pass fixes to Reporter queue
  • sleep for M minutes
  • repeat
  • pause
  • when kicked, turn on GPS
  • start receiving fixes, filling the circular buffer
  • when requested, return N fixes, or as many as we have
  • when told to stop, stop GPS
  • repeat
  • check the queue
  • send all fixes from the queue to server via UDP
  • sleep for a while
  • repeat
  • call listener passing new fix
  • repeat
  • wait for K minutes
  • check if there's new policy
  • if yes, reconfigure recorder (N,M, conditions)
  • repeat

Why not queue fixes in the listener? Listener also knows when it is enough

8 of 18

Now what

  

Recorder Thread

Reader Thread

Reporter Thread

Device Thread

Policy Thread

  • kicks reader
  • tell reader to pick up N fixes 
  • wake up when it has N or on timeout
  • stop reader
  • sleep for M minutes
  • repeat
  • pause
  • when kicked, turn on GPS
  • start receiving fixes, sending them to Reporter queue
  • when told to stop, stop GPS
  • repeat
  • check the queue
  • send all fixes from the queue to server via UDP
  • sleep for a while
  • repeat
  • call listener passing new fix
  • repeat
  • wait for K minutes
  • check if there's new policy
  • if yes, reconfigure recorder (N,M, conditions)
  • repeat

9 of 18

Next Step - No Reader Thread

  

Recorder/Listener Thread

Reporter Thread

Device Thread

Policy Thread

  • Start GPS, receiving N fixes, sending them to Reporter Queue, stopping GPS when done 
  • wake up on timeout
  • stop GPS
  • sleep for M minutes
  • repeat

  • check the queue
  • send all fixes from the queue to server via UDP
  • sleep for a while
  • repeat
  • call listener passing new fix
  • repeat
  • wait for K minutes
  • check if there's new policy
  • if yes, reconfigure recorder (N,M, conditions)
  • repeat

10 of 18

Recap

  

Recorder/Listener Thread

Reporter Thread

Device Thread

Policy Thread

  • Start GPS, receiving N fixes, sending them to Reporter Queue, stopping GPS when done 
  • wake up on timeout
  • stop GPS
  • sleep for M minutes
  • repeat
  • check the queue
  • send all fixes from the queue to server via UDP
  • sleep for a while
  • repeat
  • call listener passing new fix
  • repeat(?)
  • wait for K minutes
  • check if there's new policy
  • if yes, reconfigure recorder (N,M, conditions)
  • repeat

We have no control over this thread

11 of 18

What Sync Do We Have?

  

Recorder/Listener Thread

Reporter Thread

Device Thread

Policy Thread

  • Start GPS, receiving N fixes, sending them to Reporter Queue, stopping GPS when done 
  • wake up on timeout
  • stop GPS if it is still on
  • sleep for M minutes
  • repeat

Noticed two sleep points? When Policy Thread wakes up Recorder, we may be in the wrong place

  • check the queue
  • send all fixes from the queue to server via UDP
  • sleep for a while
  • repeat
  • call listener passing new fix
  • repeat(?)
  • wait for K minutes
  • check if there's new policy
  • if yes, reconfigure recorder (N,M, conditions) This requires waking up Recorder Thread
  • repeat

We have no control over this thread

12 of 18

Make It Simpler

  

Recorder/Listener Thread

Reporter Thread

Device Thread

Policy Thread

  • Start GPS, receiving N fixes, sending them to Reporter Queue, stopping GPS when done 
  • wake up on timeout
  • stop GPS if it is still on
  • sleep for M minutes
  • repeat

  • check the queue
  • send all fixes from the queue to server via UDP
  • sleep for a while
  • repeat
  • call listener passing new fix
  • repeat(?)
  • wait for K minutes
  • check if there's new policy
  • if yes, stop current Recorder, start a new one with new policy (if needed)
  • repeat

We have no control over this thread

13 of 18

Enter TimerTask

  

Recorder Task

Reporter Thread

Device Thread

Policy Thread

  • Start GPS, receiving N fixes, sending them to Reporter Queue, stopping GPS when done 
  • wake up on timeout
  • stop GPS if it is still on

  • check the queue
  • send all fixes from the queue to server via UDP
  • sleep for a while
  • repeat
  • call listener passing new fix
  • repeat(?)
  • wait for K minutes
  • check if there's new policy
  • if yes, cancel Recorder Task, start a new Recorder Task
  • repeat

We have no control over this thread

14 of 18

And Another TimerTask

  

Recorder Task

Reporter Thread

Device Thread

Policy Task

  • Start GPS, receiving N fixes, sending them to Reporter Queue, stopping GPS when done 
  • wake up on timeout
  • stop GPS if it is still on

  • check the queue
  • send all fixes from the queue to server via UDP
  • sleep for a while
  • repeat
  • call listener passing new fix
  • repeat(?)
  • check if there's new policy
  • if yes, cancel Recorder Timer, start a new one, with new Recorder Task

We have no control over this thread

15 of 18

Reorder by Hierarchy

  

Recorder Task

Reporter Thread

Device Thread

  • Start GPS, receiving N fixes, sending them to Reporter Queue, stopping GPS when done 
  • wake up on timeout
  • stop GPS if it is still on

  • check the queue
  • send all fixes from the queue to server via UDP
  • sleep for a while
  • repeat
  • call listener passing new fix
  • repeat(?)

We have no control over this thread

Control Task

  • check if there's new policy
  • if yes, cancel Recorder Timer, start a new one, with new Recorder Task

Controls reporting service

Controls individual reports

Autonomously sends reports

16 of 18

Reorder by Hierarchy

  

Recorder Task

(Model)

Reporter Thread 

(View)

Device Thread

  • Start GPS, receiving N fixes, sending them to Reporter Queue, stopping GPS when done 
  • wake up on timeout
  • stop GPS if it is still on

  • check the queue
  • send all fixes from the queue to server via UDP
  • sleep for a while
  • repeat
  • call listener passing new fix
  • repeat(?)

We have no control over this thread

Control Task (Controller)

  • check if there's new policy
  • if yes, cancel Recorder Timer, start a new one, with new Recorder Task

Controls reporting service

Deals with device, builds reports

Just sends reports

Look,

no synchronization!

17 of 18

References

Steve McConnell, "Cargo Cult Engineering"http://www.stevemcconnell.com/ieeesoftware/eic10.htm

C.A.R.Hoare, "Communicating Sequential Processes"http://www.usingcsp.com/

Dijkstra, Dahl, Hoare, "Structured Programming",

http://www.amazon.com/s?search-alias=stripbooks&field-isbn=0122005503

18 of 18

Thank you!

Any questions, really?