<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-654279083390275842</id><updated>2026-08-10T14:13:57.096+03:00</updated><category term="О программировании"/><category term="О жизни"/><category term="язык C++"/><category term="Поток сознания"/><category term="Foto"/><category term="Ссылки"/><category term="SObjectizer"/><category term="О работе"/><category term="Внушаить"/><category term="Мысля давеча посетила"/><category term="Кино"/><category term="Humour"/><category term="Спорт"/><category term="Дартс"/><category term="Павбывавбы"/><category term="Мои фото"/><category term="Подсмотренное"/><category term="Из непонятого"/><category term="Actor Model"/><category term="Маразм крепчал"/><category term="Multithreading"/><category term="Афигеть"/><category term="Об управлении"/><category term="Отдых"/><category term="Message-Passing"/><category term="Concurrency"/><category term="Bugs"/><category term="Вопрос залу"/><category term="Хвастаюсь"/><category term="Business"/><category term="Book review"/><category term="О компьютерах"/><category term="Знакомство с фотомастером"/><category term="Природа"/><category term="язык Ruby"/><category term="RESTinio"/><category term="Отлично сказано"/><category term="Mxx_ru"/><category term="Путешествия"/><category term="История"/><category term="Штуковина"/><category term="язык Java"/><category term="Воспоминания"/><category term="Parallel Programming"/><category term="Сиде-2012"/><category term="язык Scala"/><category term="язык Rust"/><category term="Блог"/><category term="язык D"/><category term="ACE"/><category term="Искусство"/><category term="язык Go"/><category term="Music"/><category term="Велосипедостроение"/><category term="язык C"/><category term="OpenSource"/><category term="Быть начальником?"/><category term="Отличная мысль"/><category term="CMake"/><category term="Каппадокия-2012"/><category term="Кризис в РБ"/><category term="Фантастика"/><category term="Могилев-2013-04"/><category term="Музыка"/><category term="Склерозник"/><category term="язык Erlang"/><category term="POCO"/><category term="Внезапно"/><category term="язык Haskell"/><category term="timertt"/><category term="Живопись"/><category term="Функциональное программирование"/><category term="Boost"/><category term="MQTT"/><category term="Книга &quot;Оружие победы&quot;"/><category term="Сиде-2011"/><category term="DDS"/><category term="Internet of Things"/><category term="ObjESSty"/><category term="Profileschool"/><category term="Книга &quot;Живая компания&quot;"/><category term="Книга &quot;Структура в кулаке&quot;"/><category term="Machine-2-Machine"/><category term="Must Read"/><category term="json_dto"/><category term="Книга &quot;В поисках совершенства&quot;"/><category term="Язык Eiffel"/><category term="Shrimp Demo-Project"/><category term="Война"/><category term="Akka"/><category term="Amazon&#39;s Dynamo"/><category term="ODBC"/><category term="VIM"/><category term="Библиотека OTL"/><category term="День Нептуна-2013"/><category term="Жестокость"/><category term="Лучше не скажешь"/><category term="Спиртное"/><category term="Характерный портрет"/><category term="AMQP"/><category term="Overloading Control"/><category term="Serialization"/><category term="XML"/><category term="ZeroMQ"/><category term="Книга &quot;Великие а не большие&quot;"/><category term="Книга &quot;Построенные навечно&quot;"/><category term="Погружение в Agile"/><category term="Успешные Менеджеры Программистов"/><category term="язык JavaScript"/><category term="язык OCaml"/><category term="Asio"/><category term="Carl Zeiss"/><category term="War"/><category term="gSOAP"/><category term="Эдвардс Деминг"/><category term="язык Ceylon"/><category term="&#xa;язык D#О программировании"/><category term="О жизни"/><category term="О работе#О программированииПоток сознания"/><category term="#О программированииязык Scala"/><category term="Benchmark"/><category term="Catch2"/><category term="GSM"/><category term="Kilim"/><category term="Kubuntu"/><category term="LaTeX"/><category term="MSSQL"/><category term="MinGW"/><category term="NoSQL"/><category term="OODB"/><category term="Qt"/><category term="SOAP"/><category term="SourceForge"/><category term="Unix"/><category term="doctest"/><category term="Боевик"/><category term="Генри Минцберг"/><category term="Дарс"/><category term="Книга &quot;Выход из кризиса&quot;"/><category term="Наука"/><category term="Рыбалка"/><category term="Старческое брюзжание"/><category term="язык Ada"/><category term="язык Gosu"/><category term="язык PHP"/><category term="язык Python"/><title type='text'>Размышлизмы eao197</title><subtitle type='html'>Размышления и впечатления, которые не хочется держать в себе. О программировании в частности. Ну и о творчестве, и о жизни вообще.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>3823</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-2905440149949091685</id><published>2030-01-01T00:00:00.002+03:00</published><updated>2025-05-20T06:31:53.669+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Блог"/><title type='text'>О блоге</title><content type='html'>&lt;p&gt;Более тридцати лет я занимался разработкой ПО, в основном как программист и тим-лид, а в 2012-2014гг как руководитель департамента разработки и внедрения ПО в компании Интервэйл (подробнее на &lt;a href=&quot;http://www.linkedin.com/in/eao197/&quot;&gt;LinkedIn&lt;/a&gt;). В настоящее время занимаюсь развитием компании по разработке ПО &lt;a href=&quot;http://stiffstream.com&quot;&gt;&lt;b&gt;stiff&lt;/b&gt;stream&lt;/a&gt;, в которой являюсь одним из соучредителей. Поэтому в моем блоге много заметок &lt;a href=&quot;http://eao197.blogspot.com/search/label/%D0%9E%20%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B5&quot;&gt;о работе&lt;/a&gt;, в частности &lt;a href=&quot;http://eao197.blogspot.com/search/label/%D0%9E%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B8&quot;&gt;о программировании&lt;/a&gt; и &lt;a href=&quot;http://eao197.blogspot.com/search/label/%D0%9E%20%D0%BA%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%B0%D1%85&quot;&gt;компьютерах&lt;/a&gt;, а так же &lt;a href=&quot;http://eao197.blogspot.com/search/label/%D0%9E%D0%B1%20%D1%83%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B8&quot;&gt;об управлении&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Так же я пишу &lt;a href=&quot;http://eao197.blogspot.com/search/label/%D0%9E%20%D0%B6%D0%B8%D0%B7%D0%BD%D0%B8&quot;&gt;о жизни&lt;/a&gt; вообще и о нескольких своих увлечениях: &lt;a href=&quot;http://eao197.blogspot.com/search/label/Foto&quot;&gt;о фотографии&lt;/a&gt; (включая публикацию &lt;a href=&quot;http://eao197.blogspot.com/search/label/%D0%9C%D0%BE%D0%B8%20%D1%84%D0%BE%D1%82%D0%BE&quot;&gt;своих фотографий&lt;/a&gt;, некоторые есть и на &lt;a href=&quot;http://www.zeissimages.com/standardgallery.php?puid=2701&amp;showall&quot;&gt;ZeissImages&lt;/a&gt;), &lt;a href=&quot;http://eao197.blogspot.com/search/label/%D0%A1%D0%BF%D0%BE%D1%80%D1%82&quot;&gt;о спорте&lt;/a&gt;, особенно &lt;a href=&quot;http://eao197.blogspot.com/search/label/%D0%94%D0%B0%D1%80%D1%82%D1%81&quot;&gt;о дартсе&lt;/a&gt;, и, совсем коротко, &lt;a href=&quot;http://eao197.blogspot.com/search/label/%D0%9A%D0%B8%D0%BD%D0%BE&quot;&gt;о кино&lt;/a&gt;.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/2905440149949091685'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/2905440149949091685'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2014/05/blog-post.html' title='О блоге'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-2770562979760356223</id><published>2029-12-31T10:53:00.000+03:00</published><updated>2018-04-27T17:06:39.634+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Foto"/><category scheme="http://www.blogger.com/atom/ns#" term="Мои фото"/><category scheme="http://www.blogger.com/atom/ns#" term="О жизни"/><title type='text'>[life.photo] Характерный портрет: вы и ваш мир моими глазами. Безвозмездно :)</title><content type='html'>&lt;p&gt;Вы художник? Бармен или музыкант? Или, может быть, коллекционер? Плотник или столяр? Кузнец или слесарь? Владеете маленьким магазинчиком или управляете большим производством? Реставрируете старинные часы или просто починяете примус? Всю жизнь занимаетесь своим любимым делом и хотели бы иметь фото на память?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOXzdoXx5jrFBn7G9z7Pz6GcTBgwYJysWvLXJw_fB415r9yK0jLTN0vRbSELrwto6HwKUM2GvlRv219Kl61hvnBRZYL8IN5Jp7siO0y0uxc__Kovaqgc7hjsk-jjJPmSdIQHSEgenkTOk/s800-Ic42/portrait_collage_20151001.jpg&quot;/&gt;&lt;/p&gt;

&lt;p&gt;Предлагаю сделать портрет в обстановке, связанной с вашей работой или увлечением. Абсолютно бесплатно. Очень уж мне нравится фотографировать людей в их естественной среде. Происходить это может так...&lt;/p&gt;

&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;

&lt;p&gt;...Вы делаете то, что умеете и любите, попутно рассказывая о себе и своей профессии/хобби. Я же становлюсь вашей тенью и/или собеседником, снимаю кадр за кадром в погоне за наиболее удачным снимком. Если что-то получается, то вам достаются фотографии в электронном виде, а мне -- возможность их некоммерческого использования в блоге и соцсетях.&lt;/p&gt;

&lt;p&gt;Если вы заинтересовались, то связаться со мной можно по мейлу eao197 на gmail точка com или в Skype по имени eao197. Либо же оставив комментарий к этой записи. Или в соцсетях: &lt;a href=&quot;http://vk.com/eao197&quot;&gt;VK&lt;/a&gt;, &lt;a href=&quot;https://www.facebook.com/eao197&quot;&gt;Facebook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Для съемки мне нужно знать в каких условиях будет проходить фотосессия: помещение или открытое пространство, темно там или светло, можно ли использовать вспышку или это будет невозможно в принципе и т.д. Если мое присутствие на вашем рабочем месте или рядом с ним требует какого-то предварительного согласования -- то вам самим нужно будет позаботиться об этом. Ну и было бы желательно, чтобы ваши коллеги и клиенты были в курсе и не протестовали бы против попадания в кадр.&lt;/p&gt;

&lt;p&gt;Во избежание чрезмерных ожиданий хочу сразу предупредить: я всего лишь любитель, не проффи. Поэтому результат не гарантирован. По опыту, для того, чтобы получился хороший портрет, приоткрывающий характер человека, нужен не один дубль, и даже не десять, а то и не сто. Ориентироваться нужно на 3-4 часа общения и фотосьемки, что выльется в несколько сотен кадров из которых будет отобрано всего несколько штук. Так что вам потребуется немного терпения, а мне -- капелька удачи.&lt;/p&gt;

&lt;p&gt;Вот пример того, что может получаться в результате таких съемок:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;кукольных дел мастер &lt;a href=&quot;https://goo.gl/photos/khfXG6kGQ52yELyu7&quot;&gt;Екатерина Katiedda Минакова&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;саксофонист &lt;a href=&quot;https://goo.gl/photos/t2t7v58jgVRpN4Xr8&quot;&gt;Анатолий Аксёнов&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;резчик по дереву &lt;a href=&quot;https://plus.google.com/photos/117023091752061088817/albums/6178693720360830017&quot;&gt;Виктор Россолов&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;уникальный гармонист &lt;a href=&quot;https://goo.gl/photos/k4PGyrA7MzYqf8Zu7&quot;&gt;Вячеслав Сивуха&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;кузнец &lt;a href=&quot;https://goo.gl/photos/Zq9YH84PQjXCYpgG7&quot;&gt;Дмитрий Андреев&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;реконструктор &lt;a href=&quot;https://goo.gl/photos/YF8vhEwEKfrPURo47&quot;&gt;Виталий Медведев&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Вот еще несколько примеров того, что получалось в прошлом:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhifcC-yjcJRTTk3s_e4rgb6kBJUGAT7gMbHZHzWz3Vb9h1sN_X8LamFz7DZ-2IlGrG-SUDbMWZMx7BNNV7nKErZ4n6IIckeT7r-j9jWRot-gVQgDApyNmgt_JB6n79fC-zE9bqNHJmtMpR/w1236-h824-no/20150412-144413-KLN_3957.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Танго на набережной --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggFi_ELwi-Tt6l_1o1E32y-_mgOgjLLzH0_dAxJfkXSl3s91P-pSSu9NqgSlnHzjvkidAAMUhB4XflmgKRBLWPcfIzWj1Pk2WL2Mx_smJ7_1ShOTFsTTxcb3R5NgVu1CPyAwSjrysbH9RR/w548-h823-no/20130719-200026-20130719-200026.jpg&quot; height=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- День нептуна --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXSeO_FWkX9vrWPNQTZqM7LhCsPkyJS6ARhRQGXG3-AcFBZrBhaqBYgzNOxZmsBqP7JzUSO7wpZOgTidaFMqk3MDbm9Z_o2vD0r9iQ1ASR4BGEntsWMJxhsV1QPchhU_ap-jTaTDPANp5h/w1398-h824-no/20130713-123844-20130713-123844.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- --&gt;

&lt;p&gt;&lt;img src=&quot;http://www.zeissimages.com/gallery/2701/U2701I1409694203.SEQ.0.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.zeissimages.com/gallery/2701/U2701I1402041657.SEQ.0.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.zeissimages.com/gallery/2701/U2701I1401782657.SEQ.0.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Сергей Вяхирев --&gt;

&lt;p&gt;&lt;img src=&quot;http://www.zeissimages.com/gallery/2701/U2701I1396898490.SEQ.0.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Скрипачка за столом --&gt;

&lt;p&gt;&lt;img src=&quot;http://www.zeissimages.com/gallery/2701/U2701I1394868675.SEQ.0.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Гитарист --&gt;

&lt;p&gt;&lt;img src=&quot;http://www.zeissimages.com/gallery/2701/U2701I1394868546.SEQ.0.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Коллекционер --&gt;

&lt;p&gt;&lt;img src=&quot;http://www.zeissimages.com/gallery/2701/U2701I1378559938.SEQ.0.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Музыканты в Минске под дождем --&gt;

&lt;p&gt;&lt;img src=&quot;http://www.zeissimages.com/gallery/2701/U2701I1377513249.SEQ.0.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Портрет фотографа --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQ1QNGFkWrtHiOAgTtz5zFZJ3MJvTubJPSQX95FoRm-JD_X9CuegOkzXf4Z_1fkn8uBGEj5YSJGFG1Qo0j4I3qLqtWPVBrO2NFXh2006s56zasJjQjRL0Wr6d-lBO76WMY1RCRC70GKUg/w800-h532-no/20140302-141423.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Реконструкторы в Гомеле на Прудах в 2013-м --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiT3NP_5J4-Mbu2ylqqUWg4WeWfU1Og-xhez2EF5RUUxGgPSQ9HyzJfuUvqvZkKNGz7F_r5pnmodFAcn6fcvizXMGe9sYJPAIf9en0mbIRLjN44aMTMWn1E6ifCVJxglSs3PqdtBo4ziIQ/w640-h800-no/20130703-174153.jpg&quot; height=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKur-Y7UIZqw3js9RB53-Ne-umQZuWL1wHSptbthka9hp0W6P77onZsuPdl0ioUfA18gzlB2mdVZ8j3bLiL7swCN0LEwn3Fre4MOVaUwhsbD6WdIpH0gP7K5UMBjSHcKusklCDVWc2UN8/w800-h532-no/20130703-171342.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- С первенства РБ по ката (кёкусинкай каратэ, 2015) --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiE3a2H9DeTWkbKaDtbuNIhV9O3nS7QS1ACe5yKTjJKdMKwv7ZDual0cfWcgsSJQz1n-EQsIBWEYZ1Id8paEQDHMTTXnmmux1hCHAWPdpVnWdOZHH53XSVqqDuuIuEbEiBTpwRMEWYnv9A/w1238-h824-no/20150503-105021-KLN_4268.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgCHxrHcWhn769_p48SN0iZ4L12SV0P-9_o_QaB_bsv9vSi3U5-bCm-1__lDgwsXEFZLlKRMLPYKquIjzUjDu70q6xyrjSunJiaAzS4SVd9_ZdIkEXluHVNKd-l6BxRFmPKIPEKEL5OS8/w948-h824-no/20150503-113301-KLN_4471.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- С выступления рестлеров на 9-е мая 2015 --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC20Dfr3WLZ9E5dR2cJEngLdTyQYJGMj_nJVUmJe4ZOB4544mlbtQNKlDJWP4cTbkbLxNrXVmwGOAPBRX5khJUVlPKRkqtrU_MF3QNL5IqdsEVussMcB0HAip1ZdnHcFGszOjxbOQENS8/w1238-h824-no/20150509-163040-KLN_5585.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Резчик по дереву Андрей Пастухов (9-е мая 2015) --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh91_sBu92Hln0lhoUEUmHPNeyCnTZIw5sIjsk_SYSkCbZ5NGob26lskCVVnRDcKuz64axtukTGPk2DQ5dYjx6kmCW1lRUfbRk1dvoJgyrLMqGAb85UjeTIdxTe11GXWaJ0GFIbcryPoXI/w548-h823-no/20150509-115629-KLN_5343.jpg&quot; height=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Пожилой коллекционер на 9-е мая 2015 --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCq5JemgTpg-GL1l9ST4UDAqDsSNt_yLCNb53DoqIJ23F8dIZ6cNjbE4I4rxsMlYGbCxsVW4HmgM6hCMRzZlzzVqOwltr6GDawimlvDDBa4l04ApI_7NXQim2YpTw3ym-57qdE5d0WqLI/w548-h823-no/20150509-123258-KLN_5434.jpg&quot; height=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Саксофонист Анатолий Аксёнов 31-го мая 2015 --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKUpmfVGkbT9B37uSVCDNZA3bzvzM8pnjB2JBSoUZNzDzuFuxAEY7OxLmnNy9PyunOWZy1NPfzz4d9SkSaqqiEkayrHHcm0PToKHmiyhc8gvx85MsSb8D9Unf2eMnjRsfT7pGM-dDkBbE/w1374-h914-no/&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Гончар со свистулькой в гомельском парке 31-го мая 2015 --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKc7wPx23qIvV0VhcDK8xMvnddQMP0WbrVIqLzPQoWzAyKaCvMVs1Hml6kz4nzCTFcWp_76ApLrEnInbTfL4KLatoE-R_so-Vn4V1AnSWiuAzeQU7JphHCWL0CPwKX8unvCKHAEqGzzlM/w1143-h914-no/&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Клоун на акции &quot;День красного носа&quot; 31-го мая 2015 --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyuVhUBIY1qjyRFW-IMEUj-qkMzCMF1DQ0xyYhv9cUGhI6XVrat88zYeHx9QD1dEBeANusq9fnQeoqZokj_XHbKAVWjb76Q7oCinspcbwvB-KlEqzSPKeb8Nisse2x_-7NiBrnh-Suffk/w1458-h914-no/&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Екатерина Минакова на мастерклассе по изготовлению кукол-тыквоголовок 20 июня 2015 --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-cAXLjAfasIZtlsztbKlUBbBzKyYH6BU5uV8eehc36cykLclz0uBLJrgmi1JtFyqgJZ6IZQnQ24-f40jb6tMLZUZ9BcN4gg-zaCMSFeRn6HBdwo39oEmFl4KgPkKsPd98BVVL4bqO6jo/w800/&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Два музыканта у ГЦК 24-го июня 2015 --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF_1hnFeYw2yKc2DnVJjy1J0hsVG84mKB3RwPO_bfXxS1S8kpvdtkCf1ZLfwBUFJ6XG76UkgCMXQE0R4FRUeq4iugRbVsEhG_Au9NQafUNE-9SKp-UWEdim9gENkYsqe2cXOHEEDtyCHQ/w800/&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5rZhlDaCdtFPK-iEN1g5_hQHWZNmbWpo3YNXYFdt9P9-yT1WmZu34gHWtpXUyyWAZC-jm7jS3Rw7LfHLtbaSSR_4UWhmgIu1xxP321EwnaeT_TWQXu2ksQFviImwb39UPlLDD07MLotI/w800/&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Виктор Россолов, резчик по дереву --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGMq55RIQknA7mKBSGVr4jhUUBV-t18hw9BzaDXzfpNuIcUPImXz_TY_hyphenhypheniPeKY3NCmUVGzJgbHqevMJgykdVb9i6BbE_rrqBNX0_N3zEPaxsl0XbBBZihz7hiteaRyGSnL_LUWsaHLJs/h800/&quot;/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMDaKKX2jHWf3Y6hjab0toitpjjgR7PAmzLiyMSeolf7dq2WlJ4Ig8d0h-pIUS8txw59dura-Ykg_Pe_KD_eovPtWzoxuMNfxtvQfPWXWQZpg54QDhaKVeX2d4y7WNgldwWWmBp8iTxi0/h800/&quot;/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0nAX9EHANBxYjNCGn372IbgjgfxT8puIaOS80TreWgWC6bDqa-sLLdPONk9s2G1C5IG2VKci7xw2GFoDRfCsAfW3G3vprdFMvcHlV7A0_gFfhl2X-FSo0SOYHAk_8Xw4OYWGmA4av7T4/w800/&quot;/&gt;&lt;/p&gt;

&lt;!-- Рыбак на соревнования по ловле рыбы фидером 2-го августа 2015 --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_Fz7t4qq1Sq6f2uRrAsONMzNmaO9xKFMLdd8tEiR8I5RhiFyMoJRB3qVNwJHIK8Q91bHAiaXFInpBvE-LvD1xXlZM5qiYKES9g5SkDtdaYBeZL0hokXKUbUrW946w_K6dbkka2ot2ZTU/w800/&quot;/&gt;&lt;/p&gt;

&lt;!-- Вячеслав Сивуха 29-го августа 2015 --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrT-u70zu5ct3AJGIGHNDkfuD2EeOgRD2a0UQWH_EfonOsLZje58ROKSIRFDCJ_LufKdRwfAZS8xilb3YPEjI2TD7XQo8Q3Z7E2c3USMcDXZFq_vRl6ku4CF42Wk_DqyP5B_74aTi-dAY/w800/&quot;/&gt;&lt;/p&gt;

&lt;!-- С фестиваля &quot;Минск Старажытны&quot; 12-го сентября 2015 --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4GrXCz0bPTJnbZgzsPh3homr0BwdCNq2-DqmJ7GQnSZ90e9fTaCnul5q2b7fgJ961_ls5EHZg-jJzBo4b7yrIgcrB1TScScB8LIl7Cj8OYkYQ4itZBh2NfeBojKDGS3UWX8bB9L38oWQ/s800-Ic42/20150912-151417-DSC_0882.jpg&quot;/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvDCy81e4YysNurf-0h4nFbKb2GjzVjcFVdZFCQ-Whr8wovwkVWxFK_5nu-707hJKfuu04TQptRsZYAiPfyDf6DBAdDKmG5A1yJ2QwbcSDVHBLQOQikr8X6gb6E2x5LH9OrVmER8rBYZ4/s800-Ic42/20150912-152641-DSC_0925.jpg&quot;/&gt;&lt;/p&gt;

&lt;!-- Кузнец Дмитрий Андреев (23-е сентября 2015) --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRvCyJViaygimCzZR16fUzHSBR2cCM3KUuUrf0d7P9q2zRNkvTvrLRjHSf1N5lVwLuHY1mQ-jtfGBQOSksCk2vUAY-eg4qdUlMCUMqzEslHDvV-LoCREHsZV95VbxgH2k_sM6ugTpw01E/s800-Ic42/20150923-123159-DSC_1473.jpg&quot;/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_gfleps0XNHwnhj09nDaVGyFEUBHthLYG0IHJpRKaO4WdQrryU4Gt1A79-mLt62QZOxVNMFJ5pMc23xEU2xAJGNK_V2ILa8Es2o10QcD52on86QzEdnckpKWZ_uIeXcZ47XYj-KYuskU/s800-Ic42/20150923-130645-DSC_1628.jpg&quot;/&gt;&lt;/p&gt;

&lt;!-- Реконструктор Виталий Медведев (9-е мая 2016) --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDr5QOogMAu7h-24LVKoW6URZlnr425_uWTx84T_xZt11dMx90o-rDzk9op9LCQXyeECUxOgWPFNPqohad4gBq4Dzg1vHTWhglXErpbFEzaTKH6JxYguNU_fKZz-ZaRcR5WEzbkIk7bgw/s800/20160509-140603-DSC_6134.jpg&quot;/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgITCbq_SB_JDVejEOSMFd-JM6ZGvWi4xAxNqioyQDLWiUxg51nXeZTqn_FUIfOAmzvEKe073rsqsnqxKLxE9N6Cirfg6Zw6o3HkqJhg1Zes75ka0vV_O0vOUKTWcu8JVT6qn2yFKCuO7o/s800/20160509-141604-DSC_6195-2.jpg&quot;/&gt;&lt;/p&gt;

&lt;!-- Бородач за компьютером на CoreHard Spring 2017 (13-е мая 2017)) --&gt;

&lt;a data-flickr-embed=&quot;true&quot;  href=&quot;https://www.flickr.com/photos/152498119@N03/34349688134/in/photostream/&quot; title=&quot;20170513-112141-DSC_7774&quot;&gt;&lt;img src=&quot;https://c1.staticflickr.com/5/4277/34349688134_2621e0ef2b_c.jpg&quot; width=&quot;800&quot; height=&quot;534&quot; alt=&quot;20170513-112141-DSC_7774&quot;&gt;&lt;/a&gt;&lt;script async src=&quot;//embedr.flickr.com/assets/client-code.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;!-- Дори Экстерман на CoreHard Spring 2017 (13-е мая 2017)) --&gt;

&lt;a data-flickr-embed=&quot;true&quot;  href=&quot;https://www.flickr.com/photos/152498119@N03/34349687964/in/photostream/&quot; title=&quot;20170513-120348-DSC_7816&quot;&gt;&lt;img src=&quot;https://c1.staticflickr.com/5/4274/34349687964_ef67a1b270_c.jpg&quot; width=&quot;800&quot; height=&quot;534&quot; alt=&quot;20170513-120348-DSC_7816&quot;&gt;&lt;/a&gt;&lt;script async src=&quot;//embedr.flickr.com/assets/client-code.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;!-- ДиДжей на Фестивале городской еды (27-е августа 2017) --&gt;

&lt;a data-flickr-embed=&quot;true&quot;  href=&quot;https://www.flickr.com/photos/152498119@N03/36910824456/in/dateposted/&quot; title=&quot;20170827-142946-DSC_9303&quot;&gt;&lt;img src=&quot;https://farm5.staticflickr.com/4377/36910824456_4a02bc95a5_c.jpg&quot; width=&quot;534&quot; height=&quot;800&quot; alt=&quot;20170827-142946-DSC_9303&quot;&gt;&lt;/a&gt;&lt;script async src=&quot;//embedr.flickr.com/assets/client-code.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;!-- Жонглер на Дне Красного носа (27-е августа 2017) --&gt;

&lt;a data-flickr-embed=&quot;true&quot;  href=&quot;https://www.flickr.com/photos/152498119@N03/36957765561/in/photostream/&quot; title=&quot;20170827-134632-DSC_9214&quot;&gt;&lt;img src=&quot;https://farm5.staticflickr.com/4346/36957765561_689280daeb_c.jpg&quot; width=&quot;534&quot; height=&quot;800&quot; alt=&quot;20170827-134632-DSC_9214&quot;&gt;&lt;/a&gt;&lt;script async src=&quot;//embedr.flickr.com/assets/client-code.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;!-- Клоун на мотоцикле на Дне Красного носа (27-е августа 2017) --&gt;

&lt;a data-flickr-embed=&quot;true&quot;  href=&quot;https://www.flickr.com/photos/152498119@N03/37099333605/in/photostream/&quot; title=&quot;20170827-131334-DSC_9010&quot;&gt;&lt;img src=&quot;https://farm5.staticflickr.com/4375/37099333605_dce23edd09_c.jpg&quot; width=&quot;800&quot; height=&quot;534&quot; alt=&quot;20170827-131334-DSC_9010&quot;&gt;&lt;/a&gt;&lt;script async src=&quot;//embedr.flickr.com/assets/client-code.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;!-- Скрипач на Невском в Питере (апрель 2018) --&gt;

&lt;a data-flickr-embed=&quot;true&quot;  href=&quot;https://www.flickr.com/photos/152498119@N03/27868900178/in/dateposted/&quot; title=&quot;20180422-155704-DSCF0015&quot;&gt;&lt;img src=&quot;https://farm1.staticflickr.com/912/27868900178_ceeabf5305_c.jpg&quot; width=&quot;800&quot; height=&quot;533&quot; alt=&quot;20180422-155704-DSCF0015&quot;&gt;&lt;/a&gt;&lt;script async src=&quot;//embedr.flickr.com/assets/client-code.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;!-- Гитарный мастер Евгений в Питере (апрель 2018) --&gt;

&lt;a data-flickr-embed=&quot;true&quot;  href=&quot;https://www.flickr.com/photos/152498119@N03/26800424547/in/photostream/&quot; title=&quot;20180422-143118-DSCF9903&quot;&gt;&lt;img src=&quot;https://farm1.staticflickr.com/825/26800424547_cede9a2743_c.jpg&quot; width=&quot;800&quot; height=&quot;533&quot; alt=&quot;20180422-143118-DSCF9903&quot;&gt;&lt;/a&gt;&lt;script async src=&quot;//embedr.flickr.com/assets/client-code.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;p&gt;А можно отнестись к этой затее и более широко. Не обязательно иметь экзотическую профессию или уникальное хобби. Достаточно быть неординарным человеком и быть готовым провести несколько часов под прицелом фотоаппарта, желательно в подходящем антураже...&lt;/p&gt;

&lt;!-- Девушка из Танго на набережной --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLZ6yiBD4483bYfWnvrGBy3OXRqyEwkO2eSvhpGmF-rXTn5RCNNycMd9GVuW_0mfNpt1S7cUazdeQm7p1xQNnW9TbdZmeo5_RqgZfgdeL45CCwCTnyv-o1f5BCdNyER53aK2-lmEc-cX0I/w1238-h824-no/20130719-195618-20130719-195618.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Лёша Юша в Минске --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipDa7WAOebKiuNEAeJkkBfryC2LZ4BzAjRI7bwKqcO8f4Zma89qMnrlbkbX1YR2RaTsmfCbZAWEN1U4gOQHqd_hLbD7jb44dhcWCMqjuBpgePi8Oz8495R2tXyUMPiQli9233_OYngRJw/w800-h569-no/20131215-114227.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Андрей Тарасенко на Belarus Open --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1_kdV4N5wWkEaOlL-ipso65N57CfWXJg2Huo-qpamYMYJ0wGVUtu-LUHlPqVeToiDpnA1DahqY9l3Cp5zRdm9j5SpklDqdLxcznr-duoR2R45-eTEfZD6lNzXa1iljRiIhtYZVcxHLU4/w800-h532-no/20130824-201046.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiO0MNULOvLkhXM_yE8t-x5KNvUKuXrPPcsh5oLRT5RBPSm3WoHF2YRXKgdwD9PcwlO10YIWzl6pLQCwE5F_fgSLHu_o0lgCNnckYeY5_Y-CR52PB-2LjZ9K3rm5NrQath4lB_E1MbMDEE/w800-h532-no/20140504-203526.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.zeissimages.com/gallery/2701/U2701I1420460994.SEQ.0.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtyd8XUzToyw2hFKQjHuStquKmK6TgiN9pPjT_oajIEZtqDXh2LJWFnMA8oNBKqZr3I258JxibKqhRzIUOpy0WdCKMYv3_UbILLm1F2olymQG906Z-L1b83lxQMQA_ZKdKYrBZmsf6qftb/w800-h640-no/20131215-082410.jpg&quot; width=&quot;800&quot;/&gt;&lt;/p&gt;

&lt;!-- Алексей Голубев 1-го сентября 2015 --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZjUgHdf8cV_1MOpQ2KiMdtNWlEIqfKzo2TPn7f0hQLdIaNblQvfiozDWZ2P_1olUKYVN45RXMckjIzeihvE7kdpviUmDCW4l1FP2DOal-F_jZ9BPJdDfmLrJcZY_Lsr9z6FhehGJgtkg/w800/&quot;/&gt;&lt;/p&gt;

&lt;!-- Девушка играет на свистульке. Минск Старажытны, 12-го сентябры 2015 --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIQPL058wfGCdzrKqSUrsL3Gi-C0L7F8mIJzgiw2CZ8HXt_sCreAywMCPQCcZz_-EdYA8_d2HF3sViWJLyRVRLtBjUyB9sXr0zsXjEFG_WaoxAceFuwxZWB5HU5abLPa5w2I5qk5N9_0Q/s800-Ic42/20150912-144846-DSC_0820-2.jpg&quot;/&gt;&lt;/p&gt;

&lt;!-- Алексей Юша (Минск Старажытны, 12-го сентября 2015) --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsbqLqASBIlzY4F-drzVLaD2_P8U3APefX5_jQST1m5h6kHMsIVvisZLoGMUG_UhhDcLnL0StuusP2aAPAHg5hfcEXdbjVMmN6HU0ruH5truTxawOf4MQABpkHIh_a9smRUx315z_L5gA/s800-Ic42/20150912-125946-DSC_0471.jpg&quot;/&gt;&lt;/p&gt;

&lt;!-- Владислав Волков (Москва, 9-е февраля 2016) --&gt;

&lt;p&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvMXbkjzlRN6V9g5vvKwPtYupIhvyT6iMkJtW8tXW-GBZMQCrMs_YTdOLRoR1ruXLYPA-i6avsoL5p1FOEr3fnf7PBfdsWcAf4OZ-C1aDxmQEPjFGlFiUKCVXYpA7xY3YTZIqrUKxGpHw/s800-Ic42/20160209-124944-DSCF2643.jpg&quot;/&gt;&lt;/p&gt;

&lt;!-- Коля Шмаков на CoreHard Spring 2017 (13-е мая 2017)) --&gt;

&lt;a data-flickr-embed=&quot;true&quot;  href=&quot;https://www.flickr.com/photos/152498119@N03/34349688574/in/dateposted/&quot; title=&quot;20170513-103826-DSC_7656&quot;&gt;&lt;img src=&quot;https://c1.staticflickr.com/5/4290/34349688574_d1b88f8f08_c.jpg&quot; width=&quot;800&quot; height=&quot;534&quot; alt=&quot;20170513-103826-DSC_7656&quot;&gt;&lt;/a&gt;&lt;script async src=&quot;//embedr.flickr.com/assets/client-code.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;!-- Ретро-фотограф на Дне Города (16-е сентября 2017) --&gt;

&lt;a data-flickr-embed=&quot;true&quot;  href=&quot;https://www.flickr.com/photos/152498119@N03/36447681394/in/dateposted/&quot; title=&quot;20170916-142459-DSC_9446&quot;&gt;&lt;img src=&quot;https://farm5.staticflickr.com/4408/36447681394_1c98df6081_c.jpg&quot; width=&quot;800&quot; height=&quot;534&quot; alt=&quot;20170916-142459-DSC_9446&quot;&gt;&lt;/a&gt;&lt;script async src=&quot;//embedr.flickr.com/assets/client-code.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;!-- Музыканты на Дне Города (16-е сентября 2017) --&gt;

&lt;a data-flickr-embed=&quot;true&quot;  href=&quot;https://www.flickr.com/photos/152498119@N03/36887823000/in/photostream/&quot; title=&quot;20170916-154013-DSC_9543&quot;&gt;&lt;img src=&quot;https://farm5.staticflickr.com/4331/36887823000_2d451b3b7a_c.jpg&quot; width=&quot;800&quot; height=&quot;534&quot; alt=&quot;20170916-154013-DSC_9543&quot;&gt;&lt;/a&gt;&lt;script async src=&quot;//embedr.flickr.com/assets/client-code.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/2770562979760356223/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/2770562979760356223' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/2770562979760356223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/2770562979760356223'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2015/04/lifephoto_19.html' title='[life.photo] Характерный портрет: вы и ваш мир моими глазами. Безвозмездно :)'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOXzdoXx5jrFBn7G9z7Pz6GcTBgwYJysWvLXJw_fB415r9yK0jLTN0vRbSELrwto6HwKUM2GvlRv219Kl61hvnBRZYL8IN5Jp7siO0y0uxc__Kovaqgc7hjsk-jjJPmSdIQHSEgenkTOk/s72-c-Ic42/portrait_collage_20151001.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-5395799970589730923</id><published>2026-08-10T08:42:29.532+03:00</published><updated>2026-08-10T14:13:57.096+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Humour"/><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><title type='text'>[prog.sarcasm] Если долго сидеть на берегу, то можно увидеть как Erlang-еры...</title><content type='html'>&lt;p&gt;...&lt;a href=&quot;https://www.linux.org.ru/forum/development/18355784&quot;&gt;переписывают свой софт на Rust&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;Моя идея о том, чтобы переписать наш Flussonic с Erlang на Rust оказалась совершенно прекрасной и у меня совершенно прекрасные результаты. Захват 10 000 камер на сервер - это прямо скажем серьезный результат, на рынке таких предложений мало.&lt;/blockquote&gt;

&lt;p&gt;Это слова Макса Лапшина, одного из самых известных пользователей Erlang-а в Рунете (ссылки на пару статей которого были даже у меня в блоге). Он же и автор &lt;a href=&quot;https://www.linux.org.ru/forum/development/13592001?cid=13593525&quot;&gt;мема&lt;/a&gt; о том, что писать на С++ -- это выгребать корки по утрам.&lt;/p&gt;

&lt;p&gt;Сколько было в прошлом разговоров о том, насколько хорош Erlang и насколько Erlang подходит и для таких задач, где, казалось бы, C++у самое место, а не одному из самых медленных динамически-типизированных языков. И все это для того, чтобы в итоге отказаться от Erlang-а в пользу нативного компилируемого языка, прямого конкурента С++ по производительности и ресурсоемкости.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Upd.&lt;/b&gt;В этой теме на LOR-е еще &lt;a href=&quot;https://www.linux.org.ru/forum/development/18355784?cid=18356270&quot;&gt;прекрасное добавилось&lt;/a&gt; от Лапшина (это ответ на вопрос уперся ли Erlang в потолок производительности):&lt;/p&gt;

&lt;blockquote&gt;Во все потолки, какие можно было.&lt;br/&gt;

И производительность, и количество библиотек, и количество людей и всё прочее.&lt;br/&gt;

Когда стало ясно, что прийдется самому руками писать QUIC, тут я слегка устал от эрланга.&lt;br/&gt;

О перфомансе вида «принять 10 000 камер» и речи не идет, причем если бы не медленный сторадж, новый код можно поковырять и до 20 тыс (просто это не нужно).
&lt;/blockquote&gt;

&lt;p&gt;При всем моем уважении к Erlang-у и людям, которые его создали, но такие факторы, как &quot;производительность&quot; и &quot;количество людей&quot;, как по мне, так были очевидны много-много лет назад.&lt;/p&gt;

&lt;hr/&gt;

&lt;p&gt;Если говорить серьезно, то когда вам повезло работать на проекте в течении 10-15-20 и более лет, то у вас есть возможность наблюдать за тем, как принятые вами же решения, которые когда-то давно казались крутыми и удачными, через годы не просто перестают такими быть, а нуждаются в замене на что-то, что сейчас кажется крутым и удачным (и далее по рекурсии).&lt;/p&gt;

</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/5395799970589730923/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/5395799970589730923' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/5395799970589730923'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/5395799970589730923'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/08/progsarcasm-erlang.html' title='[prog.sarcasm] Если долго сидеть на берегу, то можно увидеть как Erlang-еры...'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-3110039922620474253</id><published>2026-08-04T08:46:14.350+03:00</published><updated>2026-08-04T08:46:35.725+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="О жизни"/><title type='text'>[life.audiophile] Неожиданно приятное открытие в VE Megatron</title><content type='html'>&lt;p&gt;Несколько лет назад попал ко мне в руки USB-ЦАП Megatron от Venture Electronics (хороший обзор на него можно посмотреть здесь: &lt;a href=&quot;https://www.youtube.com/watch?v=6CT4ZQgjWHo&quot;&gt;YouTube&lt;/a&gt; или &lt;a href=&quot;https://rutube.ru/video/498df9872dc65ba7138e7f7c207ec4d7/&quot;&gt;RuTube&lt;/a&gt;). Попасть-то попал, но большую часть времени лежал без дела. По звуку с ним все OK, но требует, зараза, высокоомные наушники. Мои вкладыши на 300ом приходится слушать на минимальной громкости.&lt;/p&gt;

&lt;p&gt;В общем, большую часть времени валялся Megatron в ящике стола. И, возможно, я бы от него давно избавился бы, но лень было заниматься продажей.&lt;/p&gt;

&lt;p&gt;А вот буквально на днях случайно выяснилось, что по 3.5mm разъему Megatron поддерживает гарнитуру!&lt;/p&gt;

&lt;p&gt;И это решило проблему, с которой мне приходилось мириться на протяжении многих месяцев. А именно: на работе я подключаю к компьютеру USB-ЦАП чтобы слушать музыку в наушниках. Но когда возникает необходимость рабочего созвона через какой-то мессенджер или Zoom/Telemost, то приходится переключаться на гарнитуру, которая втыкается в 3.5mm разъем компьютера. И это переключение я регулярно забываю делать. Не говоря уже о том, что сама по себе эта необходимость раздражает.&lt;/p&gt;

&lt;p&gt;Но, к счастью, Megatron делает все эти манипуляции ненужными. Достаточно в 3.5mm разъем Megatron-а воткнуть наушники с гарнитурой, в 4.4mm (или 2.5mm) разъем -- наушники для музыки, а сам Megatron по USB подключить к компьютеру. И все. Слушаешь себе спокойно музыку (хоть из локального хранилища, хоть со стримминга), а когда нужно созвониться, то просто берешь другие наушники, подключенные к тому же самому Megatron-у и все.&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4LmDtMufs6hr5pkV6m1GJN19dRpjCer9kvv8YR93IT0YLwKkBXGcXTUFb571dZm9VJHyN2NaDo_e3rwNThmX3MNroilyXMGv2_dKYk-aretAzQ7UzF7LHtV8Sswivsmqo3WBJSKT_1JnZUEyH-nQhtOzhXHdvmtGIdXU2AK4XrI51u3Qn29iwXq2ZaPc/s1920/1785821864157.jpg&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;600&quot; data-original-height=&quot;1584&quot; data-original-width=&quot;1920&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4LmDtMufs6hr5pkV6m1GJN19dRpjCer9kvv8YR93IT0YLwKkBXGcXTUFb571dZm9VJHyN2NaDo_e3rwNThmX3MNroilyXMGv2_dKYk-aretAzQ7UzF7LHtV8Sswivsmqo3WBJSKT_1JnZUEyH-nQhtOzhXHdvmtGIdXU2AK4XrI51u3Qn29iwXq2ZaPc/s600/1785821864157.jpg&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;PS. Почему для музыки и для созвонов разные наушники? Ну просто так получатеся, что дорогие динамики я не ставлю в наушники с гарнитурным кабелем. Эти кабеля не самые надежные и за пару-тройку лет выходят из строя (а то и раньше, тут как повезет с качеством самого гарнитурного блока). А менять кабель все-таки спокойнее, когда ты знаешь, что динамики дешевые и если случайно повредишь при разборке наушников, то сильно обидно не будет.&lt;/p&gt;

</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/3110039922620474253/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/3110039922620474253' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/3110039922620474253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/3110039922620474253'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/08/lifeaudiophile-ve-megatron.html' title='[life.audiophile] Неожиданно приятное открытие в VE Megatron'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4LmDtMufs6hr5pkV6m1GJN19dRpjCer9kvv8YR93IT0YLwKkBXGcXTUFb571dZm9VJHyN2NaDo_e3rwNThmX3MNroilyXMGv2_dKYk-aretAzQ7UzF7LHtV8Sswivsmqo3WBJSKT_1JnZUEyH-nQhtOzhXHdvmtGIdXU2AK4XrI51u3Qn29iwXq2ZaPc/s72-c/1785821864157.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-7556569567509749949</id><published>2026-08-01T08:34:44.697+03:00</published><updated>2026-08-01T08:34:44.697+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Кино"/><category scheme="http://www.blogger.com/atom/ns#" term="О жизни"/><category scheme="http://www.blogger.com/atom/ns#" term="Ссылки"/><title type='text'>[life.cinema] Очередной кинообзор (2026/07)</title><content type='html'>&lt;p&gt;Традиционный отчет о просмотренных за минувший месяц фильмах. Традиционно в начале каждого из списков идет то, что понравилось больше, а в конце то, что не понравилось вообще. В целом же почти ничего не могу рекомендовать, большая часть отсмотренного оказалаь &quot;ну такое себе&quot; 😣&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Фильмы&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/205202/annot/&quot;&gt;День разоблачения (Disclosure Day, 2026)&lt;/a&gt;. Не ждал ничего выдающегося и получил приятный для просмотра фильм. Наблюдать за происходящим было интересно, в финале ожидал чего-то подобного (до сих пор помню разочарование от финала &quot;Близких контактов третьей степени&quot; того же автора), поэтому в этом моменте разочаровать меня кино не смогло. В целом, на фоне остального выходящего сейчас шлака, очень даже приличный фильмец.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/euro/204243/annot/&quot;&gt;Стервятники (Vultures или Rapaces, 2025)&lt;/a&gt;. Тот самый случай, когда от кино вообще ничего не ждешь, а получаешь вполне нормальный фильм. Не шедевр, но крепкий середнячок.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/asia/169435/annot/&quot;&gt;Грязные деньги (Deoreowoon done sondaeji mara, 2023)&lt;/a&gt;. Если бы не специфика азиатской актерской игры, то был бы крепкий середнячок в стиле криминальной драмы с интересной развязкой.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/ros/188479/annot/&quot;&gt;Кто-то должен умереть (2025)&lt;/a&gt;. Отличная картинка. Хорошие актеры. Любопытный сюжет. Но авторам не удалось создать атмосферу настоящей реальности -- смотришь на происходящее на экране и не можешь поверить что такое может происходить на самом деле.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/196269/annot/&quot;&gt;Бескрайняя ночь (The Vast of Night, 2019)&lt;/a&gt;. Если вы любитель артхаусного и фестивального кино, то можете попробовать глянуть. Мне лично не зашло.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/206417/annot/&quot;&gt;Глубокие воды (Deep Water, 2026)&lt;/a&gt;. Очень и очень бюджетно. Лучше обойти мимо и не тратить свое время.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/205903/annot/&quot;&gt;Смерть Робина Гуда (The Death of Robin Hood, 2026)&lt;/a&gt;. Унылая тягомотина с непонятным для меня замыслом и невнятным сюжетом.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Сериалы&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/201693/annot/&quot;&gt;Во всем виновата она (All Her Faul, первый сезон, 2025)&lt;/a&gt;. Отличный подбор актеров. Как по мне, так по некоторым ролям попадание 100%. Не самая плохая развязка, хотя к некоторым важным моментам остаются вопросики. Однако, мне показалось, что фильм безбожно растянут. Если бы вместо 8 серий было 4, получилось бы хорошо, а так скучновато.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/210445/annot/&quot;&gt;Я тебя отыщу (I Will Find You, первый сезон, 2026)&lt;/a&gt;. Актеров хороших собрали. И они играют. Но это единственное хорошее, что есть в сериале. Когда начинаешь вдумываться в сюжет, то оказывается, что нам втирают какую-то дичь.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/ros/171388/annot/&quot;&gt;Минута тишины (первый сезон, 2024)&lt;/a&gt;. Очень картонные персонажи, очень все шаблонно, местами приторно-елейно. Но в целом не самый плохой сериал.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/206198/annot/&quot;&gt;Побег (Run, первый сезон, 2026)&lt;/a&gt;. Главным достоинством сериала является то, что в нем всего шесть небольших серий. Для меня главный вопрос -- как историю преступника с несколькими десятками успешных ограблений и двумя побегами из тюрьмы превратили в такую нудную мелодраму. Смотреть можно только ради того, чтобы полюбопытствовать а как же снимают кино в Австралии. Есть здесь какой-то свой стиль, отличный от голливудского.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/ros/199485/annot/&quot;&gt;После Фишера. Инквизитор (2026, это же третий сезон &quot;Фишера&quot;)&lt;/a&gt;. Редкая муть, смело можно пройти мимо.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Кино вне категории&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/euro/28938/annot/&quot;&gt;&quot;Человек кусает собаку&quot; или &quot;Это случается рядом с вами&quot; (C&#39;est arrivé près de chez vous, 1992)&lt;/a&gt;. Самое необычное кино из тех, что посмотрел за последние несколько лет. Рекомендовать не буду т.к. ну очень уж специфическое. Однако, на фоне сегодняшнего широпотреба выглядит более чем необычно.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/7556569567509749949/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/7556569567509749949' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/7556569567509749949'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/7556569567509749949'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/08/lifecinema-202607.html' title='[life.cinema] Очередной кинообзор (2026/07)'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-6126030081442811009</id><published>2026-07-31T23:01:17.360+03:00</published><updated>2026-07-31T23:01:17.361+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><category scheme="http://www.blogger.com/atom/ns#" term="Поток сознания"/><title type='text'>[prog.thoughts] Так как же ИИ может изменить профессию &quot;программист&quot;?</title><content type='html'>&lt;p&gt;Попробую подвести итог начатых &lt;a href=&quot;https://eao197.blogspot.com/2026/07/progthoughts_01420504552.html&quot;&gt;ранее&lt;/a&gt; размышлений.&lt;/p&gt;

&lt;p&gt;Прежде всего нужно обозначить два важнейших фактора, которые могут перевернуть все представления с ног на голову.&lt;/p&gt;

&lt;p&gt;Во-первых, это экономическая и политическая обстановка в мире. Если не будет какого-то катаклизма, сравнимого с Первой или Второй Мировыми войнами, если мировая экономика выберется из кризиса и вернется экономический рост, то у программистов в целом все будет ОК. Будет работа, которая, наверняка, сильно изменится. Но эта самая работа хотя бы будет. А вот если мир скатится во что-то вроде Великой Депрессии в США 1930-х годов, или периода Веймарской республики начала 1920-х годов, то увы. Всем будет очень и очень не очень. В том числе и программистам. А может быть программистам как раз в первую очередь.&lt;/p&gt;

&lt;p&gt;Во-вторых, это экономика конкретных ИИ-компаний, которые сейчас пытаются поделить глобальный рынок ИИ-инструментария. Говорят (говорят!), что пока что экономика у них не сходится, что они глубоко убыточны и что непонятно какова должна быть реальная стоимость их услуг для того, чтобы окупить многомиллиардные инвестиции. Если получится, что реальная рыночная цена на этот самый ИИ будет сравнима со стоимостью обычного человека, то на какое-то время программистам можно будет облегченно выдохнуть.&lt;/p&gt;

&lt;p&gt;Еще, конечно же, интересный вопрос в том, до какого уровня качества этот самый ИИ в итоге дойдет. Пока все говорят (говорят!), что ИИ с каждой новой версией становится все лучше и лучше. Хотя внешней публике и не видно во что (по деньгам инвесторов) эти улучшения обходятся.&lt;/p&gt;

&lt;p&gt;А то ведь может оказаться, что с ИИ такая же ситуация, как с аудиофилией: очень несложно и совсем не дорого дойти до 90% от теоретически возможного качества звука. Зато стоимость каждого следующего процента качества возрастает в геометрической прогрессии. Может и с ИИ так? Может мы еще даже до 90% не дошли. И каждая следующая ступень качества, когда модели будут выдавать более точные решения и меньше галлюцинировать, будет обходиться на порядок дороже предыдущей. Чтобы в итоге стало не выгодно вкладывать деньги в повышение этого самого качества.&lt;/p&gt;

&lt;p&gt;Ну да ладно, давайте представим, что Третьей Мировой на наше счастье не случится и ИИ продолжит развиваться семимильными шагами без роста стоимости.&lt;/p&gt;

&lt;p&gt;Думаю, что тогда наша профессия изменится. Быстро и бесповоротно.&lt;/p&gt;

&lt;p&gt;Но не исчезнет.&lt;/p&gt;

&lt;p&gt;Надобность в прикладных программистах останется. Просто их инструменты и стиль работы сильно поменяются. Программист будет сочетать в себе роль бизнес-аналитика, чтобы выяснять что же именно нужно заказчику и формулировать это в виде ТЗ, а так же тим-лида над группами ИИ-агентов, которым эти самые ТЗ затем скармливаются и которые, собственно, код и производят. И который будет отвечать за все сотворенное в таком симбиозе.&lt;/p&gt;

&lt;p&gt;А вот класс инфраструктурных программистов сильно скукожится. Совсем они не исчезнут. Но их станет сильно меньше. И нужны они будут, в основном, чтобы заниматься прокачкой ИИ-агентов (возможно, с помощью ИИ-агентов). И чтобы разгребать дерьмо, в которое рано или поздно будут скатываться проекты, где код генерируется ИИ-агентами по ТЗ от новых прикладных программистов. Такое время от времени будет случаться и придется звать на помощь специальных людей, которые помогут разобраться с произошедшим (возможно, с помощью специализированных и особо натренированных ИИ-агентов). Но таких людей будет не много.&lt;/p&gt;

&lt;p&gt;Так что тем, кто не сможет переквалифицироваться в &quot;новых прикладников&quot; или в новых &quot;разгребателей дерьма&quot;, придется отправиться на выход. Что, как по мне, очень плохая новость для тех, кто ловит кайф от ручного набора кода и самостоятельного придумывания решений для стоящих перед ними задач. Останемся мы с вами без работы, увы.&lt;/p&gt;

&lt;p&gt;Но если вы хороший прикладной программист и умеете общаться с заказчиком, то ничего страшного вам не грозит. Всего лишь нужно освоить новые инструменты и еще плотнее держать руку на пульсе самых передовых технологий.&lt;/p&gt;

&lt;p&gt;Ну вот какие-то такие у меня мысли на данный момент. Однако, прошу не считать все вышесказанное инвестиционной рекомендацией.&lt;/p&gt;

&lt;p&gt;Сам-то я пока уверен в том, что большинству из нас, программистов, в ближайшие годы придется остаться без работы не из-за ИИ, а из-за глобальных экономических (а может и не только экономических) кризисов.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/6126030081442811009/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/6126030081442811009' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/6126030081442811009'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/6126030081442811009'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/07/progthoughts_0981391758.html' title='[prog.thoughts] Так как же ИИ может изменить профессию &quot;программист&quot;?'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-8092648397899184943</id><published>2026-07-30T18:54:00.952+03:00</published><updated>2026-07-31T23:02:35.126+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><category scheme="http://www.blogger.com/atom/ns#" term="Поток сознания"/><title type='text'>[prog.thoughts] Надобность в &quot;инфраструктурниках&quot; из-за того, что людям приходилось писать код самим</title><content type='html'>&lt;p&gt;Продолжу то, что начал &lt;a href=&quot;https://eao197.blogspot.com/2026/07/progthoughts_01198913158.html&quot;&gt;ранее&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Итак, компьютеры нужны нам, людям, для решения прикладных задач. Ну, по крайней мере, с этого когда-то все начиналось: научные и инженерные расчеты, финасы, управление производством и вот это вот все. Для всего этого нужно было писать прикладные программы.&lt;/p&gt;

&lt;p&gt;Но так уж вышло, что программы всегда получались ну очень уж большими для того, чтобы программисты могли удерживать все их подробности в голове. И поэтому приходилось придумывать средства борьбы со сложностью, которая проистекала из-за этой самой многословности и объема: макросы, подпрограммы, модули, объекты и вот это вот все.&lt;/p&gt;

&lt;p&gt;Сюда же и рекомендации по написанию понятного и сопровождаемого кода: структурное программирование и отказ от goto, ограничения на объем одной подпрограммы, отсутствие глобальных переменных, инкапсуляция и сокрытие данных...&lt;/p&gt;

&lt;p&gt;Все эти штуки были созданы нами и для нас, людей. Потому что мы не можем держать в памяти одновременно большое количество деталей. Но можем бороться с подобного рода сложностями за счет абстракций.&lt;/p&gt;

&lt;p&gt;Получается, что чем более сложную задачу нам нужно решить, тем большим количеством более мощных абстракций мы должны располагать. Будь то языковые конструкции (вроде классов или шаблонов/дженериков) или библиотеки готовых &quot;компонентов&quot;. А воплощение в жизнь подобных абстракций -- это именно что работа инфраструктурных программистов. Кто-то из инфраструктурщиков развивает языки программирования для того, чтобы поднять уровень и дать возможность выражать в коде все более и более сложные вещи, при этом обеспечивая и надежность, и удобство (если не брать в рассмотрение C++, конечно же). Кто-то пишет библиотеки и фреймворки. Кто-то создает вспомогательные инструменты вроде flex/bison или ANTLR.&lt;/p&gt;

&lt;p&gt;В итоге прикладные программисты получают в свое распоряжение все больший и больший набор средств. Что дает возможность писать все более и более объемные и сложные программы. Делать это быстрее, с меньшими усилиями и с более предсказуемым результатом (если не брать в рассмотрение C++, конечно же).&lt;/p&gt;

&lt;p&gt;Или может быть лучше сказать &quot;получали&quot;?&lt;/p&gt;

&lt;p&gt;Вот, например, нужно человеку отсортировать массив целых чисел -- он пишет код для сортировки. Потом видит, что этот код приходится повторять в других местах и чтобы избежать дублирования (поскольку дублирование плохо, т.к. увеличивает объем кода с которым затем придется работать) и выносит его в повторно используемую функцию. Потом обнаруживает, что сортировать приходится не только целые числа, но и вещественные, а также строки, а иногда и структуры. И вот уже появляется тот или иной вариант обобщенной реализации сортировки. А попутно выясняется какие языковые механизмы лучше способствуют созданию этих самых обобщенных реализаций.&lt;/p&gt;

&lt;p&gt;Но эти варианты нужны лишь потому, что человеку выгодно применять абстракцию &quot;сортировка&quot; вместо того, чтобы копипастить один и тот же код снова и снова.&lt;/p&gt;

&lt;p&gt;Однако, вряд ли эта самая абстракция необходима ИИ. Написали в спецификации о том, что какие-то данные должны быть упорядочены по какому-то критерию и для ИИ этого уже достаточно. Каким образом данное требование будет отображено в коде -- реализацией сортировки &quot;по месту&quot; или обращением к какой-то готовой функции -- безразлично, это всего лишь деталь реализации. Для каких-то хорошо известных и многократно повторенных задач ИИ будет переиспользовать уже написанный когда-то людьми код. Для чего-то более экзотического ИИ сгенерирует что-то свое. Что это будет и будет ли это соответствовать тем же самым критериям &quot;хорошего&quot; кода (простота, читаемость, сопровождаемость) не суть важно, т.к. скорее всего людям и не придется заглядывать в сгенерированный код в подавляющем большинстве случаев.&lt;/p&gt;

&lt;p&gt;Т.е. те самые абстракции, которые рождались с большим трудом, конкурировали друг с другом, проходили многолетний естественный отбор и выживали чтобы стать повсеместной практикой, перестают быть вотчиной программистов людей. Я бы даже сказал, что сами эти абстракции становятся лишними.&lt;/p&gt;

&lt;p&gt;Это люди могли набить шишки на return -1, прийти к выводу, что исключения надежнее, потом собрать кучу граблей с исключениями, прийти к выводу, что нужен симбиоз, изобрести синтаксис `?` в Rust и try в Swift...&lt;/p&gt;

&lt;p&gt;Чтобы в итоге этих самых людей заменил ИИ, который будет генерить простыни Go-шного кода с примитивнейшим `if err != nil` ничуть не страдая от того, что это и многословно, и отвлекает внимание, и не обеспечивает достаточной надежности.&lt;/p&gt;

&lt;hr/&gt;

&lt;p&gt;&lt;a href=&quot;https://eao197.blogspot.com/2026/07/progthoughts_0981391758.html&quot;&gt;Продолжение.&lt;/a&gt;&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/8092648397899184943/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/8092648397899184943' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/8092648397899184943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/8092648397899184943'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/07/progthoughts_01420504552.html' title='[prog.thoughts] Надобность в &quot;инфраструктурниках&quot; из-за того, что людям приходилось писать код самим'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-1023337900754715459</id><published>2026-07-29T07:28:02.197+03:00</published><updated>2026-07-30T18:54:41.159+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><category scheme="http://www.blogger.com/atom/ns#" term="Поток сознания"/><title type='text'>[prog.thoughts] Мое деление программистов на &quot;прикладных&quot; и &quot;инфраструктурных&quot;</title><content type='html'>&lt;p&gt;Чтобы продолжить рассуждения о том, как ИИ может повлиять на будущее профессии &quot;программист&quot; (начатые &lt;a href=&quot;https://eao197.blogspot.com/2026/07/progthoughts.html&quot;&gt;здесь&lt;/a&gt; и продолженные &lt;a href=&quot;https://eao197.blogspot.com/2026/07/progthoughts_0766252012.html&quot;&gt;здесь&lt;/a&gt;) придется озвучить одну из классификаций программистов, которой придерживаюсь в последние годы.&lt;/p&gt;

&lt;p&gt;Прикладные программисты делают то, что нужно пользователю. Причем не важно, о каком именно продукте идет речь -- это может быть какая-то сделанная на коленке под заказ система складского учета для провинциальной конторы &quot;Рога и Копыта&quot;, пакет Microsoft Office или же сервер реляционной СУБД. Суть в том, что есть продукт, есть требования к нему, есть список фич, которые нужно выкатить, есть сроки, есть бюджеты, есть обязательства и т.д., и т.п. И появляется конкретный продукт для конкретного пользователя именно благодаря труду прикладных программистов.&lt;/p&gt;

&lt;p&gt;Инфраструктурные программисты делают инструменты, которые используют прикладные программисты в своей работе. Самыми яркими примерами таких инструментов являются фреймворки и библиотеки. Как общего назначения (вроде Qt, JDK или .NET Framework), так и какие-то специализированные, заточенные под конкретный проект.&lt;/p&gt;

&lt;p&gt;Хоть и те и другие до недавнего времени вроде как одинаково писали код, между ними были принципиальные отличия во многих вещах -- начиная от внимания к мелким деталям при написании кода, заканчивая мировоззрением. Или, может быть, правильнее было бы сказать начиная от мировоззрения и заканчивая мелкими деталями в коде.&lt;/p&gt;

&lt;p&gt;Цель прикладного программиста -- решить конкретную задачу стоящую перед конкретным пользователем. Если решение будет работать и удовлетворять заказчика/покупателя продукта, то не суть важно, слеплено ли оно из говна и палок, скручено из разных костылей синей изолентой или же посажено на суперклей.&lt;/p&gt;

&lt;p&gt;И это более чем правильный подход. Потому что решение нужно здесь и сейчас иначе не будет денег от заказчика/покупателя, а без денег не будет нужды ни в прикладных программистах, ни в инфраструктурных.&lt;/p&gt;

&lt;p&gt;Тогда как задача инфраструктурного программиста в том, чтобы предоставить прикладному программисту как можно больше полезных инструментов, чтобы уменьшить количество синей изоленты в прикладном коде.&lt;/p&gt;

&lt;p&gt;Яркий пример, демонстрирующий разность в подходах, довелось увидеть буквально пару дней назад в докладе &lt;a href=&quot;https://www.youtube.com/watch?v=2BNhv6NA4L0&quot;&gt;«Опыт перехода проекта „Авито.Доставка“ с Java на Go» / Илья Лапин, Сергей Поляков (Avito)&lt;/a&gt;, который мне YouTube зачем-то подсунул в рекомендациях (но оказалось довольно любопытно, благо доклад короткий и толковый):&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM4bSTq8F-KoHfxAGfn5KnACEkrSDknF250X7uzLTawCsmzZ728DHPEcTANRzPSNDlvADkViljljYhkRQmLLIbMFGb03h-tXW_LGZIldVhc_-3dN61CoG3-z0uWUQV0LS-RIDgVOCk7tGwbn_SwswA4s0g5p8zBNDYvG_9FT4g-X2dL3q_K32LUhcAJpg/s1706/Screenshot_20260728_184259.png&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;600&quot; data-original-height=&quot;960&quot; data-original-width=&quot;1706&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM4bSTq8F-KoHfxAGfn5KnACEkrSDknF250X7uzLTawCsmzZ728DHPEcTANRzPSNDlvADkViljljYhkRQmLLIbMFGb03h-tXW_LGZIldVhc_-3dN61CoG3-z0uWUQV0LS-RIDgVOCk7tGwbn_SwswA4s0g5p8zBNDYvG_9FT4g-X2dL3q_K32LUhcAJpg/s600/Screenshot_20260728_184259.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Суть в том, что на момент доклада (2018-й год) в стандартной библиотеке Go (как и в самом языке) не было такого понятия как &quot;множество&quot; (оно же Set). Понятие &quot;словарь&quot; встроенное в сам язык было (в виде штатного типа map), а вот &quot;множества&quot; -- нет.&lt;/p&gt;

&lt;p&gt;Прикладной программист: ну OK, раз нет &quot;множества&quot;, то сойдет и &quot;словарь&quot;, просто в качестве значения для ключа будет использоваться экземпляр пустой структуры. Не, ну а чё, работает же.&lt;/p&gt;

&lt;p&gt;Тогда как инфраструктурный программист от подобного впадает в ступор. Типа: &quot;а почему этот самый Set нельзя было взять и сделать?&quot; 😉&lt;/p&gt;

&lt;p&gt;PS. Убедительная просьба не воспринимать этот текст как попытку ранжирования программистов по их качеству. Типа &quot;прикладные&quot; программисты -- не настоящие программисты вовсе, тогда как &quot;инфраструктурные&quot; -- соль профессии и настоящая илитарная илита. Как раз жизнь учит тому, что все программирование живет и зарабатывает исключительно благодаря &quot;прикладным&quot; программистам, тогда как &quot;инфраструктурые&quot; являются всего лишь обслуживающим персоналом (но без этого обслуживающего персонала тоже нельзя).&lt;/p&gt;

&lt;hr/&gt;

&lt;p&gt;&lt;a href=&quot;https://eao197.blogspot.com/2026/07/progthoughts_01420504552.html&quot;&gt;Продолжение.&lt;/a&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/1023337900754715459/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/1023337900754715459' title='Комментарии: 4'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/1023337900754715459'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/1023337900754715459'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/07/progthoughts_01198913158.html' title='[prog.thoughts] Мое деление программистов на &quot;прикладных&quot; и &quot;инфраструктурных&quot;'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM4bSTq8F-KoHfxAGfn5KnACEkrSDknF250X7uzLTawCsmzZ728DHPEcTANRzPSNDlvADkViljljYhkRQmLLIbMFGb03h-tXW_LGZIldVhc_-3dN61CoG3-z0uWUQV0LS-RIDgVOCk7tGwbn_SwswA4s0g5p8zBNDYvG_9FT4g-X2dL3q_K32LUhcAJpg/s72-c/Screenshot_20260728_184259.png" height="72" width="72"/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-6365534929407112969</id><published>2026-07-28T10:08:02.764+03:00</published><updated>2026-07-28T10:08:02.764+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Мысля давеча посетила"/><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><category scheme="http://www.blogger.com/atom/ns#" term="Поток сознания"/><title type='text'>[prog.thoughts] И еще одна мысль про влияние ИИ на программирование</title><content type='html'>&lt;p&gt;Навеяно вот этой статьей: &lt;a href=&quot;https://habr.com/ru/articles/1058500/&quot;&gt;Английский вместо кода&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Когда я приходил в профессию на программиста возлагались следующие задачи:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;выяснить что именно нужно сделать (здесь подразумевается общение с заказчиком и умение сформировать более-менее адекватное ТЗ по результатам этого общения);&lt;/li&gt;

  &lt;li&gt;решить как именно это будет сделано (архитектура, алгоритмы, сторонние библиотеки, форматы данных и вот это вот все);&lt;/li&gt;

  &lt;li&gt;воплотить решение в коде (чистый, работающий, тестируемый, сопровождаемый код и вот это вот все);&lt;/li&gt;

  &lt;li&gt;протестировать сделанное.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Плюсом сюда же могло попасть (и зачастую попадало) участие во внедрении сделанного. А потом и сопровождение, включая оперативное реагирование на инциденты с внезапной побудкой в полтретьего ночи или срочным выездом на объект заказчика.&lt;/p&gt;

&lt;p&gt;Никаких бизнес-аналитиков и тестировщиков в то время в наших палестинах еще не существовало как класса, появилось все это лет на 5-10 позже (хотя на Западе, как я слышал, к началу 1990-х все это уже было). Ну да не суть.&lt;/p&gt;

&lt;p&gt;Суть же в том, что для некоторых настоящее программирование заключалось прежде всего в &quot;воплотить решение в коде&quot; + (кому-то в больше степени, кому-то в меньшей) &quot;решить как именно сделать&quot; и &quot;протестировать сделанное&quot; (иногда в формулировке &quot;заставить это все работать в конце-то концов!&quot;). А общение с заказчиком и формирование ТЗ было худшим из периодов и настоящим наказанием.&lt;/p&gt;

&lt;p&gt;Постепенно профессия подвергалась влиянию специализации: выделение ролей &quot;бизнес-аналитик&quot;, &quot;архитектор&quot;, &quot;тестировщик&quot;, &quot;внедренец&quot; и т.д., уменьшало объем задач, ложившихся на плечи одного &quot;программиста&quot;. Но задача писать чистый, работающий, тестируемый и сопровождаемый код, к счастью, все еще оставалась главной для программиста.&lt;/p&gt;

&lt;p&gt;Теперь же эту задачу забирает на себя ИИ. И работа для остающихся в профессии специалистов (вроде как) смещается в сторону &quot;выяснить что именно нужно сделать&quot; и, в некоторой степени, &quot;решить как именно это сделать&quot;. В смысле формулирования более-менее однозначно трактуемых ИИ-шкой спецификаций -- как раз то, о чем идет речь в упомянутой статье.&lt;/p&gt;

&lt;p&gt;Только вот для некоторых это уже не будет тем самым настоящим программированием от которого эти некоторые получали наибольший кайф и в котором пытались достичь своего наивысшего мастерства.&lt;/p&gt;

&lt;p&gt;Мне сложно судить какой процентный состав этих самых &quot;некоторых&quot; и насколько нас таких много. К сожалению, в их число попадаю и я, а этого уже достаточно. Грустно размышлять о том, что в недалеком будущем ты, как программист, будешь заниматься разве что формулированием бизнес-правил вида &quot;если пользователь зашел на страницу с описанием предоставленных ему персональных скидок, но не воспользовался ими в течении 24 часов, то направить пользователю дополнительное напоминание&quot;.&lt;/p&gt;

&lt;p&gt;Как по мне, так это уже и не программирование вовсе.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/6365534929407112969/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/6365534929407112969' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/6365534929407112969'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/6365534929407112969'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/07/progthoughts_0766252012.html' title='[prog.thoughts] И еще одна мысль про влияние ИИ на программирование'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-7933784411231981250</id><published>2026-07-27T16:29:51.442+03:00</published><updated>2026-07-27T16:29:51.443+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Мысля давеча посетила"/><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><category scheme="http://www.blogger.com/atom/ns#" term="Поток сознания"/><title type='text'>[prog.thoughts] Подумалось тут про ИИ и будущее программирования...</title><content type='html'>&lt;p&gt;Продвинутые ИИ модели дошли до того, чтобы &lt;a href=&quot;https://bun.com/blog/bun-in-rust&quot;&gt;переписывать большие проекты&lt;/a&gt; и &lt;a href=&quot;https://www.opennet.ru/opennews/art.shtml?num=65963&quot;&gt;генерировать реализации по спецификациям&lt;/a&gt; с минимальным участием человека. А люди, плотно использующие ИИ для разработки ПО все больше говорят о том, что работа с ИИ агентами становится похожа на работу тим-лида или даже технического лида: раздаешь задания, контролируешь исполнение, сам практически ничего не пишешь и, может быть, даже не читаешь то, что ИИ генерирует (хотя бы потому, что объемы сгенерированного кода будут превышать возможности человека-ревьювера).&lt;/p&gt;

&lt;p&gt;В связи с этим подумалось, что наступает золотая эпоха тех специалистов, которые были вынуждены программировать ну хоть как-то. Вроде физиков, химиков и биологов, которым нужно было делать вычислительные эксперименты, для чего приходилось осваивать программирование хотя бы в минимальной степени. В лучшем случае на Python или Pascal, но скорее на Fortran, а в особо запущенных случаях и на С++.&lt;/p&gt;

&lt;p&gt;Вот они теперь смогут переложить реализацию вычислительной части на ИИ. И смогут сосредоточиться на том, чтобы решить что и как расчитывать, не тратя свою энергию на воплощение своих вычислительных моделей в коде. С кодом как раз ИИ вполне себе справится.&lt;/p&gt;

&lt;p&gt;PS. Прошу не воспринимать вышесказанное как прогноз, не нужно запоминать этот твит. На самом деле данный пост начинался как большой и глубоко пессимистический текст с самыми мрачными фантазиями о недалеком будущем. Но потом я решил, что лучше бы попробовать найти в происходящем что-нибудь хорошее 🙂&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/7933784411231981250/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/7933784411231981250' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/7933784411231981250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/7933784411231981250'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/07/progthoughts.html' title='[prog.thoughts] Подумалось тут про ИИ и будущее программирования...'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-8611717330705226893</id><published>2026-07-25T14:24:49.261+03:00</published><updated>2026-07-27T19:29:09.722+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Multithreading"/><category scheme="http://www.blogger.com/atom/ns#" term="Вопрос залу"/><category scheme="http://www.blogger.com/atom/ns#" term="Из непонятого"/><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><category scheme="http://www.blogger.com/atom/ns#" term="язык C++"/><title type='text'>[prog.c++.multithreading] Сломал себе мозг пытаясь понять что не нравится thread sanitizer-у</title><content type='html'>&lt;p&gt;&lt;b&gt;Upd. Похоже, что проблема сперва была в том, что SO-5 подключался в проект через vcpkg и когда проект компилировался с TSan, то линковался SO-5, собранный без TSan. А когда я включил исходники SO-5 в сам проект, чтобы все компилировалось с одинаковыми ключами, то ошибся с порядком команд в CMakeLists.txt и при компиляции SO-5 опции для TSan не учитывались. Если же собрать и SO-5, и остальной проект с одинаковыми опциями, то данной проблемы не возникает (пока?).&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;В текущем проекте thread sanitizer периодически выдает предупреждение о data race на фрагменте, который относится к SObjectizer-у.&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9K2NFuLrVliuGWYiaiclGnJCHeQU-pQOTBbGiM2nrOVw_MdVqm_kB3T4bQPRSlaFuR5daNisHxlIKG2i7UmNqtCLYGtZsTamLmon0g-kroQKBZk83eYJshArnHKhXKWlpE6wy7CH8ttBL8Jsgn0KmXuebsY9XmF20crDljpP01CbD0e4BS1LEl0Vqcxw/s2784/Screenshot_20260725_100808-2.png&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;600&quot; data-original-height=&quot;1349&quot; data-original-width=&quot;2784&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9K2NFuLrVliuGWYiaiclGnJCHeQU-pQOTBbGiM2nrOVw_MdVqm_kB3T4bQPRSlaFuR5daNisHxlIKG2i7UmNqtCLYGtZsTamLmon0g-kroQKBZk83eYJshArnHKhXKWlpE6wy7CH8ttBL8Jsgn0KmXuebsY9XmF20crDljpP01CbD0e4BS1LEl0Vqcxw/s600/Screenshot_20260725_100808-2.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Самое плохое то, что:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;я не понимаю в чем именно thread sanitizer видит проблему. Соответственно, неизвестно, является ли срабатывание TSan-а ложно позитивным или же есть реальная ошибка, которую следует исправить;&lt;/li&gt;
  &lt;li&gt;мне не удается повторить такую же ситуацию в тестах для самого SO-5. Т.е. в рамках проекта TSan диагностику выдает, а в мелких тестах, которые пытаются повторить тот же сценарий -- нет. Ни в какую. Что сильно затрудняет разбирательства и поиск обходных путей.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Что здесь происходит:&lt;/p&gt;

&lt;p&gt;Агент на нити T7 отсылает сообщение GiveMeTask агенту-координатору, который работает на нити T3.&lt;/p&gt;

&lt;p&gt;Агент-координатор получает сообщение и обрабатывает его. После чего начинается разрушение объекта &lt;a href=&quot;https://github.com/Stiffstream/sobjectizer/blob/c5ec4485cf6e8b0d8290c309f9a10d306252e6ca/dev/so_5/execution_demand.hpp#L60&quot;&gt;execution_demand_t&lt;/a&gt;, в котором лежит умный указатель на экземпляр сообщения.&lt;/p&gt;

&lt;p&gt;В это же время на нити T7 завершается процедура отсылки сообщения.&lt;/p&gt;

&lt;p&gt;И, как я понимаю, фокус в том, что эти два действия происходят на двух нитях очень близко друг к другу по времени.&lt;/p&gt;

&lt;p&gt;Экземпляр сообщения GiveMeTask создается на нити T7. Указатель на этот экземпляр хранится на нити T7 внутри объекта &lt;a href=&quot;https://github.com/Stiffstream/sobjectizer/blob/c5ec4485cf6e8b0d8290c309f9a10d306252e6ca/dev/so_5/atomic_refcounted.hpp#L91&quot;&gt;intrusive_ptr_t&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;На нити T3 внутри execution_demand_t так же есть свой объект intrusive_ptr_t который хранит указатель на этот же экземпляр GiveMeTask.&lt;/p&gt;

&lt;p&gt;Т.е. на двух нитях есть два разных intrusive_ptr_t, которые хранят в себе указатель на один и тот же объект GiveMeTask.&lt;/p&gt;

&lt;p&gt;При этом счетчик ссылок на GiveMeTask хранится в самом объекте GiveMeTask. Класс GiveMeTask наследуется от so_5::message_t:&lt;/p&gt;

&lt;code&gt;&lt;pre&gt;struct GiveMeTask final : public so_5::message_t
{
    const so_5::mbox_t _workerMbox;

    GiveMeTask(so_5::mbox_t workerMbox)
        : _workerMbox{ std::move(workerMbox) }
    {}
};&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;А &lt;a href=&quot;https://github.com/Stiffstream/sobjectizer/blob/c5ec4485cf6e8b0d8290c309f9a10d306252e6ca/dev/so_5/message.hpp#L46&quot;&gt;so_5::message_t&lt;/a&gt; наследуется от so_5::atomic_refcounted_t:&lt;/p&gt;

&lt;code&gt;&lt;pre&gt;class message_t : public atomic_refcounted_t
    {
        ...
    };&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;В &lt;a href=&quot;https://github.com/Stiffstream/sobjectizer/blob/c5ec4485cf6e8b0d8290c309f9a10d306252e6ca/dev/so_5/atomic_refcounted.hpp#L77&quot;&gt;so_5::atomic_refcounted_t&lt;/a&gt; счетчик ссылок хранится &lt;a href=&quot;https://github.com/Stiffstream/sobjectizer/blob/c5ec4485cf6e8b0d8290c309f9a10d306252e6ca/dev/so_5/types.hpp#L24&quot;&gt;в виде std::atomic&lt;/a&gt;. Т.е. операции инкремента-декремента количества ссылок происходят атомарно и не нуждаются в дополнительной синхронизации.&lt;/p&gt;

&lt;p&gt;Получается, что на нити T7 создается новый экземпляр GiveMeTask, указатель на него сохраняется в локальном объекте intrusive_ptr_t и счетчик ссылок на GiveMeTask выставляется в 1.&lt;/p&gt;

&lt;p&gt;На нити T7 вызывается send для GiveMeTask и формируется execution_demand_t для агента-координатора. Внутри execution_demand_t создается свой intrusive_ptr_t и счетчик ссылок для GiveMeTask получает значение 2.&lt;/p&gt;

&lt;p&gt;Затем на нити T3 происходит обработка GiveMeTask, после чего начинается разрушение execution_demand_t и его содержимого (в том числе и второго intrusive_ptr_t).&lt;/p&gt;

&lt;p&gt;Но чуть раньше на нити T7 происходит разрушение своего intrusive_ptr_t после чего счетчик ссылок в GiveMeTask опускается до 1.&lt;/p&gt;

&lt;p&gt;А уже после этого на нити T3 счетчик ссылок на GiveMeTask обнуляется и происходит разрушение объекта GiveMeTask.&lt;/p&gt;

&lt;p&gt;Происходят действия именно в этом порядке. Если бы сперва полностью разрушился execution_demand_t на нити T3 и лишь после этого началось уничтожение intrusive_ptr_t на нити T7, то деструктор GiveMeTask вызвался бы на нити T7, а не на нити T3.&lt;/p&gt;

&lt;p&gt;Т.е. с моей точки зрения здесь все OK. Но TSan видит data race. А я не понимаю про какой data race идет речь.&lt;/p&gt;

&lt;p&gt;Под катом выхлоп от TSan в текстовом виде.&lt;/p&gt;

&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;

&lt;code&gt;WARNING: ThreadSanitizer: data race (pid=105293)&lt;br&gt;
&amp;nbsp;&amp;nbsp;Write of size 8 at 0x720800038028 by thread T3:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#0 operator delete(void*, unsigned long) ../../../../src/libsanitizer/tsan/tsan_new_delete.cpp:150 (libtsan.so.2+0xa66c8) (BuildId: 2a13a7710e361d06f7babbea53065ca2be93f738)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#1 Calculation::CoordinatorImpl::GiveMeTask::~GiveMeTask() /home/eao197/sandboxes/&amp;lt;censored&amp;gt;/include/CalculationCoordinatorAgents.h:23 (&amp;lt;censored&amp;gt;+0x1420c2a) (BuildId: d95e75b5663cd24e4ecc0f7a4ab2777babe82359)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#2 so_5::intrusive_ptr_t&amp;lt;so_5::message_t&amp;gt;::dismiss_object() /home/eao197/sandboxes/&amp;lt;censored&amp;gt;/so_5/atomic_refcounted.hpp:322 (&amp;lt;censored&amp;gt;+0x16ac5db) (BuildId: d95e75b5663cd24e4ecc0f7a4ab2777babe82359)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#3 so_5::intrusive_ptr_t&amp;lt;so_5::message_t&amp;gt;::~intrusive_ptr_t() /home/eao197/sandboxes/&amp;lt;censored&amp;gt;/so_5/atomic_refcounted.hpp:178 (&amp;lt;censored&amp;gt;+0x16ac5db)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#4 so_5::execution_demand_t::~execution_demand_t() /home/eao197/sandboxes/&amp;lt;censored&amp;gt;/so_5/execution_demand.hpp:61 (&amp;lt;censored&amp;gt;+0x16ac5db)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#5 void std::destroy_at&amp;lt;so_5::execution_demand_t&amp;gt;(so_5::execution_demand_t*) /usr/include/c++/13/bits/stl_construct.h:88 (&amp;lt;censored&amp;gt;+0x16ac5db)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#6 void std::allocator_traits&amp;lt;std::allocator&amp;lt;so_5::execution_demand_t&amp;gt; &amp;gt;::destroy&amp;lt;so_5::execution_demand_t&amp;gt;(std::allocator&amp;lt;so_5::execution_demand_t&amp;gt;&amp;amp;, so_5::execution_demand_t*) /usr/include/c++/13/bits/alloc_traits.h:560 (&amp;lt;censored&amp;gt;+0x16ac5db)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#7 std::deque&amp;lt;so_5::execution_demand_t, std::allocator&amp;lt;so_5::execution_demand_t&amp;gt; &amp;gt;::pop_front() /usr/include/c++/13/bits/stl_deque.h:1580 (&amp;lt;censored&amp;gt;+0x16ac5db)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#8 so_5::disp::reuse::work_thread::details::no_activity_tracking_impl_t::serve_demands_block(std::thread::id, std::deque&amp;lt;so_5::execution_demand_t, std::allocator&amp;lt;so_5::execution_demand_t&amp;gt; &amp;gt;&amp;amp;) /home/eao197/sandboxes/&amp;lt;censored&amp;gt;/so_5/disp/reuse/work_thread/work_thread.hpp:448 (&amp;lt;censored&amp;gt;+0x16ac5db)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#9 so_5::disp::reuse::work_thread::details::work_thread_template_t&amp;lt;so_5::disp::reuse::work_thread::details::no_activity_tracking_impl_t&amp;gt;::body() /home/eao197/sandboxes/&amp;lt;censored&amp;gt;/so_5/disp/reuse/work_thread/work_thread.hpp:705 (&amp;lt;censored&amp;gt;+0x16ac5db)&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;Previous atomic write of size 8 at 0x720800038028 by thread T7:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#0 std::__atomic_base&amp;lt;unsigned long&amp;gt;::operator--() /usr/include/c++/13/bits/atomic_base.h:410 (&amp;lt;censored&amp;gt;+0x141ff80) (BuildId: d95e75b5663cd24e4ecc0f7a4ab2777babe82359)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#1 so_5::atomic_refcounted_t::dec_ref_count() /home/eao197/sandboxes/&amp;lt;censored&amp;gt;/so_5/atomic_refcounted.hpp:80 (&amp;lt;censored&amp;gt;+0x141ff80)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#2 so_5::intrusive_ptr_t&amp;lt;so_5::message_t&amp;gt;::dismiss_object() /home/eao197/sandboxes/&amp;lt;censored&amp;gt;/so_5/atomic_refcounted.hpp:317 (&amp;lt;censored&amp;gt;+0x141ff80)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#3 so_5::intrusive_ptr_t&amp;lt;so_5::message_t&amp;gt;::~intrusive_ptr_t() /home/eao197/sandboxes/&amp;lt;censored&amp;gt;/so_5/atomic_refcounted.hpp:178 (&amp;lt;censored&amp;gt;+0x141ff80)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#4 void so_5::low_level_api::deliver_message&amp;lt;Calculation::CoordinatorImpl::GiveMeTask&amp;gt;(so_5::message_delivery_mode_t, so_5::abstract_message_box_t&amp;amp;, std::type_index, std::unique_ptr&amp;lt;Calculation::CoordinatorImpl::GiveMeTask, std::default_delete&amp;lt;Calculation::CoordinatorImpl::GiveMeTask&amp;gt; &amp;gt;) /home/eao197/sandboxes/&amp;lt;censored&amp;gt;/so_5/mbox.hpp:393 (&amp;lt;censored&amp;gt;+0x141ff80)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#5 void so_5::impl::instantiator_and_sender_base&amp;lt;Calculation::CoordinatorImpl::GiveMeTask, false&amp;gt;::send&amp;lt;so_5::intrusive_ptr_t&amp;lt;so_5::abstract_message_box_t&amp;gt; const&amp;amp;&amp;gt;(so_5::intrusive_ptr_t&amp;lt;so_5::abstract_message_box_t&amp;gt; const&amp;amp;, so_5::intrusive_ptr_t&amp;lt;so_5::abstract_message_box_t&amp;gt; const&amp;amp;) /home/eao197/sandboxes/&amp;lt;censored&amp;gt;/so_5/send_functions.hpp:59 (&amp;lt;censored&amp;gt;+0x141ff80)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#6 void so_5::send&amp;lt;Calculation::CoordinatorImpl::GiveMeTask, so_5::intrusive_ptr_t&amp;lt;so_5::abstract_message_box_t&amp;gt; const&amp;amp;, so_5::intrusive_ptr_t&amp;lt;so_5::abstract_message_box_t&amp;gt; const&amp;amp;&amp;gt;(so_5::intrusive_ptr_t&amp;lt;so_5::abstract_message_box_t&amp;gt; const&amp;amp;, so_5::intrusive_ptr_t&amp;lt;so_5::abstract_message_box_t&amp;gt; const&amp;amp;) /home/eao197/sandboxes/&amp;lt;censored&amp;gt;/so_5/send_functions.hpp:231 (&amp;lt;censored&amp;gt;+0x141ff80)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#7 Calculation::CoordinatorImpl::Worker::so_evt_start() /home/eao197/sandboxes/&amp;lt;censored&amp;gt;/src/model/calc/CalculationCoordinatorAgents.cpp:30 (&amp;lt;censored&amp;gt;+0x141ff80)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#8 so_5::agent_t::demand_handler_on_start(std::thread::id, so_5::execution_demand_t&amp;amp;) /home/eao197/sandboxes/&amp;lt;censored&amp;gt;/so_5/agent.cpp:1433 (&amp;lt;censored&amp;gt;+0x1671404) (BuildId: d95e75b5663cd24e4ecc0f7a4ab2777babe82359)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#9 &amp;lt;null&amp;gt; &amp;lt;null&amp;gt; (libstdc++.so.6+0xecdb3) (BuildId: 753c6c8608b61d4e67be8f0c890e03e0aa046b8b)&lt;br&gt;
&lt;/code&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/8611717330705226893/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/8611717330705226893' title='Комментарии: 3'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/8611717330705226893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/8611717330705226893'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/07/progcmultithreading-thread-sanitizer.html' title='[prog.c++.multithreading] Сломал себе мозг пытаясь понять что не нравится thread sanitizer-у'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9K2NFuLrVliuGWYiaiclGnJCHeQU-pQOTBbGiM2nrOVw_MdVqm_kB3T4bQPRSlaFuR5daNisHxlIKG2i7UmNqtCLYGtZsTamLmon0g-kroQKBZk83eYJshArnHKhXKWlpE6wy7CH8ttBL8Jsgn0KmXuebsY9XmF20crDljpP01CbD0e4BS1LEl0Vqcxw/s72-c/Screenshot_20260725_100808-2.png" height="72" width="72"/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-3587001199798429564</id><published>2026-07-22T07:37:23.878+03:00</published><updated>2026-07-22T07:37:23.879+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><category scheme="http://www.blogger.com/atom/ns#" term="Ссылки"/><title type='text'>[prog.flame] Узнал давеча о переписывании какого-то Bun с какого-то Zig на какой-то Rust :)</title><content type='html'>&lt;p&gt;Т.к. я не тормоз, а всего лишь медленный газ, то только вчера узнал об очередном скандале на просторах этого нашего Интернета. Если кто-то, как и я, все еще не в курсе, то:&lt;/p&gt;

&lt;p&gt;Некий проект &lt;a href=&quot;https://github.com/oven-sh/bun&quot;&gt;Bun&lt;/a&gt; (говорят, что это какой-то очень и очень быстрый инструментарий для JavaScript, включая и виртуальную машину) внутри Antropic-а переписали с Zig на Rust посредством нескольких десятков параллельно работавших в течении 11 дней агентов: &lt;a href=&quot;https://bun.com/blog/bun-in-rust&quot;&gt;https://bun.com/blog/bun-in-rust&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;На рассказ об этой процедуре среагировал разработчик языка Zig и высказался в том духе, что &lt;strike&gt;баба с возу кобыле легче&lt;/strike&gt; переписали на Rust и славно, а то эти Bun-овцы уже изрядно задолбали дискредитацией всего Zig-а низким качеством своего кода: &lt;a href=&quot;https://andrewkelley.me/post/my-thoughts-bun-rust-rewrite.html&quot;&gt;https://andrewkelley.me/post/my-thoughts-bun-rust-rewrite.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Как по мне, так и то, и другое чтиво вполне себе интересное и заслуживает того, чтобы быть прочитанным.&lt;/p&gt;

&lt;p&gt;Но больше всего интересует вот какой момент. В блог-посте про переписывание с Zig на Rust приводится пример кода на Zig, который иллюстрирует заморочки, с которыми приходилось сталкиваться Bun-овцам при написании надежного кода на Zig:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ffff60&quot;&gt;fn&lt;/font&gt;&amp;nbsp;foo(a_ptr: SharedPtr(TCPSocket))&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;!&lt;/font&gt;&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90fff0&quot;&gt;const&lt;/font&gt;&amp;nbsp;a:&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;*&lt;/font&gt;TCPSocket&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;=&lt;/font&gt;&amp;nbsp;a_ptr.get();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ff80ff&quot;&gt;defer&lt;/font&gt;&amp;nbsp;a_ptr.deref();&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90fff0&quot;&gt;const&lt;/font&gt;&amp;nbsp;b&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;=&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;try&lt;/font&gt;&amp;nbsp;do_something_with_a(a);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ff80ff&quot;&gt;defer&lt;/font&gt;&amp;nbsp;b.deref();&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;// ...&lt;/font&gt;&lt;br&gt;
}&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Поскольку я не знаю Zig, то очень интересно, а это прям идиоматический код и лучше на Zig уже не получится? Или же это откровенный говнокод, низкое качество которого очевидно даже начинающим Zig-ерам?&lt;/p&gt;

&lt;p&gt;PS. Так же я не полностью согласен с тезисом, что для C++ надежность кода достигается за счет следования какому-то административно утвержденному code style (как в случае с упомянутым в блог-посте от Bun-овцев Google C++ code style guide). Многие проблемы (вроде контроля времени жизни объектов, находящихся в совместном использовании) должны решаться не соглашениями, а типами (вроде unique_ptr, shared_ptr и т.д.) Но кто я такой, чтобы рассуждать на эту тему? 😉&lt;/p&gt;

&lt;p&gt;PPS. А Rust подтверждает свою репутацию языка, на котором ничего нового не пишут, а только переписывают существующее 🤣&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/3587001199798429564/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/3587001199798429564' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/3587001199798429564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/3587001199798429564'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/07/progflame-bun-zig-rust.html' title='[prog.flame] Узнал давеча о переписывании какого-то Bun с какого-то Zig на какой-то Rust :)'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-943201720739203574</id><published>2026-07-17T07:24:17.910+03:00</published><updated>2026-07-17T07:24:17.910+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Multithreading"/><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><category scheme="http://www.blogger.com/atom/ns#" term="язык C++"/><title type='text'>[prog.c++.multithreading] Мой способ обойти ложное срабатывание в TSan с инверсией порядка захвата mutex-ов</title><content type='html'>&lt;p&gt;Продолжение &lt;a href=&quot;https://eao197.blogspot.com/2026/07/progcmultithreading-false-positive_01605290765.html&quot;&gt;вчерашней темы&lt;/a&gt; с ложно позитивным срабатыванием thread sanitizer, когда TSan ошибочно диагностировал инверсию порядка захвата mutex-ов.&lt;/p&gt;

&lt;p&gt;Поскольку в коде с точки зрения порядка блокировок все было OK, то возник вопрос: а как удовлетворить TSan, чтобы избавиться от ложной диагностики и продолжить использовать TSan для поиска других проблем?&lt;/p&gt;

&lt;p&gt;Было найдено вот такое решение:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#if defined( __SANITIZE_THREAD__ )&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;template&lt;/font&gt;&amp;lt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;typename&lt;/font&gt;&amp;nbsp;M &amp;gt;&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;class&lt;/font&gt;&amp;nbsp;tsan_friendly_lock_guard&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; M &amp;amp; m_what;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ffff60&quot;&gt;public&lt;/font&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp; tsan_friendly_lock_guard( M &amp;amp; what )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;: m_what{ what }&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;while&lt;/font&gt;( !m_what.try_lock() )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; std::this_thread::yield();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; ~tsan_friendly_lock_guard()&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_what.unlock();&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
};&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#else&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;template&lt;/font&gt;&amp;lt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;typename&lt;/font&gt;&amp;nbsp;M &amp;gt;&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;class&lt;/font&gt;&amp;nbsp;tsan_friendly_lock_guard&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::lock_guard&amp;lt; M &amp;gt; m_guard;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;public&lt;/font&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tsan_friendly_lock_guard( M &amp;amp; mutex )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : m_guard{ mutex }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {}&lt;br&gt;
&amp;nbsp;&amp;nbsp; };&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#endif&lt;/font&gt;&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Затем в тех местах кода, где TSan ругался на потенциальную инверсию порядка захвата mutex-ов, std::lock_guard был заменен на tsan_friendly_lock_guard. И оно сработало: &lt;a href=&quot;https://godbolt.org/z/fb84zsr4M&quot;&gt;https://godbolt.org/z/fb84zsr4M&lt;/a&gt;.&lt;/p&gt;


</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/943201720739203574/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/943201720739203574' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/943201720739203574'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/943201720739203574'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/07/progcmultithreading-tsan-mutex.html' title='[prog.c++.multithreading] Мой способ обойти ложное срабатывание в TSan с инверсией порядка захвата mutex-ов'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-5457083829701825533</id><published>2026-07-16T09:06:17.685+03:00</published><updated>2026-07-17T07:31:04.912+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Bugs"/><category scheme="http://www.blogger.com/atom/ns#" term="Multithreading"/><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><category scheme="http://www.blogger.com/atom/ns#" term="язык C++"/><title type='text'>[prog.c++.multithreading] Теперь уж точно false positive в thread sanitizer-е</title><content type='html'>&lt;p&gt;Следом за &lt;a href=&quot;https://eao197.blogspot.com/2026/07/progcmultithreading-false-positive.html&quot;&gt;предыдущей&lt;/a&gt;, нашел еще одну неприятную ситуацию с thread sanitizer. Но теперь это на 100% ложно позитивное срабатывание.&lt;/p&gt;

&lt;p&gt;Посмотреть можно на godbolt: &lt;a href=&quot;https://godbolt.org/z/zfGfhq89d&quot;&gt;https://godbolt.org/z/zfGfhq89d&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Суть в том, что в одной нити захватывается сперва mutex у child-а, а затем, при все еще захваченном mutex-е child-а, захватывается mutex у parent-а.&lt;/p&gt;

&lt;p&gt;А потом, когда все ранее захваченные mutex-ы освобождены, уже на другой нити сперва захватывается mutex у parent-а, а следом, не отпуская mutex parent-а, захватывается mutex у child-а.&lt;/p&gt;

&lt;p&gt;Thread sanitizer выдает предупреждение о потенциальном дедлоке из-за инверсии порядка захвата мутексов.&lt;/p&gt;

&lt;p&gt;Только вот здесь эта инверсия невозможна в принципе, т.к. сперва гарантированно заканчиваются все операции с child-ом, и лишь затем стартует нить, на которой делаются манипуляции с parent-ом.&lt;/p&gt;

&lt;p&gt;И вот как удовлетворить thread sanitizer, чтобы он в данном месте не выдавал свою диагностику... Это пока для меня большой вопрос.&lt;/p&gt;

&lt;p&gt;Upd. Похоже, это &lt;a href=&quot;https://github.com/llvm/llvm-project/issues/57955&quot;&gt;уже известная проблема. С 2022-го года&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Upd2. Найденный обходной маневр: &lt;a href=&quot;https://eao197.blogspot.com/2026/07/progcmultithreading-tsan-mutex.html&quot;&gt;вспомогательный класс tsan_friendly_lock_guard&lt;/a&gt;.&lt;/p&gt;

&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#include&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;lt;thread&amp;gt;&lt;/font&gt;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#include&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;lt;mutex&amp;gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;struct&lt;/font&gt;&amp;nbsp;info&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; std::mutex m_lock;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; info * m_parent{&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;nullptr&lt;/font&gt;&amp;nbsp;};&lt;br&gt;
&amp;nbsp;&amp;nbsp; info * m_child{&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;nullptr&lt;/font&gt;&amp;nbsp;};&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; activate( info * parent )&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::lock_guard&amp;lt; std::mutex &amp;gt; lock{ m_lock };&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_parent = parent;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_parent-&amp;gt;add_child(&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;this&lt;/font&gt;&amp;nbsp;);&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; deactivate()&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::lock_guard&amp;lt; std::mutex &amp;gt; lock{ m_lock };&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;if&lt;/font&gt;( m_child )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_child-&amp;gt;deactivate();&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; add_child( info * child )&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::lock_guard&amp;lt; std::mutex &amp;gt; lock{ m_lock };&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_child = child;&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
};&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;nbsp;main()&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; info parent, child;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; child.activate( &amp;amp;parent );&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; std::thread parallel_task{ [&amp;amp;parent] { parent.deactivate(); } };&lt;br&gt;
&amp;nbsp;&amp;nbsp; parallel_task.join();&lt;br&gt;
}&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/5457083829701825533/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/5457083829701825533' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/5457083829701825533'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/5457083829701825533'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/07/progcmultithreading-false-positive_01605290765.html' title='[prog.c++.multithreading] Теперь уж точно false positive в thread sanitizer-е'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-6693587729559435771</id><published>2026-07-15T15:40:20.303+03:00</published><updated>2026-07-18T16:58:27.830+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Bugs"/><category scheme="http://www.blogger.com/atom/ns#" term="Multithreading"/><category scheme="http://www.blogger.com/atom/ns#" term="Вопрос залу"/><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><category scheme="http://www.blogger.com/atom/ns#" term="язык C++"/><title type='text'>[prog.c++.multithreading] Интересно, это false positive от thread sanitizer-а или нет?</title><content type='html'>&lt;p&gt;&lt;i&gt;Примечание: первоначальный вариант этого поста описывал мое ошибочное предположение о том, что thread sanitizer выдал ложное срабатывание. Однако, ув.тов.Николай Меркин (кому-то он известен как Кодт с RSDN) указал на реальную ошибку. Поэтому текст был переработан.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Thread sanitizer выдал предупреждение на код, который я много лет считал корректным.&lt;/p&gt;

&lt;p&gt;Для нетерпеливых вот самодостаточный пример на godbolt: &lt;a href=&quot;https://godbolt.org/z/3xPadcnva&quot;&gt;https://godbolt.org/z/3xPadcnva&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Для всех остальных пояснение:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;на главной нити создается объект actual_repo. В этом объекте живут и std::mutex, и condition_variable (на котором будет осуществляться ожидание);&lt;/li&gt;
  &lt;li&gt;ссылка на actual_repo передается в дочернюю нить. Через какое-то время дочерняя нить вызывает для actual_repo метод stop;&lt;/li&gt;
  &lt;li&gt;главная же нить засыпает на вызове wait_for_stop у объекта actual_repo. Этот метод вернет управление только после того, как дочерняя нить вызовет stop;&lt;/li&gt;
  &lt;li&gt;когда дочерняя нить вызывает stop, то главная нить просыпается, выходит из wait_for_stop, после чего разрушается объект actual_repo;&lt;/li&gt;
  &lt;li&gt;после чего дожидаемся завершения дочерней нити и прекращаем работу.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Фокус здесь в том, что внутри stop условная переменная взводится (вызов notify_one()) без захвата мутекса.&lt;/p&gt;

&lt;p&gt;А это ведет к тому, что главная нить может проснуться и уничтожить объект actual_repo еще до того, как дочерняя нить завершит вызов stop.&lt;/p&gt;

&lt;p&gt;Т.е. деструктор для repo_basic::m_stop_initiated_cv может отработать еще до того, как на дочерней нити завершится вызов m_stop_initiated_cv.notify_one().&lt;/p&gt;

&lt;p&gt;И как раз thread sanitizer и ругается на то, что в главной нити происходит модификация содержимого repo_basic::m_stop_initiated_cv тогда как на дочерней нити мы это содержимое только только прочитали.&lt;/p&gt;

&lt;p&gt;Проблема же оказалась в том, что метод stop, вызванный на дочерней нити, не является атомарным. В нем сперва вызывается try_initiate_stop из базового класса. В этом самом try_initiate_stop захватывается mutex, меняется значение m_status, после чего mutex освобождается. Управление возвращается в метод stop и только после этого взводится m_stop_initiated_cv.&lt;/p&gt;

&lt;p&gt;Именно эта неатомарность и является корнем зла.&lt;/p&gt;

&lt;p&gt;Главная нить в методе wait_for_stop может захватить mutex и проверить m_status как раз в момент, когда на дочерней нити завершился try_initiate_stop, но еще не было обращения к m_stop_initiated_cv. И если такое произойдет, то главная нить уничтожит объект actual_repo еще до того, как на дочерней нити произойдет вызов m_stop_initiated_cv.notify_one().&lt;/p&gt;

&lt;p&gt;А это приведет к тому, что notify_one() будет вызываться уже для убитого объекта.&lt;/p&gt;

&lt;p&gt;Полагаю, на именно на эту проблему мне и указывал thread sanitizer, но я не смог с первого раза разобраться что же идет не так.&lt;/p&gt;

&lt;p&gt;Так что в данном случае thread sanitizer выявил реальную проблему.&lt;/p&gt;

&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#include&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;lt;thread&amp;gt;&lt;/font&gt;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#include&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;lt;mutex&amp;gt;&lt;/font&gt;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#include&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;lt;condition_variable&amp;gt;&lt;/font&gt;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#include&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;lt;chrono&amp;gt;&lt;/font&gt;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#include&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;class&lt;/font&gt;&amp;nbsp;repo_basic&lt;br&gt;
{&lt;br&gt;
&lt;font color=&quot;#ffff60&quot;&gt;protected&lt;/font&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp; std::mutex m_lock;&lt;br&gt;
&amp;nbsp;&amp;nbsp; std::condition_variable m_stop_initiated_cv;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;nbsp;m_status{&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;0&lt;/font&gt;&amp;nbsp;};&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; try_initiate_stop()&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::lock_guard&amp;lt; std::mutex &amp;gt; lock{ m_lock };&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;if&lt;/font&gt;( !m_status )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_status =&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;1&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;return&lt;/font&gt;&amp;nbsp;m_status;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;return&lt;/font&gt;&amp;nbsp;-&lt;font color=&quot;#ffa0a0&quot;&gt;1&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ffff60&quot;&gt;public&lt;/font&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; wait_for_stop()&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::unique_lock&amp;lt; std::mutex &amp;gt; lock{ m_lock };&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_stop_initiated_cv.wait( lock,&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&lt;font color=&quot;#ffff60&quot;&gt;this&lt;/font&gt;]{&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;return&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;0&lt;/font&gt;&amp;nbsp;!= m_status; } );&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
};&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;class&lt;/font&gt;&amp;nbsp;actual_repo :&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;protected&lt;/font&gt;&amp;nbsp;repo_basic&lt;br&gt;
{&lt;br&gt;
&lt;font color=&quot;#ffff60&quot;&gt;public&lt;/font&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;using&lt;/font&gt;&amp;nbsp;repo_basic::wait_for_stop;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; stop()&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;const&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;auto&lt;/font&gt;&amp;nbsp;r =&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;this&lt;/font&gt;-&amp;gt;try_initiate_stop();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;if&lt;/font&gt;(&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;1&lt;/font&gt;&amp;nbsp;== r )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;this&lt;/font&gt;-&amp;gt;m_stop_initiated_cv.notify_one();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
};&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;nbsp;main()&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; std::thread child_task;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;actual_repo repo;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;child_task = std::thread{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&amp;amp;repo]()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;// Take some time to the main thread to call wait_for_stop.&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; std::this_thread::sleep_for( std::chrono::milliseconds{&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;250&lt;/font&gt;&amp;nbsp;} );&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; repo.stop();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;repo.wait_for_stop();&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; child_task.join();&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; std::cout &amp;lt;&amp;lt;&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;successful completion&amp;quot;&lt;/font&gt;&amp;nbsp;&amp;lt;&amp;lt; std::endl;&lt;br&gt;
}&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/6693587729559435771/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/6693587729559435771' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/6693587729559435771'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/6693587729559435771'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/07/progcmultithreading-false-positive.html' title='[prog.c++.multithreading] Интересно, это false positive от thread sanitizer-а или нет?'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-9107636770621905359</id><published>2026-07-03T11:07:53.385+03:00</published><updated>2026-07-03T11:07:53.385+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><category scheme="http://www.blogger.com/atom/ns#" term="Язык Eiffel"/><title type='text'>[prog.eiffel] Сохраню в склерозник пример работы с anchored-типами в Eiffel</title><content type='html'>&lt;p&gt;Есть очень прикольный язык программирования -- Eiffel. А в нем есть очень прикольная фича -- &lt;a href=&quot;https://eao197.narod.ru/better_language/languages/eiffel/0_overview.html#id28&quot;&gt;заякоренные типы (anchored types)&lt;/a&gt;. Давеча пришлось в одном из разговоров про нее вспомнить и набросать небольшой пример, чтобы проверить те или иные предположения.&lt;/p&gt;

&lt;p&gt;У Eiffel-я есть &lt;a href=&quot;https://www.eiffel.org/codeboard&quot;&gt;он-лайн компилятор&lt;/a&gt; (что-то по типу godbolt, wandbox, ideone), но в нем нельзя просто так сохранить сделанное и поделиться публичной ссылкой. Поэтому помещу под кат код написанного примера, просто на память, а то вдруг еще раз потребуется.&lt;/p&gt;

&lt;p&gt;В чем суть примера?&lt;/p&gt;

&lt;p&gt;Есть базовый класс MESSAGE.&lt;/p&gt;

&lt;p&gt;Есть базовый класс ENVELOPE, который хранит в себе MESSAGE. Но класс ENVELOPE написан с использованием MESSAGE в качестве якорного типа. Что позволяет создать наследника SIGNED_ENVELOPE, который хранит уже не просто MESSAGE, а SIGNED_MESSAGE. Но менять унаследованные из ENVELOPE методы не нужно, Eiffel сам разбирается с тем, что в SIGNED_ENVELOPE методы make и change_content получают уже не MESSAGE, а SIGNED_MESSAGE.&lt;/p&gt;

&lt;p&gt;При этом Eiffel что-то может проверить в compile-time. Например, если у нас есть ссылка signed_env с типом SIGNED_ENVELOPE, то в вызов signed_env.change_content мы не может отдать просто ссылку на MESSAGE. Будет ошибка компиляции, компилятор ждет от нас SIGNED_MESSAGE (или наследника SIGNED_MESSAGE).&lt;/p&gt;

&lt;p&gt;Но если у нас есть env типа ENVELOPE и мы env присвоили signed_env (т.е. теперь env ссылается на экземпляр SIGNED_ENVELOPE), то компилятор пропустит передачу обычного MESSAGE в env.change_content. Но ошибка будет диагностирована в run-time с выбросом исключения. Т.е. &quot;обмануть&quot; Eiffel не получится: то, что Eiffel не смог поймать в compile-time, он поймает в run-time.&lt;/p&gt;

&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;

&lt;p&gt;Особенностью Eiffel-я является то, что каждый класс должен помещаться в отдельном файле. Поэтому сколько классов, столько и файлов.&lt;/p&gt;

&lt;p&gt;Файл application.e&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;class&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;APPLICATION&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;inherit&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;ARGUMENTS_32&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
create&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;make&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;feature&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#ffa500&quot;&gt;{&lt;/font&gt;&lt;font color=&quot;#90f020&quot;&gt;NONE&lt;/font&gt;&lt;font color=&quot;#ffa500&quot;&gt;}&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;-- Initialization&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;make&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;-- Run application.&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;local&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;env:&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;ENVELOPE&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;env2:&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;SIGNED_ENVELOPE&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg:&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;MESSAGE&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;do&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;create env.make (create&amp;nbsp;&lt;font color=&quot;#ffa500&quot;&gt;{&lt;/font&gt;&lt;font color=&quot;#90f020&quot;&gt;MESSAGE&lt;/font&gt;&lt;font color=&quot;#ffa500&quot;&gt;}&lt;/font&gt;.make(&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;Hello&amp;quot;&lt;/font&gt;))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;env.examine_content&amp;nbsp;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;create env2.make (create&amp;nbsp;&lt;font color=&quot;#ffa500&quot;&gt;{&lt;/font&gt;&lt;font color=&quot;#90f020&quot;&gt;SIGNED_MESSAGE&lt;/font&gt;&lt;font color=&quot;#ffa500&quot;&gt;}&lt;/font&gt;.make(&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;Bye&amp;quot;&lt;/font&gt;))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;env2.examine_content&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;env := env2&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg := create&amp;nbsp;&lt;font color=&quot;#ffa500&quot;&gt;{&lt;/font&gt;&lt;font color=&quot;#90f020&quot;&gt;SIGNED_MESSAGE&lt;/font&gt;&lt;font color=&quot;#ffa500&quot;&gt;}&lt;/font&gt;.make(&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;222&amp;quot;&lt;/font&gt;)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;env.change_content (msg)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;env.examine_content&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;end&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;end&lt;/font&gt;&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Файл msg.e&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;class&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;MESSAGE&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;br&gt;
create&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;make&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;feature&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;body:&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;STRING&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;make(b:&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;STRING&lt;/font&gt;)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;do&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;body := b&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;end&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;feature&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tell_about_itself&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;do&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;Message body is &#39;&amp;quot;&lt;/font&gt;)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(body)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;&#39;&lt;/font&gt;&lt;font color=&quot;#ffa500&quot;&gt;%N&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;&lt;/font&gt;)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;end&lt;/font&gt;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;end&lt;/font&gt;&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Файл envelope.e&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;class&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;ENVELOPE&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;
create&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;make&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;feature&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg:&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;MESSAGE&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;feature&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;make (m:&amp;nbsp;&lt;font color=&quot;#ffa500&quot;&gt;like&lt;/font&gt;&amp;nbsp;msg)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;do&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg := m&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;end&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;change_content (m:&amp;nbsp;&lt;font color=&quot;#ffa500&quot;&gt;like&lt;/font&gt;&amp;nbsp;msg)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;do&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg := m&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;end&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;examine_content&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;do&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg.tell_about_itself&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;end&lt;/font&gt;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;end&lt;/font&gt;&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Файл signed_msg.e&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;class&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;SIGNED_MESSAGE&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;inherit&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;MESSAGE&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;redefine&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tell_about_itself&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;end&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;
create&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;make&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;feature&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tell_about_itself&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;do&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;SIGNED message body is &#39;&amp;quot;&lt;/font&gt;)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(body)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;&#39;&lt;/font&gt;&lt;font color=&quot;#ffa500&quot;&gt;%N&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;&lt;/font&gt;)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;end&lt;/font&gt;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;end&lt;/font&gt;&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Файл signed_envelope.e&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;class&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;SIGNED_ENVELOPE&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;inherit&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;ENVELOPE&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;redefine&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;end&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;
create&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;make&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;feature&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg:&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;SIGNED_MESSAGE&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;end&lt;/font&gt;&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/9107636770621905359/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/9107636770621905359' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/9107636770621905359'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/9107636770621905359'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/07/progeiffel-anchored-eiffel.html' title='[prog.eiffel] Сохраню в склерозник пример работы с anchored-типами в Eiffel'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-7252333375934613413</id><published>2026-07-01T08:49:21.601+03:00</published><updated>2026-07-01T08:49:21.601+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Кино"/><category scheme="http://www.blogger.com/atom/ns#" term="О жизни"/><category scheme="http://www.blogger.com/atom/ns#" term="Ссылки"/><title type='text'>[life.cinema] Очередной кинообзор (2026/06)</title><content type='html'>&lt;p&gt;Традиционный обзор отсмотренных фильмов. Традиционно в начале каждого из списков идет то, что понравилось больше, а в конце то, что понравилось меньше.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Фильмы&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/183697/annot/&quot;&gt;Грязные деньги (In The Grey, 2026)&lt;/a&gt;. Тупо, прямолинейно, приторно красиво, но бодренько. За неимением лучшего можно посмотреть, чтобы скоротать вечер.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/202061/annot/&quot;&gt;Мандалорец и Грогу (The
  Mandalorian and Grogu, 2026)&lt;/a&gt;. Отличная сказочка для семейного просмотра с детьми младшего школьного возраста. Разве что немного мрачноватая. В любом случае кино абсолютно детское, взрослым к нему всерьез относиться не стоит.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/ros/194909/annot/&quot;&gt;Коммерсант (2026)&lt;/a&gt;. Можно смотреть. Но меня раздражало две вещи: Александр Петров в роли Александра Петрова и клиповый монтаж из очень коротких сцен. Так что фильм хорош рассказанной историей, но исполнение могло бы быть гораздо лучше.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/euro/200945/annot/&quot;&gt;Ограбить Лондон (Fuze, 2025)&lt;/a&gt;. Ничего не ждал от фильма вообще, думал обычная третьесортная поделка. Оказалось на удивление хорошо. Т.е. это далеко не шедевр, уровнем чуть повыше среднего, но на фоне всего остального шлака, прям глоток свежего воздуха.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/asia/201659/annot/&quot;&gt;Охота за тенью (Shadow&#39;s Edge, 2025)&lt;/a&gt;. Очень бодрая сказочка. Джеки Чану мое почтение.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/202995/annot/&quot;&gt;Мусорщик (Wasteman, 2025)&lt;/a&gt;. Мне показалось, что это неплохая тюремная драма. Но, во-первых, понятия не имею насколько это достоверно. И, во-вторых, смотрел на скорости 1.25, потому что на нормальной скорости было ну как-то совсем уж нудно. Тем не менее, развязка понравилась.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Сериалы&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/ros/170781/annot/&quot;&gt;Ночной (первый сезон, 2023)&lt;/a&gt;. В первой серии раздражала пара персонажей, которые выглядели на своих ролях чужеродно. Но от них быстро избавились и дальше все пошло гораздо лучше. В итоге сериал понравился (за исключением первой серии).&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/ros/189543/annot/&quot;&gt;Заложник (первый сезон, 2026)&lt;/a&gt;. Начало бодрое, затем все скатилось в какую-то сопливую Санта-Барбару. При этом сериальная затянутость ощущается даже не смотря на то, что в сезоне всего шесть серий. Ну и отдельно не понравилось то, что повествование оборвали на полуслове с явным намерением продолжить в следующем сезоне. Снято, однако, качественно. К картинке претензий нет.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/205827/annot/&quot;&gt;Бухта вдов (Widow&#39;s Bay, первый сезон, 2026)&lt;/a&gt;. Скучно, что-то реально интересное и удивляющее происходит очень редко. Сама история толком ничем не закончилась, тут нам явно предлагают ждать следующих сезонов. Купился на хвалебные отзывы в Интернете, по итогу не понравилось, жаль потраченного времени.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/205498/annot/&quot;&gt;Красота (The Beauty, первый сезон, 2026)&lt;/a&gt;. Первые серии хорошие -- тут и экшен, и драйв, и многообещающая завязка. Затем темп повествования потерялся, драйв улетучился. Финала как такового у первого сезона нет. Создатели обрывают происходящее буквально на полуслове. Возможно, когда выйдет второй сезон, и история достойным образом разовьется, то этот сериал можно будет хоть как-то оценить. Но не в его текущем виде.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Не смог досмотреть&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/206187/annot/&quot;&gt;Опасные отношения (Over Your Dead Body, 2026)&lt;/a&gt;. Это ремейк фильма &lt;a href=&quot;https://www.kinopoisk.ru/film/1439939/&quot;&gt;Поездка (I onde dager, 2021)&lt;/a&gt;. И, как по мне, так оригинал смотреть интереснее, в нем как-то все более естественно.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/200846/annot/&quot;&gt;Дьявол носит Prada 2 (The Devil Wears Prada 2, 2026)&lt;/a&gt;. Происходящее на экране невозможно воспринимать серьезно.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Вне категории&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/ros/190353/annot/&quot;&gt;Ангелы Ладоги (2026)&lt;/a&gt;. Такое впечатление, что фильм рассчитан совсем на другое поколение. Возможно, на современных детей 8-10 лет. Как мне его оценивать непонятно.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/ros/135207/annot/&quot;&gt;Литвяк (2026)&lt;/a&gt;. С одной стороны, хороший военный фильм, без пьяных командиров, трусливых комиссаров и неадекватных СМЕРШев с наганами в руках. С другой стороны, рассказанная история нисколько не зацепила, главные герои показаны так, что не успеваешь к ним прикипеть так, чтобы их гибель заставляла тебя переживать именно потому, что ты успел проникнуться к ним какими-то чувствами. Кроме того, напрягает и раздражает то, насколько много сцен в фильме снято на фоне зеленого экрана. В общем, не знаю, как оценивать. За попытку снять хороший фильм о войне -- отлично, за исполнение -- незачет 🙁&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/7252333375934613413/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/7252333375934613413' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/7252333375934613413'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/7252333375934613413'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/07/lifecinema-202606.html' title='[life.cinema] Очередной кинообзор (2026/06)'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-3980431183228838433</id><published>2026-06-29T06:47:28.424+03:00</published><updated>2026-06-29T06:47:28.424+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Мысля давеча посетила"/><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><category scheme="http://www.blogger.com/atom/ns#" term="Поток сознания"/><category scheme="http://www.blogger.com/atom/ns#" term="язык C++"/><title type='text'>[prog.thoughts] Начинаю думать, что бесстековые короутины в C++ следовало делать чуть иначе</title><content type='html'>&lt;p&gt;Прежде чем перейти к заявленной в заголовке теме небольшое погружение в контекст. Появились небольшие ресурсы для того, чтобы попробовать добавить в SObjectizer поддержку бесстековых короутин из C++20.&lt;/p&gt;

&lt;p&gt;Изначально я планировать только позволить пользователю описывать event-handler-ы, в которых можно было бы делать co_await. Но по мере продумывания способов реализации столкнулся с тем, что не имею на руках никаких механизмов запуска внешних по отношению к SO-5 короутин. А это нужно, чтобы проверить, что из event-handler-а можно дернуть, скажем, короутину из Asio, и когда она завершится, управление должным образом вернется event-handler-у.&lt;/p&gt;

&lt;p&gt;И тогда появилась мысль сделать сперва возможность асинхронной работы с mchain-ами. Сейчас в SO-5 есть синхронные версии receive и select, а что, если предоставить их асинхронные версии? Тогда в event-handler-е можно было бы написать что-то вроде:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
so_5::event_handler_task_t&lt;br&gt;
some_agent::evt_some_handler( mhood_t&amp;lt;some_msg&amp;gt; cmd )&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;auto&lt;/font&gt;&amp;nbsp;result =&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;co_await&lt;/font&gt;&amp;nbsp;so_5::async_receive( so_5::from( test_chain ), ... );&lt;br&gt;
&amp;nbsp;&amp;nbsp;...&lt;br&gt;
}
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Тогда отправляя (или не отправляя) сообщения в тестовый канал я бы мог тестировать поведение event-handler-ов.&lt;/p&gt;

&lt;p&gt;Но стоило погрузиться в задачу создания асинхронных версий async_receive и async_select-а, как стало возникать подспудное подозрение, что с C++ными бесстековыми короутинами что-то не так. И я не говорю про их мудреность (это тема отдельного разговора). Было ощущение, что несмотря на заумность и гибкость C++ных короутин в них все-таки чего-то важного не хватает.&lt;/p&gt;

&lt;p&gt;А выкристаллизовалось понимание чего же именно не хватает в процессе знакомства с &lt;a href=&quot;https://github.com/cppalliance/capy&quot;&gt;библиотекой Capy&lt;/a&gt; (которую сейчас пытаются запихнуть в Boost). Как раз авторы данной библиотеки четко выделили проблему, которую не удавалось нащупать мне. И попробовали ее решение прикрутить сбоку синей изолентой.&lt;/p&gt;

&lt;p&gt;Суть в том, что в интерфейсе короутин нет способов явно указать на каком рабочем контексте короутина должна быть продолжено. Лично мне не очевидно кто и где будет вызывать resume для coroutine_handle когда короутина окажется готова к возобновлению.&lt;/p&gt;

&lt;p&gt;Видимо, авторы короутин в C++20 предполагали, что когда короутины применяются в рамках одного фремворка, где все короутины обслуживаются одним и тем же механизмом, такой проблемы нет в принципе. Однако, если возникает необходимость подружить сразу несколько разных реализаций короутин, вот тогда эта проблема встает в полный рост.&lt;/p&gt;

&lt;p&gt;В Capy ее предлагают решать за счет введения специальной сущности -- &lt;a href=&quot;https://develop.capy.cpp.al/capy/4.coroutines/4c.executors.html&quot;&gt;Executor-а&lt;/a&gt; и за счет изменения интерфейса &lt;a href=&quot;https://develop.capy.cpp.al/capy/4.coroutines/4d.io-awaitable.html&quot;&gt;сущности Awaiter-а&lt;/a&gt;: метод await_suspend для Awaiter-а вместо одного аргумента получает два:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
std::coroutine_handle&amp;lt;&amp;gt; await_suspend(std::coroutine_handle&amp;lt;&amp;gt; h, io_env&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;const&lt;/font&gt;* env);&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;И во втором параметре передаются вещи, которые могут потребоваться короутине (и ее дочерним короутинам): executor, stop_token, allocator.&lt;/p&gt;

&lt;p&gt;За счет того, что в env есть ссылка на executor, короутина может сохранить этот executor и, когда возникает возможность возобновить работу, короутина обращается к этому executor-е с просьбой обеспечить это возобновление на должном контексте.&lt;/p&gt;

&lt;p&gt;Это как раз то, чего мне не хватало для реализации асинхронных версий receive/select. Я уже сам пришел к мысли о том, что в асинхронный receive нужно передавать какой-то coro_scheduler, который будет отвечать за то, чтобы возобновить приостановленный receive/select именно там, где это разрешено. Например, если receive вызывается из event-handler-а, то это могло бы выглядеть так:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#90f020&quot;&gt;auto&lt;/font&gt;&amp;nbsp;result =&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;co_await&lt;/font&gt;&amp;nbsp;so_5::receive(&lt;br&gt;
&amp;nbsp;&amp;nbsp;so_5::from( test_ch ).resume_by(&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;this&lt;/font&gt;-&amp;gt;so_coro_scheduler_for_this_agent() )...,&lt;br&gt;
&amp;nbsp;&amp;nbsp;... );
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;А если mchain используется вне агентов, то может быть что-то вроде:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
so_5::cpp_coro::this_thread_scheduler_t coro_scheduler;&lt;br&gt;
coro_scheduler.sync_wait(&lt;br&gt;
&amp;nbsp;&amp;nbsp;[&amp;amp;coro_scheduler, &amp;amp;ch]() -&amp;gt; so_5::cpp_coro::async_receive_task_t {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;co_await&lt;/font&gt;&amp;nbsp;so_5::receive(&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;so_5::from( ch ).resume_by( coro_scheduler )..., ...);&lt;br&gt;
&amp;nbsp;&amp;nbsp;} );&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;И каково же было мое удивление, когда знакомясь с библиотекой Capy увидел, что ее авторы тоже пришли к явной передаче executor-а.&lt;/p&gt;

&lt;p&gt;Но, повторюсь, и подход Capy, и мои попытки придумать некий условный coro_scheduler для SObjectizer-а -- это попытки прикрутить решение сбоку посредством синей изоленты.&lt;/p&gt;

&lt;p&gt;Ничего этого придумывать бы не пришлось, если бы в самом языке изначально короутины были бы сделаны чуть иначе.&lt;/p&gt;

&lt;p&gt;Например, чтобы обращение к co_await можно было параметризовать. Скажем, передавать executor/scheduler непосредственно в co_await:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ffff60&quot;&gt;co_await&lt;/font&gt;(executor) some_task();&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;И чтобы этот executor передавался бы параметром в await_resume. Может быть в виде ссылки на некоторый специальный объект environment, как это делается в Capy.&lt;/p&gt;

&lt;p&gt;Есть у меня подозрение, что с такой явной передачей executor-ов в co_await, код с короутинами и писать, и читать было бы гораздо проще.&lt;/p&gt;

&lt;p&gt;PS. Раз уж заговорил про попытку добавить поддержку короутин в SO-5, то слегка обозначу текущий статус. Пока до чего-то работающего еще далеко. Пытаюсь двигаться от простого к более сложному. Сперва хочу попробовать сделать асинхронную версию receive/select. Чтобы с ее помощью перейти к поддержке event-handler-ов в виде короутин. Затем, возможно, попробую погрузиться еще глубже, чтобы разрешить короутины в роли обработчиков входящих сообщений в receive/select (если это вообще возможно). Работы много, ресурсов мало, движется все очень медленно. Поэтому я сам в течении ближайших пару месяцев никаких значимых результатов не жду.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/3980431183228838433/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/3980431183228838433' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/3980431183228838433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/3980431183228838433'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/06/progthoughts-c.html' title='[prog.thoughts] Начинаю думать, что бесстековые короутины в C++ следовало делать чуть иначе'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-8905678328735108155</id><published>2026-06-15T10:23:37.893+03:00</published><updated>2026-06-15T11:09:15.509+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><category scheme="http://www.blogger.com/atom/ns#" term="Павбывавбы"/><category scheme="http://www.blogger.com/atom/ns#" term="Поток сознания"/><category scheme="http://www.blogger.com/atom/ns#" term="язык C++"/><title type='text'>[prog.c++.imho] Не согласен с постулатами пропозала P3097 (контракты для виртуальных методов)</title><content type='html'>&lt;p&gt;Комитет по стандартизации C++ продолжает творить дичь. Сперва в C++26 были включены кастрированные контракты (нет ключевого слова old в постусловиях, нет контрактов для виртуальных методов, нет инвариантов для экземпляров классов и циклов). Для людей, знакомых с Eiffel, контракты из C++26 выглядят как &quot;мы не осилили тему полностью, поэтому впихнули в стандарт какой-то эрзац с надеждой, что со временем допилим&quot;. Не хочу обсуждать зачем нужен эрзац вместо нормального продукта. Просто перейду к следующей дичи.&lt;/p&gt;

&lt;p&gt;Далее в C++29 включили предложение &lt;a href=&quot;http://wg21.link/p3097&quot;&gt;P3097&lt;/a&gt;, которое описывает контракты для виртуальных методов классов. И авторы этого предложения, как по мне, покусились на святое: на сформулированное много-много лет назад для Design By Contract в Eiffel-е требование о том, что производный класс может только ослабить предусловния и ужесточить постусловия, но не наоборот.&lt;/p&gt;

&lt;p&gt;И вот авторы пропозала почему-то пришли к выводу, что C++ настолько особенный, что в нем можно это требование послать в пешее эротическое.&lt;/p&gt;

&lt;p&gt;На протяжении нескольких страниц пропозала эти люди пытаются приводить &quot;аргументацию&quot; своей точки зрения. Меня эта аргументация не убеждает от слова совсем. Скорее наводит на мысль о том, что люди толком не понимают тему, о которой пытаются рассуждать и, скорее всего, не имеют опыта разработки на языках с поддержкой Design By Contract (в первую очередь на Eiffel-е, на который в данной теме и следует равняться).&lt;/p&gt;

&lt;p&gt;Первые эмоции после беглого прочтения P3097 я &lt;a href=&quot;https://www.linkedin.com/feed/update/urn:li:activity:7471797904974831616&quot;&gt;уже постил в LinkedIn&lt;/a&gt;. Сейчас попробую пройтись по нескольким фразам и примерам оттуда, чтобы как-то обосновать свое негативное отношение.&lt;/p&gt;

&lt;hr/&gt;

&lt;p&gt;В разделе &quot;3.2 Adoptability in legacy code&quot; есть интересный заход:&lt;/p&gt;

&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;

&lt;blockquote&gt;&lt;p&gt;In other words, contract assertions must not break an existing program. While false negatives are inevitable, false positives must never be forced on users by the language
design.&lt;/p&gt;
&lt;p&gt;These requirements are not unique to contract checking; they apply equally to any tool
intended to detect bugs in existing code, such as compiler warnings or static analysis tools.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Мне он кажется в принципе не правильным.&lt;/p&gt;

&lt;p&gt;Во-первых, если мы внедряем механизм, который позволяет выявлять проблемы в коде (а DbC выявляет проблемы на уровне проектирования классов, их взаимосвязей и взаимодействия), то это хорошо. Это цель внедряемого механизма. Поэтому если мы с помощью контрактов формально зафиксировали ожидания, которые ранее были неформальными, и у нас что-то поломалось, значит контракты нашли проблему о которой мы и не подозревали. Следовательно, проблема требует решения (либо в виде переделки кода, либо в переформулировании контрактов).&lt;/p&gt;

&lt;p&gt;Во-вторых, а почему бы не применить эту формулировку к такой штуке, как standard library hardening, которую также внедрили в C++26. У нас же теперь обращения к operator[] для std::span будут проверять индекс. И допустим, у нас был код:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#90f020&quot;&gt;unsigned&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;long&lt;/font&gt;&amp;nbsp;check_sum(&lt;font color=&quot;#90f020&quot;&gt;const&lt;/font&gt;&amp;nbsp;std::span&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;const&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;char&lt;/font&gt;&amp;gt; &amp;amp; s)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;unsigned&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;long&lt;/font&gt;&amp;nbsp;sum =&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;0&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;for&lt;/font&gt;(std::&lt;font color=&quot;#90f020&quot;&gt;size_t&lt;/font&gt;&amp;nbsp;i =&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;0&lt;/font&gt;; i &amp;lt;= s.size(); ++i)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sum +=&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;static_cast&lt;/font&gt;&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;unsigned&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;char&lt;/font&gt;&amp;gt;(s[i]);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;return&lt;/font&gt;&amp;nbsp;sum;&lt;br&gt;
}&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;const&lt;/font&gt;&amp;nbsp;std::string s{&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;Hello, world&amp;quot;&lt;/font&gt;&amp;nbsp;};&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;const&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;char&lt;/font&gt;&amp;nbsp;* l =&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;Hello, world&amp;quot;&lt;/font&gt;;&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;auto&lt;/font&gt;&amp;nbsp;ch1 = check_sum(s);&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;auto&lt;/font&gt;&amp;nbsp;ch2 = check_sum(l);&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Этот код работал годами поскольку в позиции s[s.size()] хранится неявно добавляемый к содержимому строки 0-символ. Мы совершали ошибку индексации, но нам это прощалось из-за особенностей представления содержимого нуль-терминированной строки и из-за того, что лишнее нулевое значение не влияет на данный алгоритм, а в std::span не было проверки границ для operator[]&lt;/p&gt;

&lt;p&gt;Но в режиме hardening мы здесь получим исключение (или вообще принудительную терминацию программы). А ведь это же тот самый &quot;breaking an existing program&quot; которого следует избегать. Но для standard library hardening мы на breaking смело идем, а вот в случае с контрактами почему-то идти не должны. В воздухе отчетливо ощущается запах двойных стандартов.&lt;/p&gt;

&lt;p&gt;Как по мне, так при внедрении некоторых фич в принципе нельзя оглядываться на легаси код. Вспомнить хотя бы всратые модули, добавленные в C++20. Так почему при внедрении контрактов нужно апеллировать к коду, в котором контрактов нет?&lt;/p&gt;

&lt;hr/&gt;

&lt;p&gt;В разделе &quot;4.8 Narrowing preconditions, widening postconditions&quot; приводится пример на котором авторы P3097 пытаются оправдать своей тезис о том, что в мире С++ нужно отойти от &quot;ослабить предусловия, ужесточить постусловия&quot; в пользу &quot;ужесточить предусловия, ослабить постусловия&quot;.&lt;/p&gt;

&lt;p&gt;Типа есть класс:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#90f020&quot;&gt;class&lt;/font&gt;&amp;nbsp;Image {&lt;br&gt;
&lt;font color=&quot;#ffff60&quot;&gt;public&lt;/font&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;virtual&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&amp;nbsp;render()&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;const&lt;/font&gt;;&lt;br&gt;
};&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;и есть его наследник:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#90f020&quot;&gt;class&lt;/font&gt;&amp;nbsp;GPUImage :&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;public&lt;/font&gt;&amp;nbsp;Image {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;bool&lt;/font&gt;&amp;nbsp;readyToRender =&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;false&lt;/font&gt;;&lt;br&gt;
&lt;font color=&quot;#ffff60&quot;&gt;public&lt;/font&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;bool&lt;/font&gt;&amp;nbsp;prepare() {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;// upload data to GPU, handle errors…&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;readyToRender =&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;true&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;return&lt;/font&gt;&amp;nbsp;readyToRender;&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&amp;nbsp;render()&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;const&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;override&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pre (readyToRender);&lt;br&gt;
};
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;В классе наследнике предусловие для метода render ужесточается. Авторы пропозала считают этот пример нормальным и используют его в качества аргумента в пользу постулата, что в С++ нам нужно иметь возможность &quot;ужесточать предусловия, ослаблять постусловия&quot;.&lt;/p&gt;

&lt;p&gt;Я же здесь вижу непонимание смысла контрактов в случае наследования.&lt;/p&gt;

&lt;p&gt;Контракт в базовом классе задает требования для всех производных классов. Если какой-то класс не может этим требованиям соответствовать, то либо у вас проблемы с формулированием контрактов, либо вы от иерархии наследования хотите чего-то странного.&lt;/p&gt;

&lt;p&gt;В данном конкретном примере класс GPUImage вообще не должен быть наследником Image (по крайней мере публичным). И возможное решение описанной &quot;проблемы&quot; не в изменении контракта, а в другой реализации GPUImage. Например, вот в такой:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#90f020&quot;&gt;class&lt;/font&gt;&amp;nbsp;GPUImage {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;class&lt;/font&gt;&amp;nbsp;ActualImage :&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;public&lt;/font&gt;&amp;nbsp;Image {...};&lt;br&gt;
&amp;nbsp;&amp;nbsp; std::optional&amp;lt;ActualImage&amp;gt; actualImage;&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;// Will be initialized in prepare.&lt;/font&gt;&lt;br&gt;
&lt;font color=&quot;#ffff60&quot;&gt;public&lt;/font&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;bool&lt;/font&gt;&amp;nbsp;prepare() {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;actualImage.emplace(...);&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;// upload data to GPU, handle errors…&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;return&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;true&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; Image &amp;amp; getActualImage()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pre (actualImage.has_value())&lt;br&gt;
&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;return&lt;/font&gt;&amp;nbsp;*actualImage;&lt;br&gt;
&amp;nbsp;&amp;nbsp; }&lt;br&gt;
};&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;В этом случае мы не можем отдать экземпляр GPUImage туда, где ждут Image, поскольку GPUImage не выполняет требования контракта. Но мы можем вызвать GPUImage.getActualImage(), чтобы получить актуальную реализацию интерфейса Image.&lt;/p&gt;

&lt;p&gt;И вот уже к getActualImage() мы можем применить любой контракт, в том числе и тот, что getActualImage() может вызываться только после того, как будет вызван prepare().&lt;/p&gt;

&lt;hr/&gt;

&lt;p&gt;В разделе &quot;4.9 Multiple inheritance&quot; приводится пример с классами EvenComputer и OddComputer:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#90f020&quot;&gt;struct&lt;/font&gt;&amp;nbsp;EvenComputer {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;virtual&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;nbsp;compute(&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;nbsp;x)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pre(isEven(x))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;post(r : isEven(r));&lt;br&gt;
};&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;struct&lt;/font&gt;&amp;nbsp;OddComputer {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;virtual&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;nbsp;compute(&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;nbsp;x)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pre(isOdd(x))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;post(r : isOdd(r));&lt;br&gt;
};&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Мол если мы отнаследуемся от обоих классов сразу и сделаем общий compute, то у нас будет нарушение контрактов из базовых классов. Поэтому нужно уметь отменять унаследованные контракты, по типу:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#90f020&quot;&gt;struct&lt;/font&gt;&amp;nbsp;Identity : EvenComputer, OddComputer {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;nbsp;compute(&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;nbsp;x)&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;override&lt;/font&gt;&amp;nbsp;{&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;return&lt;/font&gt;&amp;nbsp;x; }&lt;br&gt;
};&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Как по мне так это пример ущербности поддержки множественного наследования в C++, а не признак необходимости нарушить правило &quot;ослабление предусловий, ужесточение постусловий&quot;.&lt;/p&gt;

&lt;p&gt;В Eiffel, как в языке, где к проблемам наследования отнеслись более тщательно, чем в C++ (т.е. подумали, а не сделали &quot;как получилось&quot;), есть возможность переименования в производном классе метода из базового класса. А в C++, увы, такой возможности нет. Поэтому в C++ мы имеем то безобразие, которое видно в этой самой структуре Identity.&lt;/p&gt;

&lt;p&gt;Будь в C++ гипотетическая конструкция rename, то данный пример можно было бы переписать так:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#90f020&quot;&gt;struct&lt;/font&gt;&amp;nbsp;Identity : EvenComputer, OddComputer {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;rename&lt;/font&gt; EvenComputer::compute &lt;font color=&quot;#ffff60&quot;&gt;as&lt;/font&gt; even_compute;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;rename&lt;/font&gt; OddComputer::compute &lt;font color=&quot;#ffff60&quot;&gt;as&lt;/font&gt; odd_compute;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;// Это уже метод Identity, а не переопределение унаследованных&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;// методов compute.&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;nbsp;compute(&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;nbsp;x) {&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;return&lt;/font&gt;&amp;nbsp;x; }&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ffff60&quot;&gt;private&lt;/font&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;// А вот это уже переопределение.&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;nbsp;even_compute(&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;nbsp;x)&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;override&lt;/font&gt;&amp;nbsp;{&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;return&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;this&lt;/font&gt;-&amp;gt;compute(x); }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;nbsp;odd_compute(&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;nbsp;x)&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;override&lt;/font&gt;&amp;nbsp;{&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;return&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;this&lt;/font&gt;-&amp;gt;compute(x); }&lt;br&gt;
};&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;В этом случае для каждого унаследованного метода compute контракты из базового типа сохранились бы. Только контракт EvenComputer::compute теперь применяется не к Identity::compute, а к Identity::even_compute. И вот в таком случае:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font face=&quot;monospace&quot;&gt;
&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&amp;nbsp;use_computer(EvenCompute &amp;amp; c) { c.compute(&lt;font color=&quot;#ffa0a0&quot;&gt;0&lt;/font&gt;); }&lt;br&gt;
&lt;br&gt;
Identity my_computer;&lt;br&gt;
use_computer(my_computer);&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Внутри use_computer вызывался бы метод Identity::even_compute.&lt;/p&gt;

&lt;p&gt;Лично мне в C++ такого rename не хватает и без контрактов. И если бы rename в язык ввели, то это бы помогло и контрактам, и не только.&lt;/p&gt;

&lt;p&gt;Поэтому в данном конкретном случае авторы P3097 увидели лишь часть проблемы, неверно ее идентифицировали и, соответственно, стали решать неправильно. Дело не в контрактах, а в ущербности множественного наследования в C++. А бороться с этой ущербностью посредством каких-то специальных контрактов, придуманных под якобы &quot;особенности C++&quot;, это очень и очень странный подход, как по мне.&lt;/p&gt;

&lt;hr/&gt;

&lt;p&gt;На самом деле при чтении пропозала (недостаточно внимательном, каюсь) у меня отторжение вызывала вся аргументация авторов. Не исключено, что я мог бы поспорить с каждым из &quot;аргументов&quot;. Но уж извините, не располагаю достаточным временем, чтобы делать это.&lt;/p&gt;

&lt;p&gt;Общее впечатление: у авторов пропозала нет достаточного опыта работы с языками с поддержкой Design By Contract. И, в первую очередь, с Eiffel. А без такого опыта рассуждения о якобы проблемах DbC и уникальности C++ -- это как из анекдота про &quot;Рабинович напел&quot;.&lt;/p&gt;

&lt;p&gt;Поэтому я категорически не согласен с тем, что от принципа &quot;ослаблять предусловия, ужесточать постусловия&quot; нужно отказываться. Тем более в сторону &quot;ужесточать предусловия, ослаблять постусловия&quot;. Это выглядит как переворачивание DbC с ног на голову.&lt;/p&gt;

&lt;p&gt;Не надо так. Не нужно окончательно превращать C++ в помойку из переусложненных концепций (хватит нам короутин, модулей и экзекуторов). Есть опыт Eiffel, уже почти сорокалетний(!!!), но... Но даже так вы сделать не можете (если думаете, что можете, посмотрите еще раз на то, что есть в Eiffel и то, что &quot;есть&quot; в С++26). Однако умничаете и изобретаете велосипед с квадратными колесами вместо того, чтобы научиться ездить на обычном.&lt;/p&gt;

&lt;p&gt;Фокус с контрактами в том, что это такая же фича в распоряжении разработчика, как наследование, исключения и noexcept, перегрузка функций и операторов. Это значит, что контрактами нужно научиться пользоваться точно так же, как и другими возможностями языка. Что с контрактами точно так же будет и перебор (когда контракты делают слишком жесткими и пихают куда ни попадя), и недостаточное использование (когда от контрактов отказываются по надуманным причинам). А это значит, что разработчики будут совершать ошибки, эти ошибки затем придется устранять и это нормальный процесс. Такой же нормальный, как, например, впихивание noexcept куда ни попадя с последующим пересмотром и отказом от части noexcept.&lt;/p&gt;

&lt;p&gt;Так что нужно будет учиться пользоваться контрактами. И тот факт, что в Eiffel этим занимаются уже много десятков лет но при этом от принципа &quot;ослаблять предусловия, ужесточать постусловия&quot; там не отказались, говорит о многом.&lt;/p&gt;

&lt;p&gt;Посему не нужно изобретать велосипед с квадратными колесами только потому, что вам C++ кажется каким-то особенным языком, в котором почему-то не работает то, что работает в Eiffel. Вам, скорее всего, кажется. Но из-за того, что вы свои заблуждения протолкнули в стандарт, с этим теперь придется жить нам всем, даже тем, кто не разделяет вашей убежденности. Как с модулями, которые тоже кому-то казались хорошей идеей. Или как со спецификатором throw в C++98.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/8905678328735108155/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/8905678328735108155' title='Комментарии: 4'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/8905678328735108155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/8905678328735108155'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/06/progcimho-p3097.html' title='[prog.c++.imho] Не согласен с постулатами пропозала P3097 (контракты для виртуальных методов)'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-7112399103379867100</id><published>2026-06-12T17:51:46.788+03:00</published><updated>2026-06-12T17:51:46.788+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="SObjectizer"/><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><category scheme="http://www.blogger.com/atom/ns#" term="О работе"/><title type='text'>[prog.c++] Похоже, что SObjectizer-5 будет использоваться в еще одном проекте</title><content type='html'>&lt;p&gt;Больше двух лет сотрудничаю с интересным проектом. Занимался в рамках этого проекта разными задачами, начинал вообще с замены C++ REST SDK на RESTinio, а потом пошло поехало по нарастанию сложности 😎. Не все из этого было связано с многопоточностью, но многое.&lt;/p&gt;

&lt;p&gt;Многопоточность здесь самая обычная -- std::thread, std::mutex, std::condition_variable, немного std::atomic-ов. Ну и специфика больше про параллельную обработку данных, нежели про событийно-ориентированное программирование.&lt;/p&gt;

&lt;p&gt;Местами об отсутствии SO-5 в проекте приходилось жалеть, но, по большому счету, всерьез только один раз. Мне кажется, что та задачка на агентах решалась бы проще, чем на std::thread. Плюс еще пара-тройка мест, где простой агент с периодическим сообщением, на мой взгляд, оказался бы практичнее, чем выделенная нить с ручным циклом вокруг std::this_thread::sleep_for. Т.е. в недавнем прошлом от SO-5 полезный выхлоп вряд ли был заметным.&lt;/p&gt;

&lt;p&gt;Однако, не так давно в проекте появился фрагмент, сделанный на базе отличной (тут я совершенно серьезно) маленькой библиотеки &lt;a href=&quot;https://github.com/taskflow/taskflow&quot;&gt;Taskflow&lt;/a&gt;. Этот кусочек касался координации параллельной обработки информации. Представьте себе, что у вас в памяти несколько связанных таблиц и нужно собрать суммы некоторых столбцов этих таблиц. При этом если в какой-то ячейке одной таблицы стоит ссылка на регион другой таблицы, то в качестве значения ячейки нужно взять сумму этого региона. А если в этом регионе есть ссылки на регионы других таблиц, то процедуру нужно повторить рекурсивно.&lt;/p&gt;

&lt;p&gt;Это не точная формулировка задачи, но некоторое вполне уместное приближение.  Делать это на больших объемах данных в один поток грустно по скорости, а распараллелить не так-то и просто (есть нюансы, в которые не могу вдаваться).&lt;/p&gt;

&lt;p&gt;Такое распараллеливание средствами Taskflow было сделано, но некоторый осадочек остался:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;в Taskflow нет встроенной поддержки таймеров. Одна из идей о том как оптимальнее поделить общий объем работы на отдельные кусочки базировалась на том, чтобы контролировать процесс через некоторые интервалы времени. Типа начнем считать на текущем треде, но поставим отложенную на 250ms задачу. Если к моменту ее запуска вычисление не завершится, то задача возьмет на себя часть оставшейся работы. Если же вычисление успеет закончится, то надобность в отложенной задаче отпадет. Только вот провалидировать эту идею из-за отсутствия таймеров в Taskflow сходу не получилось;&lt;/li&gt;

  &lt;li&gt;не был понятно как в Taskflow реализовать квотирование имеющихся ресурсов для того, чтобы одно вычисление не захватило все ресурсы себе, а оставшиеся вычисления сидели бы на &quot;голодном пайке&quot;. При этом на горизонте маячит фича по приоритетам вычислений, т.е. каким-то высокоприоритеным вычислениям такая узурпация ресурсов разрешается, а вот низкоприоритетным -- нет.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Возможно, все это можно было бы сделать и средствами Taskflow, если в достаточной степени изучить ее возможности и детали реализации. Но попутно стали всплывать и другие моменты.&lt;/p&gt;

&lt;p&gt;Например, при обработке запроса от пользователя выясняется, что часть информации оказывается устаревшей и должна быть удалена. Но удалять ее прямо здесь и сейчас не выгодно, более важно отправить ответ на запрос как можно быстрее, а с удалением разбираться уже потом, в более удобное время. В случае с SObjectizer-овскими агентами подобное решается элементарно: заводится агент, который живет на собственном рабочем контексте (возможно на треде с более низким приоритетом) и который реагирует на команды удаления очередной порции устаревших данных. Когда при обработке запроса выясняется, что часть данных устарела, то этому агенту посылается команда, а обработка запроса продолжается дальше.&lt;/p&gt;

&lt;p&gt;Или, к примеру, запускается какая-то длительная операция (например, выгрузка части данных на диск). Сейчас для этой операции стартует отдельный тред, на котором операция выполняется, после чего тред завершается. Но плохо то, что таких тредов в какой-то момент может стать слишком много. Лучше бы их как-то координировать. И тут кажется, что сделать такого координатора на базе одного агента-менеджера и нескольких агентов-исполнителей несколько проще, чем посредством некой общей структуры данных, защищенной mutex-ом.&lt;/p&gt;

&lt;p&gt;В общем, набралась некая критическая масса соображений о том, что в тех или иных местах SO-5 мог быть удобнее. Поэтому решили попробовать переписать распараллеливание вычислений. Вроде бы получилось не хуже, чем на базе Taskflow. Посему эксперимент по внедрению SO-5 продолжится.&lt;/p&gt;

&lt;p&gt;Не знаю, приживется ли SO-5 в проекте окончательно. Развитие идет динамично и у команды очень легкое отношение к включению или изъятию тех или иных зависимостей. Это я с большой осторожностью отношусь к тому что включать, а что нет, и могу долго раздумывать над тем, можно ли обойтись без какой-нибудь внешней библиотеки. Но здесь ребята более шустрые и рисковые -- если подвернулось что-то потенциально полезное, то сходу добавили. Если не оправдало себя, то не менее быстро выбросили 🙂&lt;/p&gt;

&lt;p&gt;Так что может быть и SO-5 через месяц-другой-третий постигнет участь Taskflow. Поживем -- увидим. Сам я к этому отношусь спокойно: будет в проекте SO-5 -- хорошо, не будет -- не страшно. Даже если в итоге от SO-5 откажутся, то это даст еще больше полезной информации о том, где SO-5 применим, а где не очень.&lt;/p&gt;

&lt;p&gt;Пока же я рад происходящему и есть два воодушевляющих фактора:&lt;/p&gt;

&lt;p&gt;Во-первых, появляется дополнительный стимул изыскать время и ресурсы, чтобы возобновить дальнейшую работу над SObjectizer-ом. Признаюсь честно, что в последние 3-4 месяца с этим были проблемы, не хватало мне сил после основной работы находить еще по 2-3 часа в день, чтобы, скажем, вернуться к поддержке короутин в SO-5.&lt;/p&gt;

&lt;p&gt;Во-вторых, SO-5 будут изучать и пробовать в работе совершенно новые люди. Наверняка от них последуют какие-то замечания/соображения, которые позволят сделать SObjectizer еще лучше. Да и вообще опыт применения SO-5 в новом проекте лишним точно не будет.&lt;/p&gt;

&lt;p&gt;Так что будем пробовать и смотреть что из этого получится.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/7112399103379867100/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/7112399103379867100' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/7112399103379867100'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/7112399103379867100'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/06/progc-sobjectizer-5.html' title='[prog.c++] Похоже, что SObjectizer-5 будет использоваться в еще одном проекте'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-4270046275387486759</id><published>2026-06-08T08:51:00.083+03:00</published><updated>2026-06-08T08:51:00.084+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="О жизни"/><title type='text'>[life.audiophilia.diy] Попробовал давеча 10mm динамики в наушниках-затычках. На свою голову...</title><content type='html'>&lt;p&gt;Поскольку в области 15.4mm и 14.8mm динамиков для наушников-вкладышей перепробовал уже практически все, что заслуживало внимания, то решился на эксперимент с 10mm динамиками для внутриканальных наушников. Но т.к. заушные мониторы мне не подходят, то остановился на форм-факторе &quot;затычек&quot;.&lt;/p&gt;

&lt;p&gt;Взял &lt;a href=&quot;https://aliexpress.ru/item/1005008233721780.html&quot;&gt;вот эти недорогие (по меркам 10mm динамиков) драйверы&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhERmeJsi_i6d3nezHvs-wz46eWN2c-JXoKJsi0r6waioJ5R7qiYHoBeiCtqpIn45rqOAHcXnuBtGC8IA4KaWxKqUETAHfgloWDlPfB1DdWFvJg9dZeKjI2QCAcJq9_IFJu0swf1_8ULVN4XE3f4KSgQAqX4NdrUWsPzsdXS7IEcgm_VQ6sOMOoqkdwHTQ/s640/10mm_drivers_640x640.jpg&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;400&quot; data-original-height=&quot;640&quot; data-original-width=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhERmeJsi_i6d3nezHvs-wz46eWN2c-JXoKJsi0r6waioJ5R7qiYHoBeiCtqpIn45rqOAHcXnuBtGC8IA4KaWxKqUETAHfgloWDlPfB1DdWFvJg9dZeKjI2QCAcJq9_IFJu0swf1_8ULVN4XE3f4KSgQAqX4NdrUWsPzsdXS7IEcgm_VQ6sOMOoqkdwHTQ/s400/10mm_drivers_640x640.jpg&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;И установил их &lt;a href=&quot;https://aliexpress.ru/item/1005005274480792.html&quot;&gt;вот в такие корпуса&lt;/a&gt; (из черного дерева):&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEianBtY8Z0zr6sp0_QTwV2g1hvvDfi04JjMCVLsinJrzleEvofzqzA6JtDzjbYIoLBASYALGXp_GiFJSc9o4z-jRGKFewT3F1ETmbU0yAdHnpSBCfYAPd2JFGEU-ttVzmvCnRj4xJJAHE9oh2fHNFlBArXLb7_gx97cSqRRKbc2tyQKycSY18t8WhNfn68/s800/10mm_shell.jpg&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;400&quot; data-original-height=&quot;800&quot; data-original-width=&quot;800&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEianBtY8Z0zr6sp0_QTwV2g1hvvDfi04JjMCVLsinJrzleEvofzqzA6JtDzjbYIoLBASYALGXp_GiFJSc9o4z-jRGKFewT3F1ETmbU0yAdHnpSBCfYAPd2JFGEU-ttVzmvCnRj4xJJAHE9oh2fHNFlBArXLb7_gx97cSqRRKbc2tyQKycSY18t8WhNfn68/s400/10mm_shell.jpg&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Немного помучался с подбором амбушюр...&lt;/p&gt;

&lt;p&gt;Но результат получил такой, что даже и не знаю как охарактеризовать.&lt;/p&gt;

&lt;p&gt;По звуку просто афигительно. После этих затычек все перепробованные мной вкладыши даже с самыми дорогими драйверами кажутся ущербными. Тот самый случай, когда лично убедился в том, что вкладыши не умеют в бас и, особенно, в саббас.&lt;/p&gt;

&lt;p&gt;Но даже если не брать особенности НЧ, то и на всех остальных диапазонах сплошные кардинальные улучшения. Все гораздо более отчетливее. Плюс гораздо большая &quot;глубина&quot; сцены.&lt;/p&gt;

&lt;p&gt;В общем, в затычках как будто бы выходишь на совершенно другой уровень.&lt;/p&gt;

&lt;p&gt;Однако, есть подозрение, что все это далеко не бесплатно для ушей. Чтобы все эти прелести воспринимать мне нужны амбушюры размера L. И хоть я и выбрал самые мягкие из имеющихся, но все равно ощущение, что вставляешь толстые палки в слуховые каналы. Это ощущение практически исчезает минут через 7-10 после начала прослушивания, хотя того комфорта, который есть со вкладышами, когда &quot;вставил и забыл&quot;, нет и близко. Поэтому когда наушники извлекаешь, то чувствуешь пусть и небольшое, но физическое облегчение. А такой дискомфорт, хоть он и не сильный, вряд ли полезен для слуха.&lt;/p&gt;

&lt;p&gt;Так что очень стремно своими новыми затычками пользоваться. Как бы потом не пришлось расплачиваться за хороший звук проблемами с перепонками из-за усиленного образования ушной серы.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/4270046275387486759/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/4270046275387486759' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/4270046275387486759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/4270046275387486759'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/06/lifeaudiophiliadiy-10mm.html' title='[life.audiophilia.diy] Попробовал давеча 10mm динамики в наушниках-затычках. На свою голову...'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhERmeJsi_i6d3nezHvs-wz46eWN2c-JXoKJsi0r6waioJ5R7qiYHoBeiCtqpIn45rqOAHcXnuBtGC8IA4KaWxKqUETAHfgloWDlPfB1DdWFvJg9dZeKjI2QCAcJq9_IFJu0swf1_8ULVN4XE3f4KSgQAqX4NdrUWsPzsdXS7IEcgm_VQ6sOMOoqkdwHTQ/s72-c/10mm_drivers_640x640.jpg" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-6103959765247618825</id><published>2026-06-01T14:06:18.491+03:00</published><updated>2026-06-01T14:08:19.089+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Из непонятого"/><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><category scheme="http://www.blogger.com/atom/ns#" term="язык C++"/><title type='text'>[prog.c++] Попробовал познакомиться с модулями C++20 и чего-то недопонял</title><content type='html'>&lt;p&gt;Провел пару простых экспериментов с модулями C++20 и получил странные результаты.&lt;/p&gt;

&lt;p&gt;Эксперименты проводились под Windows с VS2022 и VS2026 (обновления от мая 2026-го) и ArchLinux с GCC 16.1 и clang 22.1.&lt;/p&gt;

&lt;p&gt;Ожидаемые мной результаты (т.е. отсутствие проблем компиляции/линковки) получились только с clang 22.1 и libc++. А вот с GCC и VC++ случились какие-то проблемы, которые мне сложно объяснить.&lt;/p&gt;

&lt;p&gt;Во всех случаях сборка осуществлялась через CMake и Ninja.&lt;/p&gt;

&lt;p&gt;Исходные коды описанных ниже тестовых программ можно найти &lt;a href=&quot;https://github.com/eao197/cpp-modules-experiments&quot;&gt;в этом репозитории&lt;/a&gt;.&lt;/p&gt;

&lt;hr/&gt;

&lt;p&gt;Эксперимент первый (&lt;a href=&quot;https://github.com/eao197/cpp-modules-experiments/tree/45b8067b438148b1fc4ca5c802c755463512c10e/case_001&quot;&gt;case_001&lt;/a&gt; из упомянутого репозитория). Очень простой модуль. Декларация в файле hello.ixx:&lt;/p&gt;

&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;module&lt;/font&gt;;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#include&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/font&gt;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#include&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;lt;typeinfo&amp;gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;export&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#ff80ff&quot;&gt;module&lt;/font&gt;&amp;nbsp;hello;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;export&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;namespace&lt;/font&gt;&amp;nbsp;hello&lt;br&gt;
{&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&amp;nbsp;greet();&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;template&lt;/font&gt;&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;typename&lt;/font&gt;&amp;nbsp;T&amp;gt;&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;struct&lt;/font&gt;&amp;nbsp;helper&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;static&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; a();&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;static&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; b();&lt;br&gt;
};&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;template&lt;/font&gt;&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;typename&lt;/font&gt;&amp;nbsp;T&amp;gt;&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&lt;br&gt;
helper&amp;lt;T&amp;gt;::a()&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; std::cout &amp;lt;&amp;lt;&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;helper&amp;lt;&amp;quot;&lt;/font&gt;&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;typeid&lt;/font&gt;(T).name() &amp;lt;&amp;lt;&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;&amp;gt;::a()&amp;quot;&lt;/font&gt;&amp;nbsp;&amp;lt;&amp;lt; std::endl;&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;template&lt;/font&gt;&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;typename&lt;/font&gt;&amp;nbsp;T&amp;gt;&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&lt;br&gt;
helper&amp;lt;T&amp;gt;::b()&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; std::cout &amp;lt;&amp;lt;&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;helper&amp;lt;&amp;quot;&lt;/font&gt;&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;typeid&lt;/font&gt;(T).name() &amp;lt;&amp;lt;&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;&amp;gt;::a()&amp;quot;&lt;/font&gt;&amp;nbsp;&amp;lt;&amp;lt; std::endl;&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
}&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;// export namespace hello&lt;/font&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Реализация в файле hello.cpp:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;module&lt;/font&gt;;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#include&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;module&lt;/font&gt;&amp;nbsp;hello;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;namespace&lt;/font&gt;&amp;nbsp;hello&lt;br&gt;
{&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&amp;nbsp;greet()&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; std::cout &amp;lt;&amp;lt;&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;hello, world!&amp;quot;&lt;/font&gt;&amp;nbsp;&amp;lt;&amp;lt; std::endl;&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
}&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;/*&lt;/font&gt;&lt;font color=&quot;#80a0ff&quot;&gt;&amp;nbsp;namespace hello&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#80a0ff&quot;&gt;*/&lt;/font&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Но мне кажется, что ключевой момент в том, что шаблон класса helper реализован прямо в hello.ixx.&lt;/p&gt;

&lt;p&gt;Описание библиотеки hello для CMake:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#90fff0&quot;&gt;cmake_minimum_required&lt;/font&gt;(&lt;font color=&quot;#90fff0&quot;&gt;VERSION&lt;/font&gt;&amp;nbsp;3.28)&lt;br&gt;
&lt;font color=&quot;#90fff0&quot;&gt;project&lt;/font&gt;(hello CXX)&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90fff0&quot;&gt;set&lt;/font&gt;(&lt;font color=&quot;#90fff0&quot;&gt;CMAKE_CXX_EXTENSIONS&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90fff0&quot;&gt;OFF&lt;/font&gt;)&lt;br&gt;
&lt;font color=&quot;#90fff0&quot;&gt;set&lt;/font&gt;(&lt;font color=&quot;#90fff0&quot;&gt;CMAKE_CXX_STANDARD&lt;/font&gt;&amp;nbsp;20)&lt;br&gt;
&lt;font color=&quot;#90fff0&quot;&gt;set&lt;/font&gt;(&lt;font color=&quot;#90fff0&quot;&gt;CMAKE_CXX_STANDARD_REQUIRED&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90fff0&quot;&gt;YES&lt;/font&gt;)&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90fff0&quot;&gt;add_library&lt;/font&gt;(hello)&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90fff0&quot;&gt;target_sources&lt;/font&gt;(hello&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90fff0&quot;&gt;PUBLIC&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90fff0&quot;&gt;FILE_SET&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90fff0&quot;&gt;CXX_MODULES&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90fff0&quot;&gt;FILES&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hello.ixx&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90fff0&quot;&gt;PRIVATE&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hello.cxx&lt;br&gt;
)&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Используется это в очень простой программе:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;import&lt;/font&gt;&amp;nbsp;hello;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;nbsp;main()&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; hello::greet();&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; hello::helper&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;gt;::a();&lt;br&gt;
&amp;nbsp;&amp;nbsp; hello::helper&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;long&lt;/font&gt;&amp;gt;::b();&lt;br&gt;
}&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;И здесь засада №1. В clang-е все OK, как я и ожидаю.&lt;/p&gt;

&lt;p&gt;А вот для GCC и MSVC++ ошибка компиляции -- оказывается, в методах helper::a и helper::b не определен символ type_info.&lt;/p&gt;

&lt;p&gt;Решается эта проблема добавлением в тестовую программу `&lt;tt&gt;#include &amp;lt;typeinfo&gt;&lt;/tt&gt;` для MSVC++. Тогда как для GCC нужен еще и `&lt;tt&gt;#include &amp;lt;iostream&gt;&lt;/tt&gt;`&lt;/p&gt;

&lt;p&gt;Но здесь я перестаю понимать суть модулей. Ведь типа модуль -- это самодостаточная сущность. Если в модуле был сделан нужный набор include-ов, то в месте, где импортированный из модуля метод/класс/функция используется, уже никаких дополнительных include не нужно.&lt;/p&gt;

&lt;p&gt;Такое ощущение, что GCC/VC++ для шаблонов в модуле просто сохраняют какое-то частично разобранное представление, которое просто 1-в-1 переносят в место использования шаблона и окончательный парсинг/анализ делают уже только в месте инстанцирования. Поэтому т.к. в тестовой программе не подключения заголовочного файла typeinfo, то нет и определения символа type_info.&lt;/p&gt;

&lt;p&gt;Тогда как clang делает более глубокий и честный разбор тела шаблона и с символом type_info он определяется уже при компиляции самого модуля (либо же он умудряется дополнять код тестовой программы нужными include-ами автоматически -- типа того, что если в определении модуля использовался `&lt;tt&gt;#include &amp;lt;typeinfo&gt;&lt;/tt&gt;`, то этот же include нужно неявно подставить и в то место, где совершен импорта модуля).&lt;/p&gt;

&lt;hr/&gt;

&lt;p&gt;Случай второй (&lt;a href=&quot;https://github.com/eao197/cpp-modules-experiments/tree/45b8067b438148b1fc4ca5c802c755463512c10e/case_003&quot;&gt;case_003&lt;/a&gt; из упомянутого выше репозитория).&lt;/p&gt;

&lt;p&gt;Здесь я пытался сделать хитрый финт ушами. Иногда у меня бывают очень объемные шаблоны классов, которые я разбиваю на несколько исходных файлов: один заголовочный файл с определением шаблона, но без реализации, + несколько заголовочных файлов с реализациями внутренностей шаблона.&lt;/p&gt;

&lt;p&gt;На простых .hpp-файлах это работает без проблем. А вот как сделать подобное на модулях?&lt;/p&gt;

&lt;p&gt;После некоторого выкуривания бамбука пришло такое &quot;решение&quot;.&lt;/p&gt;

&lt;p&gt;Есть отдельный module partition unit (не знаю как лучше данный термин на русский язык перевести) с определением шаблона класса (файл helper.decl.ixx):&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;export&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#ff80ff&quot;&gt;module&lt;/font&gt;&amp;nbsp;hello:helper.decl;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;export&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;namespace&lt;/font&gt;&amp;nbsp;hello&lt;br&gt;
{&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;template&lt;/font&gt;&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;typename&lt;/font&gt;&amp;nbsp;T&amp;gt;&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;struct&lt;/font&gt;&amp;nbsp;helper&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;static&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; a();&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;static&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp; b();&lt;br&gt;
};&lt;br&gt;
&lt;br&gt;
}&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;/*&lt;/font&gt;&lt;font color=&quot;#80a0ff&quot;&gt;&amp;nbsp;namespace hello&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#80a0ff&quot;&gt;*/&lt;/font&gt;&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Есть два отдельных module partition unit-а с реализацией методов a и b. В файле helper.impl.a.ixx:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;module&lt;/font&gt;;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#include&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/font&gt;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#include&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;lt;typeinfo&amp;gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;export&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#ff80ff&quot;&gt;module&lt;/font&gt;&amp;nbsp;hello:helper.impl.a;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;import&lt;/font&gt;&amp;nbsp;:helper.decl;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;export&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;namespace&lt;/font&gt;&amp;nbsp;hello&lt;br&gt;
{&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;template&lt;/font&gt;&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;typename&lt;/font&gt;&amp;nbsp;T&amp;gt;&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&lt;br&gt;
helper&amp;lt;T&amp;gt;::a()&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; std::cout &amp;lt;&amp;lt;&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;helper&amp;lt;&amp;quot;&lt;/font&gt;&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;typeid&lt;/font&gt;(T).name() &amp;lt;&amp;lt;&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;&amp;gt;::a()&amp;quot;&lt;/font&gt;&amp;nbsp;&amp;lt;&amp;lt; std::endl;&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
}&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;/*&lt;/font&gt;&lt;font color=&quot;#80a0ff&quot;&gt;&amp;nbsp;namespace hello&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#80a0ff&quot;&gt;*/&lt;/font&gt;&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;И в файле helper.impl.b.ixx:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;module&lt;/font&gt;;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#include&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/font&gt;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#include&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;lt;typeinfo&amp;gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;export&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#ff80ff&quot;&gt;module&lt;/font&gt;&amp;nbsp;hello:helper.impl.b;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;import&lt;/font&gt;&amp;nbsp;:helper.decl;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;export&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;namespace&lt;/font&gt;&amp;nbsp;hello&lt;br&gt;
{&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;template&lt;/font&gt;&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;typename&lt;/font&gt;&amp;nbsp;T&amp;gt;&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&lt;br&gt;
helper&amp;lt;T&amp;gt;::b()&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; std::cout &amp;lt;&amp;lt;&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;helper&amp;lt;&amp;quot;&lt;/font&gt;&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;typeid&lt;/font&gt;(T).name() &amp;lt;&amp;lt;&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;quot;&amp;gt;::a()&amp;quot;&lt;/font&gt;&amp;nbsp;&amp;lt;&amp;lt; std::endl;&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
}&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;/*&lt;/font&gt;&lt;font color=&quot;#80a0ff&quot;&gt;&amp;nbsp;namespace hello&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#80a0ff&quot;&gt;*/&lt;/font&gt;&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Все это собирается затем в primary module interface unit:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;export&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#ff80ff&quot;&gt;module&lt;/font&gt;&amp;nbsp;hello;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;export&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#ff80ff&quot;&gt;import&lt;/font&gt;&amp;nbsp;:helper.decl;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;export&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#ff80ff&quot;&gt;import&lt;/font&gt;&amp;nbsp;:helper.impl.a;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;export&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#ff80ff&quot;&gt;import&lt;/font&gt;&amp;nbsp;:helper.impl.b;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;export&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;namespace&lt;/font&gt;&amp;nbsp;hello&lt;br&gt;
{&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;void&lt;/font&gt;&amp;nbsp;greet();&lt;br&gt;
&lt;br&gt;
}&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;// export namespace hello&lt;/font&gt;&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Описывается в CMake так:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#90fff0&quot;&gt;cmake_minimum_required&lt;/font&gt;(&lt;font color=&quot;#90fff0&quot;&gt;VERSION&lt;/font&gt;&amp;nbsp;3.28)&lt;br&gt;
&lt;font color=&quot;#90fff0&quot;&gt;project&lt;/font&gt;(hello CXX)&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90fff0&quot;&gt;set&lt;/font&gt;(&lt;font color=&quot;#90fff0&quot;&gt;CMAKE_CXX_EXTENSIONS&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90fff0&quot;&gt;OFF&lt;/font&gt;)&lt;br&gt;
&lt;font color=&quot;#90fff0&quot;&gt;set&lt;/font&gt;(&lt;font color=&quot;#90fff0&quot;&gt;CMAKE_CXX_STANDARD&lt;/font&gt;&amp;nbsp;20)&lt;br&gt;
&lt;font color=&quot;#90fff0&quot;&gt;set&lt;/font&gt;(&lt;font color=&quot;#90fff0&quot;&gt;CMAKE_CXX_STANDARD_REQUIRED&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90fff0&quot;&gt;YES&lt;/font&gt;)&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90fff0&quot;&gt;add_library&lt;/font&gt;(hello)&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90fff0&quot;&gt;target_sources&lt;/font&gt;(hello&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90fff0&quot;&gt;PUBLIC&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90fff0&quot;&gt;FILE_SET&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90fff0&quot;&gt;CXX_MODULES&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90fff0&quot;&gt;FILES&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hello.ixx&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; helper.decl.ixx&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; helper.impl.a.ixx&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; helper.impl.b.ixx&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90fff0&quot;&gt;PRIVATE&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hello.cxx&lt;br&gt;
)&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;И в случае с clang-ом все OK. Однако.&lt;/p&gt;

&lt;p&gt;Для GCC опять таки требуется, чтобы в тестовой программе были сделаны необходимые include. Т.е. вот так OK:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#include&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/font&gt;&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;#include&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#ffa0a0&quot;&gt;&amp;lt;typelist&amp;gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#ff80ff&quot;&gt;import&lt;/font&gt;&amp;nbsp;hello;&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;nbsp;main()&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp; hello::greet();&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp; hello::helper&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;&amp;gt;::a();&lt;br&gt;
&amp;nbsp;&amp;nbsp; hello::helper&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;long&lt;/font&gt;&amp;gt;::b();&lt;br&gt;
}&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;А без include -- ошибка компиляции.&lt;/p&gt;

&lt;p&gt;Тогда как для MSVC++ делать include в тестовой программе не нужно, оно компилируется, но зато возникает ошибка линковки:&lt;/p&gt;

&lt;code&gt;cmake --build .&lt;br/&gt;
[1/1] Linking CXX executable bin\app.exe&lt;br/&gt;
FAILED: [code=4294967295] bin/app.exe
C:\WINDOWS\system32\cmd.exe /C &quot;cd . &amp;amp;&amp;amp; &quot;C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe&quot; -E vs_link_exe --msvc-ver=1951 --intdir=app\CMakeFiles\app.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100261~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100261~1.0\x64\mt.exe --manifests  -- C:\PROGRA~1\MICROS~2\18\COMMUN~1\VC\Tools\MSVC\1451~1.362\bin\Hostx64\x64\link.exe /nologo app\CMakeFiles\app.dir\main.cpp.obj  /out:bin\app.exe /implib:lib\app.lib /pdb:bin\app.pdb /version:0.0 /machine:x64 /INCREMENTAL:NO /subsystem:console  lib\hello.lib  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib &amp;amp;&amp;amp; cd .&quot;&lt;br/&gt;
LINK: command &quot;C:\PROGRA~1\MICROS~2\18\COMMUN~1\VC\Tools\MSVC\1451~1.362\bin\Hostx64\x64\link.exe /nologo app\CMakeFiles\app.dir\main.cpp.obj /out:bin\app.exe /implib:lib\app.lib /pdb:bin\app.pdb /version:0.0 /machine:x64 /INCREMENTAL:NO /subsystem:console lib\hello.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST:EMBED,ID=1&quot; failed (exit code 1120) with the following output:&lt;br/&gt;
main.cpp.obj : error LNK2019: ссылка на неразрешенный внешний символ &quot;public: static void __cdecl hello::helper&amp;lt;int&gt;::a(void)&quot; (?a@?$helper@H@hello@@SAXXZ::&lt;!hello&gt;) в функции main.&lt;br/&gt;
main.cpp.obj : error LNK2019: ссылка на неразрешенный внешний символ &quot;public: static void __cdecl hello::helper&amp;lt;long&gt;::b(void)&quot; (?b@?$helper@J@hello@@SAXXZ::&lt;!hello&gt;) в функции main.&lt;br/&gt;
bin\app.exe : fatal error LNK1120: неразрешенных внешних элементов: 2&lt;br/&gt;
ninja: build stopped: subcommand failed.&lt;/code&gt;

&lt;p&gt;И здесь я еще в большем недоумении: может это и не вина MSVC++, а проблема в CMake?&lt;/p&gt;

&lt;p&gt;Однако впечатление, что под видом модулей комитет очень и очень сильно поднасрал C++ разработчикам, только усилилось.&lt;/p&gt;

&lt;hr/&gt;

&lt;p&gt;PS. В очередной раз офигел от документации к CMake. Вроде как там &lt;a href=&quot;https://cmake.org/cmake/help/latest/manual/cmake-cxxmodules.7.html&quot;&gt;целый раздел&lt;/a&gt; посвящен поддержке модулей из C++20. Но в этом разделе я не увидел ни одного примера того, как же модули нужно декларировать в CMakeLists.txt. Пришлось гуглить и потом таскать к себе куски из разных мест.&lt;/p&gt;

&lt;p&gt;PPS. Что еще сильно не понравилось, так это то, что с какого-то бодуна стали внедрять новые расширения для module units. Вроде как в мире MS используют .ixx, тогда как в мире clang -- .cppm. Вот нафига и, главное, зачем? Расширения для файлов в C++ном проекте должны быть такими, чтобы можно было в grep одну простую маску задать и все. Поэтому .hpp/.cpp или .hxx/.cxx -- это хорошо, а вот всякие извраты с .H/.C, .hh/.cc и прочим -- фтопку. И если разработчикам навяжут какое-то новое расширение для module units, то удобство C++а лично для меня снизится еще сильнее.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/6103959765247618825/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/6103959765247618825' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/6103959765247618825'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/6103959765247618825'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/06/progc-c20.html' title='[prog.c++] Попробовал познакомиться с модулями C++20 и чего-то недопонял'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-9100826613016643119</id><published>2026-06-01T07:28:07.061+03:00</published><updated>2026-06-01T07:28:07.061+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Кино"/><category scheme="http://www.blogger.com/atom/ns#" term="О жизни"/><category scheme="http://www.blogger.com/atom/ns#" term="Ссылки"/><title type='text'>[life.cinema] Очередной кинообзор (2026/05)</title><content type='html'>&lt;p&gt;Традиционный отчет о промостренных фильмах. Традиционно в начале каждого из списков идет то, что понравилось больше, а в конце то, на что можно и не тратить свое время.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Фильмы&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kinopoisk.ru/film/5447044/&quot;&gt;Полный Такос (Operation Taco Gary&#39;s, 2026)&lt;/a&gt;. Совершенно укуренный и классный фильм. Мне зашел, но из-за его специфичности рекомендовать не могу -- наверняка понравится не всем. Однако, хороший пример того как за дешево можно снять приличную юмористическую фантастику.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/194181/annot/&quot;&gt;Эдем (Eden, 2024)&lt;/a&gt;. Хорошая история, хорошая операторская работа, отличная игра актеров. Но вот рассказана эта история так, что не особо и цепляет. Поэтому самые сильные впечатления производят реальные фотографии и кадры хроники, показанные в самом-самом конце.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/205820/annot/&quot;&gt;Они убьют тебя (They Will Kill You, 2026)&lt;/a&gt;. Неплохая черная комедия в стиле фэнтези с реками крови и грудами отрубленных конечностей.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/206640/annot/&quot;&gt;Взлом на миллион (Wardriver, 2026)&lt;/a&gt;. Не ждал от фильма ничего хорошего, но был приятно удивлен. Далеко не шедевр, но вполне себе добротный криминальный фильм с неплохими сюжетными ходами.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/205198/annot/&quot;&gt;Нормал (Normal, 2025)&lt;/a&gt;. Не понял что это было: для комедии вроде бы слишком нудный, для боевика слишком комедийный. Посмотреть можно, но лучше ничего особенного не ждать.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/196005/annot/&quot;&gt;Сезон охоты (&quot;Blood of Man&quot; или  &quot;Hunting Season&quot;, или &quot;Mermaid&quot;, 2025)&lt;/a&gt;. Добротно, но слишком уж неторопливо и маловато экшОна. По сути, весь фильм держится на харизме Мэла Гибсона.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/205828/annot/&quot;&gt;Мумия (&quot;The Mummy&quot; или &quot;Lee Cronin&#39;s The Mummy&quot;, 2026)&lt;/a&gt;. Для своего жанра, в принципе, нормально. Но манера съемки у фильма такая, что воспринимается это все как театральная постановка и поэтому погружения в атмосферу ужаса не происходит.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/asia/161233/annot/&quot;&gt;Охота (&quot;Hunt&quot; или &quot;Heon-teu&quot; или &quot;헌트&quot;, 2022)&lt;/a&gt;. Есть русский бунт, бессмысленный и беспощадный. А есть корейские боевики, не менее бессмысленные и беспощадные 🙂 А если для вас все корейцы на одно лицо и их имена вы не запоминаете вообще, то следить за логикой происходящего на экране будет совсем сложно.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/201775/annot/&quot;&gt;Мститель (Protector, 2025)&lt;/a&gt;. Что будет, если смешать &quot;Рембо&quot;, &quot;Заложницу&quot; и &quot;Джона Уика&quot; в очень-очень бюджетном кино, да еще и с типа крутой теткой в главной роли? А вот унылое говно под названием &quot;Мститель&quot; и получится.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/ros/172441/annot/&quot;&gt;Пастбища богов (2025)&lt;/a&gt;. Местами красивые пейзажи. Пожалуй, это единственное, что есть хорошего в данном &quot;кино&quot;.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Сериалы&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/135619/annot/&quot;&gt;Пацаны (The Boys, пятый сезон, 2026)&lt;/a&gt;. Самый слабый из все сезонов. Но если предыдущие понравились, то надо смотреть хотя бы для того, чтобы увидеть чем все закончилось.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/ros/196022/annot/&quot;&gt;Отпечатки (первый сезон, 2025)&lt;/a&gt;. Пока смотришь -- интересно, да и главного злодея хорошо замаскировали до самой последней серии, за что авторам респект. Но вот когда начинаешь задаваться вопросами как же такое могло происходить, то возникает устойчивое ощущение, что нам втирали какую-то дичь. Так что по итогу остались негативные впечатления.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kino-teatr.ru/kino/movie/hollywood/208337/annot/&quot;&gt;Гнев (Man on Fire, первый сезон, 2026)&lt;/a&gt;. Первые серии бодренькие, затем какие-то тягомотные сопли, а в финале какой-то сплошной маразм. Так что можно смело пройти мимо.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/9100826613016643119/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/9100826613016643119' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/9100826613016643119'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/9100826613016643119'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/06/lifecinema-202605.html' title='[life.cinema] Очередной кинообзор (2026/05)'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-1491659549669580090</id><published>2026-05-26T07:23:26.887+03:00</published><updated>2026-05-26T07:23:26.887+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Bugs"/><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><category scheme="http://www.blogger.com/atom/ns#" term="язык C++"/><title type='text'>[prog.c++.bugs] Похоже наткнулся на баг в GCC 12/13 под Linux-ом. Или нет.</title><content type='html'>&lt;p&gt;Дело было так: есть некий объемный и сложный шаблон класса-контейнера. Для тестирования было создано приложение с юнит-тестами на базе Google.Test. В состав этого приложения входит порядка 30 (тридцати) .cpp-файлов. В некоторых из них происходит следующее:
  
&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#90f020&quot;&gt;namespace&lt;/font&gt;&lt;br&gt;
{&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;template&lt;/font&gt;&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;typename&lt;/font&gt;&amp;nbsp;T&amp;gt;&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;struct&lt;/font&gt;&amp;nbsp;test_traits :&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;public&lt;/font&gt;&amp;nbsp;my_container::default_traits&amp;lt;T&amp;gt; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;static&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;constexpr&lt;/font&gt;&amp;nbsp;std::&lt;font color=&quot;#90f020&quot;&gt;size_t&lt;/font&gt;&amp;nbsp;key_size =&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;3&lt;/font&gt;;&lt;br&gt;
};&lt;br&gt;
&lt;br&gt;
}&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;/*&lt;/font&gt;&lt;font color=&quot;#80a0ff&quot;&gt;&amp;nbsp;namespace anonymous&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#80a0ff&quot;&gt;*/&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
TEST(my_container, some_test)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;my_container::my_map&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;, test_traits&amp;gt; map;&lt;br&gt;
&amp;nbsp;&amp;nbsp;...&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;// какие-то действия с map.&lt;/font&gt;&lt;br&gt;
}&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Т.е. суть в том, что в десятке .cpp-файлов есть анонимные пространства имен, в каждом из которых определяется шаблон класса с именем test_traits. Затем этот шаблон используется для инстанцирования класса-контейнера.&lt;/p&gt;

&lt;p&gt;Все это работало до тех пор, пока не был добавлен еще один .cpp-файл, в котором было практически тоже самое:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#90f020&quot;&gt;namespace&lt;/font&gt;&lt;br&gt;
{&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;template&lt;/font&gt;&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;typename&lt;/font&gt;&amp;nbsp;T&amp;gt;&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;struct&lt;/font&gt;&amp;nbsp;test_traits :&amp;nbsp;&lt;font color=&quot;#ffff60&quot;&gt;public&lt;/font&gt;&amp;nbsp;my_container::default_traits&amp;lt;T&amp;gt; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;static&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;constexpr&lt;/font&gt;&amp;nbsp;std::&lt;font color=&quot;#90f020&quot;&gt;size_t&lt;/font&gt;&amp;nbsp;key_size =&amp;nbsp;&lt;font color=&quot;#ffa0a0&quot;&gt;3&lt;/font&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;static&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;constexpr&lt;/font&gt;&amp;nbsp;my_container::mode use_mode =&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;my_container::mode::versioned;&lt;br&gt;
};&lt;br&gt;
&lt;br&gt;
}&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;/*&lt;/font&gt;&lt;font color=&quot;#80a0ff&quot;&gt;&amp;nbsp;namespace anonymous&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#80a0ff&quot;&gt;*/&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
TEST(my_container, some_test_versioned)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;my_container::my_map&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;, test_traits&amp;gt; map;&lt;br&gt;
&amp;nbsp;&amp;nbsp;...&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;// какие-то действия с map.&lt;/font&gt;&lt;br&gt;
}&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;И вот тут-то в some_test_versioned с map стали происходит странные вещи: возникали segmentation faults там, где их быть не должно было. Попытки отладить код приводили к тому, что отладчик показывал, что отрабатывают не те ветки if-ов. А отладочные печати содержали совсем не те значения, которые должны были бы быть.&lt;/p&gt;

&lt;p&gt;Было полное ощущение, что GCC сошел с ума.&lt;/p&gt;

&lt;p&gt;Проект, в рамках которого все это делается, собирается VC++ под Windows и GCC под Linux-ом. Под Linux-ами используются GCC 12 и 13. Конкретно я работаю с GCC 13, но проверил и под GCC 12. Сам проект уже не очень маленький, плюс подтягивает кучу зависимостей разного калибра (включая Folly и Abseil). Все это к тому, что мероприятие по перекомпиляции проекта под какой-то свежий GCC или clang -- это попытка с негарантированным результатом. Может повезти, а может и нет.&lt;/p&gt;

&lt;p&gt;Под Windows проверил, там ничего подобного нет, все работает как и положено. А вот под Linux-овым GCC -- проблемы.&lt;/p&gt;

&lt;p&gt;В итоге подумал о том, что GCC воспринимает все мои test_traits как нарушение ODR и я наступаю на грабли UB. Поэтому переименовал test_traits так, чтобы во всех .cpp-файлах имена оказались уникальными, даже не смотря на то, что живут они в анонимных пространствах имен.&lt;/p&gt;

&lt;p&gt;После этого все описанные выше магические проблемы разом исчезли.&lt;/p&gt;

&lt;p&gt;Есть у меня сильное подозрение, что это таки был баг в GCC. Поскольку, если мне не изменяет склероз, все, что определяется внутри анонимного пространство имен, должно быть абсолютно уникальным. В том числе это касается и шаблонов.&lt;/p&gt;

&lt;p&gt;Но на 100% не уверен. Может быть здесь дело еще и в том, что у my_container::map есть шаблонный параметр шаблона, т.е.:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
&lt;font color=&quot;#90f020&quot;&gt;namespace&lt;/font&gt;&amp;nbsp;my_container&lt;br&gt;
{&lt;br&gt;
&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;template&lt;/font&gt;&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;typename&lt;/font&gt;&amp;nbsp;T,&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;template&lt;/font&gt;&amp;lt;&lt;font color=&quot;#90f020&quot;&gt;typename&lt;/font&gt;&amp;gt;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;class&lt;/font&gt;&amp;nbsp;Traits&amp;gt;&lt;br&gt;
&lt;font color=&quot;#90f020&quot;&gt;class&lt;/font&gt;&amp;nbsp;map { ... };&lt;br&gt;
&lt;br&gt;
}&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;/*&lt;/font&gt;&lt;font color=&quot;#80a0ff&quot;&gt;&amp;nbsp;namespace my_container&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#80a0ff&quot;&gt;*/&lt;/font&gt;&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Поэтому его параметризация в тесте идет не конкретными типами, а шаблоном:&lt;/p&gt;

&lt;table width=&quot;100%&quot; bgcolor=&quot;#000040&quot;&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;font color=&quot;#c0c0c0&quot;&gt;
TEST(my_container, some_test_versioned)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;my_container::my_map&amp;lt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#90f020&quot;&gt;int&lt;/font&gt;,&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;// Это конкретный тип.&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;test_traits&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;// А это шаблон, который развернется в конкретный&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;// тип уже внутри map.&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;gt; map;&lt;br&gt;
&amp;nbsp;&amp;nbsp;...&amp;nbsp;&lt;font color=&quot;#80a0ff&quot;&gt;// какие-то действия с map.&lt;/font&gt;&lt;br&gt;
}&lt;br&gt;
      &lt;/font&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;И вот именно из-за этого ODR и нарушается. Но это не точно. И я даже не знаю в какую часть C++ного стандарта заглядывать, чтобы выяснить кто именно был не прав.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/1491659549669580090/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/1491659549669580090' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/1491659549669580090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/1491659549669580090'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/05/progcbugs-gcc-1213-linux.html' title='[prog.c++.bugs] Похоже наткнулся на баг в GCC 12/13 под Linux-ом. Или нет.'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-654279083390275842.post-907302441649927335</id><published>2026-05-21T08:48:40.421+03:00</published><updated>2026-05-21T08:48:40.421+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Bugs"/><category scheme="http://www.blogger.com/atom/ns#" term="timertt"/><category scheme="http://www.blogger.com/atom/ns#" term="О программировании"/><category scheme="http://www.blogger.com/atom/ns#" term="язык C++"/><title type='text'>[prog.c++] Обнаружился баг в timertt возрастом более 10 лет</title><content type='html'>&lt;p&gt;Пользователи &lt;a href=&quot;https://github.com/Stiffstream/sobjectizer/issues/105&quot;&gt;обнаружили в SObjectizer проблему&lt;/a&gt;, которая была вызвана неправильной работой механизма timer_heap &lt;a href=&quot;https://sourceforge.net/p/sobjectizer/wiki/Timer%20Thread%20Template/&quot;&gt;в библиотеке timertt&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Эта библиотека написана мной осенью 2014-го года для того, чтобы можно было окончательно отвязать SObjectizer от ACE. И как раз тогда, чуть ли не в самой первой версии, допущена ошибка в операции удаления таймерной заявки в механизме timer_heap. Этот timer_heap реализован в виде &lt;a href=&quot;https://en.wikipedia.org/wiki/Binary_heap&quot;&gt;binary heap&lt;/a&gt; на базе вектора. И как раз удаление из вектора и содержало проблему.&lt;/p&gt;

&lt;p&gt;То, что я допустил достаточно дурацкую ошибку совсем не удивительно. Я вообще умудряюсь делать на удивление много ошибок при реализации простых структур данных (скажем, если приходится вручную программировать интрузивный двусвязный список, то я там обязательно в паре мест накосячу). Дополнительным отягчающим фактором стало то, что специфическое для timer_heap тестирование было проведено &quot;по верхам&quot;. Думаю, что если бы в 2014-ом не поленился составить тест на базе примитивного fuzzing-а, то эта проблема вскрылась бы уже тогда. Но невнимательность + разгильдяйство сделали свое темное дело.&lt;/p&gt;

&lt;p&gt;Более удивительно то, что этот баг проявился в полный рост только сейчас, в 2026-ом. Вот это внушаить 🤔&lt;/p&gt;

&lt;p&gt;Какие выводы можно сделать?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;вложения в качественное тестирование окупаются. Недостаточное тестирование обязательно проявится. В не самый подходящий момент;&lt;/li&gt;

&lt;li&gt;существующие косяки обязательно повылазят как только библиотекой начнут пользоваться;&lt;/li&gt;

&lt;li&gt;в чем можно быть точно уверенным, так это в том, что где-то в коде есть ошибка. И, скорее всего, не одна.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PS. Что меня еще очень сильно удивило, так это то, что люди смогли найти проблемное место в не самом тривиальном (даже для меня) коде. И, к тому же, предложили патч на базе которого я в итоге и сделал исправление. Значит пишу не такой уж и страшный код, если в нем можно разобраться.&lt;/p&gt;

&lt;p&gt;PPS. Видимо, нужно найти время и вытащить timertt из старого svn-репозитория на SourceForge чтобы он продолжил жить на GitHub-е. Плюс выбросить оттуда MxxRu и перевести все на CMake (собственно, необходимость бодаться с CMake и является основным стоп-фактором). Нужно как-то себя заставить сделать это. Жаль только, что история коммитов при переносе в git потеряется 🙁&lt;/p&gt;

&lt;p&gt;PPPS. Обновление для SObjectizer-а уже опубликовано в виде версии 5.8.5.1.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eao197.blogspot.com/feeds/907302441649927335/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/654279083390275842/907302441649927335' title='Комментарии: 3'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/907302441649927335'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/654279083390275842/posts/default/907302441649927335'/><link rel='alternate' type='text/html' href='http://eao197.blogspot.com/2026/05/progc-timertt-10.html' title='[prog.c++] Обнаружился баг в timertt возрастом более 10 лет'/><author><name>eao197</name><uri>http://www.blogger.com/profile/17283739752119445290</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry></feed>