| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > RE: библиотекa распределенного общения |
| Автор: mes 28.2.2011, 12:31 |
| тема предназначена для обсуждения вопросов возникшей в теме : http://forum.vingrad.ru/forum/topic-323593/kw-distributed-discoly.html Добро пожаловать ! |
| Автор: mes 1.3.2011, 10:52 | ||||||||
| Посмотрев свежим взглядом заметил, что у нас определились два направления : 1. составление сети обработчиков мигрантов - dataflow. 2. конструирование мигранта и его исполнение.. модель по первому пункту: сеть состоит из узлов-объектов, каждый из которых имеет вход и выход:
, где msg (сообщение) - полиморфный пакет аргументов (в коде назывался migrant).. тогда объекты делятся на две условные категории : реализация и канал, где канал, это частный случай реализации отвечающий за передачу сообщения, а реализация это объект исполняющий действие ассоциированное с сообщением..
тогда для замыкания клиента на канал, код будет условно таким:
Добавлено через 11 минут и 58 секунд Переходим ко второму пункту и начнем с проблем: мигрант ( для возможности получения контроля в dataflow ) и способ упаковки аргументов/сериализация (для возможности поддержки существующих протоколов) должны задаваться и определяться пользователем .. должна быть возможность инвокинга сообщения, как для функции так и для метода.. при этом сохранить отношение одна карта на множество объектов.. |
| Автор: mes 1.3.2011, 15:41 | ||
да.. чтоб получить удобный синтаксис вызова и инвокинга..
написать несколько типов с одной сигнатурой и разным ид если нужен статический контроль, пользователь должен определить правила.. этот участок описание протокола, т.е. фактически должен являться библиотечкой используемой как клиентом, так и сервером.. т.е. составляется один раз, на N-приложений сети.. для каждого типа объекта своя карта.. или просто прямая передача вызова от функции к функции.. |
| Автор: mes 13.3.2011, 00:17 |
| еще раз попробуем определить сущности.. модель общения: сообщение посылаемое объекту тип сообщения (желательно) пользовательский сообщение состоит из ид и набора (сырых (условно бинарных) ) аргументов для безопасной обработки нам нужны (согласованные) источник и приемник этих сообщений.. источник - это условный функтор, который из переданного набора типизированных аргументов и собственного id создает сообщение.. приемник - это условный функтор, который вызывает ид-зависимый метод для аргументов сообщения.. для обеспечения согласования выбора метода, нужна карта соответствий источника к методу.. исходя из этого в задачи пользователя входит составление конвертера сырых аргументов в типизированные и обратно.. (условно сериализация/десериализация).. явных дырок вроде не видно.. |
| Автор: mes 13.3.2011, 19:14 | ||
вот пока прообраз определения отправителя : http://liveworkspace.org/code/cf501477e6dc6008e0a837667a76b96f P.S. то что в namespace dy {} - библиотечные сущности, вне его пользовательские.. для того, чтоб было более понятно, добавил client , принимающего испускаемое сообщение.. по сути его (сообщение) можно как сразу диспатчеризовать как объекту-исполнителю, так и прокси-объекту, например пересылающему каналу.. http://liveworkspace.org/code/f20d825e29ee37c68b19775061507791 |
| Автор: mes 14.3.2011, 23:16 |
| дополнил картину условной картой и зачатком вызова метода : http://liveworkspace.org/code/3fb0a366fb31a75aacb548bb3c26dbe5 более полный прообраз dy::map в соседней теме.. |
| Автор: mes 17.3.2011, 17:53 |
| еще немного подправил, убрал лишнее, чтоб все с одного обзора видно было.. http://liveworkspace.org/code/bc23e9e011e5b0d7176ba0bc2ff9ca5d |
| Автор: boostcoder 17.3.2011, 18:07 | ||
| mes, скажите, Вы сейчас исследуете связывание со статической проверкой на соответствие? зы еще, мне кажется, сильно неудобным такой способ:
много ручного кода юзеру писать придется. :( и "struct stc" тоже ручной код :( конкретно сейчас, я интегрирую discoly в реальный проект. и тут возникает куча всяких нюансов, которые не видны в тестовом проекте. в общем, все оказывается сложнее чем кажется... и обязанностей у discoly больше, чем просто связывание и вызовы... |
| Автор: mes 17.3.2011, 18:28 | ||||
не совсем.. пытаюсь определить такой минимальный каркас, который будет отражать нужную функциональность.. ну так сигнал определен как функция, а не как функция объекта.. поэтому и бинд.. при использовании cls_map, код инициализации был бы :
а тут что смущает ? что приходится тип и имя задавать ? а на что опираться контролю типобезопасности ? к тому же в любом случае должны быть определены две функции/функтора : отправитель и приемник.. |
| Автор: boostcoder 17.3.2011, 18:31 | ||
это я понимаю. просто мысль высказал и еще. для чего _stc является глобальным объектом? это обязательно? почему? |
| Автор: mes 17.3.2011, 18:36 | ||||
пока просто.. а так из предположения, что в один момент может существовать только один sender::call с одним имен.. Добавлено через 10 минут и 33 секунды
ну так приоткрыли бы занавес.. хоть одним глазком взглянуть.. |
| Автор: mes 21.3.2011, 09:50 | ||
ручное указание идентификатора нужно было в случае, когда вызову должен быть поставлен конкретный ид... но возможна ситуация, когда пользователю значение ид не важно.. для этих случаев можно генерить ид по счетчику.. в итоге определение отправителя будет следующим :
а счетчик на каждый Тraits будет свой, для исключения конфликтов между разными протоколами.. также у пользователя должна быть возможность определить принцип построения ид, например добавить префикс.. итого : http://liveworkspace.org/code/8934bc564df55dbd5bb91362ac1f5376 |
| Автор: mes 21.3.2011, 19:17 |
из за статического счетчика, при создании двух экземпляров stc элементы получат разные id.. а также нет контроля выхода за пределы позволенной енумерации.. решить проблемку можно двумя способами.. 1. сделать stc синглетоном 2. задавать при создании группы (stc) возможный диапазон значений.. вот в грязном виде : http://liveworkspace.org/code/c09a3d8b8c97d41053f6c4dfdd44114f Добавлено через 1 минуту и 20 секунд последнее так же дает возможность указывать нужный диапазон для каждой конкретной группы... Добавлено через 2 минуты и 56 секунд только мне названия ни sender, ни call не нравятся.. |
| Автор: mes 22.3.2011, 01:51 |
опробуем "превращение" функции, в функцию-член : http://liveworkspace.org/code/5e6c6afcb0288294cee90364f5ab5631 следующим шагом нужно переработать карты (dy::map) так, чтоб она была приспособлена для хранения также и функций членов на основе вышеприведенного примера.. |
| Автор: mes 22.3.2011, 11:48 |
что-то типо этого : http://liveworkspace.org/code/fd52a7513dec7d25e3dcde4a17770fb2 с подправлениями : http://liveworkspace.org/code/ef6af8435e3cff5a5b47dcebe05e8fbe |
| Автор: mes 22.3.2011, 17:50 |
| теперь надо попробовать отделить карту от объекта реализации... |
| Автор: boostcoder 22.3.2011, 18:17 | ||||
mes, а я уже два дня бьюсь над багом. только что понял в чем проблема. наверное баг в asio, или в TCP стеке. в общем, в один прекрасный момент, контекст пользователя на сервере, читает из сети такое:
а отправляется именно такое:
т.е. видно, что на часть архива накладывается другой архив. и не понятно откуда берется X в моем коде ошибок нет. проверил все множеством способов. осталось только снифером посмотреть что уходит, и что приходит. кстати, если между отправками с клиента вставить sleep на 1 мс - то ошибка пропадает. Добавлено через 5 минут и 12 секунд еще странно то, что это происходит в 95% случаев на 347 итерации |
| Автор: bsa 22.3.2011, 18:29 |
| Очень похоже на повторное использование буфера до того, как была завершена работа с ним из другой задачи. |
| Автор: boostcoder 22.3.2011, 18:36 |
| bsa, это исключено, т.к. буфер - локальная переменная функции. и кроме этой функции, никто не знает о существовании этой переменной. мьютекс есть. лочит все тело. |
| Автор: bsa 22.3.2011, 19:00 |
| boostcoder, я про буфер используемый в сетевых операциях asio. |
| Автор: boostcoder 22.3.2011, 19:19 |
| упс... нагадили в тему mes`а. попрошу модераторов почистить. |
| Автор: mes 22.3.2011, 19:32 |
зато хоть не так скучно.. а то почти один тут всегда все почему то стесняются заходить я так понимаю расчитываете на телепатов пока так : http://liveworkspace.org/code/57537e099697acca696f3fd9f6782d15 |
| Автор: boostcoder 22.3.2011, 19:35 |
та нет. просто в коде проблем нет. это какое-то неведомое мне поведение TCP стека. dcpdump доказал, что данные искажены по пути. буду тему создавать... |
| Автор: mes 22.3.2011, 19:35 | ||
как то сильно сомнительно..вероятнее неправильное использование.. Добавлено через 1 минуту и 30 секунд
а имеется минимальный проект восоздающий проблему ? |
| Автор: boostcoder 22.3.2011, 19:41 |
я использую только API`шки asio. как их модно неправильно юзать, чтоб получить баг именно на 347 итерации. зы модераторов попросил почистить тему от этого поста: http://forum.vingrad.ru/index.php?showtopic=323648&view=findpost&p=2317887 Добавлено @ 19:42 к сожалению нет :( пока нет.. Добавлено @ 19:45 в коде точно нет ошибок. все просто: 1. выделение памяти у ОС в shared_array 2. сериализация. 3. копирование в shared_array. 4. boost::asio::async_write() 5. tcpdump показывает что данные ушли. 6. на приеме данные искажены. sleep() между отправками минимум в 1мс полностью решает проблему. зы тему создаю. Добавлено через 5 минут и 49 секунд соврал. 347 - последняя итерация которая проходит благополучно. 348 - завал. Добавлено через 6 минут и 31 секунду т.е. проблема даже не в asio. |
| Автор: mes 22.3.2011, 20:58 | ||||||||||
как же тогда другие сетевые программы работают ? взять хотя бы тот же браузер... плюс искажены оно уж больно странно: "наступили на хвост"..
так может давятся данные не при отсылке, а при приеме.. Добавлено через 57 секунд
чуть чуть подправлено : http://liveworkspace.org/code/8636c3b991deea50923ecccde4f233a8 |
| Автор: boostcoder 22.3.2011, 22:58 | ||
не знаю. но думаю это не важно, т.к. tcpdump читает не при помощи моего кода, и показывает несоответствие.
вот и я не могу понять в чем причина. впервые с таким поведением столкнулся. Добавлено через 1 минуту и 3 секунды зы не могу тему создать, потому что на скрине нужно кое-что написать и указать стрелочки. а я институт по рисования не закончил. ибо сходу не понял как это сделать в GIMP |
| Автор: boostcoder 23.3.2011, 00:06 | ||
| mes, а у Вас случаем нет предположения о том, почему валится на 348`ой итерации, и почему sleep() решает проблему? отсылаю это:
|
| Автор: mes 23.3.2011, 00:14 |
| а если увеличить размер сериализуемой структуры, индекс сбойной итерации изменится ? Добавлено через 1 минуту и 4 секунды инструмент кисточка на панели инструментов и дальше от руки мышкой выводите стрелочки |
| Автор: boostcoder 23.3.2011, 00:17 |
| mes, последние три цифры - это аргумент передаваемый методу. т.е. в передающем коде используется цикл и передается его индекс. |
| Автор: mes 23.3.2011, 00:17 | ||
и все таки похоже на наложение потоков.. Добавлено через 1 минуту и 7 секунд
это я понял.. интересует будет ли она также 348й если увеличичить объем сериализуемых данных.. |
| Автор: boostcoder 23.3.2011, 00:19 | ||||||||||
это я нашел. но там что-то со слоями. потому что я рисую, и ничего не рисуется. цвет тоже вибирал. при сохранении, GIMP сказал что-то о том, что имеются слои. и сказал что их нужно активировать. и тут я озадачился... Добавлено через 2 минуты и 29 секунд
ааа, т.е. будет ли валиться на 348`ой итерации? вряд-ли. сейчас проверю... одинаково даже с одним клиентом и одним потоком. зы завтра коллегу опрошу порисовать. он вроде как умеет. по крайней мере говорит так. Добавлено через 10 минут и 23 секунды
изменил кол-во передаваемых аргументов. теперь валится на 328`ой. ожидаю это:
получаю это:
Добавлено через 13 минут и 1 секунду сочетание тройки и восьмерки сказывается? |
| Автор: mes 23.3.2011, 01:42 |
полагаю, что магическое число все ж 32767.. этим и объясняется стабильность сбоя.. но что ж все таки там натворили, не видя кода, трудно предположить.. |
| Автор: boostcoder 23.3.2011, 01:45 |
мой код не при чем. писал же, что tcpdump показывает что данные ушли. или что, запрещено использовать такие комбинации чисел в отправляемых данных? это же бред Добавлено через 1 минуту и 47 секунд а почему sleep() решает проблему? |
| Автор: mes 23.3.2011, 01:58 | ||||
ну это еще не говорит, что не Вы натворили.. Другие же работают без сбоя в этих же условиях
при чем тут комбинация чисел ? не знаю.. я не телепат |
| Автор: mes 23.3.2011, 02:16 |
| и кстати еще 10 символов не хватает.. длина строки 90, а должна быть 100.. вот там и ошибка.. Добавлено через 51 секунду там же и наш знаковый 16тибитный инт переполняется.. |
| Автор: boostcoder 23.3.2011, 02:21 | ||
архив имеет длину 94 символа. просто в конце идут 4 непечатный символа, потому я их не привел. а с чего Вы взяли что должно быть 100? |
| Автор: mes 23.3.2011, 02:42 |
| поэксперементируйте еще плиз несколько раз (чтоб хотя бы 5 примеров было) и выложите данные: длина строки, длина обреза и итерация на которой произошел обрез.. Добавлено через 1 минуту и 16 секунд и куда вы пишете ? в boost:ip::tcp::socket ? Добавлено через 2 минуты и 42 секунды приемка отправка на одном компе ? т.е. тестируете как локальный сервер ? |
| Автор: mes 23.3.2011, 12:02 |
полагаю что где то есть буфер, который опустошается через N-e время.. размер примерно равен указанной выше константе.. при слишком большой скорости записи вы переполняете его.. пауза дает возможность разгрузить буфер.. полагаю, что это буфер сокета.. но как там устроено я не в курсе.. вероятно где то не проверяется готовность условной линии передачи.. |
| Автор: boostcoder 24.3.2011, 00:48 | ||
да.
на локальной машине такой ошибки не возникает. в таком случае, boost::asio::async_* по идее не должны вызывать колбяк пока они там чего-то не сделают. я же не API системы использую. в общем прикладываю мегапростой пример воспроизводящий ошибку. |
| Автор: boostcoder 24.3.2011, 02:12 |
уже возникает... не могу понять закономерность. |
| Автор: boostcoder 24.3.2011, 15:19 |
| в венде, корректно отработало два раза из, приблизительно, тридцати. в линуксе не разу.. Добавлено через 2 минуты и 56 секунд зы mes, что-то не чистят модераторы тему. наверное это из-за того что не я ТС. |
| Автор: mes 25.3.2011, 14:35 |
| переписал (пока часть) с учетом ново-выяснившихся деталей : http://liveworkspace.org/code/8f13983022d1864d4e983ae1afa54fa1 легенда : dy::proto<> - класс описывающий группу вызовов dy::proto<>::call<Args...> - вызов группирующий из аргументов пакет сообщения dy::free_fn<> - дин. интерфейс передачи сообщения как к свободной функции dy::member_fn<> - дин. интерфейс передачи сообщения, как члену классу dy::method<> - реализация вышеназванных интерфейсов dy::map<>- карта соответствий вызова к методу dy::class_<> - класс-интерфейс обработчика сообщений.. msg - условное сообщение msg_traits - свойства условного сообщения, необходимые для взаимодействия с dy client - условный класс-реализация обработчика сообщений |
| Автор: mes 25.3.2011, 20:48 |
| еще немного дополнил : http://liveworkspace.org/code/989c8c8da555223a3522627c428c0eab вопросы на данный момент : 1. как минимальными действиями для пользователя позволить ему проинициализировать карту методов.. 2. как проинвокить tuple стандартными средствами.. (без написания рекурсивного шаблона итератора) |
| Автор: boostcoder 25.3.2011, 21:54 | ||||
с одной стороны, радует компайл-тайм проверка на соответствие сигнатур/типов. с другой стороны, сложность в использовании... Вы сами-то как считаете, дай Вам такую библиотеку, Вы бы ее с удовольствием использовали? не примите как критику. у меня сложилось два варианта: 1. использовать так, как я предложил. 2. писать кодогенератор. Добавлено @ 21:55
это хороший вопрос... что имеется ввиду? Добавлено @ 21:59 наверное это самый оптимальный вариант. ибо можно разработать синтаксис, простой и понятный пользователю, и многое возложить на кодогенератор(проверку соответствия типов/сигнатур, объединение, групировку, условный инвок, и т.д..). |
| Автор: mes 25.3.2011, 22:34 | ||||||||
То в ту сторону ее я тяну, как раз и соответствует моим пожеланиям..
без типо-безопасности я не вижу смысла в этой затеи.. слишком высок риск пропуска, и как следствие долгие часы отладки.. а вот насчет сложности, я не вижу никакой излишней.. и в частности того, чего нельзя было бы замакросить в дальнейшем для большего удобства.. если речь идет о лишнем описании сигналов (stc) , то фактически оно не является лишним.. так и так нужно было написать две функции, одну отправляющую сигнал, другую принимающую.. Во вторых stc является библиотекой, по отношению к коду приемки.. т.е. соблюдается соотношение один к несколько.. если речь о том , что надо описывать msg_traits.. то это сделано для случая когда нужно взаимодействие по вполне определенному протоколу.. что позволяет взаимодействию на разных языках.. Добавлено @ 22:35 чтоб писать кодогенератор, в любом случае должна быть конструкционная база... Добавлено @ 22:46 передать содержимое std::tuple в std::function.. Добавлено @ 22:49 еще насчет сложности.. если мы будем рассматривать общий случай, когда мы можем использовать дефолтные сообщение и ее свойства, то пользовательский код по определению реализации будет выглядеть так
что можно еще принципиально упростить в этом примере, я не вижу.. |
| Автор: boostcoder 26.3.2011, 17:53 |
еще один момент, который в моем случае препятствует использованию вашего способа в моем проекте - это наследование от шаблона. дело в том, что в моем проекте, GUI уже написан. и написан он с использованием Qt. а Qt, как известно, имеет один неприятный нюанс - запрещено наследоваться от шаблонов. т.е. класс, который предоставляет сигналы и слоты, и соответствует концепту QObject - не может наследовать шаблонный класс. это ограничение навязывает их метагенератор(moс). т.е. в вашем случае, не получится напрямую отразить Qt`ешный класс на протокол... |
| Автор: mes 26.3.2011, 18:36 |
наследование совершенно не обязательно.. можно проксировать, а можно просто замакросить определение оператора() и вспомагателей.. Добавлено через 2 минуты и 8 секунд добавил инвокинг, и условную конвертацию (аналог сериализации) (пока в грязном виде) http://liveworkspace.org/code/85c953df7972c1cbfa1a795ea3091739 |
| Автор: mes 26.3.2011, 20:59 |
| вот убрал наследование, а также добавил условное namespace dyco, в который поместил ступень описания протокола... http://liveworkspace.org/code/95331fe1e1a900a8efc253af093dee5c итого имеем три ступени : :: dy - общие элементы обеспечения взаимодействия :: dyco - описание конкретного протокола :: - клиентская приложение |
| Автор: mes 27.3.2011, 00:23 |
| как уже говорилось, есть два основных действия над сообщением 1. передача (предположительно посредством каналов) 2. исполнение (как вызов функции свободной или члена) со вторым пунктом более-мене разобрались, переходим к разбору первого.. вот с наброском канала : http://liveworkspace.org/code/3d24f56e14ba0f2444b30929fcaf7079 |
| Автор: mes 27.3.2011, 13:26 |
| набросал условный пример взаимодействия двух объектов.. http://liveworkspace.org/code/c4deb105acd2c6948586886857f0fa11 связывать можно как напрямую - для простейших случаев так и через каналы, при составлении сетей, в том числе и удаленного взаимодействия.. |
| Автор: mes 10.8.2012, 22:22 | ||
| вернем тему к жизни http://liveworkspace.org/code/4616ac827fa4cce6862f02cf81ec1509 так выглядит условный калькулятор :
|
| Автор: boostcoder 11.8.2012, 09:54 | ||||
| по крайней мере для меня, задача считается решенной, ибо решение успешно используется уже в нескольких проектах. в Вашем примере все как-то слишком сложно. пример:
необходимо дополнить этот код так:
тут, дистрибьютор знает о всех объектах регистраторах. время жизни объекта регистратора определяет время валидности регистрации. как правило, регистраторы создаются как объекты-члены регистрируемого класса. |
| Автор: mes 11.8.2012, 10:06 |
тут нет гарантии типо-безопасности... без нее задача естественно легче решаема и в текущей ситуации мне неинтересна.. |
| Автор: boostcoder 11.8.2012, 10:12 |
| гарантии я получаю путем использования общих интерфейсов на обоих сторонах. другого, внятного и удобного способа получить эти гарантии - нет. можно делать так как вы предложили. но то кол-во кода которое придется написать руками, еще больше создает вероятность ошибиться. имхо. |
| Автор: mes 11.8.2012, 10:32 | ||||||
для вас интерфейс это концевые обьекты реализующие функциональность, для меня простое согласование имен с их типами, а именно :
что грубо соответсвует :
в "классическом"стиле букв еще больше |
| Автор: mes 11.8.2012, 12:33 |
| цледующий шаг,подключил сигналы : http://liveworkspace.org/code/b69e0a200b84074e4ef4474cabcbcb37 теперь надо спрятать демух, чтоб обьект работал с воднымивыходным каналом.. |
| Автор: boostcoder 11.8.2012, 13:21 |
но зато только одна точка задающая соответствия. непонимаю цели. т.е. в чем профит? |
| Автор: mes 11.8.2012, 15:50 |
одна при декларации интерфейса и вторая при определении наследника.. Добавлено @ 15:56 не понял... я предполагаю два demuxa : один сигнальный, другой функциональный.. если не нравится - можно самому переопределить рецептор.. пример обработки сообщения без его конкретизации - логгер - ему demux совсем ненужен.. Добавлено @ 15:57 вопрос, почему оставляю доступ к сигналу ? чтоб не прятать привычный интерфейс.. Добавлено @ 16:01 концепция : есть канал, на вход скидываются сообщения, на выходе получаются и если нужно демультипликсируется.. все что снаружи от этой области в компентенции юзера.. канал можно будет замыкать на другой канал или на сокет, для трансляции сообщений за пределы приложения.. также можно устанавливать фильтры для разветвления потока сообщений... |
| Автор: boostcoder 11.8.2012, 17:06 |
дело не в том что что-то не нравится. дело в непонимании. объясните, какие плюсы в таком подходе? |
| Автор: mes 12.8.2012, 08:06 |
плюсы того, что сообщения сети отращаются на сигнал ? ну так все преимущества сиганалов.. можно подключить несколько слотов, задать порядок, отключить когда какой ненужен, заблокировать если нужно.. т.е. все тоже самое, как если б использовались сигналы просто в приложении.. или я не понял вопроса,о том,что именно смущает в этой конструкции.. без сигналов тоже можно.. для меня в концепции самоепроблематичноебыло, из за чего была пауза в теме, это то, как должен идентифицироваться вызов.. чего мне нехватало раньше, это сетевой альтернативы this.. т.е.чтоб получать не только аргументы, но и определять кто и кому послал.. поэтому сейчас первым параметром обработчика идет (ды::мсг конст&) помимо всего тема возобновлена не только из за вдохновения.. у меня появилось задание и ряд требований.. главное для это случаями нимализировать использование шаблонов в интерфейсе, т.е. чтоб определение интерфейса в нашем случае mаth_face было си-подобным.. пусть даже с увелечением нагрузки на разработчика интерфейса, в том числе и с возможностью использования внешнего кодогенератора..но при этом разрaботчик конечных классов(обработчиков ) страдать не должен.. |
| Автор: mes 12.8.2012, 16:22 |
| а вспомнил.. я ж уже поэтому пути ходил.. demux (в его текущем исполнении) плох тем, что сам решает по какому признаку определять вызов.. т.е. содержит в себе и карту и логику выборки из карты.. гораздо удобнее это иметь это в разных сущностях.. а также карта должна быть как для полных замыканий(без дополпараметров) , так для подобия членовклассов, для возможности иметь однустатическую карту на группу обьектов - это позволить отражать имя метода на указатель на обьект.. |