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

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> Программный таймер, как красиво обойти переполнение?
Genadi Zawidowsk...
сообщение Jan 24 2014, 21:28
Сообщение #16


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Цитата(Golikov A. @ Jan 24 2014, 22:48) *
да ну бросьте.
это всего навсего
584 942.41735507203247082699137494 года
ничто по сравнению с жизнью вселенной...

если тик микросекунда..., а если пико?


НА примере XP дискретность 100 наносекунд. Инкрементируется на время периода системного тика.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jan 25 2014, 05:48
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



если 100 нан, то переполнение через 58.5 тыс лет.

Лично я рассчитываю что мои устройства спокойно преодолеют этот рубеж)
Go to the top of the page
 
+Quote Post
RabidRabbit
сообщение Jan 25 2014, 07:20
Сообщение #18


Местный
***

Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040



Цитата(scifi @ Jan 24 2014, 16:17) *
Вы невнимательно читали. Типы должны быть unsigned int.
А в вашем примере перед вычитанием значения приводятся к типу int (он же int64_t) со всеми вытекающими...

Во-первых, покажите в моём примере, где "значения приводятся к типу int (он же int64_t)" sm.gif
Во-вторых, смотрите на вариант с unsigned int (правда, уже gcc 4.8.1), на всякий случай - 64-битные регистры те, что на букву r:
CODE
int gggg( unsigned int a1, unsigned int a2 )
{
40057d: 55 push %rbp
40057e: 48 89 e5 mov %rsp,%rbp
400581: 89 7d fc mov %edi,-0x4(%rbp)
400584: 89 75 f8 mov %esi,-0x8(%rbp)
//
return (a2 - a1) <= 0;
400587: 8b 45 f8 mov -0x8(%rbp),%eax
40058a: 3b 45 fc cmp -0x4(%rbp),%eax
40058d: 0f 94 c0 sete %al
400590: 0f b6 c0 movzbl %al,%eax
}
400593: 5d pop %rbp
400594: c3 retq

но конечно, это кривой пример, так как разность двух беззнаковых больше 0 и компилятор прав, что использует здесь проверку на равенство.
а вот при сравнении беззнакового числа с результатом вычитания двух беззнаковых чисел (как в итоге сделал ТС) компилятор использует кондишн "больше или равно" в беззнаковом варианте и всё работает sm.gif
Go to the top of the page
 
+Quote Post
scifi
сообщение Jan 25 2014, 07:58
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(RabidRabbit @ Jan 25 2014, 11:20) *
Во-первых, покажите в моём примере, где "значения приводятся к типу int (он же int64_t)" sm.gif

Чего там показывать? Это неявное приведение. Почитайте какую-нибудь книжку про язык Си. Ищите "integer promotion".
Go to the top of the page
 
+Quote Post
Ruslan-maniak
сообщение Oct 28 2014, 08:30
Сообщение #20


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

Группа: Участник
Сообщений: 92
Регистрация: 27-12-12
Из: Томск
Пользователь №: 74 999



НО в данном способе (с вычитанием) мы должны гарантировать это вычитание каждую миллисекунду. А иначе есть шанс прошляпить равенство таймера и счётчика и тогда всё посыпется. Ведь так?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 28 2014, 08:54
Сообщение #21


Гуру
******

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



Цитата(Ruslan-maniak @ Oct 28 2014, 10:30) *
А иначе есть шанс прошляпить равенство таймера и счётчика и тогда всё посыпется. Ведь так?
Надо проверять не равенство, "а больше или равно" или "меньше или равно" - что подходит по контексту.


--------------------
На любой вопрос даю любой ответ
"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
Ruslan-maniak
сообщение Oct 28 2014, 09:50
Сообщение #22


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

Группа: Участник
Сообщений: 92
Регистрация: 27-12-12
Из: Томск
Пользователь №: 74 999



В этом и заключается мой вопрос. В приведённом примере вычитания - нет сравнения. Там только вычитание. И срабатывает оно только тогда когда именно равенство между счётчиком и таймером. А если использовать сравнение, то опять же упираемся в переполнение счётчика. Так как красиво то сделать?

Сообщение отредактировал Ruslan-maniak - Oct 28 2014, 10:22
Go to the top of the page
 
+Quote Post
ViKo
сообщение Oct 28 2014, 10:27
Сообщение #23


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Ruslan-maniak @ Oct 28 2014, 12:50) *
В этом и заключается мой вопрос. В приведённом примере вычитания - нет сравнения. Там только вычитание.

Есть. Нужно разницу сравнить с нулем (не на равенство...).
Go to the top of the page
 
+Quote Post
Ruslan-maniak
сообщение Oct 28 2014, 10:46
Сообщение #24


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

Группа: Участник
Сообщений: 92
Регистрация: 27-12-12
Из: Томск
Пользователь №: 74 999



На практике получается что если от меньшего беззнакового отнять большее беззнаковое то результат получается больше нуля, что собственно не удивительно. И данная конструкция не работает. Конечно если гарантировать программе что проверку она будет совершать точно каждую миллисекунду, то всё будет нормально. Но я бы не стал оставлять это на авось. На данный момент пришёл к такому решению: приводить разность перед сравнением к знаковому типу. И тогда всё нормально - обмануть таймер не получается какие бы значения счётчика не брать за начальные. Что об этом думаете?
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Oct 28 2014, 10:52
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



вы про какой из примеров то?

return(TSysTimer::Counter - StartCount >= Interval); - возвращается не разница, а результат сравнения.

У вас есть время начала и текущее время, их разность всегда есть интервал прошедшего времени. Проблемы только рассчитать интервал больше либо равный максимальному значению счетчика, потому что в этом случае после Максимум - 1, будет следовать 0, из-за переполнения. Но с этим ничего не сделаешь, кроме моего варианта
в прерывании таймера считать назад...

Цитата
Что об этом думаете?

думаем что вы не правыsm.gif

допустим у нас беззнаковое число 4 бита, для удобства

все его значения
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15

берем любое начало, допустим 7.
все значения от 8 до 15, не вызывают вопросов 8-7 = 1,... 15-7 = 8, честно получаем время прошедшие от 7 до текущего значения.

идем дальше, счетчик переполнился и получилось
0, 0 - 7 == -7, как это представлено в битах? 1001, а что это в беззнаковом числе? О чудо это 9

15-7 = 8, 0 - 7 = 9, 1 - 7 == - 6 (1010) == 10 и так далее, до

6 - 7 = -1 (1111) = 15;

то есть до полного цикла счетчика все переполнения отрабатываются правильно)
Go to the top of the page
 
+Quote Post
Ruslan-maniak
сообщение Oct 28 2014, 11:01
Сообщение #26


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

Группа: Участник
Сообщений: 92
Регистрация: 27-12-12
Из: Томск
Пользователь №: 74 999



Вот взяли мы это 7, и хотим что бы таймер сработал когда счётчик дойдёт до 12. И вы предлагаете вычитать 12 - 7 и сравнивать это с нулём, но так случилось что итерация 12 - 12 не случилась 12 - 11, а за ней уже 12 - 13, и та и другая даёт результат большей нуля в битовом выражении. И получается таймер не сработал тогда когда нужно. Разве нет?

Сообщение отредактировал Ruslan-maniak - Oct 28 2014, 11:01
Go to the top of the page
 
+Quote Post
ViKo
сообщение Oct 28 2014, 11:06
Сообщение #27


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Не так (я неправильно написал выше). Вам нужен интервал 5 (12 - 7). Текущее (стартовое) значение 7, запоминаете его. Дальше читаете значение таймера, отнимаете запомненное стартовое, и сравниваете разность с нужным интервалом.
Go to the top of the page
 
+Quote Post
Ruslan-maniak
сообщение Oct 28 2014, 11:14
Сообщение #28


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

Группа: Участник
Сообщений: 92
Регистрация: 27-12-12
Из: Томск
Пользователь №: 74 999



Но таким образом на каждый случай приходится по 2 переменных: стартовое время и интервал. Если же использовать приведение разности (значение срабатывания - счётчик) к знаковому типу и сравнения получившегося с нулём, то одна переменная.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Oct 28 2014, 11:24
Сообщение #29


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Тогда потеряете половину диапазона.
Go to the top of the page
 
+Quote Post
Ruslan-maniak
сообщение Oct 28 2014, 11:30
Сообщение #30


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

Группа: Участник
Сообщений: 92
Регистрация: 27-12-12
Из: Томск
Пользователь №: 74 999



Да я как-то не рассчитываю использовать интервал более 25 дней sm.gif



Сообщение отредактировал Ruslan-maniak - Oct 28 2014, 11:31
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 Текстовая версия Сейчас: 18th June 2025 - 10:04
Рейтинг@Mail.ru


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