|
|
  |
Альтернативный вариант задания функции процесса |
|
|
|
Nov 12 2012, 07:48
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(Сергей Борщ @ Nov 12 2012, 13:13)  Выглядит слабочитаемо. Что мешает завести свой потомок TBaseProcess вне пространства имен OS, оставив в покое родной шаблон? Почему слабочитаемо? Всего-то добавлен один-единственный параметр шаблона, который должен иметь функцию exec(). Родной шаблон тоже не пострадал, всего лишь получил одного дополнительного предка. С точки зрения результирующего кода - ничего не изменилось абсолютно. С точки зрения интерфейса, предоставляемого OS::process - тоже полная идентичность. Единственное, что изменилось - добавился альтернативный способ создания процессов в оси. Имхо, сплошной профит  Цитата(Сергей Борщ @ Nov 12 2012, 13:13)  Как вариант - можно добавить обсуждаемую фичу в Extensions. Именно как отдельного наследника TBaseProcess. Не понимаю, чем оно мешает в том виде, как предлагается сейчас?
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Nov 12 2012, 15:08
|
Частый гость
 
Группа: Участник
Сообщений: 142
Регистрация: 10-11-12
Пользователь №: 74 318

|
Цитата(Сергей Борщ @ Nov 12 2012, 13:13)  Тут TProc1 передается как параметр шаблона только для того, чтобы в конструкторе взять адрес его exec. Страдает мое чувство прекрасного Так это вполне обычная практика в C++ - передавать в шаблон базового класса свой же тип: http://en.cppreference.com/w/cpp/memory/en...hared_from_thisПример оттуда: Код struct Good: std::enable_shared_from_this<Good> { ...
--------------------
|
|
|
|
|
Nov 13 2012, 06:20
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
QUOTE (AHTOXA @ Nov 11 2012, 23:00)  Вообще-то она изначально туда помещена, в объявлении. То, что некоторые компиляторы до сих пор позволяют не указывать это в реализации, не выносит exec() из пространства имён OS. Ни разу не так. Помещено туда определение шаблона process, а exec просто объявлена внутри process, и её определение вполне без проблем может быть сделано где угодно. QUOTE (AHTOXA @ Nov 11 2012, 23:00)  А где ты видишь здесь включение? Никакого включения нет. Есть вызов некой функции некоего стороннего объекта из функции exec() другого класса. Какое же это включение? А я и не говорю, что оно здесь есть. Я его и предлагаю взамен наследования на котором вы настаиваете, хотя в наследовании тут смысла вообще почти нет: из-за того, что exeс статическая, никакое наследование не позволит иметь нормальный объект с инкапсулированными данными внутри - это будет просто пространство имён с "регулировкой" уровня доступа, не более. QUOTE (AHTOXA @ Nov 12 2012, 02:15)  Йоу! Я придумал, как совместить эти два варианта Короче, переименовываем в новом варианте process в customProcess, а process объявляем вот так: CODE template<TPriority pr, size_t stack_size> class process : public customProcess<process<pr, stack_size>, pr, stack_size> { public: OS_PROCESS static void exec(); }; И всё! Старый вариант работает, и новый (наследование от customProcess) - тоже. Получается вообще замечательно: старые проекты все подхватятся без изменений, а в новых пользователь имеет возможность выбрать для себя более удобный вариант.  QUOTE (Сергей Борщ @ Nov 12 2012, 14:13)  Выглядит слабочитаемо. Что мешает завести свой потомок TBaseProcess вне пространства имен OS, оставив в покое родной шаблон? +1. QUOTE (Сергей Борщ @ Nov 12 2012, 14:13)  Тут TProc1 передается как параметр шаблона только для того, чтобы в конструкторе взять адрес его exec. Страдает мое чувство прекрасного. Возможно менее разрушительным будет добавить второй конструктор, который получает адрес exec в качестве параметра? Или сделать этот конструктор с параметром единственным, задав ему значение по умолчанию? А в потомке вызывать с адресом своего exec. Тоже некрасиво - забудешь в потомке описать такой конструктор и компилятор не отловит. Не знаю. Хотя отловит - линкер выругается, что не определен exec() в предке... Но такое сообщение неверно описывает причину ошибки. Да, всяко не очень красиво получается. А главное - ради чего? QUOTE (Сергей Борщ @ Nov 12 2012, 14:13)  Как вариант - можно добавить обсуждаемую фичу в Extensions. Именно как отдельного наследника TBaseProcess. Вот это было бы лучше всего. Расширения для того и предназначены, чтобы расширять. Там можно что угодно делать - желающие пусть юзают. QUOTE (AHTOXA @ Nov 12 2012, 14:48)  Почему слабочитаемо? Всего-то добавлен один-единственный параметр шаблона, который должен иметь функцию exec(). Родной шаблон тоже не пострадал, всего лишь получил одного дополнительного предка. С точки зрения результирующего кода - ничего не изменилось абсолютно. С точки зрения интерфейса, предоставляемого OS::process - тоже полная идентичность. Единственное, что изменилось - добавился альтернативный способ создания процессов в оси. Имхо, сплошной профит  Не понимаю, чем оно мешает в том виде, как предлагается сейчас? Ты уже попробовал в реальном коде? Работает? Кодогенерация идентична? Если на все эти вопросы ответ положительный, можно обсудить дальше. Если хочется нормальной инкапсуляции, то не нужно городить огороды, это делается легко базовыми средствами языка: CODE class TSlon { ... void exec() { for(;;) { ... } } ... };
template<> void TProc1::exec() { Slon.exec(); } Имеем полную настоящую инкапсуляцию. Кроме того, слонов тут можно катать сколько угодно. И не только слонов, но и мамонтов, бегемотов и весь остальной зоопарк. В общем, ждём результатов обкатки в железе предложенного варианта (process : public custom_process<...>).
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Nov 13 2012, 14:06
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(dxp @ Nov 13 2012, 12:20)  В общем, ждём результатов обкатки в железе предложенного варианта (process : public custom_process<...>). Проверил. Предложенный вариант даёт полностью, до байта совпадающий бинарный файл прошивки. Но я его на всякий случай прогнал в железе. Работает!  Вот исправленный OS_Kernel.h:
OS_Kernel.h.zip ( 4.47 килобайт )
Кол-во скачиваний: 160OS_Kernel.cpp остаётся родной. Прошу попробовать с другими портами, у кого есть время.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Nov 13 2012, 15:31
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(Сергей Борщ @ Nov 12 2012, 09:13)  Тут TProc1 передается как параметр шаблона только для того, чтобы в конструкторе взять адрес его exec. Страдает мое чувство прекрасного. А как иначе без вирутальных функций передать в базовый класс функцию потомка? Каждый процесс существует все равно в единственном экземпляре, все полиморфизмы в статику, шаблонами. Цитата(dxp @ Nov 13 2012, 08:20)  хотя в наследовании тут смысла вообще почти нет: из-за того, что exeс статическая, никакое наследование не позволит иметь нормальный объект с инкапсулированными данными внутри - это будет просто пространство имён с "регулировкой" уровня доступа, не более. А этого (регулировки уровня доступа) мало? Все процессы существуют в единственном экземпляре, поэтому статическая exec() не пугает. Цитата(dxp @ Nov 13 2012, 08:20)  Код class TSlon { ... void exec() { for(;;) { ... } } ... };
template<> void TProc1::exec() { Slon.exec(); } Этот вот TSlon::exec() перестал быть функцией процесса. Потерял доступ к protected в TBaseProcess. Их там (пока) и немного, но тут уже «страдает чувство прекрасного» у меня. По поводу сущностей: «предоставлять функцию процесса» -- это задача базового класса процесса. И если про что-то в системе я думаю «это -- процесс», то мне естественно думать «занчит, оно должно біть потомком базового класса процесса». Ну так вот сижу я и думаю «так, мне нужен процесс обслуживания индикации» «другие будут дергать этот процесс такой-то функцией, которая будет помещать запросы в очередь» «ага, у процесса должна быть очередь» Но в результате делаю класс процесса, о котором думал (class TSlon) и класс процесса процесса (typedef OS::process<…> TSlonProc). Цитата(AHTOXA @ Nov 13 2012, 16:06)  Предложенный вариант даёт полностью, до байта совпадающий бинарный файл прошивки. Но я его на всякий случай прогнал в железе. Ну :-) Вдруг эти байты только с виду одинаковые :-D Цитата(AHTOXA @ Nov 13 2012, 16:06)  OS_Kernel.cpp остаётся родной. Прошу попробовать с другими портами, у кого есть время. Ой, если не замотаюсь, завтра на работе (оно там в реальной винде живет) проверю с IAR, но только методом file compare. И мне кажется, что тоже разницы должно быть 0.00, и платы все равно нет под рукой. gcc/avr не вижу смысла проверять, front-end тот же.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Nov 13 2012, 15:59
|
Частый гость
 
Группа: Участник
Сообщений: 142
Регистрация: 10-11-12
Пользователь №: 74 318

|
Цитата(dxp @ Nov 13 2012, 12:20)  Ни разу не так. Помещено туда определение шаблона process, а exec просто объявлена внутри process, и её определение вполне без проблем может быть сделано где угодно. Это совершенно неверно. Согласно стандарту языка С++, специализация шаблонной функции должно быть выполнено только в том пространстве имён где был объявлен шаблон. То, что некоторые компиляторы допускают иную трактовку, является их ошибкой. Вот выдержка из стандарта (14.7.3/1): Цитата An explicit specialization shall be declared in the namespace of which the template is a member, or, for member templates, in the namespace of which the enclosing class or enclosing class template is a member. An explicit specialization of a member function, member class or static data member of a class template shall be declared in the namespace of which the class template is a member. В любом случае компиляторы подтянуться к стандарту, код перестанет компилироваться и придётся писать Код namespace OS { template <> OS_PROCESS void TProc1::exec() { ...
--------------------
|
|
|
|
|
Nov 13 2012, 16:52
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
QUOTE (AHTOXA @ Nov 13 2012, 21:06)  Проверил. Предложенный вариант даёт полностью, до байта совпадающий бинарный файл прошивки. Но я его на всякий случай прогнал в железе. Работает!  Молодец! QUOTE (ReAl @ Nov 13 2012, 22:31)  А этого (регулировки уровня доступа) мало? Конечно мало. Тут речь про инкапсуляцию ведут, а оная подразумевает наличие законченного целостного объекта. Но на деле никакого объекта и в помине нет, а есть сборная солянка из статических членов, засунутых в общее пространство имён. Т.е. ни абстракции, ни отделения интерфейса от реализации (т.к. и интерфейса-то никакого нет) - ничего этого нет. За что боремся? QUOTE (ReAl @ Nov 13 2012, 22:31)  Все процессы существуют в единственном экземпляре, поэтому статическая exec() не пугает. Пугать-то не пугает, но и ничего этот подход не даёт. QUOTE (ReAl @ Nov 13 2012, 22:31)  Этот вот TSlon::exec() перестал быть функцией процесса. Потерял доступ к protected в TBaseProcess. Их там (пока) и немного, но тут уже «страдает чувство прекрасного» у меня. А зачем ему этот доступ? Всё, что предназначено для доступа с уровня пользовательской программы, помещено в public секцию, остальное - для внутренних служебных целей. Поэтому разрешение доступа юзеру к этому представлению - это никакое не благо, а дырка в защите. Если там есть что-то, к чему надо дать доступ на уровне прикладного кода, это надо поместить в открытую секцию. QUOTE (ReAl @ Nov 13 2012, 22:31)  По поводу сущностей: «предоставлять функцию процесса» -- это задача базового класса процесса. Не базового класса процесса, а собственно процесса. Базовый класс процесса нужен для повышения эффективности и является "технологическим". QUOTE (ReAl @ Nov 13 2012, 22:31)  И если про что-то в системе я думаю «это -- процесс», то мне естественно думать «занчит, оно должно біть потомком базового класса процесса». Это почему это? Процесс - это транспорт, который выполняет "транспортную" функцию. А уж чем его загрузишь, то он и повезёт. Отождествлять грузовик с перевозимым грузом, является, имхо, не очень удачной идеей. QUOTE (ReAl @ Nov 13 2012, 22:31)  Ну так вот сижу я и думаю «так, мне нужен процесс обслуживания индикации» «другие будут дергать этот процесс такой-то функцией, которая будет помещать запросы в очередь» «ага, у процесса должна быть очередь» А если этот процесс не только обслуживает индикацию, но и, например, клавиатуру опрашивает? Что мешает на одном "автобусе" катать и пионеров, и бабушек? По моему опыту, как раз-таки, нередко один процесс обслуживает более, чем одну сущность. QUOTE (ArtDenis @ Nov 13 2012, 22:59)  Это совершенно неверно. Согласно стандарту языка С++, специализация шаблонной функции должно быть выполнено только в том пространстве имён где был объявлен шаблон. То, что некоторые компиляторы допускают иную трактовку, является их ошибкой. Вот выдержка из стандарта (14.7.3/1): Вы путаете declaration (объявление) и definition (определение). Также вы путате явную (explicit) специализацию и полную (full) специализацию. Приведённый вами пункт стандарта гласит о том, что если используется явная специализация, то она должна быть объявлена в том же простанстве имён. Но где там сказано, что на должна быть определена в этом пространстве имён? У нас там нигде явной специализации не объявляется. QUOTE (ArtDenis @ Nov 13 2012, 22:59)  В любом случае компиляторы подтянуться к стандарту, код перестанет компилироваться и придётся писать CODE namespace OS { template <> OS_PROCESS void TProc1::exec() { ... А этот код - это определение полной (а не объявление явной) специализации функции. Т.ч. всё в порядке, ничего компилироваться не перестанет, пусть там копиляторы хоть подтянутся, хоть отожмутся.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Nov 13 2012, 18:44
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(dxp @ Nov 13 2012, 18:52)  Отождествлять грузовик с перевозимым грузом, является, имхо, не очень удачной идеей. ... Что мешает на одном "автобусе" катать и пионеров, и бабушек? Давайте только определимся -- грузовик или автобус. И если таки грузовик, то для бабушек с пионерами придётся рядом поставить телегу с креслами и на верёвочке к грузовику прицепить. Хотя нынешний процесс -- скорее шасси, на которое можно пассажирскую газельку навесить, можно бортовую. Предлагается только вариант на шлее тянуть за этим шасси телегу. Цитата(dxp @ Nov 13 2012, 18:52)  Процесс - это транспорт, который выполняет "транспортную" функцию. Ну да. Только я считаю абсолютно полноправным (равноправным с другими) вариант Код class Тгрузовик : public Ттранспорт; class Тавтобус : public Ттранспорт; И не считаю, что всегда и везде единственно правильно Код class Тгрузовик { public: едь(); }; Ттранспорт<..> транспорт1; Тгрузовик грузовик; транспорт1::толкай() { грузовик.едь(); } Может, я наглухо испорчен борландсишным Код class TMyThread : public TThread { protected: virtual void execute(); // А в этой теме предлагается вместо virtual передать базе тип потомка но мне это не кажется настолько ненормальным, что нельзя это добавить в саму ОС. Другое дело, если бы это ломало все существующие наработки, но оно же прозрачно для старых проектов. И не у меня последнего такая хотелка, как видим.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Nov 14 2012, 01:17
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
QUOTE (AHTOXA @ Nov 14 2012, 00:04)  Ладно, раз уж у Гарри такая идиосинкразия к этому варианту, то давайте сделаем его расширением. Я попробовал, оказывается это работает точно так же  Вот, приаттачу пока сюда, а на днях выложу в репозиторий (Уж здесь-то, я думаю, возражений не последует?).
CustomProcess.h.zip ( 634 байт )
Кол-во скачиваний: 152Э-э, мы, вроде, договорились, что если реализация не страдает, то принимаем. Т.ч. это можно не расширением, а основным вариантом делать. Клади в trunk, попробуем при случае. QUOTE (ReAl @ Nov 14 2012, 01:44)  Хотя нынешний процесс -- скорее шасси, на которое можно пассажирскую газельку навесить, можно бортовую. Предлагается только вариант на шлее тянуть за этим шасси телегу. Да, скорее просто платформа для перевозки. Проблема в том, она не очень хорошо переделывается ни в полноценный грузовик, ни в автобус (из-за статика). QUOTE (ReAl @ Nov 14 2012, 01:44)  Ну да. Только я считаю абсолютно полноправным (равноправным с другими) вариант CODE class Тгрузовик : public Ттранспорт; class Тавтобус : public Ттранспорт; И не считаю, что всегда и везде единственно правильно CODE class Тгрузовик { public: едь(); }; Ттранспорт<..> транспорт1; Тгрузовик грузовик; транспорт1::толкай() { грузовик.едь(); } Да, это хорошая схема, годная, против такой я бы не возражал. Вот если получится это: QUOTE (AHTOXA @ Nov 14 2012, 00:04)  И ещё попробую сделать вариант с нестатическим exec(). Тоже в виде расширения. Чтоб уж совсем была инкапсуляция  то тогда в корне пересмотрим подход. Почему там статик, я сейчас уже не помню, то ли что-то не получалось по-иному сделать, то ли тогда видение было таким, идеология. Исторически сложилось. Исходно упор был на минимизацию и лёгкость, нынче времена меняются, можно и основные концепции пересмотреть в каких-то пределах. QUOTE (ReAl @ Nov 14 2012, 01:44)  Может, я наглухо испорчен борландсишным CODE class TMyThread : public TThread { protected: virtual void execute(); // А в этой теме предлагается вместо virtual передать базе тип потомка но мне это не кажется настолько ненормальным, что нельзя это добавить в саму ОС. Другое дело, если бы это ломало все существующие наработки, но оно же прозрачно для старых проектов. И не у меня последнего такая хотелка, как видим. Ну, с методами (виртуальными функциями) в борланде всё понятно - там-то это как правило именно тред - поток управления, который имеет начало и конец - вызвали его, он отработал и кончился. И тут нужна гибкость при вызове, чтобы можно строить элегантные схемы с обработкой - вызывать автоматом нужный в каждом контексте метод. Это не про нас. Что касается самой схемы передачи типа объекта аргументом шаблона, который участвует в наследовании, то это основа для создания стратегий (Александреску). Это достаточно глубокая вещь. В данном же случае это просто синтаксический выверт, и как ты выражаешься: "страдает моё чувство прекрасного".  Но как уже сказал выше, раз с совместимостью и кодогенерацией никаких проблем нет, пусть будет этот вариант, если он кому-то больше нравится (хотя я не вижу, повторяю, в этом особого смысла - инкапсулированного объекта не получается, придётся руками объявлять все поля-данные вне пределов класса и т.д.).
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Nov 14 2012, 03:33
|
Частый гость
 
Группа: Участник
Сообщений: 142
Регистрация: 10-11-12
Пользователь №: 74 318

|
Цитата(dxp @ Nov 13 2012, 22:52)  Вы путаете declaration (объявление) и definition (определение). Также вы путате явную (explicit) специализацию и полную (full) специализацию. Приведённый вами пункт стандарта гласит о том, что если используется явная специализация, то она должна быть объявлена в том же простанстве имён. Но где там сказано, что на должна быть определена в этом пространстве имён? У нас там нигде явной специализации не объявляется. На самом деле на этот пункт стандарта я вышел погуглив сообщение об ошибке. К сожалению, из той цитаты, что я привёл, действительно не ясно насчёт определения ф-ции. В общем, задал вопрос на RSDN: http://www.rsdn.ru/forum/cpp/4963144.all. Там есть спецы, знающие стандарт наизусть
--------------------
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|