Working with updates in MTProto
Apart from the basic operations required to work with MTProto update sequences, implementations also have to take care to postpone updates received via the socket while filling gaps in the event and Update sequences, as well as avoid filling gaps in the same sequence.
An interesting and easy way this can be implemented, instead of using various locks, is by running background threads, like in MadelineProto.
- A background feeder thread for each sequence, associated to a FIFO queue is initialized and then paused (event sequence FeedLoop, common sequence SeqLoop).
- Another set of updater threads is started: one for the common sequence, one for each channel sequence (UpdateLoop).
When a getDifference is requested, a signal resumes the updater thread, which starts fetching difference until the gap is filled, then it pauses itself again.
When a new Updates constructor or event is received, it is added to the FIFO queue of the correspondent feeder thread, and a signal is sent to said thread. The signal wakes up the thread, which starts parsing the queued events: as per update handling, duplicates are eliminated, correct events are accepted and the state is updated. When a gap is encountered, the updater thread is resumed: the feeder thread waits until the updater thread is paused again. Finally, the manually fetched difference is prepended to the feeder FIFO queue, to parse it before any additional update that was fetched from the socket while fetching the difference.
The simplicity of this approach is in its sequentiality:
- Each thread can only execute one action at a time.
- Each event is fetched one by one from the FIFO queue
- Threads cannot start handling a new event received from the socket while fetching the difference, or while still handling the previous one
- Only one part of the application at a time can trigger a getDifference, to avoid re-fetching and re-saving the same difference twice.