Threading model
Meikipop uses a multi-threaded design where each major component runs in its own daemon thread. All threads share aSharedState object that coordinates communication through thread-safe queues and events.
SharedState class
TheSharedState class is the central coordination point for all threads:
running: Global flag to signal all threads to terminate gracefullyscreenshot_trigger_event: Signals when a new screenshot should be captured- Queues: Custom
LatestValueQueueinstances that only keep the most recent value screen_lock: Prevents the popup from being included in screenshots
LatestValueQueue
A specialized queue that only stores the most recent value:Core components
Meikipop consists of six main threaded components that communicate through the shared state:TrayIcon (non-threaded)
The system tray icon provides user interaction: Features:- Settings dialog access
- OCR provider selection
- Scan mode toggle (manual/auto)
- Scan area selection (region/screens)
- Pause/resume functionality
- Quit application
src/gui/tray.py:28):
Application lifecycle
The main application flow (fromsrc/main.py:44):
Data flow diagram
Here’s how data flows through the system:All threads are daemon threads, meaning they will automatically terminate when the main thread exits.
Thread safety
Meikipop uses several strategies to ensure thread safety:- LatestValueQueue: Thread-safe queue implementation with internal locking
- screen_lock: RLock prevents popup from being captured in screenshots
- _data_lock: Protects popup’s latest data from concurrent access
- Daemon threads: All worker threads are marked as daemon to ensure clean shutdown
- Atomic operations: Config changes are atomic and use file-based persistence