Russian Qt Forum

Qt => Общие вопросы => Тема начата: yashaka от Февраль 18, 2010, 15:29



Название: usleep() usage
Отправлено: yashaka от Февраль 18, 2010, 15:29
Столкнулся с такой проблемой - usleep() спит дольше чем необходимо.
Вот доказательства:)
Код:
#include <QtCore>
class SleepThread : public QThread
{
public:
    SleepThread(QObject *parent = 0) : QThread(parent)
    {
    }
    ~SleepThread()
    {
    }
protected:
    void run()
    {
        str = "1\t2\t1 000\t14 000\t15 000\t16 000\t17 000\t50 000\t100 000\t";
        qDebug() << str << endl;
        str.clear();

        for (int i = 0; i < 20; ++i) {
            testUSleep(1);
            testUSleep(2);
            testUSleep(1000);
            testUSleep(14000);
            testUSleep(15000);
            testUSleep(16000);
            testUSleep(17000);
            testUSleep(50000);
            testUSleep(100000);
            qDebug() << str << endl;
            str.clear();
        }
    }
private:
    QString str;
    QTime t1, t2;

    void testUSleep(int t)
    {
        t1 = QTime::currentTime();
        usleep(t);
        t2 = QTime::currentTime();
        str += QString::number(t1.msecsTo(t2)) + "\t";
    }

};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    SleepThread sleeper;
    sleeper.start(QThread::TimeCriticalPriority);
    sleeper.wait();
    return a.exec();
}
Результат исполнения примера:

Код:
"1	2	1 000	14 000	15 000	16 000	17 000	50 000	100 000	" 
"0 0 0 15 32 15 16 47 109 "
"0 0 0 16 15 16 16 62 94 "
"0 15 0 16 16 15 16 47 109 "
"0 0 0 16 15 32 15 47 110 "
"0 0 0 15 16 15 16 63 93 "
"0 0 16 16 15 16 15 47 110 "
"0 0 0 15 16 16 31 47 93 "
"16 0 0 16 15 16 16 62 94 "
"0 0 0 15 32 15 16 47 109 "
"0 0 0 16 15 16 16 62 94 "
"0 16 0 15 16 15 16 47 109 "
"0 0 0 16 16 31 15 47 110 "
"0 0 0 15 16 16 15 63 93 "
"0 0 16 16 15 16 16 46 110 "
"0 0 0 15 16 16 31 47 94 "
"15 0 0 16 15 16 16 62 94 "
"0 0 0 16 31 15 16 47 109 "
"0 0 0 16 16 15 16 62 94 "
"0 16 0 15 16 16 15 47 109 "
"0 0 0 16 16 31 16 46 110 "

// В первой строке  указано время в микросекундах которое передавалось usleep()
// Соответственно в столбцах время паузы в милисекундах

Выходит на эту функцию положится нельзя?
Или это я что то не так делаю? Или QTime врет? И вообще с чем могут быть связаны такие пересыпания?
// В примере я запускаю поток с наивысшим приоритетом, так как заметил что чем он ниже тем чаще такие "выбросы", а иногда и больше...

Если это действительно проблема usleep, то как тогда мне можно сделать паузы в размере десятков микросекунд и в 1 милисекунду?
//в принципе можно циклы гонять столько сколько нужно (перед этим высчитав), но хотелось бы чего то более точного что ли...


Название: Re: usleep() usage
Отправлено: kuzulis от Февраль 18, 2010, 15:41
Это проблема ОС! а т.к. Ваша ОС - не из ряда RTOS  (догадываюсь :) ) - то и положиться на точное измерение времени нельзя (ИМХО),
тем более эти паузы будут отличаться в зависимости от нагрузки на ОС...


Название: Re: usleep() usage
Отправлено: yashaka от Февраль 19, 2010, 09:49
"Эх, жизнь моя жестянка...":)
Ну что же, придется как то научиться с этим жить))))
Спасибо за ответ!


Название: Re: usleep() usage
Отправлено: SASA от Февраль 20, 2010, 13:23

Если это действительно проблема usleep, то как тогда мне можно сделать паузы в размере десятков микросекунд и в 1 милисекунду?

В винде usleep вызывает Sleep(). А он приостанавливает поток - операция накладная. Переключить поток, дать поработать другим, вернуться к нашему потоку. Давно (на четвертом пне) Sleep(1) равнялось минимум 15 мсек.


Название: Re: usleep() usage
Отправлено: Alex Custov от Февраль 21, 2010, 08:44
sleep как правило передаёт управление в планировщике задач следующей задаче. Когда планировщик вернётся к этой задаче и установит, что она уже не спит, зависит от настроек (например в linux от CONFIG_HZ). Отсюда задача может проспать дольше, чем ей сказали через sleep. Накладность задачи тут ни при чём.


Название: Re: usleep() usage
Отправлено: Firefox от Март 09, 2010, 21:48
я вот кстати задержки реализовывала по другому,уже не помню, но со sleep что-то не так было, какой вариант лучше?
Код:
QTime t_time;
for(;t_time<elapsed(1000);)
{
qApp->processEvents();
}


Название: Re: usleep() usage
Отправлено: Alex Custov от Март 09, 2010, 21:57
я вот кстати задержки реализовывала по другому,уже не помню, но со sleep что-то не так было, какой вариант лучше?

Сначала нужно разобраться что не так было со sleep, т.к. данный код, естественно, - костыль.


Название: Re: usleep() usage
Отправлено: Firefox от Март 09, 2010, 22:06
ну например у еня приложение закрываться должно по нажатию на esc, если я нажимаю кнопку в момент когда работает sleep то закроется оно когда закончиться задержка. а у меня она допустим 15 секунд. и что мне ждать. в цикле всё закрывается сразу. и ещё - что такое на вашем жаргоне костыль?я конечно интуитивно понимаю, но словами не могу подобрать


Название: Re: usleep() usage
Отправлено: Alex Custov от Март 10, 2010, 00:02
ну например у еня приложение закрываться должно по нажатию на esc, если я нажимаю кнопку в момент когда работает sleep то закроется оно когда закончиться задержка. а у меня она допустим 15 секунд. и что мне ждать. в цикле всё закрывается сразу

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


Название: Re: usleep() usage
Отправлено: Firefox от Март 10, 2010, 13:19
 у меня очень много процессов сразу работает, например один текст с задержкой меняется на другой  и всё это в таймере каждую секунду. таймер запускается по нажатию на кнопку. если у меня задержка 5 сек, то таймер просто стопариться. а так получается. а как со слотом?я не знаю такого решения. подскажите хоть в общем что за  и как работает


Название: Re: usleep() usage
Отправлено: Igors от Март 10, 2010, 16:58
у меня очень много процессов сразу работает, например один текст с задержкой меняется на другой  и всё это в таймере каждую секунду. таймер запускается по нажатию на кнопку. если у меня задержка 5 сек, то таймер просто стопариться. а так получается. а как со слотом?я не знаю такого решения. подскажите хоть в общем что за  и как работает
Использовать usleep не стоит (по крайней мере в UI для пользователя) по причине его тормознутости и отсутствия всякой гибкости. Нормальное решение - зарядить одиночный (или многоразовый) таймер который пошлет нужный сигнал в нужное время. При получении этого сигнала будут выполнены нужные действия.

"Костыль" на молодежном жаргоне означает - сиюминутное, "быстрое" решение проблемы, за которое, однако, придется расплачиваться в дальнейшем. "Латание дырок" вместо того чтобы сделать "капитально"


Название: Re: usleep() usage
Отправлено: Alex Custov от Март 10, 2010, 20:38
"Костыль" на молодежном жаргоне означает - сиюминутное, "быстрое" решение проблемы, за которое, однако, придется расплачиваться в дальнейшем.

Почему на молодёжном? :) http://lurkmore.ru/Костыль (http://lurkmore.ru/Костыль)