-
Черга включає в себе
sync.Mutex
для забезпечення контролю доступу до спільного слайсу команд з різних рутин, він нам буде гарантувати, що міжLock()
таUnlock()
тільки одна рутина матиме доступ до ресурсу. -
Метод
pull()
реалізовано таким чином, що він спочатку викликаєLock()
, потім перевіряє чи пустий слайс з командами, якщо це так, то встановлюєnoCommand
вtrue
, та викликаєUnlock()
, щоб далі чекати значення з каналуpushed
у який, у разі додавання нової команди приходить сигнал. Як тільки ми дочекались знову викликається Lock() та береться елемент з слайсу. Така імплементація блокує цикл виконанняEventLoop
поки черга пуста, але вже хтось запустив цикл. В кінці завдяки defer, виконаєтьсяUnlock()
-
Метод
push()
також викликаєLock()
, потім додає елемент в слайс і перевіряє, чи чекає хтось на новий елемент в слайсі, якщо це так, то відравляє у каналpushed
сигнал. В кінці завдяки defer, виконаєтьсяUnlock()
-
Метод
length()
просто повертає довжину слайса команд, але робить це безпечно завдяки використанняMutex
. Він знадобиться при перевірці умови виходу з циклу подій.
- Це допоміжна внутрішня команда, що реазіує інтерфейс
Command
, яка знадобиться нам, щоб безпечно вставновлювати значення змінної про фініш циклу, адже ми читаємо прапор фінішу з іншої рутини, тоді як виставляти можемо з нашої основної. В даній стурктурі ми передаємо при ініціалізації функцію, котра викличеться в методіExecute()
-
EventLoop займається асинхронним виконанням команд, які можна додати через метод
Post()
, який просто викличеpush()
на черзі команд -
При виклику
Start()
ми ініціалзізуємо чергу, та канал в який ми будемо посилати сигнал у разі коли цикл подій опрацював всі події та хтось чекає на завершення. Далі в іншій рутині запусається цикл котрий працює доти, доки черга не пуста та ніхто не чекає на завершення, в тілі циклу ми отримуємо команду за допомогоюpull()
(як говорилось вище він заблокує потік виконання, якщо команди немає), і дочекавшись з нього команду викликаємо на ній методExecute()
, якщо ми вийшли з циклу нам потрібно ще надіслати значення в канал, що ми закінчили і той хто нас чекає міг теж завершитись -
І нарешті метод
AwaitFinish()
нам потрібен для того, щоб сказати циклу подій, що хтось чекає на те, щоб цикл завершивсь, але прапорець про завершення просто так не можна поставити вtrue
, тому ми й користуємось спеціальною командою, яка описана вище. Опублікувавши команду, що встановить прапорець в значення, що хтось чекає фінішу, ми очікуємо значення з каналу, який сповістить нам що ми завершились та виходимо.
-
Метод
parse()
розбиває вхідний рядок на команду та її параметри, і викликає з нимиcompose()
. -
Метод
compose()
знаходить зі списку структуру команди, відповідно до аргументу-імені. Потім копіює та встановлює поля структури за допомогоюsetArgs()
. -
Метод
setField()
встановлює окреме поле структури команди.