Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > RE: библиотекa распределенного общения


Автор: mes 28.2.2011, 12:31
тема предназначена для обсуждения вопросов возникшей в теме : 
http://forum.vingrad.ru/forum/topic-323593/kw-distributed-discoly.html

Добро пожаловать ! smile

Автор: mes 1.3.2011, 10:52
Посмотрев свежим  взглядом заметил, что у нас определились два направления :
1. составление сети обработчиков мигрантов - dataflow.
2. конструирование мигранта и его исполнение..

модель по первому пункту:
 сеть состоит из узлов-объектов, каждый из которых имеет вход и выход:
Код

concept object
{
    void dispatch(msg const&);
    void (*event)(msg const&);
};

, где msg (сообщение) - полиморфный пакет аргументов (в коде назывался migrant)..

тогда объекты делятся на две условные категории : реализация и канал,
где канал, это частный случай реализации отвечающий за передачу сообщения,
а реализация  это объект исполняющий действие ассоциированное с сообщением.. 
Код

struct tcp_channel // канал
{      
    tcp_channel () {
       _soket .on_read = [&](.. ) 
        {
             ..
             event ( msg(..)  ); 
        };
    }

    void dispatch (msg const& m) { _soket.write ( m );  }
    void (*event)(msg const&);

    tcp_socket _socket;
};

Код

struct client // реализация
{
    void dispatch (msg const& m) { invoke ( _map, this,  m );  }
    void (*event)(msg const&);

    void on_msg1() {
         ..
         event ( msg(..) );
    }
  
   struct map : dy::cls_map<client_impl> 
   {
         map()
         {
              at( msg_type1 ) = &client::on_msg1;
         }
   } static _map;
}

тогда для замыкания клиента на канал, код будет условно таким:
Код


client _client;
tcp_channel  _channel;
dy::connect(_channel, _client); // channel -> client
dy::connect(_client, _channel);  // client -> channel


Добавлено через 11 минут и 58 секунд
Переходим ко второму пункту и начнем с проблем:

мигрант ( для возможности получения контроля в dataflow )
и способ упаковки аргументов/сериализация  (для возможности поддержки существующих протоколов) 
должны задаваться и определяться пользователем .. 

должна быть возможность инвокинга сообщения, как для функции так и для метода.. 
при этом сохранить отношение одна карта на множество объектов.. 

Автор: boostcoder 1.3.2011, 15:25
Цитата(mes @  28.2.2011,  12:31 Найти цитируемый пост)
тема предназначена для обсуждения вопросов возникшей в теме : 
библиотека распределенного общения

цель аргументирована и представлена правильно.

НО:
Цитата

template<typename A1>
struct invoker<void(A1)> : i_invoker

...

template<typename A1, typename A2>
struct invoker<void(A1,A2)> : i_invoker

это сделано только для разного кол-ва аргументов?


Цитата

dy::type<void(std::string, std::string)> welcome;
dy::type<void(std::string)> quit;

как предполагается поступить в том случае, когда у нескольких типов сигнатура одна, а их назначение разное?


Цитата

struct stc {
dy::type<void ( std::string
              , std::string )>     welcome;
                 
dy::type<void ( std::string )>     quit;
    stc () : welcome ({"welcome"})
           , quit({"quit"})
           {}
} _stc;

я понимаю что это нужно. но это лишний кусок работы возлагаемой на юзера. есть идеи как упростить это?


в этой теме:
Цитата

   struct map : dy::cls_map<client_impl> 
   {
         map()
         {
              at( msg_type1 ) = &client::on_msg1;
         }
   } static _map;


я так понял, пример приведен для регистрации методов самого client? а как будет выглядеть это все, если, к примеру, нужно зарегистрировать объекты-члены client`а?

Автор: mes 1.3.2011, 15:41
Цитата(boostcoder @  1.3.2011,  14:25 Найти цитируемый пост)
это сделано только для разного кол-ва аргументов?

да.. чтоб получить удобный синтаксис вызова и инвокинга.. 

Цитата(boostcoder @  1.3.2011,  14:25 Найти цитируемый пост)
ак предполагается поступить в том случае, когда у нескольких типов сигнатура одна, а их назначение разное?

написать несколько типов с одной сигнатурой и разным ид 
smile

Цитата(boostcoder @  1.3.2011,  14:25 Найти цитируемый пост)
но это лишний кусок работы возлагаемой на юзера. 

если нужен статический контроль, пользователь должен определить правила.. 
этот участок описание протокола, т.е. фактически должен являться библиотечкой используемой как клиентом, так и сервером.. 
т.е. составляется один раз, на N-приложений сети.. 

Цитата(boostcoder @  1.3.2011,  14:25 Найти цитируемый пост)
у, нужно зарегистрировать объекты-члены client`а?

для каждого типа объекта своя карта.. или просто прямая передача вызова от функции к функции.. 


Автор: mes 13.3.2011, 00:17
еще раз попробуем определить сущности..
модель общения: сообщение посылаемое объекту
тип сообщения (желательно) пользовательский
сообщение состоит из ид и набора  (сырых (условно бинарных) ) аргументов
для безопасной обработки нам нужны (согласованные) источник и приемник этих сообщений.. 

источник - это условный функтор, который из переданного набора типизированных аргументов и собственного id создает сообщение.. 
приемник - это условный функтор, который вызывает ид-зависимый метод для аргументов сообщения.. 
для обеспечения согласования выбора метода, нужна карта соответствий источника к методу.. 

исходя из этого в задачи пользователя входит составление конвертера сырых аргументов в типизированные и обратно.. 
(условно сериализация/десериализация)..

явных дырок вроде не видно..

Автор: mes 13.3.2011, 19:14
Цитата(mes @  12.3.2011,  23:17 Найти цитируемый пост)
источник - это условный функтор, который из переданного набора типизированных аргументов и собственного id создает сообщение.. 

вот пока прообраз определения отправителя :
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, скажите, Вы сейчас исследуете связывание со статической проверкой на соответствие?

зы
еще, мне кажется, сильно неудобным такой способ:
Цитата

    _map[_stc.ident] = std::bind(&client::on_ident, this, std::placeholders::_1);
    _map[_stc.quit]  = std::bind(&client::on_quit,  this, std::placeholders::_1);

много ручного кода юзеру писать придется. :(
и "struct stc" тоже ручной код :(

конкретно сейчас, я интегрирую discoly в реальный проект. и тут возникает куча всяких нюансов, которые не видны в тестовом проекте. в общем, все оказывается сложнее чем кажется... и обязанностей у discoly больше, чем просто связывание и вызовы...

Автор: mes 17.3.2011, 18:28
Цитата(boostcoder @  17.3.2011,  17:07 Найти цитируемый пост)
Вы сейчас исследуете связывание со статической проверкой на соответствие?

не совсем.. пытаюсь определить такой минимальный каркас,  который будет отражать нужную функциональность.. 

Цитата(boostcoder @  17.3.2011,  17:07 Найти цитируемый пост)
 мне кажется, сильно неудобным такой способ:

ну так сигнал определен как функция, а не как функция объекта.. поэтому и бинд.. 
при использовании cls_map, код инициализации был бы :
Код

    _map[_stc.ident] = &client::on_ident;        
    _map[_stc.quit]  = &client::on_quit;  


Цитата(boostcoder @  17.3.2011,  17:07 Найти цитируемый пост)
и "struct stc" тоже ручной код 

а тут что смущает ?  что приходится тип и имя задавать ? а на что опираться контролю типобезопасности ?
к тому же в любом случае должны быть определены две функции/функтора : отправитель и приемник.. 


Автор: boostcoder 17.3.2011, 18:31
Цитата(mes @  17.3.2011,  18:28 Найти цитируемый пост)
а на что опираться контролю типобезопасности ?
к тому же в любом случае должны быть определены две функции/функтора : отправитель и приемник..

это я понимаю. просто мысль высказал smile

и еще. для чего _stc является глобальным объектом? это обязательно? почему?

Автор: mes 17.3.2011, 18:36
Цитата(boostcoder @  17.3.2011,  17:31 Найти цитируемый пост)
и еще. для чего _stc является глобальным объектом? это обязательно? почему?

пока просто.. 
а так из предположения, что в один момент может существовать только один sender::call с одним имен..

Добавлено через 10 минут и 33 секунды
Цитата(boostcoder @  17.3.2011,  17:07 Найти цитируемый пост)
 и обязанностей у discoly больше, чем просто связывание и вызовы... 

ну так приоткрыли бы занавес.. хоть одним глазком взглянуть..  smile 


Автор: mes 21.3.2011, 09:50
Цитата(boostcoder @  17.3.2011,  17:07 Найти цитируемый пост)
и "struct stc" тоже ручной код :(

ручное указание идентификатора нужно было в случае,  когда вызову должен быть поставлен конкретный ид...
но возможна ситуация, когда пользователю значение ид не важно.. для этих случаев можно генерить ид по счетчику.. 
в итоге определение отправителя будет следующим :
Код

struct stc : dy::sender<traits> {
   call<std::string> ident;
   call<std::string> quit;
} _stc;

а счетчик на каждый Тraits  будет свой, для исключения конфликтов между разными протоколами..
также у пользователя должна быть возможность определить принцип построения ид, например добавить префикс..
итого :
http://liveworkspace.org/code/8934bc564df55dbd5bb91362ac1f5376

Автор: mes 21.3.2011, 19:17
Цитата(mes @  21.3.2011,  08:50 Найти цитируемый пост)
итого :

из за статического счетчика,  при создании двух экземпляров stc элементы получат разные id..
а также нет контроля выхода за пределы позволенной енумерации.. 
решить проблемку можно двумя способами.. 
1. сделать stc синглетоном
2. задавать при создании группы (stc) возможный  диапазон значений..
вот в грязном виде :
http://liveworkspace.org/code/c09a3d8b8c97d41053f6c4dfdd44114f

Добавлено через 1 минуту и 20 секунд
последнее так же дает возможность указывать нужный диапазон для каждой конкретной группы...

Добавлено через 2 минуты и 56 секунд
только мне названия ни sender, ни call не нравятся.. 

Автор: mes 22.3.2011, 01:51
Цитата(mes @  17.3.2011,  17:28 Найти цитируемый пост)
ну так сигнал определен как функция, а не как функция объекта..

опробуем "превращение" функции, в функцию-член :
http://liveworkspace.org/code/5e6c6afcb0288294cee90364f5ab5631

следующим шагом нужно переработать карты (dy::map) так, чтоб она была приспособлена для хранения также и функций членов
на основе вышеприведенного примера.. 

Автор: mes 22.3.2011, 11:48
Цитата(mes @  22.3.2011,  00:51 Найти цитируемый пост)
нужно переработать карту

что-то типо этого :
http://liveworkspace.org/code/fd52a7513dec7d25e3dcde4a17770fb2

с подправлениями :
http://liveworkspace.org/code/ef6af8435e3cff5a5b47dcebe05e8fbe

Автор: mes 22.3.2011, 17:50
теперь надо попробовать отделить карту от объекта реализации... 

Автор: boostcoder 22.3.2011, 18:17
smile 
mes, а я уже два дня бьюсь над багом. только что понял в чем проблема. наверное баг в asio, или в TCP стеке.
в общем, в один прекрасный момент, контекст пользователя на сервере, читает из сети такое:
Цитата

22 serialization::archive 9 0 0 8 servimpl 2 m1 32 22 serialization::archiveX22 seria

а отправляется именно такое:
Цитата

22 serialization::archive 9 0 0 8 servimpl 2 m1 32 22 serialization::archive 9 347

т.е. видно, что на часть архива накладывается другой архив. и не понятно откуда берется X
в моем коде ошибок нет. проверил все множеством способов.
осталось только снифером посмотреть что уходит, и что приходит.

кстати, если между отправками с клиента вставить sleep на 1 мс - то ошибка пропадает.

Добавлено через 5 минут и 12 секунд
еще странно то, что это происходит в 95% случаев на 347 итерации smile 

Автор: 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
Цитата(boostcoder @  22.3.2011,  18:19 Найти цитируемый пост)
упс..

зато хоть не так скучно.. а то почти один тут всегда smile
все почему то стесняются заходить  smile 


Цитата(boostcoder @  22.3.2011,  17:17 Найти цитируемый пост)
 в один прекрасный момент, контекст пользователя на сервере

я так понимаю расчитываете на телепатов  smile  smile 

Цитата(mes @  22.3.2011,  16:50 Найти цитируемый пост)
теперь надо попробовать отделить карту от объекта реализации... 

пока так :
http://liveworkspace.org/code/57537e099697acca696f3fd9f6782d15

Автор: boostcoder 22.3.2011, 19:35
Цитата(mes @  22.3.2011,  19:32 Найти цитируемый пост)
я так понимаю расчитываете на телепатов

та нет. просто в коде проблем нет. это какое-то неведомое мне поведение TCP стека. dcpdump доказал, что данные искажены по пути. буду тему создавать...

Автор: mes 22.3.2011, 19:35
Цитата(boostcoder @  22.3.2011,  17:17 Найти цитируемый пост)
наверное баг в asio, или в TCP стеке

как то сильно сомнительно..вероятнее неправильное использование..

Добавлено через 1 минуту и 30 секунд
Цитата(boostcoder @  22.3.2011,  18:35 Найти цитируемый пост)
 просто в коде проблем нет. это какое-то неведомое мне поведение TCP стека

а имеется минимальный проект восоздающий проблему ? 

Автор: boostcoder 22.3.2011, 19:41
Цитата(mes @  22.3.2011,  19:35 Найти цитируемый пост)
вероятнее неправильное использование..

я использую только API`шки asio. как их модно неправильно юзать, чтоб получить баг именно на 347 итерации.

зы
модераторов попросил почистить тему от этого поста: http://forum.vingrad.ru/index.php?showtopic=323648&view=findpost&p=2317887

Добавлено @ 19:42
Цитата(mes @  22.3.2011,  19:35 Найти цитируемый пост)
а имеется минимальный проект восоздающий проблему ?

к сожалению нет :( пока нет..

Добавлено @ 19:45
Цитата(mes @  22.3.2011,  19:35 Найти цитируемый пост)
а имеется минимальный проект восоздающий проблему ?

в коде точно нет ошибок. все просто:
1. выделение памяти у ОС в shared_array
2. сериализация.
3. копирование в shared_array.
4. boost::asio::async_write()
5. tcpdump показывает что данные ушли.
6. на приеме данные искажены.

sleep() между отправками минимум в 1мс полностью решает проблему.


зы
тему создаю.

Добавлено через 5 минут и 49 секунд
Цитата(boostcoder @  22.3.2011,  19:41 Найти цитируемый пост)
баг именно на 347 итерации.

соврал. 347 - последняя итерация которая проходит благополучно. 348 - завал.

Добавлено через 6 минут и 31 секунду
Цитата(boostcoder @  22.3.2011,  19:41 Найти цитируемый пост)
5. tcpdump показывает что данные ушли.

т.е. проблема даже не в asio.

Автор: mes 22.3.2011, 20:58
Цитата(boostcoder @  22.3.2011,  18:35 Найти цитируемый пост)
это какое-то неведомое мне поведение TCP стека. dcpdump доказал, что данные искажены по пути.

как же тогда другие сетевые программы работают ? взять хотя бы тот же браузер... 
плюс искажены оно уж больно странно: "наступили на хвост".. 

Цитата(boostcoder @  22.3.2011,  18:41 Найти цитируемый пост)
Цитата

tcpdump показывает что данные ушли.

т.е. проблема даже не в asio.

так может давятся данные не при отсылке, а при приеме..

Добавлено через 57 секунд
Цитата(mes @  22.3.2011,  18:32 Найти цитируемый пост)
Цитата

теперь надо попробовать отделить карту от объекта реализации... 

пока так :
http://liveworkspace.org/code/57537e099697...96f3fd9f6782d15 

чуть чуть подправлено :
http://liveworkspace.org/code/8636c3b991deea50923ecccde4f233a8

Автор: boostcoder 22.3.2011, 22:58
Цитата(mes @  22.3.2011,  20:58 Найти цитируемый пост)
так может давятся данные не при отсылке, а при приеме..

не знаю. но думаю это не важно, т.к. tcpdump читает не при помощи моего кода, и показывает несоответствие.

Цитата(mes @  22.3.2011,  20:58 Найти цитируемый пост)
как же тогда другие сетевые программы работают ? взять хотя бы тот же браузер... 

вот и я не могу понять в чем причина. впервые с таким поведением столкнулся.

Добавлено через 1 минуту и 3 секунды
зы
не могу тему создать, потому что на скрине нужно кое-что написать и указать стрелочки. а я институт по рисования не закончил. ибо сходу не понял как это сделать в GIMP smile 

Автор: boostcoder 23.3.2011, 00:06
mes, а у Вас случаем нет предположения о том, почему валится на 348`ой итерации, и почему sleep() решает проблему?
отсылаю это:
Цитата

22 serialization::archive 9 0 0 8 servimpl 2 m1 32 22 serialization::archive 9 347
22 serialization::archive 9 0 0 8 servimpl 2 m1 32 22 serialization::archive 9 348


Автор: mes 23.3.2011, 00:14
а если увеличить размер сериализуемой структуры, индекс сбойной итерации изменится ?

Добавлено через 1 минуту и 4 секунды
Цитата(boostcoder @  22.3.2011,  21:58 Найти цитируемый пост)
 ибо сходу не понял как это сделать в GIMP

инструмент кисточка на панели инструментов и дальше от руки мышкой выводите стрелочки smile

Автор: boostcoder 23.3.2011, 00:17
mes, последние три цифры - это аргумент передаваемый методу. т.е. в передающем коде используется цикл и передается его индекс.

Автор: mes 23.3.2011, 00:17
Цитата(boostcoder @  22.3.2011,  23:06 Найти цитируемый пост)
почему sleep() 

и все таки похоже на наложение потоков..

Добавлено через 1 минуту и 7 секунд
Цитата(boostcoder @  22.3.2011,  23:17 Найти цитируемый пост)
, последние три цифры - это аргумент передаваемый методу. т.е. в передающем коде используется цикл и передается его индекс. 

это я понял.. интересует будет ли она также 348й если увеличичить объем сериализуемых данных.. 

Автор: boostcoder 23.3.2011, 00:19
Цитата(mes @  23.3.2011,  00:14 Найти цитируемый пост)
инструмент кисточка на панели инструментов и дальше от руки мышкой выводите стрелочки

это я нашел.
но там что-то со слоями. потому что я рисую, и ничего не рисуется. цвет тоже вибирал. при сохранении, GIMP сказал что-то о том, что имеются слои. и сказал что их нужно активировать. и тут я озадачился...

Добавлено через 2 минуты и 29 секунд
Цитата(mes @  23.3.2011,  00:17 Найти цитируемый пост)
интересует будет ли она также 348й если увеличичить объем сериализуемых данных.. 

ааа, т.е. будет ли валиться на 348`ой итерации? вряд-ли. сейчас проверю...

Цитата(mes @  23.3.2011,  00:17 Найти цитируемый пост)
и все таки похоже на наложение потоков..

одинаково даже с одним клиентом и одним потоком.

зы
завтра коллегу опрошу порисовать. он вроде как умеет. по крайней мере говорит так.

Добавлено через 10 минут и 23 секунды
Цитата(mes @  23.3.2011,  00:17 Найти цитируемый пост)
нтересует будет ли она также 348й если увеличичить объем сериализуемых данных.. 

изменил кол-во передаваемых аргументов.
теперь валится на 328`ой.

ожидаю это:
Цитата

22 serialization::archive 9 0 0 8 servimpl 2 m1 38 22 serialization::archive 9 328 3 328

получаю это:
Цитата

22 serialization::arch^22 serialization::archive 9 0 0 8 servimpl 2 m1 38 22 serialization:


Добавлено через 13 минут и 1 секунду
Цитата(boostcoder @  23.3.2011,  00:19 Найти цитируемый пост)
валиться на 348`ой

Цитата(boostcoder @  23.3.2011,  00:19 Найти цитируемый пост)
валиться на 328`ой

сочетание тройки и восьмерки сказывается? smile 

Автор: mes 23.3.2011, 01:42
Цитата(boostcoder @  22.3.2011,  23:19 Найти цитируемый пост)
сочетание тройки и восьмерки сказывается?

полагаю, что магическое число все ж 32767.. этим и объясняется стабильность сбоя.. 
но что ж все таки там натворили, не видя кода, трудно предположить.. 

Автор: boostcoder 23.3.2011, 01:45
Цитата(mes @  23.3.2011,  01:42 Найти цитируемый пост)
но что ж все таки там натворили

мой код не при чем. писал же, что tcpdump показывает что данные ушли.
или что, запрещено использовать такие комбинации чисел в отправляемых данных? это же бред smile

Добавлено через 1 минуту и 47 секунд
Цитата(mes @  23.3.2011,  01:42 Найти цитируемый пост)
полагаю, что магическое число все ж 32767

а почему sleep() решает проблему?

Автор: mes 23.3.2011, 01:58
Цитата(boostcoder @  23.3.2011,  00:45 Найти цитируемый пост)
мой код не при чем. писал же, что tcpdump показывает что данные ушли.

ну это еще не говорит, что не Вы натворили.. Другие же работают без сбоя в этих же условиях smile

Цитата(boostcoder @  23.3.2011,  00:45 Найти цитируемый пост)
или что, запрещено использовать такие комбинации чисел в отправляемых данных? это же бред 

при чем тут комбинация чисел ?

Цитата(boostcoder @  23.3.2011,  00:45 Найти цитируемый пост)
а почему sleep() решает проблему?

не знаю.. я не телепат smile

Автор: mes 23.3.2011, 02:16
и кстати еще 10 символов не хватает.. длина строки 90, а должна быть 100.. 
вот там и ошибка..

Добавлено через 51 секунду
там же и наш знаковый 16тибитный инт переполняется.. 


Автор: boostcoder 23.3.2011, 02:21
Цитата(mes @  23.3.2011,  02:16 Найти цитируемый пост)
и кстати еще 10 символов не хватает.. длина строки 90, а должна быть 100.. 

архив имеет длину 94 символа. просто в конце идут 4 непечатный символа, потому я их не привел.
а с чего Вы взяли что должно быть 100?

Автор: mes 23.3.2011, 02:42
поэксперементируйте еще плиз несколько раз (чтоб хотя бы 5 примеров было)
и выложите данные:  длина строки, длина обреза и итерация на которой произошел обрез..

Добавлено через 1 минуту и 16 секунд
и куда вы пишете ? в boost:ip::tcp::socket ?

Добавлено через 2 минуты и 42 секунды
приемка отправка на одном компе ? т.е. тестируете как локальный сервер ?


Автор: mes 23.3.2011, 12:02
Цитата(boostcoder @  23.3.2011,  00:45 Найти цитируемый пост)
а почему sleep() решает проблему?

полагаю что где то есть буфер, который опустошается через N-e время.. 
размер примерно равен указанной выше константе..
при слишком большой скорости записи вы переполняете его..
пауза дает возможность разгрузить буфер..
полагаю, что это буфер сокета.. но как там устроено я не в курсе.. 
вероятно где то не проверяется готовность условной линии передачи..



Автор: boostcoder 24.3.2011, 00:48
Цитата(mes @  23.3.2011,  02:42 Найти цитируемый пост)
и куда вы пишете ? в boost:ip::tcp::socket ?

да.

Цитата(mes @  23.3.2011,  02:42 Найти цитируемый пост)
приемка отправка на одном компе ? т.е. тестируете как локальный сервер ?

на локальной машине такой ошибки не возникает.

Цитата(mes @  23.3.2011,  12:02 Найти цитируемый пост)
вероятно где то не проверяется готовность условной линии передачи..

в таком случае, boost::asio::async_* по идее не должны вызывать колбяк пока они там чего-то не сделают. я же не API системы использую.

в общем прикладываю мегапростой пример воспроизводящий ошибку.

Автор: boostcoder 24.3.2011, 02:12
Цитата(boostcoder @  24.3.2011,  00:48 Найти цитируемый пост)
на локальной машине такой ошибки не возникает.

уже возникает... не могу понять закономерность.

Автор: 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
Цитата(mes @  25.3.2011,  20:48 Найти цитируемый пост)
еще немного дополнил :
http://liveworkspace.org/code/989c8c8da555...522627c428c0eab

с одной стороны, радует компайл-тайм проверка на соответствие сигнатур/типов.
с другой стороны, сложность в использовании...

Вы сами-то как считаете, дай Вам такую библиотеку, Вы бы ее с удовольствием использовали?
не примите как критику.

у меня сложилось два варианта:
1. использовать так, как я предложил.
2. писать кодогенератор.

Добавлено @ 21:55
Цитата(mes @  25.3.2011,  20:48 Найти цитируемый пост)
1. как минимальными действиями для пользователя позволить ему проинициализировать карту методов.. 

это хороший вопрос...

Цитата(mes @  25.3.2011,  20:48 Найти цитируемый пост)
2. как проинвокить tuple стандартными средствами..

что имеется ввиду?

Добавлено @ 21:59
Цитата(boostcoder @  25.3.2011,  21:54 Найти цитируемый пост)
2. писать кодогенератор.

наверное это самый оптимальный вариант.
ибо можно разработать синтаксис, простой и понятный пользователю, и многое возложить на кодогенератор(проверку соответствия типов/сигнатур, объединение, групировку, условный инвок, и т.д..).

Автор: mes 25.3.2011, 22:34
Цитата(boostcoder @  25.3.2011,  20:54 Найти цитируемый пост)
Вы сами-то как считаете, дай Вам такую библиотеку, Вы бы ее с удовольствием использовали?

То в ту сторону ее я тяну, как раз и соответствует моим пожеланиям.. smile

Цитата(boostcoder @  25.3.2011,  20:54 Найти цитируемый пост)
с одной стороны, радует компайл-тайм проверка на соответствие сигнатур/типов.
с другой стороны, сложность в использовании...

без типо-безопасности я не вижу смысла в этой затеи.. 
слишком высок  риск пропуска, и как следствие долгие часы отладки.. 

а вот насчет сложности, я не вижу никакой излишней.. 
и в частности того, чего нельзя было бы замакросить в дальнейшем для большего удобства.. 

если речь идет о лишнем описании сигналов (stc) , то фактически оно не является лишним..
так и так нужно было написать две функции, одну отправляющую сигнал, другую принимающую.. Во вторых stc является библиотекой, по отношению к коду приемки..
т.е. соблюдается соотношение один к несколько.. 

если речь о том , что надо описывать msg_traits.. то это сделано для случая когда нужно взаимодействие по вполне определенному протоколу.. что позволяет взаимодействию на разных языках..

Добавлено @ 22:35
Цитата(boostcoder @  25.3.2011,  20:54 Найти цитируемый пост)
 писать кодогенератор.

чтоб писать кодогенератор, в любом случае должна быть конструкционная база...

Добавлено @ 22:46
Цитата(boostcoder @  25.3.2011,  20:54 Найти цитируемый пост)
что имеется ввиду?

передать содержимое std::tuple в std::function..

Добавлено @ 22:49
еще насчет сложности.. если мы будем рассматривать общий случай, когда мы можем использовать дефолтные сообщение и ее свойства, то пользовательский код по определению реализации будет выглядеть так
Код

// протокол
struct stc : dy::proto<> {
   stc () : proto_t (10,12) {} 
   
   call<std::string> ident;
   call<std::string> quit;
         
} _stc;


Код

// реализация обработчика
struct client : dy::class_<client>
{
   void on_ident (const std::string&) { std::cout << "on_ident "; }
   void on_quit  (const std::string&) { std::cout << "on_quit "; }
};
//<--
//строка_инициализации_карты ()
( _stc.ident, &client::on_ident )
( _stc.quit,  &client::on_quit );

что можно еще принципиально упростить в этом примере, я не вижу.. 

Автор: boostcoder 26.3.2011, 17:53
Цитата(mes @  25.3.2011,  22:34 Найти цитируемый пост)
struct client : dy::class_<client>

еще один момент, который в моем случае препятствует использованию вашего способа в моем проекте - это наследование от шаблона.
дело в том, что в моем проекте, GUI уже написан. и написан он с использованием Qt. а Qt, как известно, имеет один неприятный нюанс - запрещено наследоваться от шаблонов. т.е. класс, который предоставляет сигналы и слоты, и соответствует концепту QObject - не может наследовать шаблонный класс. это ограничение навязывает их метагенератор(moс).
т.е. в вашем случае, не получится напрямую отразить Qt`ешный класс на протокол...

Автор: mes 26.3.2011, 18:36
Цитата(boostcoder @  26.3.2011,  16:53 Найти цитируемый пост)
наследование от шаблона

наследование совершенно не обязательно.. 
можно проксировать, а можно просто замакросить определение оператора() и вспомагателей..

Добавлено через 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
вернем тему к жизни smile Пришло немножко вдохновения, решил попробовать заново :
http://liveworkspace.org/code/4616ac827fa4cce6862f02cf81ec1509

так выглядит условный калькулятор : 
Код

namespace math_face {
  
dy::msg_type<int, int> do_add = { "math.do_add" };
dy::msg_type<int>      re_add = { "math.re_add" };
  
}

struct math_client 
{
  math_client (dy::channel & ch)
     : _channel (ch)
     , _my_name ("math_client")
     , _service_name ("math_service")
  {
  }

  void add (int a, int b)
  {

     _cxt_for_add.a = a;
     _cxt_for_add.b = b;
     
     send (math_face::do_add(a,b));
  }
  
  void re_add (const dy::msg&, int c)
  {
  
     std::cout << ":=> " << _cxt_for_add.a <<" + " <<  _cxt_for_add.b;   
     std::cout << " = " << c;           
  }
  

protected:  

  void send (dy::content const& c)
  {
        _channel.send (_my_name, _service_name, c ); 
  }
  
private:
  dy::channel & _channel;  
  std::string   _my_name;   
  std::string   _service_name;  
  
  struct cxt_for_add { int a, b; } _cxt_for_add;
  
};

struct math_service 
{
  math_service(dy::channel & ch)
     : _channel (ch)
     , _my_name ("math_service")
  {
  }
  
  void do_add (const dy::msg & m, int a, int b)
  {
     _channel.send (_my_name, m.sender_id, math_face::re_add (a+b) ); 
  }
  
  dy::channel & _channel;  
  std::string   _my_name;   
};

int main ()
{
   dy::channel _chan;
   dy::msg_logger  _logger; 
   dy::distributor _distributor;
   
   _chan._receptors.push_back(&_logger);
   _chan._receptors.push_back(&_distributor);   
   
   math_client _client(_chan);
   math_service _service(_chan);

   _distributor.add_method(math_face::re_add,  dy::make_method (&_client,  &math_client::re_add));     
   _distributor.add_method(math_face::do_add,  dy::make_method (&_service, &math_service::do_add));
 
   
   _client.add (29, 47);
        
}

Автор: boostcoder 11.8.2012, 09:54
по крайней мере для меня, задача считается решенной, ибо решение успешно используется уже в нескольких проектах. в Вашем примере все как-то слишком сложно.
пример:
Код

// исходный класс
struct calc {
   void add(int a, int b) {}
   void sub(int a, int b) {}
};

// использование
calc c;
c.add(2,3);
c.add(4,5);

необходимо дополнить этот код так:
Код

// общий для всего приложения
distributor distr;
// регистратор для математического сервиса
object_registry reg = distr.get_registry("math::calc");
// регистрируем процедуры
reg.on("add", &calc::add);
reg.on("sub", &calc::sub);
// вызов
distr.invoke(...);

тут, дистрибьютор знает о всех объектах регистраторах. время жизни объекта регистратора определяет время валидности регистрации.
как правило, регистраторы создаются как объекты-члены регистрируемого класса.

Автор: mes 11.8.2012, 10:06
Цитата(boostcoder @  11.8.2012,  08:54 Найти цитируемый пост)
reg.on("add", &calc::add);
reg.on("sub", &calc::sub);

тут нет гарантии типо-безопасности... без нее задача естественно легче решаема и в текущей ситуации мне неинтересна.. smile

Автор: boostcoder 11.8.2012, 10:12
гарантии я получаю путем использования общих интерфейсов на обоих сторонах.
другого, внятного и удобного способа получить эти гарантии - нет.
можно делать так как вы предложили. но то кол-во кода которое придется написать руками, еще больше создает вероятность ошибиться. имхо.

Автор: mes 11.8.2012, 10:32
Цитата(boostcoder @  11.8.2012,  09:12, пост2510858)
гарантии я получаю путем использования общих интерфейсов на обоих сторонах.
другого, внятного и удобного способа получить эти гарантии - нет.

для вас интерфейс это концевые обьекты реализующие функциональность, для меня  простое согласование имен с их типами, а именно : 

Код

namespace math_face {
  
dy::msg_type<int, int> do_add = { "math.do_add" };
dy::msg_type<int>      re_add = { "math.re_add" };
  
}
.. 
.. math_face::do_add(a,b); // формирование вызова удаленной фукции 

что грубо соответсвует :
Код

namespace math_face {
struct do_add {
   virtual void do_add(int,int) =0;
};
struct  re_add {
  virtual void re_add(int)=0;
};

}


в "классическом"стиле букв еще больше smile

Автор: mes 11.8.2012, 12:33
цледующий шаг,подключил сигналы :
http://liveworkspace.org/code/b69e0a200b84074e4ef4474cabcbcb37

теперь надо спрятать демух, чтоб обьект работал с воднымивыходным каналом.. 

Автор: boostcoder 11.8.2012, 13:21
Цитата(mes @  11.8.2012,  10:32 Найти цитируемый пост)
в "классическом"стиле букв еще больше

но зато только одна точка задающая соответствия.

Цитата(mes @  11.8.2012,  12:33 Найти цитируемый пост)
цледующий шаг,подключил сигналы :

непонимаю цели. т.е. в чем профит?

Автор: mes 11.8.2012, 15:50
Цитата(boostcoder @  11.8.2012,  12:21 Найти цитируемый пост)
но зато только одна точка задающая соответствия.

одна при декларации интерфейса и вторая при определении наследника..

Добавлено @ 15:56
Цитата(boostcoder @  11.8.2012,  12:21 Найти цитируемый пост)
непонимаю цели. т.е. в чем профит?

не понял...
я предполагаю два demuxa : один сигнальный, другой функциональный.. если не нравится - можно самому переопределить рецептор.. пример обработки сообщения без его конкретизации - логгер - ему demux совсем ненужен..

Добавлено @ 15:57
Цитата(boostcoder @  11.8.2012,  12:21 Найти цитируемый пост)
. т.е. в чем профит?

вопрос, почему оставляю доступ к сигналу ? чтоб не прятать привычный интерфейс..

Добавлено @ 16:01
концепция : есть канал, на вход скидываются сообщения, на выходе получаются и если нужно демультипликсируется.. все  что снаружи от этой области в компентенции юзера.. 
канал можно будет замыкать  на другой канал или на сокет, для трансляции сообщений за пределы приложения.. также можно устанавливать фильтры для разветвления потока сообщений...

Автор: boostcoder 11.8.2012, 17:06
Цитата(mes @  11.8.2012,  15:50 Найти цитируемый пост)
если не нравится

дело не в том что что-то не нравится. дело в непонимании.
объясните, какие плюсы в таком подходе?

Автор: mes 12.8.2012, 08:06
Цитата(boostcoder @  11.8.2012,  16:06 Найти цитируемый пост)
объясните, какие плюсы в таком подходе?

плюсы того, что сообщения сети отращаются на сигнал ? ну так все преимущества сиганалов.. можно подключить несколько слотов, задать порядок, отключить когда  какой ненужен, заблокировать если нужно.. т.е. все тоже самое, как если б использовались  сигналы просто в приложении.. или я не понял вопроса,о том,что именно смущает в этой конструкции.. без сигналов тоже можно.. для меня в концепции самоепроблематичноебыло, из за чего была пауза в теме, это то, как должен идентифицироваться вызов.. чего мне нехватало раньше, это сетевой альтернативы this.. т.е.чтоб получать не только аргументы, но и определять кто и кому  послал.. поэтому сейчас первым параметром обработчика идет (ды::мсг конст&)
помимо всего тема возобновлена не только из за вдохновения.. у меня появилось задание и ряд требований.. главное для это случаями нимализировать использование шаблонов в интерфейсе, т.е. чтоб определение интерфейса в нашем случае mаth_face было си-подобным.. пусть даже с увелечением нагрузки на разработчика интерфейса, в том числе и с возможностью использования внешнего кодогенератора..но при этом разрaботчик конечных классов(обработчиков ) страдать не должен.. 


Автор: mes 12.8.2012, 16:22
а вспомнил.. я ж  уже поэтому пути ходил..  demux (в его текущем исполнении) плох тем, что сам решает по какому признаку определять вызов.. т.е. содержит в себе и карту и логику выборки из карты.. гораздо удобнее это иметь это в разных сущностях.. а также карта должна быть как для полных замыканий(без дополпараметров) , так для подобия членовклассов, для возможности иметь однустатическую карту на группу обьектов - это позволить отражать имя метода на указатель на обьект.. 


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)