| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Очень быстрая синхронизация |
| Автор: cupper 17.5.2012, 17:42 | ||||
| Делаем кроссплатформенно. В общем такая проблема. Есть два потока, T1, T2. T1 крутится в цикле, с интервалом в 5mcs (тобишь очень быстро). В Т2 цикл выполняется с интервалов в 300 миллисекунд. Нужно между ними синхронизатор две переменный (одна структура из двух полей).
Т.е. действие выполненное в T1 и время когда оно было выполнено. Нужно сделать минимальную задержку в T1. Так что мютексы, отпадают. Есть две идеи: 1. В структура State добавляем булев флаг (аля критической секции)
Плохо то, что если и Т1 и Т2 выполняются одним ядром (псевдо мультипоточность) и мы например в Т1 начали работу (state.lock = true), потом планировщик переключился в T2, то T2 будет болтаться в пустом цыкле, пока управление не будет передано опять в T1 который освободит псевдомютекс. Вообще вероятность этого велика ли ? что столь мелкие части кода будет вставлено переключение контекстов ? Самая долгая операция будет time(NULL). 2. Обе переменные State вместить в одну int64 и работать с ней атомарно. Это будет вообще без блокировок. Но просто лень возиться с побитовыми операциями |
| Автор: Леопольд 17.5.2012, 22:32 | ||
Может можно сделать проще с обычным мьютексом?
смысл в том что синхронизация будет происходить не чаще чем раз в секунду (при условии что оба потока одновременно залочили мьютекс). |
| Автор: volatile 18.5.2012, 00:05 |
Если экшенов немного. 3, как здесь или 4, то можно попытаться их запихать с time_t в одну атомарную 32-битную переменную. за счет младших битов например, или старших, смотря чем вы готовы пожертвовать, точностью или абсолютной величиной. это и будет, имхо |
| Автор: Леопольд 18.5.2012, 08:06 | ||
Да и time_t скоро будет 64 бита. Хотя, тут можно "схитрить", из потока в поток передавать только N младших бит, недостающие биты брать из сискола time() Но мне больше по душе первый вариант. IMHO, он производительнее (нет второго сискола) и правильно хендлится смена сис. времени. |
| Автор: cupper 18.5.2012, 14:08 | ||||||||
думал об этом. Но это может привести к по секундному провалу времени выполнения th1.
Вот это уже боле печалька. Но задача решается под конкретного заказчика, с не сказать что топовыми, но и не со старыми серверами.
Порядок важен до секунд до 10-20 (а может и 60-ти, зависит от настройки). 32битная time_t мне и так уже душу режит что это только до 2038 года Состояний у меня не больше 8. Т.е. 3 млашие бита, т.е. точность до 8 секунд. Думаю пойдет. В крайнем случае можно расширить до 4 бит, и точность будет до 16 секунд, что тоже приемлемо. Но думаю, из за пункта выше, это в принципе не так важно. Но зато, наконец то до меня дошло как решить проблему 2038 года для себя То, что разработка ведется на 64 битной системе, но собирается под x32 не дает мне понять сейчас time_t уже 64 для любой архитектуры или все еще зависит от разрядности ? Может можно как то явно обращаться к time64 ? Под винду это есть _time64, но вот под линукс... там я что то этого не нашел.
не понял. |
| Автор: Леопольд 18.5.2012, 20:50 | ||||
Ты не рассматривал возможность использования condition variable? |
| Автор: volatile 18.5.2012, 23:50 | ||||
Леопольд, не очень хороший код. Между вывовами время, может измениться. и где гарантия что это не затронет 4 старших бита? маловероятно, пожалуй. Но тем не менее, не чисто. (Раз неприятность может случиться, то по законам Мерфи она обязательно случится).
Ну раз так, что проще запихать экшены, просто в младщие разряды. Можно конечно и сохранить точность времени, как предложил Леопольд, путем дополнительного вызова ::time(), но там толко нужно делать округление. Но раз это не столь необходимо, то это, уже видимо оверкилл. задача же стояла, "самое быстрое..." |
| Автор: Леопольд 19.5.2012, 10:19 | ||||
Это будет происходить раз в 8 лет, думаю можно как-то похендлить это "переполнение" , например не доверять значениям (local_data >> 4) & 0xFFFFFFF == 0xFFFFFFF.
Добавлено @ 10:28 Константа неправильная, должна быть 0xFFFFFFF (поправил в примере) |
| Автор: cupper 21.5.2012, 08:39 | ||||||||||
Не реалтайм, но счет идет как раз на микросекунды. Даже лишнее переключение потоков уже наверно скажется на общей картине.
не тот случай.
Я не понял подход, как это должно работать с 4 младшими битами и дополнительным time ? Опустим переменную состояние. Оставим только время time32_t в потоке th1 оно должно обновляться на каждой итерации цикла (или например с интервалом в 1-20 секунду) (это имело бы смысл если бы операции > И = сильно различались по времени в пользу >. Но они же по сути с одинаковой скоростью выполняются, так смысл усложнять ?)
в потоке th2 каждый 300 миллисекунд считывается a.time. Куда втыкается
и зачем ? |
| Автор: volatile 21.5.2012, 23:20 | ||
Это вопрос ко мне? |
| Автор: cupper 22.5.2012, 16:40 | ||||
вадимо нет, резко поменялась задача, ту пришлось пока отложить. Но курс на реализацию уже выбран. |