LINUX.ORG.RU

Обновился инструмент для работы с агентами в C++: SObjectizer 5.5.0

 , , ,


4

1

SObjectizer — это реализация модели акторов для C++, позволяющая программировать на C++ с использованием работающих на разных нитях агентов, общающихся между собой посредством сообщений. SObjectizer существенно упрощает разработку событийно-ориентированных приложений, для параллельной и независимой обработки событий в которых требуется многопоточность и/или распределенность. SObjectizer использовался для создания как для мелких утилит, так и серьезных распределенных приложений, работающих под большой нагрузкой в режиме 24x7.

Последние несколько лет SObjectizer развивается на SourceForge как OpenSource проект под BSD-лицензией. Подробнее об истории, текущем состоянии и направлении движения SObjectizer можно прочитать здесь.

Версия 5.5.0 является результатом очередного, очень значимого этапа развития проекта.

Главное отличие v.5.5.0 от предыдущих версий — это отсутствие зависимости от ACE Framework. Т.е. теперь ACE в коде ядра SObjectizer не используется вообще, для SObjectizer достаточно наличия стандартной библиотеки C++11. Это означает, что SObjectizer уменьшился в размере, нужно меньше времени на сборку SObjectizer-проектов, упрощается поддержка различных компиляторов и платформ. В частности, эта версия SObjectizer тестировалась посредством MSVS2013 (Windows), GCC 4.8/4.9 (Windows, Linux), Clang 3.5.0 (Linux).

Из более мелких изменений можно отметить прямую поддержку std::chrono при работе с отложенными/периодическими сообщениями, а так же небольшое изменение названий некоторых классов/функций (с сохранением старых имен для обеспечения совместимости). Более подробная информация о нововведениях в v.5.5.0 доступна в соответствующем разделе Wiki проекта. Так же увеличилось количество страниц с описаниями базовых вещей SObjectizer.

Версия 5.5.0 может быть загружена из раздела Files или получена из Subversion-репозитория.

Примечание. Этот релиз содержит только ядро SObjectizer (т.е. проект so_5). Никакие другие подпроекты (вроде so_log или so_sysconf) в релиз не включены. Возможно, сборка SObjectizer Assembly со всеми подпроектами будет сформирована и опубликована позже (если она действительно кому-то потребуется).

PS. Анонс делается просто для того, чтобы уведомить, что такой проект есть, живет, развивается. Доступен под BSD-лицензий, т.е. даром, в том числе и для коммерческих проектов. Это не просьба сделать code review. И не попытка кому-то что-то «продать».

PPS. Специально для желающих постебаться над синтаксисом и посравнивать программирование на C++ с Perl-ом. Вот классический пример Hello, World. В традиционном, ООП-шном варианте, с созданием класса агента и переопределением виртуальных методов (хотя есть и более модерновый вариант, с использованием С++ных лямбда-функций):

#include <iostream>

// Main SObjectizer header files.
#include <so_5/all.hpp>

// Definition of an agent for SObjectizer.
class a_hello_t : public so_5::rt::agent_t
{
	public:
		a_hello_t( so_5::rt::environment_t & env )
			: so_5::rt::agent_t( env )
		{}

		// A reaction to start of work in SObjectizer.
		virtual void
		so_evt_start() override
		{
			std::cout << "Hello, world! This is SObjectizer v.5."
				<< std::endl;

			// Shutting down SObjectizer.
			so_environment().stop();
		}

		// A reaction to finish of work in SObjectizer.
		virtual void
		so_evt_finish() override
		{
			std::cout << "Bye! This was SObjectizer v.5."
				<< std::endl;
		}
};

int
main( int, char ** )
{
	try
	{
		// Starting SObjectizer.
		so_5::launch(
			// A function for SO Environment initialization.
			[]( so_5::rt::environment_t & env )
			{
				// Creating and registering single agent as a cooperation.
				env.register_agent_as_coop( "coop", new a_hello_t( env ) );
			} );
	}
	catch( const std::exception & ex )
	{
		std::cerr << "Error: " << ex.what() << std::endl;
		return 1;
	}

	return 0;
}

PPPS. Специально для желающих узнать, чем SObjectizer лучше libcppa/CAF. В двух словах — это две совершенно разные разработки, ставящие перед собой разные цели и достигающие их разными способами. Подробнее здесь и здесь.

★★★★
Ответ на: комментарий от eao197

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

хорошо что нашёл в себе силы в этом признаться

anonymous ()
Ответ на: комментарий от anonymous

седьмая пачка попкорна...

Ну и как вам шоу? ;)

А вообще, это большое от зрителей зависит. Будут наброс вопросы, можно будет еще на пару пачек удовольствие продлить. Полагаю, тимлидусы анонимусы не упустят возможности блеснуть банальной эрудицией :)))

Да и у нас будет больше информации о том, что и где нужно доработать напильником.

eao197 ★★★★ ()
Ответ на: комментарий от eao197

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

как минимум до этих пор — ненужно.

anonymous ()
Ответ на: комментарий от eao197

так себе шоу...

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

Да и у нас будет больше информации о том, что и где нужно доработать напильником.

это если будут замечания типа «в этом инструменте вот это ... лучше реализовать вот так ... потому что ...»

а бредни типа «сам инструмент говно, потому что я дартаньян» нужно игнорить, тем более когда они исходят от анонима

anonymous ()
Ответ на: комментарий от anonymous

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

Никто не будет решать за вас ваши личные проблемы. Тем более в опенсорсе.

eao197 ★★★★ ()
Ответ на: комментарий от anonymous

это если будут замечания типа «в этом инструменте вот это ... лучше реализовать вот так ... потому что ...»

Это было бы здорово. Но, видимо, мы пока еще не научились преподносить анонсы релизов так, чтобы заинтересовать публику. Чему тоже нужно учиться.

Но даже такие обсуждения позволяют отвлечься от постоянной работы и посмотреть на результаты со стороны. Это дает свои результаты. Например, по следам этого треда в бранче 5.5.1 уже можно писать:

  st_free.handle( [this]( const msg_take & evt )
      {
        st_taken.activate();
        so_5::send< msg_taken >( evt.m_who );
      } );
вместо
  so_subscribe( so_direct_mbox() ).in( st_free )
    .event( [this]( const msg_take & evt )
      {
        so_change_state( st_taken );
        evt.m_who->deliver_signal< msg_taken >();
      } );
В общем-то пустяк, но буковок становится меньше. Хотя из-за старых привычек старый код у меня лично нареканий не вызывал. Ну так, значит так.

eao197 ★★★★ ()
Ответ на: комментарий от eao197

тут он имел ввиду что у него уже реализовано априори круче

anonymous ()
Ответ на: комментарий от eao197

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

anonymous ()
Ответ на: комментарий от eao197

мы пока еще не научились преподносить анонсы релизов

анонсы не виноваты в том, что анонсировать нечего

anonymous ()
Ответ на: комментарий от anonymous

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

Ну и? Вы предлагаете еще и мне этим заняться?

Для чего, собственно? Чтобы при анонсе очередной версии SO мы могли написать: «в этой версии представлено два алгоритма решения задачи обедающих философов — алгоритм Дейкстры (см.пространство имен dining_philosophers::dijkstra) и МаниЧанди/Мисра (см.пространство имен dining_philosophers::manichandy_misra)»...

Это что, будет кому-то интересно за пределами академического мира?

eao197 ★★★★ ()
Ответ на: комментарий от anonymous

тут он имел ввиду что у него уже реализовано априори круче

Сомневаюсь. Ему просто в очередной раз нужно сказать, какой он умный.

eao197 ★★★★ ()
Ответ на: комментарий от eao197

Это что, будет кому-то интересно за пределами академического мира?

это интересно всем, кто решает нетривиальные параллельные задачи.

можно, конечно, не напрягая спинной мозг запилить giant_lock (см своё решение задачи о философах) и продолжать кукарекать какое конкурентное у тебя concurrency.

anonymous ()
Ответ на: комментарий от anonymous

это интересно всем, кто решает нетривиальные параллельные задачи.

Во-первых, вы каким боком к этой предметной области?

Во-вторых, в мире кому-то нужно решать и тривиальные параллельные задачи. Желательно удобными инструментами.

можно, конечно, не напрягая спинной мозг запилить giant_lock (см своё решение задачи о философах) и продолжать кукарекать какое конкурентное у тебя concurrency.

Это конечно, мог бы быть знатный наброс. Если бы не тот факт, что в вашем собственном решении этот самый giant_lock так же присутствует. О чем вам уже давно еще один аноним сказал.

eao197 ★★★★ ()
Ответ на: комментарий от eao197

вашем собственном решении этот самый giant_lock

обоснуй

anonymous ()
Ответ на: комментарий от anonymous

вашем собственном решении этот самый giant_lock

обоснуй

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

Отсутствие дедлоков в вашем решении (хотя вроде бы это решение самого Дейкстры) определяется тем, что один философ всегда будет находится за пределами стола. Это приводит к тому, что один из философов имеет возможность захватить две ложки — одна всегда свободна для захвата. А когда этот философ заканчивает есть, то его соседи получают шанс захватить освободившиеся ложки.

Однако, такое решение требует централизованного хранения информации о том, сколько философов сидят за столом. Как эта информация будет храниться — уже не суть. Будь то родной Unix-овый семафор, или ваша его реализация на mutex+condition+counter — не важно. Важно, что любой философ, который переходит из состояния Thinking в Hungry, должен попробовать модифицировать эту информацию и получить разрешение сесть за стол. И любой философ, который хочет встать из-за стола, должен так же модифицировать эту информацию.

Т.о. образуется единственная точка сериализации двух типов запросов для философов: разрешение сесть за стол и уведомление о выходе из-за стола. Тот самый giant_lock.

В моем решении такой giant_lock так же есть в виде арбитра/официанта. Но под этим lock-ом выполняется только обновление информации о занятости вилок и об очередях к ним. В моем коде нет захвата ресурсов. Фактически, там происходит только раздача тикетов агентам-философам. Получив тикет философ понимает, что ресурсы свободны, никто больше к ним не сунется и может инициировать операции с ними на своем контексте. Как раз к вопросу о тяжести вилок, философ может поднимать их уже после того, как арбитр/официант дал ему разрешение. Поэтому, кстати же, термин арбитр более подходит, чем официант — арбитр только раздает разрешения, тогда как официант раздает вилки.

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

eao197 ★★★★ ()
Ответ на: комментарий от eao197

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

anonymous ()
Ответ на: комментарий от anonymous

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

После этого ваши потуги на «всех, кто решает нетривиальные параллельные задачи» ничего кроме иронии вызывать не могут.

eao197 ★★★★ ()
Ответ на: комментарий от anonymous

значит, непонятно. что именно?

Да с вами уже всем все понятно.

Остается только повторить: очень и очень разумно с вашей стороны сохранять анонимность.

eao197 ★★★★ ()
Ответ на: комментарий от eao197

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

anonymous ()
Ответ на: комментарий от anonymous

так себе шоу...

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

Ну вот к вопросу у тоннах кода. Тут уже упоминался пример Hello, World из фреймворка Theron. Вот как он выглядит:

#include <Theron/Theron.h> 

// Actor type that prints strings.
// Derives from Theron::Actor.
class Printer : public Theron::Actor
{
public:

    // Constructor, passes the framework to the baseclass.
    Printer(Theron::Framework &framework) : Theron::Actor(framework)
    {
        // Register the message handler.
        RegisterHandler(this, &Printer::Print);
    }

private:

    // Handler for messages of type std::string.
    void Print(const std::string &message, const Theron::Address from)
    {
        // Print the string.
        printf("%s\n", message.c_str());

        // Send a dummy message back for synchronization.
        Send(0, from);
    }
}; 

int main()
{
    // Construct a framework and instantiate a Printer within it.
    Theron::Framework framework;
    Printer printer(framework);

    // Construct a receiver to receive the reply message.
    Theron::Receiver receiver;

    // Send a string message to the Printer.
    // We pass the address of the receiver as the 'from' address.
    if (!framework.Send(
        std::string("Hello world!"),
        receiver.GetAddress(),
        printer.GetAddress()))
    {
        printf("ERROR: Failed to send message\n");
    }

    // Synchronize with the dummy message sent in reply to make sure we're done.
    receiver.Wait();
} 

Его можно написать на SObjectizer так, как показано ниже. Главное различие в примерах в том, что в Theron-е для того, чтобы дождаться факта завершения обработки сообщения агент Printer отвечает сообщением на адрес отправителя. В SObjectizer адресов отправителей с сообщениями не сопоставлено. Да в данном случае это и не нужно, т.к. за счет механизма синхронных запросов можно отослать асинхронное сообщение агенту, который обработает его где-то на своем контексте, когда ему будет удобно. А вот отправитель все это время будет ждать завершения обработки своего запроса. Именно этот фокус используется в коде ниже:

#include <iostream>

#include <so_5/all.hpp>

// В SObjectizer нельзя просто послать std::string.
// Сообщения с данными внутри должны быть наследниками message_t.
struct message : public so_5::rt::message_t
{
	std::string msg;

	message( std::string m ) :	msg( std::move(m) ) {}
};

// Агент, который будет печатать посланные ему строчки текста.
class printer : public so_5::rt::agent_t
{
public :
	// Конструктор должен получить среду, в которой работает агент
	// и эта среда должна быть передана в базовый класс.
	printer( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env )
	{
		// Оформляем подписку на сообщения message, которые
		// идут на собственный mbox этого агента.
		so_subscribe_self().event( &printer::print );
	}

private :
	// Обработка сообщения.
	void print( const message & evt )
	{
		// Просто печатаем сообщение.
		std::cout << evt.msg << std::endl;

		// Ничего назад отсылать не нужно, т.к. в примере
		// будут использоваться другие средства для определения
		// момента обработки сообщения.
	}
};

int main()
{
	try
	{
		// Создание среды и все нужные для ее запуска действия
		// производятся внутри so_5::launch. Все ошибки выбрасываются
		// как исключения, поэтому никаких кодов возврата обрабатывать
		// не нужно.
		so_5::launch( []( so_5::rt::environment_t & env ) {
			// Агента нужно создать и зарегистрировать внутри среды.
			auto agent = new printer( env );
			env.register_agent_as_coop( "hello", agent );

			// Делаем отсылку сообщения агенту с ожиданием окончания
			// его обработки. Сообщение будет отослано и обработано
			// асинхронно. Агент не будет знать, что его кто-то
			// ждет. Но текущая нить будет приостановлена.
			// Метод run_one указывает, что нужно просто дождаться
			// окончания обработчика сообщения, никаких результатов
			// забирать не нужно.
			// Метод wait_forever указывает, что ждать нужно пока
			// агент не обработает сообщение.
			agent->so_direct_mbox()->run_one().wait_forever()
				// Вот здесь объект-сообщение конструируется
				// и отсылается агенту-приемнику.
				.make_sync_get< message >( "Hello, World" );

			// Все, логика примера завершена. Среду можно останавливать.
			env.stop();
		} );
		return 0;
	}
	catch( const std::exception & x )
	{
		std::cerr << "Error: " << x.what() << std::endl;
	}
	return 2;
}
eao197 ★★★★ ()
Ответ на: комментарий от eao197

Кстати, а зачем эти требования наследования от некоторых базывых типов? Для агентов это ещё куда ни шло, а вот для сообщений...

// другой анонимус, если что

anonymous ()
Ответ на: комментарий от anonymous

Кстати, а зачем эти требования наследования от некоторых базывых типов? Для агентов это ещё куда ни шло, а вот для сообщений...

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

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

В SO4 было решено, что сообщением может быть любая структура/класс, общий наследник не нужен. Соответственно, счетчик ссылок пришлось хранить вне экземпляра сообщения. Поэтому в SO4 отсылка сообщения означала создание двух динамических объектов — самого сообщения и специального враппера, внутри которого был и счетчик ссылок. Соответственно, лишняя аллокация/деаллокация памяти в многопоточной программе — это не есть хорошо. Хотя для SO4 это было не критично, т.к. там были другие источники тормозов, например, текстовые имена агентов/сообщений/событий, плюс общий системный словарь.

На практике же пользы от отсутствия общего базового класса для сообщений так и не было. Отсылались всегда экземпляры классов, который были именно сообщениями. Никто не отсылал какие-нибудь POINT-ы из Win32 или QWidget-ы.

Поэтому в SO5 для увеличения производительности было решено хранить счетчик ссылок внутри экземпляра сообщения. А самый простой и надежный способ заставить пользователя помещать этот счетчик ссылок в свое сообщение — это наследование от общей базы.

Наверное, если бы мы начали делать SO5 сейчас, а не четыре года назад, мы бы задействовали move semantic и variadic templates. Это бы позволило дешево и прозрачно оборачивать пользовательские объекты в свой класс, унаследованный от message_t. Но тогда уровень поддержки C++11 был совсем другим. Поэтому шли так, чтобы минимально зависеть от степени продвинутости основных компиляторов под Win и Unix.

Ну и, имхо, у такого подхода есть свои преимущества.

Во-первых, нам, как разработчикам SO5, проще делать быструю доставку сообщений до получателя. В качестве ключа подписки используется typeid для типа сообщения. По этому ключу в словаре подписок агента сразу определяется, нужно ему это сообщение в его текущем состоянии или нет. Фактически, это одна проверка по hash-map-у. А вот если бы пользователь мог подписаться на произвольный тип, вроде std::string, то возник бы вопрос: как различать несколько методов-событий, получающих std::string? Нужно было бы как-то привязываться к значению. Т.е. при доставке сообщения мало проверить, что агенту нужны std::string-и, нужно затем еще пройтись и по списку разрешенных значений (для этого в libcaf как раз и сделали свой eDSL для паттерн-матчинга в C++ и добавили суррогатную поддержку Erlang-овских атомов).

Во-вторых, при разработке больших приложений структуры сообщений со временем меняются. Т.е. раньше было сообщение reconnect, в котором было два атрибута. Прошло время, пришлось поменять типы этих атрибутов и добавить новые. Когда сообщение — это структура, то меняется ее определение, но сигнатуры методов остаются неизменными. Т.е. как были:

void evt_reconnect_when_connected(const reconnect &);
void evt_reconnect_when_disconnected(const reconnect &);
void evt_reconnect_when_not_configured(const reconnect &);
так они и останутся. А вот если бы у всех этих методов был список параметров, то при изменении этого списка пришлось бы менять кучу сигнатур. Причем с получателями-то еще просто. Но ведь еще нужно менять и код отправки сообщений.

В общем, когда показываешь маленькие примеры, то там наследование от message_t/signal_t выглядит чрезмерно. Но чем больше становится проект, чем дольше над ним работают, тем больше выигрыш от такого наследования.

eao197 ★★★★ ()
Ответ на: комментарий от eao197

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

Кстати, можно на примерах показать. В CAF/libcppa есть пример dining_philosophers. Вот простой агент оттуда:

void chopstick(event_based_actor* self) {
  self->become(
    on(atom("take"), arg_match) >> [=](const actor& philos) {
      // tell philosopher it took this chopstick
      self->send(philos, atom("taken"), self);
      // await 'put' message and reject other 'take' messages
      self->become(
        // allows us to return to the previous behavior
        keep_behavior,
        on(atom("take"), arg_match) >> [=](const actor& other) {
          self->send(other, atom("busy"), self);
        },
        on(atom("put"), philos) >> [=] {
          // return to previous behaivor, i.e., await next 'take'
          self->unbecome();
        }
      );
    }
  );
}
Компилятор не может помочь проконтролировать, что ему будут отсылать сообщения «take» и «put». Вдруг кто-то по ошибке напишет «Take» и «Put»?

Опять же, этот агент отсылает сообщение taken с одним параметром. Компилятор не помогает проверить, а действительно ли у этого сообщения имя taken, а не Taken. И действительно ли в этом сообщении один параметр или два? Или не одного?

Если сообщения оформлены в виде структур, то компилятор проверяет и корректность имен, и корректность вызова конструктора и т.д. Поэтому данный пример в SO будет выглядеть вот так:

class a_fork_t : public agent_t
{
public :
  a_fork_t( environment_t & env ) : agent_t( env ) {}

  virtual void so_define_agent() override
  {
    st_free.activate();

    st_free.handle( [this]( const msg_take & evt )
        {
          st_taken.activate();
          send< msg_taken >( evt.m_who, so_direct_mbox() );
        } );

    st_taken.handle( []( const msg_take & evt )
        {
          send< msg_busy >( evt.m_who );
        } )
      .handle< msg_put >( [this]() { st_free.activate(); } );
  }

private :
  const state_t st_free = so_make_state( "free" );
  const state_t st_taken = so_make_state( "taken" );
};

По объему кода агента получается приблизительно одно и то же. Но вот дополнительных определений для структур сообщений нужно больше:
struct msg_take : public message_t
{
  const mbox_ref_t m_who;

  msg_take( mbox_ref_t who ) : m_who( std::move( who ) ) {}
};

struct msg_busy : public signal_t {};

struct msg_taken : public message_t
{
  const mbox_ref_t m_who;

  msg_taken( mbox_ref_t who ) : m_who( std::move( who ) ) {}
};

struct msg_put : public signal_t {};
Но зато весь код агента контролируется компилятором. И если кто-то решит удалить сообщение msg_taken или изменит его имя, или формат конструктора, то компилятор сразу даст по рукам.

Поэтому не так важно, будут ли типы сообщений производны от общей базы или нет. Важно, чтобы это были структуры, а не наборы захардкоженных значений. Ну а то, что в SO5 требуется наследование от message_t, то это вот такая деталь реализации.

eao197 ★★★★ ()
Ответ на: комментарий от eao197

Тот самый starvation о котором я, по вашему предположению, ничего не знаю :)

конечно не знаешь. это даже не обсуждается.

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

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

anonymous ()
Ответ на: комментарий от anonymous

конечно не знаешь. это даже не обсуждается.

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

eao197 ★★★★ ()
Ответ на: комментарий от eao197

Но ваш уровень уже всем здесь понятен.

пока в этом топике неоднократно (раза 3-4) обосрался ты (куда ни копнёшь чуть глубже базвордов — на те здрасьте). причём, на элементарных вопросах, известных любому студенту.

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

anonymous ()
Ответ на: комментарий от anonymous

при этом, ты так и не осилил правильное решение.

Молодой человек, вы серьезно верите в том, что в разработке софта есть такое понятие, как «правильное решение»?

eao197 ★★★★ ()
Ответ на: комментарий от eao197

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

давай поиграем на твоём поле, ок. а своё ненужно — закопай.

anonymous ()
Ответ на: комментарий от anonymous

т.е. в очередной раз съезжаешь с темы?

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

хочешь рассказать что мне менеджер разрешит?

Причем здесь менеджер? Разработка софта — это же не сдача экзамена преподавателю — смог повторить доказательство теоремы или не смог. Это поиск компромиссов. На каждом уровне есть свои условия которые нужно соблюсти и свои ограничения, в которые нужно вписаться. В том числе и на техническом уровне. Удивительно, что человек, декларирующий себя как тимлид, этого не понимает.

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

Это кто говорит? Какое-то анонимное ЧМО, у которого не хватает смелости ответить за свои слова хотя бы заведением ника, вокруг которого хоть какая-то репутация будет накапливаться? Сударь — вы никто, звать вас никак, ничего вы не знаете, не умеете, и доказать обратного не в состоянии.

eao197 ★★★★ ()
Ответ на: комментарий от eao197

По теме здесь уже все было сказано.

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

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

из этих нерадивых студентов и вырастают такие бездарности. недостаток системы образования, да.

условия которые нужно соблюсти и свои ограничения

т.е. наговнокодить в лоб чего-нибудь. почему бы и нет?

человек, декларирующий себя как тимлид

этот человек принимает важные технические решения... и... внезапно... может их обосновать

Это кто говорит?

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

anonymous ()
Ответ на: комментарий от anonymous

Вообще вы оба производите плохое впечатление.

anonymous ()
Ответ на: комментарий от anonymous

ты хочешь повернуть дискуссию в конструктивное русло?

anonymous ()
Ответ на: комментарий от anonymous

С каждым собеседником я общаюсь так, как он того заслуживает.

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

eao197 ★★★★ ()
Ответ на: комментарий от eao197

общаюсь так, как он того заслуживает.

выражай свои мысли яснее: постольку, поскольку он признаёт мою «гениальность»

anonymous ()
Ответ на: комментарий от eao197

Если некоторые фрагменты обсуждения из-за этого читать неприятно

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

anonymous ()
Ответ на: комментарий от anonymous

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

Возможно, в этот раз лучше пусть автор библиотеки придумает задачу и покажет красивое решение с использованием библиотеки, а вы покажите, что «ненужно», желательно кодом=)

anonymous ()
Ответ на: комментарий от anonymous

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

anonymous ()
Ответ на: комментарий от anonymous

с этой явно не задалось

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

anonymous ()
Ответ на: комментарий от anonymous

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

Дело не в задаче. Чтобы это показать, достаточно вспомнить, кто в первый раз употребил слово «говно» в этой теме. И кто употребил его в последний раз. Собственно, в этом причина неконструктивности.

eao197 ★★★★ ()
Ответ на: комментарий от eao197

Прям как в детском саде... «Да он первый начал».

Тут мы имеем явный тупик в дискуссии и не в ваших интересах это дело продолжать.

Лучше подумайте над задачей с красивым решением, где ваша библиотека покажет себя хорошо. И пусть анонимус покажет «ненужность». Это будет уже игра на вашем поле, но тем не менее... Потом можно будет и на поле анонимуса сыграть попробовать.

anonymous ()
Ответ на: комментарий от anonymous

Прям как в детском саде... «Да он первый начал».

Вопрос не в том, кто первый начал, а какие цели преследует каждый из собеседников. Произносимые слова лишь иллюстрируют эти цели.

Придумывать демо-задачи для обсуждения на форуме — это, может быть, для чего-то нужно, но смысла в этом я не вижу. Есть другие вещи, которыми следует заниматься.

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

eao197 ★★★★ ()
Ответ на: комментарий от anonymous

Потом можно будет и на поле анонимуса сыграть попробовать.

уже попробовали. думаю, достаточно.

anonymous ()
Ответ на: комментарий от eao197

какие-то вопросы по библиотеке

один из самых существенных вопросов, заданный (и не только мной) ещё на первой странице: зачем она нужна?

anonymous ()
Ответ на: комментарий от anonymous

один из самых существенных вопросов, заданный (и не только мной) ещё на первой странице: зачем она нужна?

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

Пример чего был здесь продемонстрирован на вами же указанной задаче, когда один и тот же код продолжал успешно работать при смене условий. А именно — при переводе агентов-философов с отдельной рабочей нити для каждого на общий пул рабочих потоков. При существенном, на порядки, увеличении количества этих агентов. Тогда как ваше решение к таким объемам параллельно работающих агентов не может приблизится в принципе.

Другого ответа на вопрос «зачем» не будет вне зависимости от того, удовлетворяет он спрашивающего или нет.

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

eao197 ★★★★ ()
Ответ на: комментарий от eao197

Облегчает, а для некоторых, существенно облегчает

ложь.

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

ты реализовал быстрое переключение контекстов (которое в железе реализовано слишком медленно). трудозатраты по этой задаче я уже оценил: несколько часов/дней (в зависимости от требуемой функциональности). это сравнимо со временем изучения твоей библиотеки (а нормальные люди пробуют несколько перед принятием решения).

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

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

anonymous ()
Ответ на: комментарий от anonymous

ложь.

Конечно, вам виднее. Никому верить нельзя, вам можно (с)

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

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

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

Кто хочет делать свой — пусть делает, здесь никто не заставляет использовать SObjectizer, CAF или Theron.

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

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

eao197 ★★★★ ()
Ответ на: комментарий от eao197

банальная вещь

банальность библиотеки заключается в том, что только переключение контекстов в ней толком реализовано.

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

событийно-ориентированная. нужна развитая система событий (см libevent или winapi).

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

anonymous ()
Ответ на: комментарий от anonymous

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

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

eao197 ★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.