2014-01-06 5 views
1

Я хочу реализовать быстрый регистратор, содержащий записи журнала, и когда приходит определенный триггер, он очищает последние X-сообщения.Могу ли я «заставить» поток проснуться?

Итак, идея состоит в том, чтобы удерживать все сообщения в циклическом буфере, и как только у нас есть триггер, нажмите его идентификатор в очередь, который отслеживает другой поток (один поток во всей системе). этот поток будет возвращать X-сообщения и стирать их. Я знаю, как обрабатывать сообщения, которые пишутся во время попытки очистки, сообщения, которые были перезаписаны, до того, как я сбросил сообщения, которые были очищены, когда я пытаюсь их обновить.

Моя проблема в том, У меня есть 20 потоков, пишущих сообщения, и всего 10 ядер, во время пословицы между исполнением потока 2 «писателя» весь буфер будет перезаписан несколько раз.

Есть ли способ, которым «моя» нить может «заставлять» нить «писателя» выполнить (или дать ей время среза? Я думаю, нет, но все еще ... вы можете советовать любым другим способом/дизайн, чтобы решить эту проблему.

+1

Зависит, но при одновременном многократном обращении к жесткому диску будет насыщаться скоростью жесткого диска задолго до того, как он насытит скорость обработки процессора. Для простоты, у меня было бы только 1 написать поток: - /. В любом случае, мьютексы или блокировки файлов были бы полезны для обеспечения доступа только 1 (fifo) потока к буферам или месту записи. – IdeaHat

+0

@MadScienceDreams: да, у меня есть один автор (обновленный вопрос соответственно). но проблема остается, буфер перезаписывается до того, как писатель получит возможность сбросить его. – yosim

+0

Вы можете дать этому потоку более высокий приоритет, так как он будет сигнализирован (через условную переменную, мьютекс, семафор, блокировку читателей-писателей, независимо от того, что вы хотите), системный планировщик выполнил бы этот поток. Обратите внимание, что ваша проблема может быть лучше решена с лучшим дизайном. Если ваш буфер будет перезаписан без вашего контроля, вам необходимо пересмотреть механизм ведения журнала. – Shahbaz

ответ

0

Я написал нечто подобное раньше, когда вызовы методов журнала фактически помещаются в очередь, в которой отслеживается другой поток (T-Logger). Это освобождает другие потоки от необходимости звонить базовые API-интерфейсы журналов и хорошо работают в приложениях с низкой задержкой.

Если вы хотите явно буферировать и затем записывать триггер, я бы порекомендовал делать все записи из e, например T-Logger, а затем используйте какой-то conditional variable, чтобы сигнализировать T-Logger, что теперь он должен идти и записывать элементы в очереди в основной файл журнала.

Как упоминалось в комментариях к вопросу, вы должны избегать нескольких потоков, пытающихся сделать IO. IO невероятно медленный, и все ваши потоки, пытающиеся записать в файл, заставят их отказаться от своих циклов процессора, ожидающих завершения ввода-вывода.

+0

@Shahbaz - правда. Я немного перефразировал свой ответ. – Sean

+0

Да, у меня будет только один поток, делающий записи. главный вопрос заключается в том, является ли условие переменной гарантией того, что поток проснется, как только он будет сигнализирован? Я не смог найти такую ​​гарантию (хотя, возможно, я не выглядел достаточно глубоко ...) – yosim

+0

@yosim - условная переменная вызовет любой поток, который ждет от него перехода к «управляемому» состоянию, и в какой-то момент ОС планирует запланировать поток на процессоре и запустить его. У вас никогда не будет решения, которое приведет к тому, что ожидающий поток начнет работать немедленно, так как ОС придется принимать во внимание планирование всех потоков. – Sean

1

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

Например, на C++ 11 вы можете посмотреть std::condition_variable.

Редактировать. Как отмечалось в комментариях, диск IO работает медленно, поэтому вам нужно извлечь сообщения в память в потоке записи и только потом записать их на диск. Во время ввода-вывода буфер может быть перезаписан входящими сообщениями.

+0

Является ли сигнализация потока, который в настоящее время спят при условии, gaurantees, что он проснется? Я пробовал это с помощью mutex, и это не сработало, я думал о состоянии, но я не смог найти такую ​​гарантию. – yosim

+0

Условная переменная, специально предназначенная для решения таких ситуаций, поэтому поток проснется! На самом деле даже [поддельные пробуждения] (http://www.cplusplus.com/reference/ condition_variable/конд ition_variable/wait /) возможны с некоторыми реализациями. Можно реализовать условные выражения с точки зрения взаимных исключений, но мьютексы в первую очередь предназначены для «взаимного исключения». –

0

Звучит как классический случай использования семафора, инициализированный длиной кругового буфера. При вызове журнала из потоков, требующих журнала, необходимо получить блок из семафора, прежде чем продолжить, а поток протоколирования будет передавать семафор при извлечении записи из очереди. Если буфер закончится, любой поток, пытающийся выполнить запись, будет блокироваться до тех пор, пока не будет места для записи в журнале.

Очевидно, что круглый буфер/очередь/любой контейнер для записей журнала должен быть потокобезопасным.

+0

Вы можете достичь того же без семафора. просто сохраните последний индекс, который вы покраснели, и если ваш следующий индекс - это индекс - вы должны заблокировать/сделать что-то еще, когда буфер заполнен. Однако у этого есть 2 основных недостатка: 1-й, регистратор не должен блокироваться. Но что более важно, не все сообщения должны быть очищены. Очень возможно, что у нас будет мало рук на стойке сообщений без мигания даже одного, а затем, всего лишь флеша. – yosim

Смежные вопросы