Есть у меня код который обеспечивает асинхронное выполнение тасков.
Стандартный случай, потоко безопасная очередь, одни в нее кладут, другие берут от туда и выполняют функтор.
Есть пару ухищрений, типа дедлайнов и cancel_hook в случае если таска просрочилась. Ну т.е. кладя задачу в очередь у нее либо вызовется метод execute() либо cancel().
Нужно мне добавить возможность сбора следующей статистики. 1. Сколько задача устанавливалась в очередь (при установки в очередь как минимум нужно схватить мютекс, как максимум есть capacity и ожидания в случае если они досиг лимита) 2. Сколько по времение задача провела в очедеи то тех поо пока ее от туда не вытащили. 3. сколько выполнялась 4. все это усредненное
Как сделано сейчас: статистика хранится в самом объекте который ставится в очередь и далее везде где нужно ее замерять, она устанавливается в сам объект. И в конце из объекта она куда то там сохраняется (т.е. объект нужно еще параметризировать тем куда ее сохранять).
схематично это выглядит так: push:
- Засеч время при входе в метод
- захватить мютекс
- поставить задачу в очередь
- засеч время выхода из метода
- отпустить мютекс
pop:
- Захватить мютекс
- получить задачу из очереди
- засем время начала выполнения
- выполнение задачи
- зачем время завершения
- сохранить статистику в X
Мне не нравиться, что эту статистику приходится хранить в объектe. Поидее пользователю на нее вообще насрать. Хужее, что ее надо не просто получать, ее нужно хранить и аккамулировать, т.е. мы должны напрягать пользователя тем, что бы он подумал об этом. Мне кажется логичным что эта статистика должна накапливаться в самой очереди без участия пользователя. Но так как нужно знать когда объект был пушнут и когда был попнут, эту статистику как то нужно связать с самим объектом.
Хранить что то типо отдельного маппинга это вообще не решение. Притом сбор этоq статистики происходит на разных уровнях. Если немного подумать, то видно что информацию о пуше мы может собирать только под мютексом. А статистику о выполнении задачи нужно уже собирать на уровне выше. А еще cancel() выполняется опять на другом уровне. Единственно что объединяет все эти уровни это только объект (пользовательский тип).
А теперь добавляем что все это шаблонное, и все уровни пронизаци одним шаблонным типом (который указаль пользователь). А напрягать пользователя тем, что бы его шаблонный тип отвечал нашему специальному интерфейсу для сбора статистики нехочется. Даже если все это мы сделаем за него а ему нужно просто унаследоватся.
Может кто делал такое? Посоветуйте?