Теоретически, вместо бесконечного цикла, можно с помощью функции select и ее более мощных аналогов, ждать пока сокет listen_sd станет доступен для чтения, а лишь потом один раз вызвать accept. Но лично я не вижу в моем способе с циклом никаких особых недостатков.
Как-то тоже был интерес к написанию http-сервера в качестве тестового задания. А получился пост :) В нем как раз можно и более «мощные средства» найти. В них бывает польза… Правда приведенный материал без ssl.
Как-то в одной конторе был очередной обеденный треп с поругиванием очередного продукта. И было замечание одного коллеги, что есть ПО, которое ругают, а есть, которое не используют.
Нынче модный тренд — ругать С++… Но идеалов нет, и вполне может быть, что некоторые восхваляемые на данный момент языки скоро так же будут поругиваться. Не стоит смотреть однобоко и давать 1001 подтверждение того, что С++ уже так безнадежен.
BaseBuilder'у очень не повредил бы виртуальный деструктор, а UnifiedFactory не плохо было бы сделать NonCopyable, всеж в нем есть поля указателей, хоть и в мапе…
Красиво рассказываете… Хотелось бы узнать где такое бывает (хоть в личку намекните :) ). Но самое интересное, что бывает после такого приятного собеседования: кандидат получает работу, примерно отвечающаю тому, о чем говорили на собеседовании (не надо забывать, что собеседование — это двусторонний процесс равноправного общения, а не принцип «преподаватель и студент на экзамене») или как в анекдоте «не надо путать туризм с видом на жительство»?
Согласен. Была такая практика: писали некоторую логику «классически» и никак не выходил «каменный цветочек», переписали на конечных автоматах, тоже не легко получилось, но удалось завершить и как-то струтурировать поведение и снизить кол-во странных логических багов. Кода логики получилось меньше, чем при классике, но вот таблица переходов стала великовата и страшновата :)
Напоминает одно из прошлых решений, в котором был некоторый менеждер сообщений. В менеждер можно было складывать сообщения от разных компонент из разных потоков и подписываться на сообщения, которые обрабатывались в одном потоке.
Приведенный в начале стаьи пример с копрованием можно решить и без многопоточности — порты завершения ввода вывода. Да, с дополнительным потоком оно как бы проще, но UI и многопоточность очень много несут подводных камней — некоторые действия зависят от того в каком потоке вы что-то инициализировали, а в каком что-то пытаетесь рисовать.
Мое мнение — стремиться минимизировать количество потоков в программе, т.к. потоки дают весьма «простое» на первый взгляд архитектурное решение, но со временем накапливают множество потенциальных ошибок, которые произойдут в самый неподходящий момент.
Маски, порог бинаризации, сглаживающие фильтры — У. Прэтт «Цифровая обработка изображений», помню часто гонял эту книжку в студенчестве. Все, что Вы описали здорово, +1.
Меня более бы интерсова иные вопросы, если сможете дать ответ, буду очень рад.
1. Как выбрать оптимально порог бинаризации? (в работе, что я привел выше, он вроде советуется около 80% от суммарной яркости изображения)
2. После бинаризации остается шум в виде незначащих элементов. Как его свести к минимуму?
3. В полученных изображениях в контурах имеются разрывы зачастую. Какие бы вы посоветовали алгоритмы поиска связанных контуров? Пожалуй это самый меня интересующий вопрос :)
Идея зацепила, пока не знаю к чему бы применить, но, вспоминая труды Александреску :) пришло в голову некоторое обобщенное решение с применением списков типов.
В Списке типа можно указать все типы, с которыми мы хотим связываться, в том числе и с собой.
Данное решение писалось под MSVC++ 2005, доберусь до gcc и там проверю. Зачастую бывает писанное в студии с первого раза не компилится в gcc.
Данное решение не проверяет если пользователь в один список типов включил несколько одинаковых типов.
В общем если кому интерсно, то вот еще + 1 вариант к предложенному автором.
Все ж дело личное — хочешь используй, не хочешь не используй.
Несколько моих попыток побаловаться с др языками всегда приводили к ощущениям «и тут жмет» и «тут не хватает». Мб просто также банальная нехватка знаний этих прочих языков.
А вообще всему свои задачи.
Да, многие писали свои велики. Вот, что получилось у меня несколько лет назад. Этому даж нашлись единомышленники. У меня как всегда хватило только интереса на «скилет», т.е. на самое интересное — на событийную модель и на несколько стратегий создания окошек, а «коллеги по цеху», увлекающиеся более деталям реализации, написали альтернативные штуки.
Да, велосипедостроение оно повышает навык, но реже бывает востребовано. Востребовано, только его косвенное влияние — опыт!
Странно, но если забивать гвозди микроскопом особенно в оконную раму, то это как минимум не удобно, но извернуться всеж наверно можно и расколотив ни одно стекло поиметь не плохую сноровку в забивании гвоздей микроскопом в оконную раму, только кому такой опыт потом продать-то… Однако, есть молоток, к тому же они бывают разных весов…
Язык C++ имеет очень много возможностей и существует множество подходов в программировании. Инструмент выбирается по задаче, а строгие суждения «хорошо» и «плохо» в таком гибком языке, как C++ они, на мой взгляд, не совсем уместны.
Так же положительный пример автора с парой случайных чисел в его же ключе можно и сделать отрицательным: значения хоть и случайны, но могут быть из разных диапазонов, например 1..10 и 50...250 и где-то в логике это мб учитывается, а потом вспоминай и лазь по коду смотри, что и как обрабатывается :) Так что смотря с какой колокольни смотреть на проблему.
Как-то тоже был интерес к написанию http-сервера в качестве тестового задания. А получился пост :) В нем как раз можно и более «мощные средства» найти. В них бывает польза… Правда приведенный материал без ssl.
Мое мнение — стремиться минимизировать количество потоков в программе, т.к. потоки дают весьма «простое» на первый взгляд архитектурное решение, но со временем накапливают множество потенциальных ошибок, которые произойдут в самый неподходящий момент.
Меня более бы интерсова иные вопросы, если сможете дать ответ, буду очень рад.
1. Как выбрать оптимально порог бинаризации? (в работе, что я привел выше, он вроде советуется около 80% от суммарной яркости изображения)
2. После бинаризации остается шум в виде незначащих элементов. Как его свести к минимуму?
3. В полученных изображениях в контурах имеются разрывы зачастую. Какие бы вы посоветовали алгоритмы поиска связанных контуров? Пожалуй это самый меня интересующий вопрос :)
В Списке типа можно указать все типы, с которыми мы хотим связываться, в том числе и с собой.
Данное решение писалось под MSVC++ 2005, доберусь до gcc и там проверю. Зачастую бывает писанное в студии с первого раза не компилится в gcc.
Данное решение не проверяет если пользователь в один список типов включил несколько одинаковых типов.
В общем если кому интерсно, то вот еще + 1 вариант к предложенному автором.
#include <iostream> #include <vector> #include <algorithm> template <typename H, typename T> struct TypeList { typedef H Head; typedef T Tail; }; struct NullType { }; #define TYPE_LIST_1(t1) \ TypeList<t1, NullType> #define TYPE_LIST_2(t1, t2) \ TypeList<t1, TYPE_LIST_1(t2) > #define TYPE_LIST_3(t1, t2, t3) \ TypeList<t1, TYPE_LIST_2(t2, t3) > #define TYPE_LIST_4(t1, t2, t3, t4) \ TypeList<t1, TYPE_LIST_3(t2, t3, t4) > #define TYPE_LIST_5(t1, t2, t3, t4, t5) \ TypeList<t1, TYPE_LIST_4(t2, t3, t4, t5) > template <typename T> struct TypeWrap { }; template <typename TClass, typename TLinkedClasses> class LinkHolder : public LinkHolder<TClass, typename TLinkedClasses::Tail> { public: typedef typename TLinkedClasses::Head LinkType; virtual ~LinkHolder() { LinkPool Tmp = Links; for (LinkPool::const_iterator i = Tmp.begin() ; i != Tmp.end() ; ++i) (*i)->DelLink(static_cast<TClass *>(this)); } using LinkHolder<TClass, typename TLinkedClasses::Tail>::AddLink; using LinkHolder<TClass, typename TLinkedClasses::Tail>::DelLink; void AddLink(LinkType *link) { if (std::find(Links.begin(), Links.end(), link) != Links.end()) return; Links.push_back(link); link->AddLink(static_cast<TClass *>(this)); } void DelLink(LinkType *link) { LinkPool::iterator Iter = std::find(Links.begin(), Links.end(), link); if (Iter == Links.end()) return; LinkType *Link = *Iter; Links.erase(Iter); Link->DelLink(static_cast<TClass *>(this)); } template <typename T> unsigned GetLinkCount() const { return GetLinkCountImpl(TypeWrap<T>()); } template <typename T> T* GetLink(unsigned index) const { return GetLinkImpl(TypeWrap<T>(), index); } protected: using LinkHolder<TClass, typename TLinkedClasses::Tail>::GetLinkCountImpl; unsigned GetLinkCountImpl(const TypeWrap<LinkType> &) const { return static_cast<unsigned>(Links.size()); } using LinkHolder<TClass, typename TLinkedClasses::Tail>::GetLinkImpl; LinkType* GetLinkImpl(const TypeWrap<LinkType> &, unsigned index) const { return Links.size() > index ? Links[index] : 0; } private: typedef std::vector<LinkType *> LinkPool; LinkPool Links; }; template <typename TClass> class LinkHolder<TClass, NullType> { public: virtual ~LinkHolder() { } void AddLink() { } void DelLink() { } unsigned GetLinkCountImpl(const TypeWrap<NullType> &) const { return -1; } NullType* GetLinkImpl(const TypeWrap<NullType> &, unsigned) const { return 0; } }; class A; class B; class C; class A : public LinkHolder<A, TYPE_LIST_3(A, B, C)> { public: void A2B(); void Stop(); }; class B : public LinkHolder<B, TYPE_LIST_3(A, B, C)> { public: void B2C(); }; class C : public LinkHolder<C, TYPE_LIST_3(A, B, C)> { public: void C2A(); }; void A::A2B() { std::cout << __FUNCTION__ << std::endl; unsigned Count = GetLinkCount<B>(); for (unsigned i = 0 ; i < Count ; ++i) GetLink<B>(i)->B2C(); } void A::Stop() { std::cout << __FUNCTION__ << std::endl; } void B::B2C() { std::cout << __FUNCTION__ << std::endl; unsigned Count = GetLinkCount<C>(); for (unsigned i = 0 ; i < Count ; ++i) GetLink<C>(i)->C2A(); } void C::C2A() { std::cout << __FUNCTION__ << std::endl; unsigned Count = GetLinkCount<A>(); for (unsigned i = 0 ; i < Count ; ++i) GetLink<A>(i)->Stop(); } int main() { A a; std::auto_ptr<B> b(new B); C c; a.AddLink(&a); a.AddLink(b.get()); a.AddLink(&c); b->AddLink(&a); b->AddLink(b.get()); b->AddLink(&c); c.AddLink(&a); c.AddLink(b.get()); c.AddLink(&c); a.A2B(); b.reset(0); std::cout << std::endl; a.A2B(); }Несколько моих попыток побаловаться с др языками всегда приводили к ощущениям «и тут жмет» и «тут не хватает». Мб просто также банальная нехватка знаний этих прочих языков.
А вообще всему свои задачи.
Да, велосипедостроение оно повышает навык, но реже бывает востребовано. Востребовано, только его косвенное влияние — опыт!
Язык C++ имеет очень много возможностей и существует множество подходов в программировании. Инструмент выбирается по задаче, а строгие суждения «хорошо» и «плохо» в таком гибком языке, как C++ они, на мой взгляд, не совсем уместны.
Так же положительный пример автора с парой случайных чисел в его же ключе можно и сделать отрицательным: значения хоть и случайны, но могут быть из разных диапазонов, например 1..10 и 50...250 и где-то в логике это мб учитывается, а потом вспоминай и лазь по коду смотри, что и как обрабатывается :) Так что смотря с какой колокольни смотреть на проблему.