На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
[!] Как относитесь к модерированию на этом форуме? Выскажите свое мнение здесь
Модераторы: Qraizer
Страницы: (14) 1 [2] 3 4 ...  13 14 все  ( Перейти к последнему сообщению )  
> SObjectizer 5.3.0
    Цитата MyNameIsIgor @
    Цитата D_KEY @
    У вас итак хорошо получается, испорчу еще.

    Ну, вот, ты как всегда :yes-sad:

    Ну когда-то я лез в любые споры. Сейчас деградировал.

    Добавлено
    eao197, замечу, что у вас конструктива от сообщения к сообщению все меньше. "Не умеете читать C++" и пр. - не аргументы.
      Цитата eao197 @
      Вы не то что-то заметили. if там используется не для определения типа сообщения, а для проверки количества оставшихся попыток для отсылки ping-а.

      Именно это я и заметил. Только дело в том, что это можно решить с помощью сопоставления с образцом, как, например, здесь. Кстати, как это будет на SO?
      Цитата eao197 @
      Необходимостью хранения счетчика ссылок на экземпляр сообщения.

      И для чего здесь наследование от какого-то типа?
      Цитата eao197 @
      Остается пожелать только, чтобы через 10+ лет сопровождением подобного кода пришлось заниматься именно вам.

      Договорились :D
      Цитата eao197 @
      Нет. Просто не нужная работа.

      Ну, не такая большая работа, прямо скажем :)
      Цитата eao197 @
      Не правильно

      Ну, скажите как правильно.
      Цитата eao197 @
      Без guard-ов жизни нет, совсем.

      Ага, нету, как и без акторов :crazy: Я говорю не о возможности жизни, а об её облегчении.
      Цитата eao197 @
      Возьмите пример, указанный kovrin, перепишите его на Boost.Fiber и посмотрите, получится ли у вас менее адово

      Хорошо, попробую.
      Цитата eao197 @
      А потом попробуйте на тех же boost.fiber переписать пример, который bsivko привел на SObjectizer

      Там слишком много артефактов реализации/библиотеки, чтобы ясно уловить смысл. Я же попросил вас пояснить разницу.

      Ну, а теперь самая приятная часть ответа :D
      Цитата eao197 @
      Хотя вряд ли вы вообще что-то понимаете в C++ и последствиях таких ошибок, как деление на ноль, выход за пределы массива с перезаписью чужой памяти, обращение по неверному указателю и т.д.

      Цитата eao197 @
      Как показали ваши высказывания выше, вы вообще мало чего видите.

      Цитата eao197 @
      Да у вас вообще со зрением что-то

      У-тю-тю-тю-тю :lool: Раз такие переходы на личности, то всё же мои аргументы по существу.
      Ну, я вам так скажу: я достаточно знаю C++, чтобы не звать целого Энтони Уильямса для решения школьной задачи определения сигнаты функтора.

      Добавлено
      eao197, знаете, а я ведь давно ваш блог читаю. Даже ваши аргументы по поводу D нравятся, часто на них ссылался. А сейчас смотрю - да вы обычный... чудак ;)

      Добавлено
      Цитата D_KEY @
      Ну когда-то я лез в любые споры. Сейчас деградировал

      У тебя есть ценное качество не вызывать в оппоненте ненависть. А то вон его как понесло, крутого то нашего :lol:
        простите за нубский вопрос, но я так и не понял, SO работает на green threads или на обычных OS threads? если на зеленых, то как планировщик организовывает вытесняющую многозадачность между акторами?
          Цитата Radagast @
          простите за нубский вопрос, но я так и не понял, SO работает на green threads

          Да вы мечтатель! :D У них подход другой - нефиг тянуть в язык всякую эрланговскую хрень!

          Обещанный код пинг-понга на boost.fibers. С комментария соответствующего кода на Go для оценки адовости :)
          ExpandedWrap disabled
            using namespace boost::fibers;
             
            struct Ball {       //type Ball struct {
                int hints;      //  hits int
            };                  //}
             
            void player(str::string title, unbounded_queue<Ball>& table, unbounded_queue<std::string>& lose) {          //func player(title string, table chan *Ball, lose chan string) {
                for(Ball ball; table.pop(ball) == queue_op_status::success;) {                                          //  for ball := range table {
                    if(ball.hints > 0) {                                                                                //      if ball.hits > 0 {
                        std::cout << title << ' ' << ball.hints << std::endl;                                           //          fmt.Println(title, ball.hits)
                        ball.hints--;                                                                                   //          ball.hits--
                        table.push(ball);                                                                               //          table <- ball
                    } else {                                                                                            //      } else {
                        lose.push(title);                                                                               //          lose <- title
                        breal;                                                                                          //          break
                    }                                                                                                   //      }
                }                                                                                                       //  }
            }                                                                                                           //}
             
            int main() {                                                                                                //func main() {
                unbounded_queue<Ball> table;                                                                            //  table := make(chan *Ball)
                unbounded_queue<std::string> lose;                                                                      //  lose  := make(chan string)
                fiber ping { [&table, &lose] { player("ping", table, lose); } };                                        //  go player("ping", table, lose)
                fiber pong { [&table, &lose] { player("pong", table, lose); } };                                        //  go player("pong", table, lose)
             
                table.push(Ball{10});                                                                                   //  table <- &Ball{10}
                std::string title;                                                                                      //  ...
                lose.pop(title);                                                                                        //  ...
                std::cout << title << " lost" << std::endl;                                                             //  fmt.Println(<-lose, "lost")
                                                                                                                        //  close(table)
                ping.join();                                                                                            //  ...
                pong.join();                                                                                            //  ...
            }                                                                                                           //  }


          Добавлено
          Ах, да, Radagast, libcppa может работать на green threads с помощью boost.context.
          Сообщение отредактировано: MyNameIsIgor -
            Цитата
            Цитата eao197 @
            Вы не то что-то заметили. if там используется не для определения типа сообщения, а для проверки количества оставшихся попыток для отсылки ping-а.

            Именно это я и заметил. Только дело в том, что это можно решить с помощью сопоставления с образцом, как, например, здесь. Кстати, как это будет на SO?


            Решить что? Счетчик попыток -- это состояние агента. Его нужно хранить в самом агенте. Оттуда там и if.

            В приведенном вами примере состояние передается в сообщении. SO это было бы как-то так:
            ExpandedWrap disabled
              struct msg_step : public so_5::rt::message_t
              {
                size_t pos;
                msg_step( size_t a ) : pos( a ) {}
              }
               
              coop->define_agent()
                .on_start( [mbox]() { mbox->deliver_signal( new msg_step(0) ); }
                .on_event( [&env, mbox]( const msg_step & msg ) {
                  if( msg.pos != array_size(animation_step) )
                  {
                    draw_kirby(animation_step[msg.pos]);
                    env.schedule_timer( new msg_step( msg.pos+1 ), mbox, 150 );
                  }
                  else
                  {
                    std::cout << std::endl;
                    env.stop();
                  }
                } );


            Поскольку в SO нет сопоставления с образцом, он использует typeid(msg_step) для того, чтобы имея список поток сообщений понять, что именно это сообщение должно быть передано агенту. А вот на структуру сообщения SO не смотрит -- его задача доставить, а как будет разбираться с сообщением пользователь, это уже задача пользователя.

            Цитата
            Цитата eao197 @
            Необходимостью хранения счетчика ссылок на экземпляр сообщения.

            И для чего здесь наследование от какого-то типа?


            Ну вот libcppa создает обертку вокруг тупла неявно. В SO это делается путем наследования от базового типа.

            Цитата
            Цитата eao197 @
            Нет. Просто не нужная работа.

            Ну, не такая большая работа, прямо скажем :)


            Фиг знает. Я так понимаю, что наследование там не спроста сделано. Видимо, кроме наследования нужно еще что-то менять в класса. И не известно, как от этого зависят клиенты или наследники.

            Цитата
            Цитата eao197 @
            Не правильно

            Ну, скажите как правильно.


            Я уже все написал. Раз вы так хорошо знаете C++, как об этом думаете, то знаете, что большой класс ошибок в C++ не ловится вовремя вообще, либо же, в лучшем случае, ведет к краху всего приложения. В отличии от Erlang-а. Соответственно, в Erlang-е можно писать процесс не сильно заморачиваясь на многие вещи. А в C++ нельзя. Поэтому акторы в C++ требуют более пристального внимания. А когда оно есть, то польза от мониторинга агентов оказывается меньше, чем в Erlang-e.

            Если же обработчик события выбрасывает обычного наследника std::exception, то SO дает возможность пользователю определить, что делать. Поступить по-умолчанию (т.е. грохнуть приложение), остановить RunTime SO, дерегистрировать только кооперацию с этим агентом, или вообще проигнорировать.

            Цитата
            Цитата eao197 @
            Без guard-ов жизни нет, совсем.

            Ага, нету, как и без акторов :crazy: Я говорю не о возможности жизни, а об её облегчении.


            Ну, если quard-ы облегчают вам жизнь и вы пишете программы уровня draw_kirby, тогда да, серьезное облегчение.

            Цитата
            Цитата eao197 @
            А потом попробуйте на тех же boost.fiber переписать пример, который bsivko привел на SObjectizer

            Там слишком много артефактов реализации/библиотеки, чтобы ясно уловить смысл. Я же попросил вас пояснить разницу.


            Смысл прост, очень похож на тот, который в приведенном kovrin-ым примере на Go: пинги шлются не более N раз, понг отсылается только в ответ на полученный ping, следующий ping (если это возможно) отсылается только после получения pong-а.

            Цитата
            У-тю-тю-тю-тю :lool: Раз такие переходы на личности, то всё же мои аргументы по существу.


            В очередной раз вы сами себе что-то выдумали.

            Цитата
            Ну, я вам так скажу: я достаточно знаю C++, чтобы не звать целого Энтони Уильямса для решения школьной задачи определения сигнаты функтора.


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

            Цитата
            eao197, знаете, а я ведь давно ваш блог читаю. Даже ваши аргументы по поводу D нравятся, часто на них ссылался. А сейчас смотрю - да вы обычный... чудак ;)


            А вы попробуйте со мной по существу поговорить. Я вам перечислил вещи, которые мне не нравятся в libcppa. Это не значит, что libcppa отстой, а SO рулез. Просто вот такое отношение к некоторым вещам. Могу, если интересно, развивать эти темы. Могу объяснить, почему в SO что-то сделано так, а не иначе. Могу рассказать, почему я бы не стал делать, как в libcppa. Это просто требует времени и соответствующих вопросов. Но когда разговор заходит на уровне "различия между каменным топором или стальным", то да, какой смысл мне с очередным... чудаком общаться не как очередному... чудаку?

            Добавлено
            Цитата Radagast @
            простите за нубский вопрос, но я так и не понял, SO работает на green threads или на обычных OS threads? если на зеленых, то как планировщик организовывает вытесняющую многозадачность между акторами?

            На нитях OS. Зеленые потоки мы не используем.

            Добавлено
            Цитата MyNameIsIgor @
            Обещанный код пинг-понга на boost.fibers. С комментария соответствующего кода на Go для оценки адовости :)

            Спасибо, интересно.
              Цитата MyNameIsIgor @
              table.push(ball);

              Поскольку я никогда не использовал Boost.Fiber и unbounded_queue, то объясните, пожалуйста, что/кто гарантирует, что после помещения ball в очередь table этот ball будет вытащен именно другим файбером, а не тем же самым, который поместил только что ball в очередь?
                Цитата eao197 @
                Решить что? Счетчик попыток -- это состояние агента. Его нужно хранить в самом агенте.

                It depends.
                Цитата eao197 @
                Поскольку в SO нет сопоставления с образцом, он использует typeid(msg_step)

                Вообще-то, это несвязанные вещи. libcppa использует свою информацию о типе из-за необходимости сериализации, которая в свою очередь необходима для удалённого взаимодействия. Кстати, а у вас как с этим обстоят дела?
                Цитата eao197 @
                Ну вот libcppa создает обертку вокруг тупла неявно. В SO это делается путем наследования от базового типа.

                Так и спрашиваю: с чего бы? Почему мне надо от чего-то наследоваться, чтобы кинуть int?
                Цитата eao197 @
                Фиг знает. Я так понимаю, что наследование там не спроста сделано. Видимо, кроме наследования нужно еще что-то менять в класса. И не известно, как от этого зависят клиенты или наследники.

                Там реализация, которую не надо всякий раз писать руками. В мануале неплохой пример со стеком с разными состояниями, что позволяет оставлять сообщения в ящике до перехода стека в другое состояние. Как это будет на SO?
                Цитата eao197 @
                Я уже все написал. Раз вы так хорошо знаете C++, как об этом думаете, то знаете, что большой класс ошибок в C++ не ловится вовремя вообще, либо же, в лучшем случае, ведет к краху всего приложения. В отличии от Erlang-а. Соответственно, в Erlang-е можно писать процесс не сильно заморачиваясь на многие вещи. А в C++ нельзя. Поэтому акторы в C++ требуют более пристального внимания. А когда оно есть, то польза от мониторинга агентов оказывается меньше, чем в Erlang-e.

                Если же обработчик события выбрасывает обычного наследника std::exception, то SO дает возможность пользователю определить, что делать. Поступить по-умолчанию (т.е. грохнуть приложение), остановить RunTime SO, дерегистрировать только кооперацию с этим агентом, или вообще проигнорировать.

                Так в SO как в libcppa, в чём же ваше претензии? :-?
                Цитата eao197 @
                Ну, если quard-ы облегчают вам жизнь и вы пишете программы уровня draw_kirby, тогда да, серьезное облегчение.

                Опять по существу ответить нечего? :) Я говорю о возможностях, которые не влияют на остальную функциональность, потому те, кому это нравится, могут использовать.
                Цитата eao197 @
                Смысл прост, очень похож на тот, который в приведенном kovrin-ым примере на Go: пинги шлются не более N раз, понг отсылается только в ответ на полученный ping, следующий ping (если это возможно) отсылается только после получения pong-а.

                Код, на который я дал ссылку, так и делает, за исключением того, что количество пинг-понгов там зашито. Ну, аналог кода korvin'а я привёл.
                Цитата eao197 @
                Я уже достаточно пожил на свете, чтобы не страдать от того, что чего-то не знаю.

                Но ещё недостаточно, чтобы научиться вести техническую дискуссию :)
                Цитата eao197 @
                А вы попробуйте со мной по существу поговорить. Я вам перечислил вещи, которые мне не нравятся в libcppa

                Я с вами именно по существу и разговариваю. Все мои высказывания касались ваших претензий и не являлись нападками на вас.
                Цитата eao197 @
                Но когда разговор заходит на уровне "различия между каменным топором или стальным", то да, какой смысл мне с очередным... чудаком общаться не как очередному... чудаку?

                Вы сами задали такой тон своим отношением
                Цитата eao197 @
                не идет ни в какое сравнение
                  Цитата eao197 @
                  Поскольку я никогда не использовал Boost.Fiber и unbounded_queue, то объясните, пожалуйста, что/кто гарантирует, что после помещения ball в очередь table этот ball будет вытащен именно другим файбером, а не тем же самым, который поместил только что ball в очередь?

                  Да, я суровый косячник :D Надо будет написать Оливеру, чтобы запилил полноценные каналы, пока ещё не поздно, а не оставлял это на пользователей.
                  ExpandedWrap disabled
                    using namespace boost::fibers;
                     
                    struct Ball {       //type Ball struct {
                        int hints;      //  hits int
                    };                  //}
                     
                    void player(str::string title, unbounded_queue<Ball>& table_in, unbounded_queue<Ball>& table_out,           //func player(title string, table chan *Ball, lose chan string) {
                                unbounded_queue<std::string>& lose) {                                                           // ...
                        for(Ball ball; table_in.pop(ball) == queue_op_status::success;) {                                       //  for ball := range table {
                            if(ball.hints > 0) {                                                                                //      if ball.hits > 0 {
                                std::cout << title << ' ' << ball.hints << std::endl;                                           //          fmt.Println(title, ball.hits)
                                ball.hints--;                                                                                   //          ball.hits--
                                table_out.push(ball);                                                                           //          table <- ball
                            } else {                                                                                            //      } else {
                                lose.push(title);                                                                               //          lose <- title
                                breal;                                                                                          //          break
                            }                                                                                                   //      }
                        }                                                                                                       //  }
                    }                                                                                                           //}
                     
                    int main() {                                                                                                //func main() {
                        unbounded_queue<Ball> table_ping, table_pong;                                                           //  table := make(chan *Ball)
                        unbounded_queue<std::string> lose;                                                                      //  lose  := make(chan string)
                        fiber ping { [&table_ping, &table_pong, &lose] { player("ping", table_ping, table_pong, lose); } };     //  go player("ping", table, lose)
                        fiber pong { [&table_ping, &table_pong, &lose] { player("pong", table_pong, table_ping, lose); } };     //  go player("pong", table, lose)
                     
                        table_ping.push(Ball{10});                                                                              //  table <- &Ball{10}
                        std::string title;                                                                                      //  ...
                        lose.pop(title);                                                                                        //  ...
                        std::cout << title << " lost" << std::endl;                                                             //  fmt.Println(<-lose, "lost")
                                                                                                                                //  close(table)
                        ping.join();                                                                                            //  ...
                        pong.join();                                                                                            //  ...
                    }                                                                                                           //  }


                  Добавлено
                  Значит, к вопросам о поддержке в SO удалённого взаимодействия и обработки разных сообщений в зависимости от состояний актора добавляется третий: а как с кроссплатформенностью? Как я понял, есть зависимость от такого монстра, как ACE. На Android/iOS соберётся?
                    Цитата MyNameIsIgor @
                    Цитата eao197 @
                    Решить что? Счетчик попыток -- это состояние агента. Его нужно хранить в самом агенте.

                    It depends.

                    Это если в общем говорить, тогда, действительно, где-то нужно хранить, где-то нужно передавать. В примере, приведенном bsivko изначально требовалось сделать хранение в агенте для того, чтобы показать, как в ad-hoc-агентах сохранять состояние через захват переменной по ссылке.

                    Цитата MyNameIsIgor @
                    Цитата eao197 @
                    Поскольку в SO нет сопоставления с образцом, он использует typeid(msg_step)

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

                    Мы в SO-4 использовали что-то похоже, на то, что предлагает libcppa для удаленного взаимодействия. Там так же нужно было отдельно декларировать поля сообщения и сам SO-4 формировал код по сериализации/десериализации структур. Более того, была утилита командной строки, которая позволяла задавать значение полей сообщения в stdin и засылала их внутрь SO-4 приложения.

                    Но со временем мы от этого ушли в сторону более мощной системы сериализации. А так же и поменяли подход к построению распределенных приложений на основе SO. Сейчас этими вещами занимается mbapi_4 (для сериализации используется ObjESSty -- что-то вроде Protobuf-а). Но, поскольку mbapi_4 -- это всего лишь т.н. layer, коих на SO можно навесить несколько, то вместо mbapi_4 можно сделать обмен сообщениями посредством AMQP и Protobuf-а.
                    Цитата MyNameIsIgor @
                    Цитата eao197 @
                    Ну вот libcppa создает обертку вокруг тупла неявно. В SO это делается путем наследования от базового типа.

                    Так и спрашиваю: с чего бы? Почему мне надо от чего-то наследоваться, чтобы кинуть int?

                    Потому, что мы по другому подходили к организации взаимодействия агентов. Агент A должен отослать агенту B какое-то осмысленное сообщение, например, "влючить лампочку" или "остановить двигатель". Соответственно, сообщение должно быть описано типом. Какая уже структура будет у типа -- это уже детали, может там один int, может два. А, поскольку мы уже заставляем пользователя вводить тип сообщения, то с точки зрения ООП естественным образом напрашивается его наследование от чего-нибудь.
                    Цитата MyNameIsIgor @
                    Цитата eao197 @
                    Фиг знает. Я так понимаю, что наследование там не спроста сделано. Видимо, кроме наследования нужно еще что-то менять в класса. И не известно, как от этого зависят клиенты или наследники.

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

                    Я пока не совсем понял, что там с состояниями у акторов libcppa. Поэтому не могу сейчас ответить. Если укажете конкретный пример, который бы вам было бы интересно увидеть переписанным на SO, я постараюсь это сделать.
                    Цитата MyNameIsIgor @
                    Так в SO как в libcppa, в чём же ваше претензии? :-?

                    Мне не нравится то, что в C++ 1-в-1 перенесли механизм из Erlang-а, польза от которого в C++ очень сомнительна. Это то, про что Страуструп говорит, как о попытке использования не подходящих к языку приемов. Как в свое время пытались делать библиотеки контейнеров для C++, требуя, чтобы все элементы контейнера были унаследованы от какого-нибудь общего Object-а.
                    Цитата MyNameIsIgor @
                    Цитата eao197 @
                    Я уже достаточно пожил на свете, чтобы не страдать от того, что чего-то не знаю.

                    Но ещё недостаточно, чтобы научиться вести техническую дискуссию :)

                    Техническая еще только начинается.
                    Цитата MyNameIsIgor @
                    Вы сами задали такой тон своим отношением
                    Цитата eao197 @
                    не идет ни в какое сравнение

                    Это не отношение. Это констатация того, что в libcppa сделали то, что в SO вообще никогда не пытались сделать. Поэтому, если пользователю от системы актеров нужно именно сопоставление с образцом, то возможности SObjectizer здесь бесполезно начинать сравнивать. Что вовсе не означает, что SObjectizer отстает от libcppa как каменный топор от стального. Скорее это просто попытка сравнить отбойный молоток с дрелью. Вроде как дырки оба инструмента позволяют делать...
                      Всё, я спать, D_KEY продолжит, он всё равно не спит...
                        Цитата MyNameIsIgor @
                        а как с кроссплатформенностью? Как я понял, есть зависимость от такого монстра, как ACE. На Android/iOS соберётся?

                        Сейчас да, сильно зависим от ACE. Может быть, в версии 5.4 постараемся от ACE уйти, хотя бы в самом ядре SO-5.

                        Про Android/iOS не знаю, никогда не связывался с этими платформами. По-идее, сам SO зависит только от GCC. А вот как с ACE -- хз, надо посмотреть.
                        Уверен, что если бы у меня под рукой был соответствующий инструментарий, то заработало бы и там.
                          Цитата MyNameIsIgor @
                          Всё, я спать, D_KEY продолжит, он всё равно не спит...

                          >:(
                            Цитата MyNameIsIgor @
                            Да, я суровый косячник

                            Еще одна штука. После чтения результата из очереди lose нужно закрыть обе очереди table*.
                            Иначе один из файберов заснет навечно на извлечении очередного сообщения. И весь пример уснет на одном из вызовом join.
                              Цитата eao197 @
                              то с точки зрения ООП естественным образом напрашивается его наследование от чего-нибудь

                              Нет, не напрашивается.

                              Цитата eao197 @
                              Еще одна штука. После чтения результата из очереди lose нужно закрыть обе очереди table*.
                              Иначе один из файберов заснет навечно на извлечении очередного сообщения. И весь пример уснет на одном из вызовом join.

                              Возможно в этом нет необходимости. По крайней мере в Go (и в Racket) — нет, все горутины прибьются автоматически при завершении программы. В данном случае это устраивает, close я добавил скорее просто для «аккуратности».
                                Цитата korvin @
                                Цитата eao197 @ Вчера, 02:03
                                то с точки зрения ООП естественным образом напрашивается его наследование от чего-нибудь

                                Нет, не напрашивается.


                                Судя по количеству разного ООП (например, Simula, Smalltalk, C++, Object Pascal, Java, Ruby, Self, JavaScript) мнения так же могут быть совершенно разными. Я высказал свое.
                                В предыдущей версии SObjectizer-а, SO-4, в качестве типа сообщения мог быть любой класс/структура, наследование было не обязательно. По факту, никакой выгоды от этого не было, только лишние заботы для разработчиков SO-4. Поэтому в SO-5 мы пошли вот по такому пути. Никаких реальных проблем на практике с этим нет.

                                Но с точки зрения какой-то абстрактной теоритической чистоты, возможно, в наследовании от общей базы есть что-то нехорошее.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (14) 1 [2] 3 4 ...  13 14 все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0757 ]   [ 18 queries used ]   [ Generated: 29.03.24, 15:50 GMT ]