Pull to refresh
105
0

Пользователь

Send message
Теоретически, вместо бесконечного цикла, можно с помощью функции select и ее более мощных аналогов, ждать пока сокет listen_sd станет доступен для чтения, а лишь потом один раз вызвать accept. Но лично я не вижу в моем способе с циклом никаких особых недостатков.


Как-то тоже был интерес к написанию http-сервера в качестве тестового задания. А получился пост :) В нем как раз можно и более «мощные средства» найти. В них бывает польза… Правда приведенный материал без ssl.
Супер! Очень точное и хорошее описание.
Как-то в одной конторе был очередной обеденный треп с поругиванием очередного продукта. И было замечание одного коллеги, что есть ПО, которое ругают, а есть, которое не используют.
Нынче модный тренд — ругать С++… Но идеалов нет, и вполне может быть, что некоторые восхваляемые на данный момент языки скоро так же будут поругиваться. Не стоит смотреть однобоко и давать 1001 подтверждение того, что С++ уже так безнадежен.
Читали «Менеджер мафии»? Если нет, советую. Найдете много полезного.
BaseBuilder'у очень не повредил бы виртуальный деструктор, а UnifiedFactory не плохо было бы сделать NonCopyable, всеж в нем есть поля указателей, хоть и в мапе…
Челябинские мужики настолько суровы, что даже настройки хранят в реестре :)
Красиво рассказываете… Хотелось бы узнать где такое бывает (хоть в личку намекните :) ). Но самое интересное, что бывает после такого приятного собеседования: кандидат получает работу, примерно отвечающаю тому, о чем говорили на собеседовании (не надо забывать, что собеседование — это двусторонний процесс равноправного общения, а не принцип «преподаватель и студент на экзамене») или как в анекдоте «не надо путать туризм с видом на жительство»?
dynamic ввели в C#, а void* в C++ существует с далекого прошлого. По степени поганства примерно одно и тоже — долгий хэппидебаг
Согласен. Была такая практика: писали некоторую логику «классически» и никак не выходил «каменный цветочек», переписали на конечных автоматах, тоже не легко получилось, но удалось завершить и как-то струтурировать поведение и снизить кол-во странных логических багов. Кода логики получилось меньше, чем при классике, но вот таблица переходов стала великовата и страшновата :)
Напоминает одно из прошлых решений, в котором был некоторый менеждер сообщений. В менеждер можно было складывать сообщения от разных компонент из разных потоков и подписываться на сообщения, которые обрабатывались в одном потоке.
Приведенный в начале стаьи пример с копрованием можно решить и без многопоточности — порты завершения ввода вывода. Да, с дополнительным потоком оно как бы проще, но UI и многопоточность очень много несут подводных камней — некоторые действия зависят от того в каком потоке вы что-то инициализировали, а в каком что-то пытаетесь рисовать.
Мое мнение — стремиться минимизировать количество потоков в программе, т.к. потоки дают весьма «простое» на первый взгляд архитектурное решение, но со временем накапливают множество потенциальных ошибок, которые произойдут в самый неподходящий момент.
Маски, порог бинаризации, сглаживающие фильтры — У. Прэтт «Цифровая обработка изображений», помню часто гонял эту книжку в студенчестве. Все, что Вы описали здорово, +1.
Меня более бы интерсова иные вопросы, если сможете дать ответ, буду очень рад.
1. Как выбрать оптимально порог бинаризации? (в работе, что я привел выше, он вроде советуется около 80% от суммарной яркости изображения)
2. После бинаризации остается шум в виде незначащих элементов. Как его свести к минимуму?
3. В полученных изображениях в контурах имеются разрывы зачастую. Какие бы вы посоветовали алгоритмы поиска связанных контуров? Пожалуй это самый меня интересующий вопрос :)
Попробуй
<source lang="cpp"></source>
typename то я зачастую и забываю… gcc быстро напоминает об этом :)
Идея зацепила, пока не знаю к чему бы применить, но, вспоминая труды Александреску :) пришло в голову некоторое обобщенное решение с применением списков типов.
В Списке типа можно указать все типы, с которыми мы хотим связываться, в том числе и с собой.
Данное решение писалось под 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 и где-то в логике это мб учитывается, а потом вспоминай и лазь по коду смотри, что и как обрабатывается :) Так что смотря с какой колокольни смотреть на проблему.

Information

Rating
Does not participate
Registered
Activity