Форум: "Начинающим";
Текущий архив: 2010.03.07;
Скачать: [xml.tar.bz2];
Внизиз регулярной процедуры в экземпляр класса Найти похожие ветки
← →
antonn © (2010-01-02 21:12) [0]С новым годом :)
Еще один вопрос про многопоточность.
Есть класс TSomeClass который управляет проигрыванием звука через api бибилиотеки bass.dll, для простоты решим что он просто в своих методах вызывает функции bass и ничего более.
В апи bass есть функция, позволяющая использовать процедуру для обратного вызова, отрабатывающую по окончании проигрывания (либо в процессе проигрывания, для создания loop - бесконечного проигрывания конкретного куска):function BASS_ChannelSetSync(handle: DWORD; type_: DWORD; param: QWORD; proc: SYNCPROC; user: Pointer): HSYNC; stdcall;
метод в классе и "регулярная" процедура:
procedure LoopSyncProc(handle:HSYNC; channel,data:DWORD; tmp:Pointer); stdcall;
begin
.. //"что то важное"
end;
procedure TSomeClass.Play(filename:string);
var i:integer;
begin
.. //p^[i] - динамический массив в классе TSomeClass
p^[i].chan:=BASS_StreamCreateFile(FALSE,pchar(filename),0,0,0 {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF});
if p^[i].chan<>0 then begin
BASS_ChannelSetSync(p^[i].chan,BASS_SYNC_END,0,LoopSyncProc, nil);
..
end;
end;
Так вот вопрос - как в этой процедуре обратиться к создаваемому экземпляру класса TSomeClass? :)
Наскоком придумал только одно: создать класс-"транслятор", создавать в юните его экземпляр (в секции initialization), имеющий обработчик на который будет вешаться метод класса TSomeClass. В LoopSyncProc обращаться к этому экземпляру-"передатчика" и вызвывать обработчик, который доберется до экземпляра TSomeClass.
Но помоему это бредово выглядит :)
Далее, экземпляр TSomeClass будет создаваться в отдельном потоке, а класс-"транслятор" насколько я понимаю в основном? следовательно обращения к нему нужно обвязать критическими секциями...
Какие есть более пряморукие методы решения такой задачи (обратиться (конкретно - выставить в динамеческом массиве в классе в элементе пару значений) из LoopSyncProc к экземпляру класса)? Критична скорость и "самодостаточность" (т.е. без посылов sendmessage, класс может быть в своем потоке или нет, без обращений к нему от окна для передачи сообщения, итп).
← →
Кука съела ник (2010-01-02 21:31) [1]
> Какие есть более пряморукие методы решения такой задачи
http://www.rsdn.ru/forum/cpp/804847.flat.aspx#804847
← →
антонн (2010-01-02 21:36) [2]не вьехал как это можно реализовать на дельфи :(
← →
Кука съела ник (2010-01-02 21:39) [3]антонн (02.01.10 21:36) [2]
Использовать параметр user в BASS_ChannelSetSync, передать туда указатель на экземпляр класса вместо nil, вынуть в LoopSyncProc из параметра tmp, преобразовать к указателю на класс
← →
antonn © (2010-01-03 00:18) [4]тут да, выйдет.
А в общем случае как решаются такие задачи?
← →
jack128_ (2010-01-03 00:39) [5]
>
> А в общем случае как решаются такие задачи?
вот как, кука, съевший ник описал, так и решается.
Ну есть еще вариант с динамической генерацией кода. но это используется только в том случае, если разработчики апи не предусматривали параметра UserData для калбека.
← →
antonn © (2010-01-03 00:49) [6]
> если разработчики апи не предусматривали параметра UserData
> для калбека.
>
вот я и говорю что без него, как тогда выкручиваться из ситуации?
ЗЫ Опять имя не сохраняется в форме ответа :(
← →
Кука съела ник (2010-01-03 01:30) [7]
> вот я и говорю что без него, как тогда выкручиваться из
> ситуации?
Через использование глобальной переменной
← →
antonn © (2010-01-03 02:39) [8]
> Через использование глобальной переменной
а если у меня несколько экземпляров класса? да еще каждый в свом потоке будет создаваться?
← →
Кука съела ник (2010-01-03 02:43) [9]antonn © (03.01.10 02:39) [8]
Тогда ты заводишь глобальный список (динамический массив), каждым элементом которого будет запись из HANDLE который ты передаешь в BASS_blah_blah и экземпляра класса. Внутри callback-а по HANDLE находишь класс. Если много потоков, то список защищаешь критической секцией, прежде чем к нему обратиться.
← →
Демо © (2010-01-03 07:29) [10]
> antonn © (02.01.10 21:12)
Посмотри реализацию TThread, в нём поточной процедуре передаётся указатель на класс, который в ней используется.
← →
Ганя (2010-01-04 10:38) [11]если каждый в своем потоке, то можно использовать глобальные Threadvar
но лучше всего конечно передать параметром.
← →
Юрий Зотов © (2010-01-04 11:57) [12]> antonn
По-видимому, речь шла вот о чем:
procedure LoopSyncProc(...; Tmp: Pointer); stdcall;
...
TSomeClass(Tmp).SomeMethod(...);
end;
procedure TSomeClass.Play(...);
...
BASS_ChannelSetSync(..., LoopSyncProc, Pointer(Self))
end;
Попробуйте - если это сработает, то создавайте хоть 100 экземпляров в 100 потоках (конечно, при условии, что сама библиотека BASS потокобезопасна).
← →
antonn © (2010-01-04 16:06) [13]да, про self я уже понял, но на будущее хотел узнать что делать если функция не имеет параметров (просто своей отработкой уведомляет о чем-то, либо параметры в ней не связаны с "родителем"), в итоге остается что то глобальное в критических секциях...
← →
Кука съела ник (2010-01-04 17:05) [14]antonn © (04.01.10 16:06) [13]
Если функция не предусматривает ассоциацию контекста с обрабатываемыми параметрами, значит, эту ассоциацию нужно делать вручную, до вызова функции. Если что-то многопоточное, то для сделанных вручную ассоциаций надо обеспечивать потокобезопасность, других путей пока не придумано.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2010.03.07;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.007 c