crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

4 страниц V  < 1 2 3 4 >  
Ответить в данную темуНачать новую тему
> Сложная синхронизация
mezmay
  опции профиля:
сообщение 10.1.2015, 15:59
Сообщение #11


Активный участник
***

Группа: Участник
Сообщений: 272
Регистрация: 13.7.2009
Из: Ростов-на-Дону
Пользователь №: 904

Спасибо сказали: 16 раз(а)




Репутация:   1  


Вопрос в том как сделать этот поток B. Jack работает и вызывает коллбэки в своем потоке, но как мне зауправлять этим потоком?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 10.1.2015, 22:07
Сообщение #12


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Не надо им управлять, вам нужно просто передавать в коллбэк правильные данные
Вроде
struct data {
QAtomicInt guard;
int shift_left;
float volume_left;
float volume_right;
Filter *filter_left;
Filter *filter_right;
}

Цитата
int jack_client_create_thread ( jack_client_t * client,
jack_native_thread_t * thread,
int priority,
int realtime,
void *(*)(void *) start_routine,
void * arg <- Сюда передайте указатель на структуру данных с QAtomicInt например для синхронизации


В коллбэке arg примет то же значение что вы передали, если я все правильно понял(обычно так работает)
В начале коллбэка лочите структуру(например используя testAndSet на QAtomicInt) или ждете пока она освободится, затем читаете данные, разлочиваете.

В GUI треде лочите структуру или ждете пока она освободится, записываете данные, разлочиваете.
Для отладки попробуйте сначала то же самое с мутексами, если будет тормозить, переходите на atomic. Можно будет поиграть и с разными барьерами, чтобы улучшить быстродействие.

Пока структура залочена, вы просто ничего с ней не делаете.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
mezmay
  опции профиля:
сообщение 10.1.2015, 23:19
Сообщение #13


Активный участник
***

Группа: Участник
Сообщений: 272
Регистрация: 13.7.2009
Из: Ростов-на-Дону
Пользователь №: 904

Спасибо сказали: 16 раз(а)




Репутация:   1  


Цитата
лочите структуру(например используя testAndSet на QAtomicInt) или ждете пока она освободится

Это можете подробнее объяснить?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 11.1.2015, 13:52
Сообщение #14


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Ну во первых, можно использовать обычный QMutex, я не думаю что он будет сильно хуже самопального.
Во вторых, заводите два значения например(это упрощенный мутекс)
int LOCKED = 1;
int UNLOCKED = 0;

Потом лочите структуру
while (!str->guard.testAndSetOrtdered(UNLOCKED, LOCKED));
//Здесь можно пользоватся
str->guard.fetchAndStoreOrdered(UNLOCKED);
// Здесь структура разлочена

В третьих можно использовать две одинаковых структуры и один QAtomicPointer, суть такая - меняем структуру на которую не указывает указатель в данный момент, и с тех пор больше не трогаем структуру, это в принципе упрощенный вариант того, что предложила Iron Bug, т.е. кольцевой буфер из двух элементов, возможно потребуется завести два буфера - один для входящих данных, один для исходящих.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
mezmay
  опции профиля:
сообщение 11.1.2015, 15:11
Сообщение #15


Активный участник
***

Группа: Участник
Сообщений: 272
Регистрация: 13.7.2009
Из: Ростов-на-Дону
Пользователь №: 904

Спасибо сказали: 16 раз(а)




Репутация:   1  


guard.fetchAndStoreOrdered(UNLOCKED);

Я правильно понимаю что эта функция просто присваивает значение (ну и возвращает которое было)? Она в любом случает сделает присваивание за 1 раз, цикл не нужен?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 12.1.2015, 22:05
Сообщение #16


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Да, она просто перезаписывает.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 13.1.2015, 9:46
Сообщение #17


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

Группа: Модератор
Сообщений: 1611
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 219 раз(а)




Репутация:   12  


Цитата(lanz @ 11.1.2015, 15:52) *
это упрощенный мутекс

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

да, про циклические буферы я говорила не в смысле синхронизации, а в смысле передачи данных между потоками. синхронизация доступа потоков к очередям или буферам может быть какая угодно. можно по-разному реализовать обмен, но чем шустрее будут работать связанные с работой железа callback'и - тем правильнее. железяка (или неуправляемый входящий поток) не может ожидать и получаемые данные всегда имеют приоритет. отдавать их можно и с задержкой, а принимать надо по мере поступления.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
mezmay
  опции профиля:
сообщение 13.1.2015, 12:25
Сообщение #18


Активный участник
***

Группа: Участник
Сообщений: 272
Регистрация: 13.7.2009
Из: Ростов-на-Дону
Пользователь №: 904

Спасибо сказали: 16 раз(а)




Репутация:   1  


Цитата(Iron Bug @ 13.1.2015, 9:46) *
это спинлок (spinlock)
Цитата(Iron Bug @ 13.1.2015, 9:46) *
синхронизация доступа потоков к очередям или буферам может быть какая угодно
какие еще есть варианты (не через мьютексы и семафоры)?

Цитата(Iron Bug @ 13.1.2015, 9:46) *
...не уступая процессорное время другим потокам
разве потокам не поочередно предоставляются отрезки времени?

Сообщение отредактировал mezmay - 13.1.2015, 12:26
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 13.1.2015, 20:16
Сообщение #19


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Цитата(Iron Bug @ 13.1.2015, 9:46) *
это не мьютекс, это спинлок (spinlock)

Технически, мьютекс это семафор с одним ресурсом, так что тут нет противоречий. Спинлок это деталь реализации именно операции захвата семафора. Но это все непринципиально :lol:

Цитата
спинлок отличается от мьютекса тем, что при залоченном ресурсе поток будет долбиться в него

Технически :lol: , можно реализовать мьютекс так, чтобы он сначала пытался захватится спинлоком и только потом уходил в переключение.

Цитата(Iron Bug @ 13.1.2015, 9:46) *
обрати внимание, что на одноядерном проце или на машине с одним простым процессором спинлок сожрёт всё процессорное время и, скорее всего, завесит машину

Если нет ОС, которая переключает потоки, тогда да. Но если ОС не переключает потоки, зачем синхронизация? Про завесит тоже не понял.

Цитата
какие еще есть варианты (не через мьютексы и семафоры)?

Мьютекс и семафор это абстрактные понятия, реализации их могут быть разные(см. выше), но я знаю только через объекты ОС и через атомарные операции/volatile переменные.

Цитата
разве потокам не поочередно предоставляются отрезки времени?

Да, но можно отказаться от своего отрезка и засуспендить поток до наступления определенного события, ОС разбудит. Обычно этот способ предпочтительный, потому что не использует процессорное время для ожидания освобождения ресурса. Но соответственно он и медленнее.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 14.1.2015, 13:39
Сообщение #20


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

Группа: Модератор
Сообщений: 1611
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 219 раз(а)




Репутация:   12  


Цитата(lanz @ 13.1.2015, 22:16) *
Технически, мьютекс это семафор с одним ресурсом, так что тут нет противоречий. Спинлок это деталь реализации именно операции захвата семафора. Но это все непринципиально

это как раз принципиально. потому что базируется на разной реализации и используется для разных целей.
упрощённо разницу я пояснила. если углубляться, нужно ковырять до ассемблерных вызовов и принципов работы очередей команд и синхронизации обращений к памяти. просто из имени этой функции очевидно, что она базируется на ассемблерной синхронизации. иначе такое странное название не придумать: оно просто отражает смысл конкретного вида синхронизации. в последних версиях GCC все виды синхронизации стали функциями стандартной библиотеки, до этого всё делалось вручную, на ассемблере. и ОС тут ни при чём, это архитектура процессора.
если хочешь понять разницу - читай про реализацию мьютексов и спинлоков. можно, например, здесь:
http://stackoverflow.com/questions/5869825...nstead-of-mutex
там не подробно, но понятно и доступно написано в первом ответе.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

4 страниц V  < 1 2 3 4 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 19.4.2024, 20:11