std::future
Вошедший господин в синей спецодежде бесцеремонно вперился в меня взглядом:
- Так-так, на диване валяемся, мороженое поглощаем в темноте?
- У меня Эбола! - вяло огрызнулся я.
- А вот и нет.
"Не врач, - мгновенно пришла мне мысль, - точно шарлатан, дистанционно обучался!"
- Тогда хантавирус!
- Нет.
- Ну уж ветрянку точно заработал!
Тут я рванул футболку на груди, намереваясь эффектно продемонстрировать ужасающие язвы на комиссарском теле. Тишотка, правда, рваться ради меня не пожелала, пришлось ее стыдливо приподнять.
- О! - оживился наш коновал, - да это вас комарики покусали. Много их в этом году...
Да уж явно больше, чем предков у класса std::future. По версии gcc он наследуется от шаблонного базового класса __basic_future.
𝚝𝚎𝚖𝚙𝚕𝚊𝚝𝚎<𝚝𝚢𝚙𝚎𝚗𝚊𝚖𝚎 _𝚁𝚎𝚜> 𝚌𝚕𝚊𝚜𝚜 𝚏𝚞𝚝𝚞𝚛𝚎 : 𝚙𝚞𝚋𝚕𝚒𝚌 __𝚋𝚊𝚜𝚒𝚌_𝚏𝚞𝚝𝚞𝚛𝚎<_𝚁𝚎𝚜> {...}
В самом наследнике никакой полезной нагрузки нет, только методы, типа get().
Нырнув глубже, видим, что шаблонный класс __basic_future не так прост, он наследуется от еще одного базового класса __future_base.
𝚝𝚎𝚖𝚙𝚕𝚊𝚝𝚎<𝚝𝚢𝚙𝚎𝚗𝚊𝚖𝚎 _𝚁𝚎𝚜>
𝚌𝚕𝚊𝚜𝚜 __𝚋𝚊𝚜𝚒𝚌_𝚏𝚞𝚝𝚞𝚛𝚎 : 𝚙𝚞𝚋𝚕𝚒𝚌 __𝚏𝚞𝚝𝚞𝚛𝚎_𝚋𝚊𝚜𝚎 {
𝚙𝚛𝚒𝚟𝚊𝚝𝚎:
__𝚜𝚝𝚊𝚝𝚎_𝚝𝚢𝚙𝚎 _𝙼_𝚜𝚝𝚊𝚝𝚎;
...
Уже что-то, целый член класса _M_state типа __state_type.
Проверим еще и базированный класс, чтоб ничего не упустить.
𝚜𝚝𝚛𝚞𝚌𝚝 __𝚏𝚞𝚝𝚞𝚛𝚎_𝚋𝚊𝚜𝚎 {
𝚜𝚝𝚛𝚞𝚌𝚝 _𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎 {...};
...
Как и ожидалось, в __future_base содержатся просто базовые структуры для определения результата. Базовый результирующий класс - _Result_base, результирующий класс для обычных объектов _Result, и объектов со своими аллокаторами _Result_alloc.
Никаких состояний базовые классы не хранят, поэтому вернемся к __state_type. По определению, это обернутый в умный указатель _State_base:
𝚝𝚢𝚙𝚎𝚍𝚎𝚏 𝚜𝚑𝚊𝚛𝚎𝚍_𝚙𝚝𝚛<_𝚂𝚝𝚊𝚝𝚎_𝚋𝚊𝚜𝚎> __𝚜𝚝𝚊𝚝𝚎_𝚝𝚢𝚙𝚎;
Что есть _State_base зависит от макроса _GLIBCXX_ASYNC_ABI_COMPAT.
#𝚒𝚏𝚍𝚎𝚏 _𝙶𝙻𝙸𝙱𝙲𝚇𝚇_𝙰𝚂𝚈𝙽𝙲_𝙰𝙱𝙸_𝙲𝙾𝙼𝙿𝙰𝚃
𝚌𝚕𝚊𝚜𝚜 _𝚂𝚝𝚊𝚝𝚎_𝚋𝚊𝚜𝚎;
#𝚎𝚕𝚜𝚎
𝚞𝚜𝚒𝚗𝚐 _𝚂𝚝𝚊𝚝𝚎_𝚋𝚊𝚜𝚎 = _𝚂𝚝𝚊𝚝𝚎_𝚋𝚊𝚜𝚎𝚅𝟸;
#𝚎𝚗𝚍𝚒𝚏
Очевидно, что это макрос для обратной совместимости. Давным-давно до gcc 4.9 внутренние базовые классы для управления состоянием асинхронных вызовов назывались _State_base и _Async_state_common. Начиная с GCC 4.9, разработчики библиотеки оптимизировали и обновили эти реализации, заменив их на новые классы _State_baseV2 и _Async_state_commonV2.
Чтоб легаси не ломалось, как печенька, подкинули этот макрос.
Ну а в классе _State_baseV2 собралось все самое интересное.
𝚌𝚕𝚊𝚜𝚜 _𝚂𝚝𝚊𝚝𝚎_𝚋𝚊𝚜𝚎𝚅𝟸 {
𝚝𝚢𝚙𝚎𝚍𝚎𝚏 _𝙿𝚝𝚛<_𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎> _𝙿𝚝𝚛_𝚝𝚢𝚙𝚎;
𝚎𝚗𝚞𝚖 _𝚂𝚝𝚊𝚝𝚞𝚜 : 𝚞𝚗𝚜𝚒𝚐𝚗𝚎𝚍 {
__𝚗𝚘𝚝_𝚛𝚎𝚊𝚍𝚢,
__𝚛𝚎𝚊𝚍𝚢
};
_𝙿𝚝𝚛_𝚝𝚢𝚙𝚎 _𝙼_𝚛𝚎𝚜𝚞𝚕𝚝;
__𝚊𝚝𝚘𝚖𝚒𝚌_𝚏𝚞𝚝𝚎𝚡_𝚞𝚗𝚜𝚒𝚐𝚗𝚎𝚍<> _𝙼_𝚜𝚝𝚊𝚝𝚞𝚜;
𝚊𝚝𝚘𝚖𝚒𝚌_𝚏𝚕𝚊𝚐 _𝙼_𝚛𝚎𝚝𝚛𝚒𝚎𝚟𝚎𝚍 = 𝙰𝚃𝙾𝙼𝙸𝙲_𝙵𝙻𝙰𝙶_𝙸𝙽𝙸𝚃;
𝚘𝚗𝚌𝚎_𝚏𝚕𝚊𝚐 _𝙼_𝚘𝚗𝚌𝚎;
...
Вот мы и добрались до переменных, описывающих состояние future. Как удачно получилось, что atomic_flag и once_flag уже нами реализованы!
С типом _Ptr_type, то есть, с _Ptr<_Result_base> тоже проблем быть не должно, ведь это просто
𝚝𝚎𝚖𝚙𝚕𝚊𝚝𝚎<𝚝𝚢𝚙𝚎𝚗𝚊𝚖𝚎 _𝚁𝚎𝚜>
𝚞𝚜𝚒𝚗𝚐 _𝙿𝚝𝚛 = 𝚞𝚗𝚒𝚚𝚞𝚎_𝚙𝚝𝚛<_𝚁𝚎𝚜, _𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎::_𝙳𝚎𝚕𝚎𝚝𝚎𝚛>;
Умный указатель с пользовательским удалителем! Логично, если _Res это наследник _Result_base, то Deleter должен вызвать метод _M_destroy().
𝚜𝚝𝚛𝚞𝚌𝚝 _𝙳𝚎𝚕𝚎𝚝𝚎𝚛 {
𝚟𝚘𝚒𝚍 𝚘𝚙𝚎𝚛𝚊𝚝𝚘𝚛()(_𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎* __𝚏𝚛) 𝚌𝚘𝚗𝚜𝚝 { __𝚏𝚛->_𝙼_𝚍𝚎𝚜𝚝𝚛𝚘𝚢(); }
};
Это значит, что этот тип проблем не доставит. Остался только один шаг верификации нашей модели future, чтоб понять, будет ли это работать в нашей rtos.
Просмотры: 33