Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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.006 c
15-1261171821
Юрий
2009-12-19 00:30
2010.03.07
С днем рождения ! 19 декабря 2009 суббота


2-1262180202
RWolf
2009-12-30 16:36
2010.03.07
DBGrid + скролл


15-1261690221
Юрий
2009-12-25 00:30
2010.03.07
С днем рождения ! 25 декабря 2009 пятница


1-1239551806
Student
2009-04-12 19:56
2010.03.07
Сохранение и поиск в Web странице


2-1262514706
ЭлЭрДжи
2010-01-03 13:31
2010.03.07
Вопрос по типизированным файлам.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский