Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Точный Sleep()


Автор: NextAlex 20.3.2006, 18:57
Привет всем!

Возникла проблема, с которой никак не могу справиться. Есть программа, работающая с железякой через COM-порт. В бесконечном цикле записывается несколько управляющих пакетов, последний из которых - запрос состояния после чего считывается ответ. Всё бы хорошо, но нужно чтобы общение проходило на максимально возможной скорости, в смысле цикл запись-чтение повторялся с максимально возможной частотой. Но при записи в порт без временного разрыва между пакетами происходит толи переполнение буфера записи, толи железяка не успевает принимать передаваемые пакеты и появляются потери данных. Помахавшись я понял что после записи пакета необходимо делать паузу около 5 мс и тогда полный порядок, но стандартный Sleep() делает паузу с точностью в 10 - 15 мс, а написанный мной держит точно, но слишком уж сильно загружает процессор, что не удивительно smile .
Посоветуйте что можно сделать.
вот мой sleep:
Код

void sleep(int mstime){
     LARGE_INTEGER a, b, f; 
     __int64 m_Time, count;
        m_Time = 0;
     QueryPerformanceFrequency(&f); 
     QueryPerformanceCounter(&a);
     b = a;
     while ((m_Time/1000) < (__int64)mstime){
         Sleep(0);
        QueryPerformanceCounter(&b);
        m_Time = (__int64)(b.QuadPart - a.QuadPart)*1000000/(__int64)(f.QuadPart); 
     }
}

ну и функция записи:
Код

void WriteBoard(int _buffer[])
{
    UCHAR __buffer[5];
    unsigned long BytesWritten;
        for (int i = 0; i < len; i++){
            __buffer[i] = (_buffer[i]&0xFF);
        }
        if (BoardHandle != INVALID_HANDLE_VALUE){
            WriteFile(BoardHandle, __buffer, 5, &BytesWritten, NULL);
        }
        FlushFileBuffers(BoardHandle);
        sleep(5);
}

Автор: _hunter 20.3.2006, 19:07
понизь приоритет потока.
+ что ты хотел? -- и скорость держать и ресурсы не занимать?

Автор: NextAlex 20.3.2006, 19:20
Цитата(_hunter @ 20.3.2006, 19:07 Найти цитируемый пост)
что ты хотел? -- и скорость держать и ресурсы не занимать?

я понимаю что ты эксперт и все понты smile (без обид), но таки осмелюсь спросить - ты код моего sleep-а смотрел ? smile
Ресурсы в моем случае занимает как раз sleep, потому что строка Sleep(0) выполняется порядка 4-5 микросекунд и запрос времени около 2-3 микросекунд, соответственно на каждую милисекунду слипа проходит порядка 150 циклов конкретно загрузки процессора ...

Автор: _hunter 20.3.2006, 19:46
смотрел. ни слова о приоритете потока там нет.
+ непонятны твои претензии. пусть один sleel уходит 8мкс. тогда на 1000 sleel-ов уйдет 8сек (нигде не ошибся? )
а если ты понизиш приоритет -- за это же время управление на твой поток передадут 500 раз ( при наличии других потоков )

Автор: maxim1000 20.3.2006, 20:12
в подобных случаях, ИМХО, самый эффективный путь использования скорости канала - подтверждение приема
т.е. когда железяка готова принимать, она посылает сигнал, когда не готова - другой
в COM-порте для этого есть специальных линии: RTS, CTS
1 - можно передавать, 0 - нельзя
(или наоборот, не помню)

ну или можно в сам поток данных вставлять пакеты такого назначения

если железяка своя - реализовать это проблем не составит
если чужая - стоит посмотреть, нет ли у нее какого-нибудь способа сообщать готовность...

Автор: NextAlex 21.3.2006, 00:10
_hunter, а я и не говорил что там есть что-то о приоритете ... smile
просто этот способ не подходит, поскольку кроме общения с железякой программа параллельно выполняет еще насколько задач и если приоритет потока чтения/записи не будет хотя бы NORMAL_PRIORITY, то задержки начинают появляться в самый неподходящий момент и становится еще хуже. А Sleep(0) не передает управление другим потокам, поэтому ресурсов такая схема загребает по-максимуму.

maxim1000, насчет RTS и CTS я знаю, но железяка не поддерживает эти сигналы и переделать возможности пока нет.
Посему потребность в точном слипе остается.
Может кто-то знает как вообще работает Sleep ? Или может кто встречал исходники чего-то подобного ?
И еще может кто знает как перехватить прерывание мыши ?

Автор: bilbobagginz 21.3.2006, 00:39
переходи на *nix и юзай usleep() ( микрослип - микросекунды )
или вообще rtc ( real time clock )

пока.

Автор: NextAlex 21.3.2006, 00:43
bilbobagginz, к чему и стремлюсь, тока вот под виндами нужно сначала доделать smile

Автор: _hunter 21.3.2006, 12:05
Цитата(NextAlex @ 20.3.2006, 23:10 Найти цитируемый пост)
А Sleep(0) не передает управление другим потокам, поэтому ресурсов такая схема загребает по-максимуму.

в смысле? единственно что делает Sleep(0) -- это передает управление другому потоку.
Цитата(NextAlex @ 20.3.2006, 23:10 Найти цитируемый пост)
если приоритет потока чтения/записи не будет хотя бы NORMAL_PRIORITY, то задержки начинают появляться в самый неподходящий момент и становится еще хуже

значит нужно алгоритм перебрать. может буфферизацию ввести

Автор: NextAlex 21.3.2006, 15:28
_hunter, мне это начинает надоедать
Цитата(_hunter @ 21.3.2006, 12:05 Найти цитируемый пост)
единственно что делает Sleep(0) -- это передает управление другому потоку
- читай мануалы - они рулез
Тебе прислать программку, которая будет спать по этому методу секунд 30, чтобы ты мог ощутить всю полноту тормозов smile ? Или сам напишешь ?

Цитата(_hunter @ 21.3.2006, 12:05 Найти цитируемый пост)
значит нужно алгоритм перебрать. может буфферизацию ввести

я понимаю что ты умный и все такое и я на самом деле так думаю после того как почитал парочку твоих постов, но вот упрямый ты как стадо баранов. Будь человеком - оставь мои потоки и алгоритм в покое smile
Скажи что-нить дельное насчет слипа...

Автор: SergeCpp 21.3.2006, 15:34
MSDN

Sleep

The Sleep function suspends the execution of the current thread for at least the specified interval.

To enter an alertable wait state, use the SleepEx function.

VOID Sleep(
DWORD dwMilliseconds
);

Parameters
dwMilliseconds
[in] Minimum time interval for which execution is to be suspended, in milliseconds.
A value of zero causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run. If there are no other threads of equal priority ready to run, the function returns immediately, and the thread continues execution.

Автор: Earnest 21.3.2006, 15:44
Цитата(NextAlex @ 21.3.2006, 15:28 Найти цитируемый пост)
_hunter, мне это начинает надоедать

Веди себя прилично, будь другом - это ведь ты помощи просишь.

Тебе русским языком говорят - не получится под Win сделать более точный Sleep (разве что таким способом, как ты сделал в начале, с пожиранием процессорного времени). То, что стандартный Sleep работает с довольно большой дискретностью - завязано на передачу управления между потоками, а не потому, что дяди из Редмонда туда тебе назло задержки встроили.
Так что ищи другой выход - пересматривай свои алгоритмы, как уже было сказано.

Автор: SergeCpp 21.3.2006, 15:52
MSDN

The SleepEx function suspends the current thread until one of the following occurs:

An I/O completion callback function is called

Не поможет?

Автор: NextAlex 21.3.2006, 16:20
Earnest, К сожалению не могу никак вспомнить твое имя, посему буду обращаться как получится ...
Насчет того что я обратился за помощью я в курсе, но меня честно говоря раздражает когда знающий человек начинает ну если ни нести пургу, то во всяком случае не может толком пояснить свою мысль. Я старался не сказать _hunter ничего сильно обидного, хотя в первый момент желание было.
Почему слип спит неодинаковое время я тоже знаю ... а вот насчет дискретности (если ты конечно это слово хотела сказать) могу с тобой довольно активно поспорить, есть желание - пиши в аську smile .
Если за невозможности создать более точный слип под виндами выскажется еще кто-то, то я скорее всего соглашусь с этим, а пока вопрос остается открытым.
Алгоритмы пересмотрены были уже не один раз.

PS. Дабы избежать лишних непоняток прошу мнение излагать более внятно чем _охотник.
PPS. Я не хочу никого обидеть, просто временами у меня стиль общения не очень приятный и подзадолбался я в последние дни. Посему у всех на кого мои слова произвели плохое впечатление и на кого они еще произведут таковое прошу прощения.

Автор: _hunter 21.3.2006, 16:52
значит ставь задачу заново. потому как из первого твоего поста следует что проблемой является чрезмерная загрузка процессора, а из последнего -- низкая точность решения...

Автор: NextAlex 21.3.2006, 17:20
_hunter, пытался добавить тебе плюс в репутацию за то что не обиделся, но за неимением необходимого количества постов не получилось, посему добавь себе сам от моего имени smile .
По большому счету изменение алгоритма или приоритета потока я выходом не считаю.
Уточненние задачи: нужен аналог стандартной функции Sleep(), который будет отличаться более точным временем сна (хотя бы ±2мс) и не будет слишком сильно грузить процессор.
Кстати, признаю что изначально вопрос был поставлен не совсем точно ...
SergeCpp, по-моему она отличается только тем что может быть прервана, но сейчас попробую.

Автор: Romikgy 21.3.2006, 17:23
Цитата(NextAlex @ 21.3.2006, 15:20 Найти цитируемый пост)
ничего сильно обидного

плохо smile старался
Цитата(NextAlex @ 21.3.2006, 15:20 Найти цитируемый пост)
Почему слип спит неодинаковое время я тоже знаю

раз знаешь то чего спрашиваешь?
Имхо если железяка ваша, в ней ковырятся нужно

Автор: NextAlex 21.3.2006, 17:37
Цитата(Romikgy @ 21.3.2006, 17:23 Найти цитируемый пост)
Имхо если железяка ваша, в ней ковырятся нужно

я бы с удовольствием smile , но есть еще несколько приколов, подтверждающих мою уверенность в том что проблема не в железяке а в виндах. Кроме того в железяке я уверен на все 110%.

Автор: Romikgy 21.3.2006, 17:47
1. вопрос, почему посылаются только по 5 байтов?
имхо посылатся должен весь пакет, а железяка, должна переваривать что кому, если она многофункциональная,
и 2. винда никогда не гарантировала, соблюдения каких либо интервалов, она многопотоковая (имхо могу с названием путать гуру поправят) и для каждого процесса выделяется квант процессорного времени (думаю что это ты и так знаешь smile) так что просить у винды , чтобы она чтото точно меряла, не сильно, имхо, разумно,
надо юзать события, или привязыватся к порту/железу ,
мож ксати ждущий таймер те подойдет, но тоже не уверен, что у него точность выше

Автор: NextAlex 21.3.2006, 18:06
Цитата(Romikgy @ 21.3.2006, 17:47 Найти цитируемый пост)
вопрос, почему посылаются только по 5 байтов?

это и есть весь пакет
Цитата(Romikgy @ 21.3.2006, 17:47 Найти цитируемый пост)
так что просить у винды , чтобы она чтото точно меряла, не сильно, имхо, разумно

етсть много неразумных вещей, которые почему-то работают smile , а ждущий таймер по тем же законам пашет ...

Автор: Earnest 21.3.2006, 18:10
Цитата(Romikgy @ 21.3.2006, 17:47 Найти цитируемый пост)
мож ксати ждущий таймер те подойдет, но тоже не уверен, что у него точность выше

А я уверена - точно такая же (из той же бочки наливают). Сама не так давно сильно обломалась.
Т.е. не спасет.


Автор: Romikgy 22.3.2006, 09:51
Цитата(NextAlex @ 21.3.2006, 17:06 Найти цитируемый пост)
ждущий таймер по тем же законам пашет

имхо не совсем

Цитата(Earnest @ 21.3.2006, 17:10 Найти цитируемый пост)
из той же бочки наливают

Пусть будет так smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)