|
|
  |
Структура функций, В чём преимущество ? |
|
|
|
Feb 14 2014, 00:34
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 3-07-11
Пользователь №: 66 028

|
Здравствуйте, есть вот такая хитрая структура (тут мне не совсем понятно что делает union и зачем он там нужен) CODE typedef struct __WIZCHIP { uint16_t if_mode; ///< host interface mode uint8_t id[6]; ///< @b WIZCHIP ID such as @b 5100, @b 5200, @b 5500, and so on. /** * The set of critical section callback func. */ struct _CRIS { void (*_enter) (void); ///< crtical section enter void (*_exit) (void); ///< critial section exit }CRIS; /** * The set of @ref\_WIZCHIP_ select control callback func. */ struct _CS { void (*_select) (void); ///< @ref \_WIZCHIP_ selected void (*_deselect)(void); ///< @ref \_WIZCHIP_ deselected }CS; /** * The set of interface IO callback func. */ union _IF { /** * For BUS interface IO */ struct { uint8_t (*_read_byte) (uint32_t AddrSel); void (*_write_byte) (uint32_t AddrSel, uint8_t wb); }BUS; /** * For SPI interface IO */ struct { uint8_t (*_read_byte) (void); void (*_write_byte) (uint8_t wb); }SPI; // To be added // }IF; }_WIZCHIP;
Заполнение её (.if_mode .id и др указывают место расположение ? т.е при таком подходе можно их местами менять ? ) Код _WIZCHIP WIZCHIP = { .id = _WIZCHIP_ID_, .if_mode = _WIZCHIP_IO_MODE_, .CRIS._enter = wizchip_cris_enter, .CRIS._exit = wizchip_cris_exit, .CS._select = wizchip_cs_select, .CS._deselect = wizchip_cs_deselect, .IF.BUS._read_byte = wizchip_bus_readbyte, .IF.BUS._write_byte = wizchip_bus_writebyte // .IF.SPI._read_byte = wizchip_spi_readbyte, // .IF.SPI._write_byte = wizchip_spi_writebyte }; Работа с ней выглядит так Код WIZCHIP.CS._select(); т.е получается просто вызывается функция wizchip_cs_select() Так вот чём преимущество такого подхода WIZCHIP.CS._select(); по сравнению с просто вызовом функции wizchip_cs_select(); ? И на сколько дольше выполняется первый метод по сравнению со вторым?
|
|
|
|
|
Feb 14 2014, 13:57
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(pokk @ Feb 14 2014, 04:34)  Так вот чём преимущество такого подхода WIZCHIP.CS._select(); по сравнению с просто вызовом функции wizchip_cs_select(); ? Код с етим WIZCHIP не зависит от конкретной платы. А это даёт такой профит: например, его можно собрать в либу и больше не тратить времени на перекомпиляцию. Разумеется, в мелких проектах сие значения не имеет, но правильность подхода придает уверенность, что оно может работать и в составе более сложных систем без изменений. Удачная декомпозиция на независимые модули никогда не останется лишним капризом - рано или поздно себя проявит. Цитата И на сколько дольше выполняется первый метод по сравнению со вторым? если вызываемая функция в том же модуле и описана как static - то ни насколько.
|
|
|
|
|
Feb 14 2014, 14:14
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(pokk @ Feb 14 2014, 02:34)  т.е получается просто вызывается функция wizchip_cs_select()
Так вот чём преимущество такого подхода WIZCHIP.CS._select(); по сравнению с просто вызовом функции wizchip_cs_select(); ? И на сколько дольше выполняется первый метод по сравнению со вторым? Думаю никакого преимущества здесь нет. Просто у того китайского программитста возможно какие-то шаблонные подходы наработанные на других проектах. Социокультурные особенности может быть. Главное ведь чтобы ему самому нравилось. А я например такому коду сразу делаю беспощадный рефакторинг.
|
|
|
|
|
Feb 17 2014, 07:14
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 3-07-11
Пользователь №: 66 028

|
Спасибо за помощь. Я примерно так и думал только где-то там в комментариях увидел про ОС. Думал что-то с ней может быть связанно. Цитата Удачная декомпозиция на независимые модули никогда не останется лишним капризом - рано или поздно себя проявит. Это точно сейчас вот с этим воюю, так как изначально чёрти что понаделал.
|
|
|
|
|
Feb 17 2014, 16:36
|
self made
   
Группа: Свой
Сообщений: 855
Регистрация: 7-03-09
Из: Toronto, Canada
Пользователь №: 45 795

|
Цитата(_Pasha @ Feb 14 2014, 08:57)  Код с етим WIZCHIP не зависит от конкретной платы. А это даёт такой профит: например, его можно собрать в либу и больше не тратить времени на перекомпиляцию. Разумеется, в мелких проектах сие значения не имеет, но правильность подхода придает уверенность, что оно может работать и в составе более сложных систем без изменений. Удачная декомпозиция на независимые модули никогда не останется лишним капризом - рано или поздно себя проявит.
если вызываемая функция в том же модуле и описана как static - то ни насколько. Все это можно было бы достичь и без таких извращений. Виртуальные функции на С, это все-таки ужасный изврат. Какая связь между независимыми модулями, и этим кодом?
|
|
|
|
|
May 3 2014, 10:41
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(ViKo @ May 3 2014, 12:31)  Что такое callback функция? И в Википедии читал, и все равно не понимаю. Функция, вызываемая по указателю на нее? Функция, вызывающая функцию, указатель на которую передан в параметрах? Кто бы определил ясно и четко. Вижу, этим термином злоупотребляют, где ни попадя. В чем преимущество по сравнению с "функцией, вызываемой из функции"? Недавно читал доку wifi_stack_api_reference_v0.8.pdf и там прикольное определение было: "Callback programming is a style of computer programming, which allows lower layer of software to call functions defined on a higher layer. Callback is piece of code or a reference to a piece of code that is passed as an argument." Там же ссылка. "Сallback function is a function that is called through a function pointer. If you pass the pointer (address) of a function as an argument to another, when that pointer is used to call the function it points to it is said that a call back is made."
Сообщение отредактировал doom13 - May 3 2014, 11:04
|
|
|
|
|
May 3 2014, 11:08
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(ViKo @ May 3 2014, 14:50)  В том и дело, что по Википедии получается, не обязательно по событию, а просто в качестве параметра функции. Или это принципиальное свойство? Ну, любая функция так или иначе вызывается по событию  Принципиальное свойство - параметризуемость вызываемого объекта (не обязательно передача именно как параметра функции, т.к. это может быть отдельная структура и т.п). Вещь простая, но дать краткое и исчерпывающее определение, не опускаясь при этом в частности, трудно.
|
|
|
|
|
May 3 2014, 19:47
|

Знающий
   
Группа: Участник
Сообщений: 974
Регистрация: 4-04-08
Из: далека
Пользователь №: 36 467

|
Цитата(ViKo @ May 3 2014, 05:50)  В том и дело, что по Википедии получается, не обязательно по событию, а просто в качестве параметра функции. Или это принципиальное свойство? Не знаю то там в википедии, но смысл именно чтобы по какомуто событию передать данные обратно. Асинхронно! Именно это и имеют ввиду "callback". Когда он "обратно позвонит" неизвестно. Ждать нам некогда. Поэтому вот финкция и "будут деньги - звони, а мне некогда"
--------------------
Верить нельзя никому, даже себе. Мне - можно.
|
|
|
|
|
May 3 2014, 23:10
|

Знающий
   
Группа: Участник
Сообщений: 974
Регистрация: 4-04-08
Из: далека
Пользователь №: 36 467

|
Цитата(ViKo @ May 3 2014, 17:01)  Обратно - это куда? "Сигнал посылаем - вы что это там? А нас посылают обратно!" Можете привести пример менее аб... абстрактный? Привожу. Посылаю CAN message. Записать я его по SPI записал. Теперь когда результат доставки будет - неизвестно, а мне надо еще посылать. Передаю "позывные" своего message и говорю: свиснешь как доставишь - получилось, нет.. И передаю следующий в буффер.. Вот когда будет результат доставки, CAN вызовет callback (позовет меня обратно) и скажет смог или нет
--------------------
Верить нельзя никому, даже себе. Мне - можно.
|
|
|
|
|
May 4 2014, 13:01
|

Знающий
   
Группа: Участник
Сообщений: 974
Регистрация: 4-04-08
Из: далека
Пользователь №: 36 467

|
Цитата(AHTOXA @ May 4 2014, 01:29)  По-моему, callback - это просто. Например, есть функция вывода jpg-картинки на экран. Она умеет декодировать картинку. Но не знает, как отрисовать пиксель на экране. Мы вызываем её, и в качестве параметра передаём указатель на функцию отрисовки пикселя. Такой подход позволяет уменьшить связность программ. Можно не передавать функцию в качестве параметра при вызове каждый раз, а передать её один раз при инициализации библиотеки. Функция может выполняться в отдельном потоке. Тогда она будет вызывать наш callback асинхронно. Но это уже частности, суть от этого не меняется. нет, это не callback. Это аналог виртуальной функции в C++, которая может быть подменена на ходу. Callback всегда асинхронен. И всегда по какому то событию. Цитата(ViKo @ May 4 2014, 01:13)  Handshake? По-моему, вы спекулянт (понятиями). Это абсолютно другое понятие.
--------------------
Верить нельзя никому, даже себе. Мне - можно.
|
|
|
|
|
May 4 2014, 15:10
|

Знающий
   
Группа: Участник
Сообщений: 974
Регистрация: 4-04-08
Из: далека
Пользователь №: 36 467

|
Цитата(AHTOXA @ May 4 2014, 08:09)  Вы что-то путаете. callback - это функция обратного вызова. И всё. Нет гарантии что каллбэк синхронен. Именно поэтому он так и называется. "Право на звонок" передается другому треду. Если функция вызывается из того же треда то это не каллбэк. Как там экономно такси вызывают? Звонишь на номер и отключаешся. Ждешь каллбэк. Полная аналогия.
--------------------
Верить нельзя никому, даже себе. Мне - можно.
|
|
|
|
|
May 4 2014, 18:36
|

Знающий
   
Группа: Участник
Сообщений: 974
Регистрация: 4-04-08
Из: далека
Пользователь №: 36 467

|
Цитата(AHTOXA @ May 4 2014, 11:56)  Ага. Было "Callback всегда асинхронен", теперь "Нет гарантии что каллбэк синхронен"  А это одно и тоже. он асинхроннен, но в теории может совпасть. Цитата(ViKo @ May 4 2014, 13:19)  Что есть "обратный вызов"? По-моему, это неправильная печать перевод. Можно представить что-то вроде "туда-обратно". Типа, функция, возвращающаяся назад, а не вызывающая другие функции. Нет. Не то. Не понимаю, что не понятно? Это не "туда обратно". Это аналогично прерыванию. Время события как правило неизвестно. Поэтому ни какие "туда-обратно". Это не "функция возвращающаяся назад". И не "вызывающая другие функции". У ембеддеров есть понятие прерывания, у десктопных или как вы их называете, обычных программеров прерывания нет. Если ему надо переслать чтото в последовательный порт, он запишет данные в буффер, вызовет функцию работы с портом, передаст туда аддресс callback функции и уйдет по делам делать другую работу. Когда посылка завершится, система вызовет callback и передаст туда результаты. Никакая это не "тудаобратно". И не "возвращающаяся назад"
--------------------
Верить нельзя никому, даже себе. Мне - можно.
|
|
|
|
|
May 4 2014, 18:43
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(ViKo @ May 5 2014, 00:19)  Что есть "обратный вызов"? По-моему, это неправильная печать перевод. Можно представить что-то вроде "туда-обратно". Типа, функция, возвращающаяся назад, а не вызывающая другие функции. Нормальный перевод. Мы вызываем библиотечную функцию, она в процессе своей работы вызывает нас обратно, через переданную ей в качестве параметра функцию обратного вызова. Цитата(A. Fig Lee @ May 5 2014, 00:36)  А это одно и тоже. он асинхроннен, но в теории может совпасть. Ну хватит уже нести чушь. Вы неправильно понимаете, что такое callback. Вот пример синхронного калбэка: EnumWindowsЦитата BOOL WINAPI EnumWindows( _In_ WNDENUMPROC lpEnumFunc, _In_ LPARAM lParam );
Parameters: lpEnumFunc [in] Type: WNDENUMPROC A pointer to an application-defined callback function. For more information, see EnumWindowsProc.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
May 4 2014, 18:55
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(AHTOXA @ May 4 2014, 21:43)  Нормальный перевод. Мы вызываем библиотечную функцию, она в процессе своей работы вызывает нас обратно, через переданную ей в качестве параметра функцию обратного вызова. По-вашему, получается, callback - это функция, в которую передали другую функцию в качестве параметра. Так прямо "вызывает"? Может, все таки, возвращается? Разве вызываемая функция не вернется в вызывающую (библиотечную, в вашем примере)? По-моему, callback - это как раз та функция, которую передали. Функция, возвращающаяся назад...? Так они все назад...
|
|
|
|
|
May 4 2014, 18:58
|
Знающий
   
Группа: Свой
Сообщений: 781
Регистрация: 3-10-04
Из: Санкт-Петербург
Пользователь №: 768

|
Цитата(ViKo @ May 4 2014, 21:19)  Что есть "обратный вызов"? По-моему, это неправильная печать перевод. Можно представить что-то вроде "туда-обратно". Типа, функция, возвращающаяся назад, а не вызывающая другие функции. Не хочу использовать понятие функции, поскольку возможны подмены из математики. Переход по адресу подпрограммы с возвратом - вызов подпрограммы, что и есть "вызов функции". Себе Вы можете представить что угодно, но поскольку Вы не нативный носитель языка и не лингвист, то лучше обратиться к причинам, по которым "callback" появился. Причины просты: при декомпозиции программы появляются отдельные независимые модули, которые могут получать данные, которые должны обрабатываться различно в зависимости от контекста выполнения. Поэтому им не надо их обрабатывать, а надо сообщить о них "знающему" модулю. Это легко сделать, когда программа монолитна, а если модули независимы, то необходимо передавать в связанные модули адреса подпрограмм для "обратной связи" по обработке данных. Вот подпрограмма, адрес которой передается в таком случае - имеет жаргонизм "callback". P.S. И прошу помнить о раздельной компиляции модулей.
|
|
|
|
|
May 4 2014, 19:10
|
Знающий
   
Группа: Свой
Сообщений: 781
Регистрация: 3-10-04
Из: Санкт-Петербург
Пользователь №: 768

|
Цитата(ViKo @ May 4 2014, 22:06)  То есть, события, асинхронность - не при чем? Просто передаем один из возможных методов (функций)? Конечно (Только "методы" - это такое ограничение на "функции", которое наложил C++). Вот у Вас есть программно-аппаратный модуль, который программирует таймер, обрабатывает от него прерывания. Он все знает о таймере. Вы его запрограммируете и все. А как узнать, что время, которое Вы заказали, прошло? Надо передать адрес подпрограммы, которая будет вызвана по истечении времени. Это как раз простейший пример "callback" подпрограммы. P.S. В данном контексте подпрограмма для "обратной связи" модулей.
|
|
|
|
|
May 4 2014, 19:17
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(Tiro @ May 4 2014, 22:10)  Вот у Вас есть программно-аппаратный модуль, который программирует таймер, обрабатывает от него прерывания. Он все знает о таймере. Вы его запрограммируете и все. А как узнать, что время, которое Вы заказали, прошло? Надо передать адрес подпрограммы, которая будет вызвана по истечении времени. Это как раз простейший пример "callback" подпрограммы.
P.S. В данном контексте подпрограмма для "обратной связи". Возникло прерывание (событие). Обработчик вызвал некую функцию (она callback?). Все, doom13 дал ссылку. Собственно, я так и думал.
|
|
|
|
|
May 4 2014, 19:38
|
Знающий
   
Группа: Свой
Сообщений: 781
Регистрация: 3-10-04
Из: Санкт-Петербург
Пользователь №: 768

|
Цитата(ViKo @ May 4 2014, 22:17)  Возникло прерывание (событие). Обработчик вызвал некую функцию (она callback?). Выкиньте из головы понятия "события", "функции" применительно к общему контексту выполнения программы. Пользуйтесь нативной понятийной базой. Вот прерывание и подпрограмма - из нативной. А теперь несколько грубых переводов: - настройка callback = подпрограмме А сообщен адрес подпрограммы В для обработки данных, которых подпрограмма А не может обработать - прерывание = аппаратное состояние, обрабатываемое подпрограммой А - обработчик = подпрограмма А - событие = изменилось аппаратное состояние - callback = подпрограмма А вызвала подпрограмму В Не при каждом аппаратном событии модуля А произойдет callback модуля В. Callback модуля В = событие модуля В. Для модуля С все тоже самое. Рекурсивно.
|
|
|
|
|
May 4 2014, 19:48
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(ViKo @ May 5 2014, 00:55)  По-вашему, получается, callback - это функция, в которую передали другую функцию в качестве параметра. Так прямо "вызывает"? Может, все таки, возвращается? Разве вызываемая функция не вернется в вызывающую (библиотечную, в вашем примере)? По-моему, callback - это как раз та функция, которую передали. Функция, возвращающаяся назад...? Так они все назад...  Уф... %) Я не понимаю, что вам не понятно. Давайте прямо на примере этой самой функции EnumWindows. Ваша программа хочет получить список всех окон в системе и поэтому вызывает функцию EnumWindows(). Функция EnumWindows() умеет находить все окна в системе. Но что с ними делать дальше, она понятия не имеет. Это знаете вы - вы хотите напечатать названия этих окон. Поэтому вы создаёте специальную функцию - функцию обратного вызова (callback) PrintWindow(), которая печатает название окна, которое передано ей. И передаёте функцию PrintWindow() в качестве параметра при вызове EnumWindows(). Ваша функция PrintWindow() - это как раз и есть callback. Теперь функция EnumWindows() для каждого найденного окна вызовет этот callback. Потом она завершит свою работу, и вернёт управление вашей программе. То есть, у вас в программе есть функция main(), и есть функция PrintWindow(). Вы вызываете из main() библиотечную функцию EnumWindows(PrintWindow). Тогда контроль в вашей программе будет передаваться так: main() - EnumWindows() - PrintWindow() - PrintWindow() - PrintWindow() - PrintWindow()- ... - main(). Что касаемо названия "callback". Вызов из пользовательской программы библиотечной функции - это нормальный вызов. Вызов наоборот - из библиотечной функции пользовательской функции - обратный вызов. Всё логично
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
May 4 2014, 23:54
|

Знающий
   
Группа: Участник
Сообщений: 974
Регистрация: 4-04-08
Из: далека
Пользователь №: 36 467

|
Цитата(AHTOXA @ May 4 2014, 13:43)  Ну хватит уже нести чушь. Вы неправильно понимаете, что такое callback. Вот пример синхронного калбэка: EnumWindowsCallback ВСЕГДА асинхронный, строго говоря. и в этом случае тоже. Смысл в том, что мы передаем другой программе/объекту/кернелу/треду "управление". Что оно будет делать и когда нас позовет неизвестно. И EnumWindows не исключение. Другой вопрос, что вернется функция после вызова каллбэка. Но это чисто применение синхронизейшн примитивов. Точно так же можно позвать функцию передачи данных в сериал порт, передать туда каллбэк функцию, котораю будет сигналить объект, а мы после вызова нашей функции будем ждать этот обьект. И абсолютно асинхронный каллбэк "вдруг стал синхронным". На самом деле в обоих случаях сам каллбэк был асинхронным. Иначе это уже не будет то, что называют каллбэком Цитата(ViKo @ May 4 2014, 14:06)  То есть, события, асинхронность - не при чем? Просто передаем один из возможных методов (функций)? И что же тогда означает "callback"? Именно асинхронность и события причем. Вот я, например, написал библиотеку для связи через ethernet. Периодически она будет передавать данные из сети пользователю. Когда - неизвестно. Как пользователю получить данные? Типичное применение - при инициализации моей библиотеки он передает мне callback функцию, которую я буду звать, когда чтото прийдет. Цитата(AHTOXA @ May 4 2014, 14:48)  Что касаемо названия "callback". Вызов из пользовательской программы библиотечной функции - это нормальный вызов. Вызов наоборот - из библиотечной функции пользовательской функции - обратный вызов. Всё логично  Необязательно. Не всякая функция, которую вызывают через пойнтер, является каллбэком
--------------------
Верить нельзя никому, даже себе. Мне - можно.
|
|
|
|
|
May 5 2014, 05:26
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(A. Fig Lee @ May 5 2014, 05:54)  Callback ВСЕГДА асинхронный, строго говоря. и в этом случае тоже. Неверно. Асинхронный - это кода управление вернулось после вызова, а вызовы callback-а продолжают поступать. В данном случае callback именно синхронный. Точно так же, как и в примере с сортировкой qsort. Ещё раз повторяю: callback и асинхронность - вещи ортогональные.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
May 5 2014, 12:12
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(XVR @ May 5 2014, 14:38)  2 ТС - вы смешали в одну кучу назначение callback'ов, их реализацию и смысл самого понятия callback. Все 3 части могут иметь разные реализации и/или толкования, и не надо их путать  Вообще-то, это не ТС смешал.  Там уже все закончилось. Я набрел на тему поиском по слову callback. Думал, могу получить короткий точный ответ. А вы своим сообщением путаницы добавили.  Дайте уж и свое толкование всех частей.
|
|
|
|
|
May 5 2014, 12:45
|

Знающий
   
Группа: Участник
Сообщений: 974
Регистрация: 4-04-08
Из: далека
Пользователь №: 36 467

|
Цитата(AHTOXA @ May 5 2014, 00:26)  Неверно. Асинхронный - это кода управление вернулось после вызова, а вызовы callback-а продолжают поступать. В данном случае callback именно синхронный. Точно так же, как и в примере с сортировкой qsort. Ещё раз повторяю: callback и асинхронность - вещи ортогональные. Нет. Он синхронный только потому что его принудительно синхронизировали. Такими вещами как WaitForSingleObject. То, что вы этого не видите, ничего не значит. Любой каллбэк можно засинхронизировать по отношению к вызывающей функции. Но он как был по сути асинхронным, так как мы не имеем никакого контроля над самим каллбэком, так и остался.
--------------------
Верить нельзя никому, даже себе. Мне - можно.
|
|
|
|
|
May 5 2014, 13:39
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Цитата(ViKo @ May 5 2014, 16:12)  Дайте уж и свое толкование всех частей. Их уже давали тут, но все в куче Если хотите, то вот - Понятие callback'а - дословно 'обратный вызов'. Точнее это оповещение о каком то событии, которое (оповещение) передает тот, у кого это событие произошло, тому, кто этот самый callback установил. В установке callback'а обязательно присутствуют 2 стороны - одна предоставляет сам callback, вторая его активирует в соответствующий момент. Назначение callback'а - может быть самое разное. Это может быть сигнализация о наступлении аппаратного прерывания, сигнализация о срабатывании программного события (WaitForSingleObject), доставка пользовательского event'а (в различных оконных системах), наступление каких то программно/аппаратных событий (исчерпании кольцевого DMA буфера например) Реализация callback'а - указатель на функцию callback'а, переданный в виде параметра в вызов интерфейсной процедуры. Тот же самый указатель, помещенный в какой то структуре в памяти. Виртуальные функции в С++. Примитив ОС (HANDLE от CreateEvent).
|
|
|
|
|
May 5 2014, 16:58
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(A. Fig Lee @ May 5 2014, 18:45)  Нет. Он синхронный только потому что его принудительно синхронизировали. Такими вещами как WaitForSingleObject. То, что вы этого не видите, ничего не значит. Любой каллбэк можно засинхронизировать по отношению к вызывающей функции. Если его засинхронизировали, то он синхронный. Если он синхронный, то он совершенно точно не асинхронный. По-моему, это очевидно. ЗЫ. Задание на дом - поищите скрытую асинхронность (такие вещи как WaitForSingleObject) в реализации callback-ов в функции qsort() например.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
May 5 2014, 18:22
|
Местный
  
Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778

|
Цитата(aaarrr @ May 3 2014, 14:29)  Хорошо, напишем так: это функция, вызываемая по событию, и заранее не определенная для вызывающего её (условно "библиотечного") кода. А это как называется? Или где здесь событие? Код void fooInit(struct foo *x, void * (*dmalloc) (size_t sz)) { lowInit(x->ba1); ... x->dma1 = dmalloc(1024 * x->szE); x->dma2 = dmalloc(1024 * x->szE); ... irqEnable(x->irqN); }
... fooInit(&ifc1, dmalloc_seg1); fooInit(&ifc2, dmalloc_seg2); Попытаюсь дать свое опрделение callback функции. Начать надо с того, что подразумевается разделение кода на некие уровни, слои абстракции. Каждый слой может использовать только более нижние слои для реализации своих функций. Каждый такой вызов это прямой вызов callforward. Если где-то надо вызвать код более высого слоя, то это обратный вызов callback. Самый известный пример, доставка событий. А самая известная реализация в C языках это указатель на функцию.
Сообщение отредактировал amaora - May 5 2014, 18:25
|
|
|
|
|
May 5 2014, 19:35
|

Знающий
   
Группа: Участник
Сообщений: 974
Регистрация: 4-04-08
Из: далека
Пользователь №: 36 467

|
Цитата(AHTOXA @ May 5 2014, 11:58)  Если его засинхронизировали, то он синхронный. Если он синхронный, то он совершенно точно не асинхронный. По-моему, это очевидно. Именно. Что сам по себе он всегда асинхронный. Чтоб был синхронным надо пляски с бубном. Пляски с бубном прямого отношения к каллбэку не имеют, но имеют к тому что он асинхронный. Приходится синхронизировать. А так да, можно все что угодно засинхронизировать. Цитата(amaora @ May 5 2014, 13:22)  А это как называется? Или где здесь событие? Нет никакого каллбэка здесь. Вызов функции через пойнтер есть. Абстракция есть. Виртуальная функция средствами С, так сказать.
--------------------
Верить нельзя никому, даже себе. Мне - можно.
|
|
|
|
|
May 5 2014, 20:24
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(GetSmart @ May 6 2014, 01:22)  А что логичного в вводе лишней сущности на 100% аналогичной параметру-функции? Её частный случай - виртуальная/перегруженная функция (объекта). Их все тоже колбэками обзывать? Это не просто параметр-функция. Это такой параметр-функция, который вызывается в процессе работы вызываемой функции (той, которой мы передали параметр). Я уже приводил пример простейшего callback-а: параметр compare функции qsort(). Функция qsort() умеет быстро сортировать, но не знает, что она сортирует. Поэтому она вызывает пользовательскую функцию сравнения. Вот это и есть callback в чистом виде. Цитата(GetSmart @ May 6 2014, 01:22)  ИМХО A. Fig Lee указал на ключевой признак - вызов из другого треда. Нет, это совершенно не обязательно.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
May 5 2014, 20:37
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(AHTOXA @ May 6 2014, 02:24)  Это не просто параметр-функция. Это такой параметр-функция, который вызывается в процессе работы вызываемой функции (той, которой мы передали параметр). Я уже приводил пример простейшего callback-а: ... Неубедительно. Параметр-функция для того и существует, чтобы его/её вызывать "оттуда". И как раз функция, которая будет вызывать другую функцию через параметр не знает о ней ничего, кроме списка передаваемых ей параметров. Хотя, из другого треда это уже динамически настраеваемый адрес event-а. Всё-таки где отличия от параметра-функции или это 100% аналог?
Сообщение отредактировал GetSmart - May 5 2014, 21:57
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
May 5 2014, 21:59
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(ViKo @ May 6 2014, 02:31)  А разве может быть иное? Да. Функция может не вызывать переданный ей параметр-функцию в процессе своей работы  Может просто сохранить в переменной, например. Или возвращать адрес функции-параметра. Цитата(GetSmart @ May 6 2014, 02:37)  Неубедительно. Вы не согласны с тем, что параметр функции qsort() является callback-ом? Так это не я придумал, это общепринято. То, что вы с A. Fig Lee считаете callback'ом - это асинхронный callback, частный случай callback'а. Вот вам, например, статья про сравнение асинхронных и синхронных callback'ов. Там есть и определения для этих двух вариантов. Цитата(GetSmart @ May 6 2014, 02:37)  Всё-таки где отличия от параметра-функции или это 100% аналог? Вот выше я привёл два примера функции-параметра, не являющихся callback'ами. Но обычно эти понятия синонимы.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
May 5 2014, 22:48
|

Знающий
   
Группа: Участник
Сообщений: 974
Регистрация: 4-04-08
Из: далека
Пользователь №: 36 467

|
Цитата(AHTOXA @ May 5 2014, 16:59)  Вы не согласны с тем, что параметр функции qsort() является callback-ом? Так это не я придумал, это общепринято. CC2520 не является Zigbee трансивером, но в мануале она так обзывается. Если нет факта callbacka, значит это не callback. qsort, это ни какой ни бэк, это последовательная енумерация. Без всяких коллов и бэков.
--------------------
Верить нельзя никому, даже себе. Мне - можно.
|
|
|
|
|
May 6 2014, 07:30
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Цитата(ViKo @ May 5 2014, 22:00)  А мне понятнее вариант 'в'. Вызвали callback функцию, и она вернула, то, чего нам не хватало.  callback может ничего не возвращать Цитата А синхронизации - не вижу. Для этого есть другие элементы. Семафоры, например. Одно другому не мешает. И синхронизировать можно через вызов функции callback'а, и сам семафор использовать в качестве callback'а (callback - это не обязательно функция  )
|
|
|
|
|
May 7 2014, 05:21
|
Местный
  
Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778

|
Цитата(ViKo @ May 5 2014, 23:48)  А если указатель указывает на функцию более низкого уровня, тогда как? И по какому критерию делить на уровни? Тогда это прямой вызов. По указателю или нет, значения не имеет. Как делить на уровни решает тот кто пишет код. Файловая система например обычно на уровень выше драйвера устройства хранения.
|
|
|
|
|
May 7 2014, 10:53
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(A. Fig Lee @ May 6 2014, 04:48)  Если нет факта callbacka, значит это не callback. Голосуем. Кто за этот вариант?  А то чёткость признаков отсутствует. Цитата(amaora @ May 7 2014, 11:21)  Файловая система например обычно на уровень выше драйвера устройства хранения. Драйвер устройства хранения вызывает функции файловой системы?
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
May 7 2014, 13:30
|

Знающий
   
Группа: Участник
Сообщений: 974
Регистрация: 4-04-08
Из: далека
Пользователь №: 36 467

|
Цитата(GetSmart @ May 7 2014, 05:53)  Голосуем. Кто за этот вариант?  +1. Кстати по поводу "qsort callback" Это как "шампанское" "Советское шампанское". Все называют. Хотя правильное определение шампанского, если спросить: игристое вино произведенное в провинции Шампань. А так да, шампанское является игристым вином..
--------------------
Верить нельзя никому, даже себе. Мне - можно.
|
|
|
|
|
May 7 2014, 16:39
|
Местный
  
Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778

|
Цитата(GetSmart @ May 7 2014, 14:53)  Драйвер устройства хранения вызывает функции файловой системы? Если да, то это будет callback. Даже если функция вызывается по статическому адресу. Или если вызывается синхронно, например fopen->fs_open_xxx->drv_read_blk->fs_alloc_blk. Главное, что вызов направлен в обратную строну, назад.
|
|
|
|
|
May 7 2014, 18:28
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(GetSmart @ May 7 2014, 19:17)  Как в жизни. "Перезвони(те) мне" = асинхронность + разговор за чужой счёт (чужой тред). Плюс нет 100% гарантии, что перезвонит  Понятие асинхронности не связано с понятием обратного вызова. Обратный вызов - это просто направление. Мне не нравится аналогия с телефоном, но если уж её применять, то это будет выглядеть так: - Вы звоните оператору сортировки (qsort company), и делаете заказ - отсортировать список гостей на свадьбу.
- При этом вы сообщаете ему номер жены для консультаций о порядке сортировки (compare). Трубку не кладёте, ждёте результата.
- Оператор в процессе сортировки перезванивает вашей жене другому номеру (compare) и уточняет (кого с кем посадить).
- По окончании сортировки оператор сообщает вам результат.
Это получается синхронный callback. То же самое, но вы кладёте трубку после заказа, а оператор перезванивает вам после выполнения - асинхронный. Добавлю, что понятие callback-функция появилось в программировании задолго до появления многозадачности и многопоточности. Цитата(A. Fig Lee @ May 7 2014, 19:30)  Кстати по поводу "qsort callback" Это как "шампанское" "Советское шампанское". Все называют. Хотя правильное определение шампанского, если спросить: Не болтайте ерундой. Это именно callback. Такова устоявшаяся терминология в данной отрасли (программирование).
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
May 7 2014, 19:16
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(ViKo @ May 8 2014, 00:37)  Переведите это на язык программы. Что значит "не кладете трубку" и что "кладете"? Очень просто. Если "не кладёте трубку" - все вызовы колбэков идут _до_ возврата из функции сортировки. Если "кладёте" - вызовы могут идти после возврата из функции сортировки. То есть, мы из main() вызвали qsort(), qsort в процессе работы много раз вызвал compare(), отсортировал, и только после этого вернул управление в main(). Здесь compare - синхронный callback. Второй вариант. Мы вызвали qsort_async(compare, done). Этот qsort вернул управление сразу, мы можем делать что-то другое. А qsort в это время работает, вызывает compare. Это уже асинхронные обратные вызовы. Ну и когда он отсортирует, он вызовет ф-ю done(). Такой callback называют completion routine.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
May 7 2014, 20:11
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(AHTOXA @ May 7 2014, 22:16)  Второй вариант. Мы вызвали qsort_async(compare, done). Этот qsort вернул управление сразу, мы можем делать что-то другое. А qsort в это время работает, вызывает compare. Это уже асинхронные обратные вызовы. Ну и когда он отсортирует, он вызовет ф-ю done(). Такой callback называют completion routine. Первый вариант - понятно. А второй - предполагает многозадачную или многопроцессорную систему? А, может, пускай они уже сами по себе работают - один проц сортирует, а другой... перемешивает  ? Ах, да, еще же прерывания есть...
|
|
|
|
|
May 7 2014, 22:16
|

Знающий
   
Группа: Участник
Сообщений: 974
Регистрация: 4-04-08
Из: далека
Пользователь №: 36 467

|
Цитата(AHTOXA @ May 7 2014, 14:16)  Очень просто. Если "не кладёте трубку" - все вызовы колбэков идут ... Никуда они не идут. Дозвонится не получится. Управление надо получить сначала Цитата(AHTOXA @ May 7 2014, 13:28)  Не болтайте ерундой. Это именно callback. Такова устоявшаяся терминология в данной отрасли (программирование). Нет. Не согласен.
--------------------
Верить нельзя никому, даже себе. Мне - можно.
|
|
|
|
|
May 8 2014, 08:08
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(ViKo @ May 8 2014, 02:11)  Первый вариант - понятно. А второй - предполагает многозадачную или многопроцессорную систему? Да, естественно. Асинхронность подразумевает несколько потоков выполнения. Цитата(GetSmart @ May 8 2014, 08:40)  "Их" устоявшаяся терминология понятна. Как минимум два типа вызовов, принципиально непохожих. Но зачем-то обозванных одним обобщающим термином. Причём, кто-то и семафоры в эту "кучу" "притягивает" как способ возврата информации. Термин в принципе тоже понятен - обратный вызов из библиотеки. Вас постоянно сбивает аналогия с телефоном. Но между телефонным обратным вызовом и обратным вызовом функции есть принципиальная разница: телефонный обратный вызов обычно производится по тому же самому телефону, который инициировал вызов. В случае же с вызовом функции - вызывается другая функция, не та, что инициировала весь этот процесс. Поэтому представить синхронный колбэк по телефону сложнее (приходится приплетать жену  ).
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
May 10 2014, 14:40
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
QUOTE (AHTOXA @ May 8 2014, 01:28)  Понятие асинхронности не связано с понятием обратного вызова. Обратный вызов - это просто направление. Мне не нравится аналогия с телефоном, но если уж её применять, то это будет выглядеть так: - Вы звоните оператору сортировки (qsort company), и делаете заказ - отсортировать список гостей на свадьбу.
- При этом вы сообщаете ему номер жены для консультаций о порядке сортировки (compare). Трубку не кладёте, ждёте результата.
- Оператор в процессе сортировки перезванивает вашей жене другому номеру (compare) и уточняет (кого с кем посадить).
- По окончании сортировки оператор сообщает вам результат.
Это получается синхронный callback. То же самое, но вы кладёте трубку после заказа, а оператор перезванивает вам после выполнения - асинхронный. Добавлю, что понятие callback-функция появилось в программировании задолго до появления многозадачности и многопоточности. Не болтайте ерундой. Это именно callback. Такова устоявшаяся терминология в данной отрасли (программирование). Всё верно, ни убавить, ни добавить. За пример с телефоном и сортировкой отдельный респект.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|