Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2010.03.07;
Скачать: CL | DM;

Вниз

из регулярной процедуры в экземпляр класса   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.014 c
15-1261527698
KilkennyCat
2009-12-23 03:21
2010.03.07
VBA и application.processmessage


15-1261465203
MonoLife
2009-12-22 10:00
2010.03.07
Кто-нибудь пользуется yahoo почтой?


15-1261387411
Юрий Зотов
2009-12-21 12:23
2010.03.07
Регулярные выражения


3-1235913922
sco
2009-03-01 16:25
2010.03.07
ошибка в SQL коде


2-1262463589
AntonioBanderas
2010-01-02 23:19
2010.03.07
Принадлежность точки отрезку