реклама на сайте
подробности

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> Альтернативный вариант задания функции процесса
AHTOXA
сообщение Nov 14 2012, 07:47
Сообщение #31


фанат дивана
******

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



Цитата(dxp @ Nov 14 2012, 07:17) *
Э-э, мы, вроде, договорились, что если реализация не страдает, то принимаем. Т.ч. это можно не расширением, а основным вариантом делать. Клади в trunk, попробуем при случае.

Да я просто подумал, что незачем заставлять хорошего человека переступать через себя, если есть другой вариант, ничем не хуже. Расширение ничем не отличается в использовании, кроме необходимости добавления строчки #include "CustomProcess.h" в scmRTOS_extensions.h.
Думаю, что это не смертельноsm.gif
В общем, подумай ещё немножко, а я тем временем допилю его (там ещё не охвачен вариант с двумя стеками, и ещё что-то по мелочи), и выложу куда скажешь.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 14 2012, 08:46
Сообщение #32


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Сергей Борщ @ Nov 14 2012, 09:29) *
то указатель был бы на функцию-член, а он совсем другой и зависящий от реализации.

Рассуждаю.
А если сделать дополнительную статическую функцию, скажем, start(), с параметром типа "тип процесса", в init_stack_frame() использовать ее вместо exec, в стековый фрейм на место регистра, в котором передается параметр, класть this, А функция уже будет делать param->exec(). Т.е. мы не вдаемся в дебри реализации указателя на функцию-член, этим занимается компилятор в start(), exec может быть нестатическим. Как-то так... Еще неплохо бы объявить exec как noreturn, чтобы компилятор догалася заменить вызов exec() на переход в нее. В принципе, такое изменение достойно релиза 4.1. И продумать совместимость с текущими исходниками.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Nov 14 2012, 09:17
Сообщение #33


фанат дивана
******

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



Давайте я сюда добавлю ссылки на уже придуманные варианты. Вот вариант раз, вот вариант два. Я собственно их и хотел покрутить. Тем более, что с новым параметром шаблона это делать проще.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 14 2012, 11:25
Сообщение #34


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (AHTOXA @ Nov 14 2012, 11:17) *
Я изобрел ведосипед. "Говорят, у дураков мысли сходятся. Но у умных - ЧАЩЕ!"


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
dxp
сообщение Nov 14 2012, 11:57
Сообщение #35


Adept
******

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



QUOTE (Сергей Борщ @ Nov 14 2012, 15:46) *
А если сделать дополнительную статическую функцию, скажем, start(), с параметром типа "тип процесса", в init_stack_frame() использовать ее вместо exec, в стековый фрейм на место регистра, в котором передается параметр, класть this, А функция уже будет делать param->exec(). Т.е. мы не вдаемся в дебри реализации указателя на функцию-член, этим занимается компилятор в start(), exec может быть нестатическим. Как-то так... Еще неплохо бы объявить exec как noreturn, чтобы компилятор догалася заменить вызов exec() на переход в нее. В принципе, такое изменение достойно релиза 4.1. И продумать совместимость с текущими исходниками.

Нормальный ход. Вопрос остаётся с совместимостью. Как вариант - реализовать в расширениях, пользователь сам выбирает, что ему больше нравится. Я до сих пор не ощущаю необходимости объединять код реализации процесса с кодом прикладной программы, но если народ хочет (а его уже большинство по сравнению со мной), то возражать не могу.

P.S. Сам пока этим заниматься не могу, завален по уши текучкой, т.ч. инициативные товарищи - ваша инициатива - ваша реализация. sm.gif Делайте расширение (думаю, сразу в trunk). Кстати, интересный вопрос, можно ли будет использовать гибридную схему - часть процессов по традиционному варианту, часть по новому? Навскидку вижу препятствие - разный способ вызова (напрямую и через указатель). Вот если б можно было совместить этих ужа с ежом, это было бы действительно клёво. Хотя бы тем, что совместимость точно никуда не денется.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
ReAl
сообщение Nov 14 2012, 12:51
Сообщение #36


Нечётный пользователь.
******

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



Цитата(dxp @ Nov 14 2012, 13:57) *
Кстати, интересный вопрос, можно ли будет использовать гибридную схему - часть процессов по традиционному варианту, часть по новому? Навскидку вижу препятствие - разный способ вызова (напрямую и через указатель). Вот если б можно было совместить этих ужа с ежом, это было бы действительно клёво. Хотя бы тем, что совместимость точно никуда не денется.
Когда уже всё в стековом кадре, то все равно должно быть. А вот для формирования...
Отдельно уже проверенные на совместимость process / custom_process, с применением process всё как раньше, но можно отнаследоваться от coustom_process вручную.
Отдельно какой-то process_object, который имеет свою статическую функцию и соответствующая функция для форимрования начального стекового кадра.

Хотя как раз для формирования кадра может быть одна функция, просто принимать два указателя -- на функцию и на аргумент для неё void* типа (или хорошо подумать какого -- у MSP430X ведь слово 16 бит а указатели могут быть длиннее?).

process / custom_process будут передвавть указатель на exec и 0

process_object будет передавать указатель на статическую функцию и this.

Переключателю задач и компании до лампочки, как оно было инициализировано.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
ArtDenis
сообщение Nov 14 2012, 13:43
Сообщение #37


Частый гость
**

Группа: Участник
Сообщений: 142
Регистрация: 10-11-12
Пользователь №: 74 318



Всё-таки расставлю точки над i по поводу текущего варианта специализации функции процесса. На RSDN мне ответили, что реализация специализации функции шаблонного класса может быть сделана за пределами именованной области где был объявлен шаблон класса, но для этого надо обязательно надо сделать объявление этой специализации функции в той именованной области, где был объявлен шаблон класса.
Т.е. нельзя писать
Код
typedef OS::process<OS::pr0, 200> TestProcess;

template<> void TestProcess::exec()
{
}


Правильно писать так:
Код
typedef OS::process<OS::pr0, 200> TestProcess;

namespace OS
{
    template<> void TestProcess::exec(); // предварительно объявляем в void TestProcess::exec в namespace OS
}

// реализуем void TestProcess::exec в глобальной области видимости
template<> void TestProcess::exec()
{
}


В общем, как-то так


--------------------
http://ufa-darts.ru/ - собираем дартс-лигу в Уфе
Go to the top of the page
 
+Quote Post
ReAl
сообщение Nov 14 2012, 13:45
Сообщение #38


Нечётный пользователь.
******

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



Цитата(ArtDenis @ Nov 14 2012, 05:33) *
В общем, задал вопрос на RSDN: http://www.rsdn.ru/forum/cpp/4963144.all. Там есть спецы, знающие стандарт наизусть sm.gif

Ну да.
Только конкретно у gcc где-то нелады и вышло, что
Код
namespace OS {
    template<> TProc1::exec();
}

template<> TProc1::exec()
{
    ...
}
он всё компилирует нормально, но выдаёт предупреждение redundant redeclaration и как предыдущее объявление тычет носом в OS_Kernel.h, в объявление неспециализированной функции в теле
Код
        template<TPriority pr, size_t stack_size>
        class process : public TBaseProcess
        {
        public:
            INLINE_PROCESS_CTOR process();

            OS_PROCESS static void exec();  // <---- вот сюда

Но при этом просто
Код
template<> TProc1::exec()
{
    ...
}
не собирает, тут ему уже того объявления недостаточно.
Вот и вышло, что минимальной кровью так, определение-объявление одним махом:
Код
namespace OS {
    template<> TProc1::exec()
    {
        ...
    }
}
что тоже допускается.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
ArtDenis
сообщение Nov 14 2012, 14:00
Сообщение #39


Частый гость
**

Группа: Участник
Сообщений: 142
Регистрация: 10-11-12
Пользователь №: 74 318



Цитата(ReAl @ Nov 14 2012, 19:45) *
Ну да.
Только конкретно у gcc где-то нелады и вышло, что
Код
namespace OS {
    template<> TProc1::exec();
}

template<> TProc1::exec()
{
    ...
}

void потерялся. Поэтому и предупреждение вышло.

Тот пример, что я выкладывал сообщением выше компилируется без предупреждений.


--------------------
http://ufa-darts.ru/ - собираем дартс-лигу в Уфе
Go to the top of the page
 
+Quote Post
ReAl
сообщение Nov 14 2012, 15:01
Сообщение #40


Нечётный пользователь.
******

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



Цитата(ArtDenis @ Nov 14 2012, 16:00) *
void потерялся. Поэтому и предупреждение вышло.

Ой, ну это я тут из головы забыл, в тексте void есть.
И без него совершенно другая ругань
Код
namespace OS {
   template<> TProc1::exec(); // Строка 161
}

template<> TProc1::exec() // Строка 164
{
    DRIVER(PROC1,OUT);
    DRIVER(TIMER1_TO_PROC1,OUT);
    for(;;) {
        OFF(PROC1);
        Timer1_Ovf.wait();
        ON(PROC1);
        OFF(TIMER1_TO_PROC1);
    }
} // TProc1::exec()
Код
==== Compiling ./src/main.cpp
./src/main.cpp:161:29: error: expected constructor, destructor, or type conversion before ‘;’ token
./src/main.cpp:164:25: error: ISO C++ forbids declaration of ‘exec’ with no type
./src/main.cpp:164:12: error: template-id ‘exec<>’ for ‘int OS::process<(OS::TPriority)0u, 100u>::exec()’ does not match any template declaration

Цитата(ArtDenis @ Nov 14 2012, 16:00) *
Тот пример, что я выкладывал сообщением выше компилируется без предупреждений.
-Wredundant-decls есть?
С ним и с -Wredundant-decls
Код
namespace OS {
   template<> void TProc1::exec(); // Строка 161
}

template<> void TProc1::exec()  // Строка 164
{
    DRIVER(PROC1,OUT);
    DRIVER(TIMER1_TO_PROC1,OUT);
    for(;;) {
        OFF(PROC1);
        Timer1_Ovf.wait();
        ON(PROC1);
        OFF(TIMER1_TO_PROC1);
    }
} // TProc1::exec()
Код
==== Compiling ./src/main.cpp
./src/main.cpp:161:33: warning: redundant redeclaration of ‘static void OS::process<pr, stack_size>::exec() [with OS::TPriority pr = (OS::TPriority)0u, unsigned int stack_size = 100u]’ in same scope
../scmRTOS/Common/OS_Kernel.h:333:36: warning: previous declaration of ‘static void OS::process<pr, stack_size>::exec() [with OS::TPriority pr = (OS::TPriority)0u, unsigned int stack_size = 100u]’


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
ArtDenis
сообщение Nov 14 2012, 15:21
Сообщение #41


Частый гость
**

Группа: Участник
Сообщений: 142
Регистрация: 10-11-12
Пользователь №: 74 318



Цитата(ReAl @ Nov 14 2012, 21:01) *
-Wredundant-decls есть?

Да, с -Wredundant-decls такое-же предупреждение вылезло. Честно говоря даже не знаю что оно означает.


--------------------
http://ufa-darts.ru/ - собираем дартс-лигу в Уфе
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Nov 15 2012, 19:49
Сообщение #42


фанат дивана
******

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



Я вот что подумал. В момент вызова TBaseProcess::init_stack_frame() у нас уже гарантированно имеется в нужных регистрах указатель на TBaseProcess. Таким образом, ничего формировать не надо, достаточно лишь честно сохранить контекст, подменив PC адресом начала функции-члена exec().
Для пробы можно сделать в конструкторе наследника, как-то так:
Код
class BaseVirtualProcess : public TBaseProcess
{
public:
    INLINE_PROCESS_CTOR BaseVirtualProcess(stack_item_t * StackPoolEnd, TPriority pr)
        : TBaseProcess(StackPoolEnd, pr, 0 // - не нужен)
    {
        reinit_stack_frame();
    }
protected:
    OS_PROCESS virtual void exec() {}; // это наш виртуальный exec()
private:
    void reinit_stack_frame()
    {
        StackPointer += 16;                           // отменим деятельность TBaseProcess::init_stack_frame()
        *(--StackPointer)  = 0x01000000L;             // xPSR
        *(--StackPointer)  = reinterpret_cast<uint32_t>(&exec); // вот здесь адрес виртуального exec
        // и тут честно сохраняем остальные регистры, в том числе и self. (наверное будет ассемблерная процедура в порте)
    }
};

Правда reinterpret_cast здесь не проходит, надо какой-то ещё способ получить адрес exec().

---
Добавлю ссылочку про получение адреса функции-члена. На завтраsm.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
ReAl
сообщение Nov 15 2012, 20:19
Сообщение #43


Нечётный пользователь.
******

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



Не надо адрес функции-члена... Слова C++ extensions (а у кого-то может такого расширения не быть) и необходимость выключить предупреждение настораживают.

Лучше со статической функцией и this ей как аргумент. Прозрачнее.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
ArtDenis
сообщение Nov 16 2012, 03:41
Сообщение #44


Частый гость
**

Группа: Участник
Сообщений: 142
Регистрация: 10-11-12
Пользователь №: 74 318



AHTOXA, Указатель на нестатическую функцию член класса в с++ - это не настоящий указатель. Его структура и размер зависят от компилятора. Поэтому чтобы узнать адрес ф-ции, надо выяснить где именно в структуре этого указателя "сидит" конкретно адрес для перехода.
А зачем вообще нужна нестатическая функция для процесса? Всё равно каждый процесс существует в единственном экземпляре.


--------------------
http://ufa-darts.ru/ - собираем дартс-лигу в Уфе
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Nov 16 2012, 19:41
Сообщение #45


фанат дивана
******

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



Цитата(ArtDenis @ Nov 16 2012, 09:41) *
AHTOXA, Указатель на нестатическую функцию член класса в с++ - это не настоящий указатель. Его структура и размер зависят от компилятора. Поэтому чтобы узнать адрес ф-ции, надо выяснить где именно в структуре этого указателя "сидит" конкретно адрес для перехода.

Я понимаю это. Потому и говорил не об указателе на функцию-член, а об её адресе. Но вот нестандартность такого решения - это действительно плохо.
Цитата(ArtDenis @ Nov 16 2012, 09:41) *
А зачем вообще нужна нестатическая функция для процесса? Всё равно каждый процесс существует в единственном экземпляре.

Чтобы обращаться к членам класса. Чтобы инициализировать их в конструкторе. Чтобы обращаться к унаследованным функциям класса, в конце концов. Короче, чтоб инкапсуляцияsm.gif

Цитата(ReAl @ Nov 16 2012, 02:19) *
Не надо адрес функции-члена...

Ладно, ладноsm.gif
Сделал вариант с виртуальным exec().
В процессе работы обратил внимание, что TKernelAgent::cur_proc() - private. Мне непонятно такое недоверие к потомкам TKernelAgent:)
Пришлось выкручиваться так:
Код
TBaseProcess* base = const_cast<TBaseProcess*>(get_proc(cur_proc_priority()));

вместо тривиального
Код
TBaseProcess* base = cur_proc();


Обратил внимание, что gcc довольно своеобразно понимает атрибут noreturn. Он перестаёт восстанавливать испорченные регистры, но всё равно сохраняет их! sm.gif
За счёт этого, кстати, вариант с виртуальным exec не проигрывает по стеку варианту с вызовом Slon.exec() из SlonProc::exec().
Хотя нет, всё равно проигрывает. Там же вызов через виртуальный транк...

В общем, вот, смотрите/критикуйте:
CODE
#ifndef VIRTUALPROCESS_H_
#define VIRTUALPROCESS_H_

#include <scmRTOS.h>

namespace OS
{

class BaseVirtualProcess : public TBaseProcess, public TKernelAgent
{
public:
INLINE_PROCESS_CTOR BaseVirtualProcess(
stack_item_t * StackPoolEnd
, TPriority pr
#if scmRTOS_DEBUG_ENABLE == 1
, stack_item_t * aStackPool
#endif
) : TBaseProcess(
StackPoolEnd
, pr
, launch_exec
#if scmRTOS_DEBUG_ENABLE == 1
, aStackPool
#endif
)
{
}
protected:
OS_PROCESS virtual void exec() { for(;;){} };
private:
OS_PROCESS static void launch_exec()
{
for(;;) // eliminate compiler warning
{
TBaseProcess* base = const_cast<TBaseProcess*>(get_proc(cur_proc_priority()));
// TBaseProcess* base = cur_proc(); // private!
BaseVirtualProcess* proc = static_cast<BaseVirtualProcess*>(base);
proc->exec();
}
}
};


template<TPriority pr, size_t stack_size>
class VirtualProcess : public BaseVirtualProcess
{
public:
INLINE_PROCESS_CTOR VirtualProcess()
: BaseVirtualProcess(&Stack[stack_size/sizeof(stack_item_t)]
, pr
#if scmRTOS_DEBUG_ENABLE == 1
, Stack
#endif
)
{
}
private:
stack_item_t Stack[stack_size/sizeof(stack_item_t)];
};

} // namespace OS


#endif /* VIRTUALPROCESS_H_ */


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post

4 страниц V  < 1 2 3 4 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 15th July 2025 - 09:32
Рейтинг@Mail.ru


Страница сгенерированна за 0.01525 секунд с 7
ELECTRONIX ©2004-2016