Pull to refresh
153
0
Павел Остапенко @mt_

User

Send message
Простите, а что негативного в символе победы добра над злом? Отличный исторический герб. Этот образ почитают почти двадцать веков по всему миру.
В статье вроде мало оценочных суждений, зато много статистики. Чем вам статистика не угодила?
Странно, у меня в 21.0.1180.83 оба Брюса — синие.
Имеется в виду, что под фразой «процесс установки собственного сервера прост» вывешена картинка, которую поймут не более 0,1% пользователей Сети. В текущих условиях у данного проекта непозволительно высокая входная планка. Что автоматически делает проект не «распределённой социальной сетью», а «тестовым прототипом социальной сети будущего для профессиональных айтишников».
Интересно бы посмотреть расчёты, за сколько эта турбина «отобьёт» ресурсы и энергию, потраченные на её создание, установку, подключение и обслуживание. Я могу ошибаться, но мне представляется, что хотя бы на «ноль» она выйдет не меньше чем лет через 15-20, если вообще выйдет.

Далее. Турбина даёт 6 МВт мощности. Но реальная мощность будет постоянно «гулять». Каким образом энергосеть будет в реальном режиме времени, 24 часа в сутки, компенсировать постоянные перекосы в мощности разных ветвей системы? И что будет, когда таких турбин в энергосистеме будет хотя бы 25%-35%? Насколько повысится стоимость такой энергосистемы хотя бы в масштабах города?
Хорошо, предположим оптимизировали. А как быть с бинарными файлами, которые вполне могут содержать эти сочетания байт? Вероятность появления сочетания двух определённых байтов — 1/2^8^2, то есть в среднем одно такое сочетание на файл размером 64Ки.
Отлично подходит для ситуаций, когда пару десятков пользователей в параллели будут загружать большие картинки. )
Короткий и простой ответ таков: методика, сама по себе, гарантирует уничтожение всех объектов, но она не гарантирует необходимое время жизни объекта.
Если же эту методику объединить с упомянутой в статье идеей строгой инкапсуляции, то в большинстве случаев и эта проблема будет решена. Строгая инкапсуляция говорит о том, что объект передаёт указатели на свои члены в ходе исполнения своих функций-членов. То есть, вне жизни объекта, доступа к указателям на его члены просто не будет, ещё на этапе компиляции.
Возможно, мой дзен проектирования не так крут, поэтому в сложных динамических случаях я пару раз сталкивался с необходимостью передавать указатель на объект, не имея возможности гарантировать его существования в момент, когда (отложенный) обрабатывающий код будет выполнен. В этих случаях я пользовался штатным классом фреймворка, который по сути представляет собой вариант умного указателя, который обнуляет внутренний указатель при вызове деструктора объекта. Вполне допускаю, что возможно более правильно спроектировать систему, чтобы умные указатели не были нужны даже в этом случае.
Это всё конспирология.
Сейчас, даже если изобретёшь машину времени, нужно будет привлечь инвесторов и вложить солидные бюджеты на рекламу и выход на рынок.
Тогда вы не совсем чётко описали задачу.
Что конкретно нужно? Чтобы было совсем просто, без обратной связи? Уберите всю лишнее, а промежуточные данные дайте менеджеру в массив (можно ассоциативный). Это будет 7 строчек.
Чем это будет сложнее вашего кода?
Тогда покажите, упрощённо, что есть у вас, чтобы можно было сравнить.
Что «это»?
забыл конструктор GUI написать с аргументом GUIReporter * — но думаю, Вы и сами поняли.
Может я что-то не так понял — тогда поправьте. Пока всё получается довольно тривиально. Единственное, работу менеджера вынес в отдельный поток, т.к. любые расчёты в GUI — плохая практика.

class IntermediateSource
{
public:
	virtual const IntermediateData &GetSource(const String &) = 0;
};

class GUIReporter
{
public:
	virtual GUIData GetState() = 0;
};

class Renderer
{
public:
	Renderer(IntermediateSource *_source) :source(_source), shutdown(false)
	{
		//thread -> Renderer::Work()
	}
	void Shutdown() {shutdown = true;}
public: 
	//thread: renderer
	void Work()
	{
		const IntermediateData &data = source->GetSource(/*...*/);
		while (!shutdown)
		{
			//...
		}
	}
private:
	IntermediateSource *source;
	volatile bool       shutdown;
};

class RenderManager : public IntermediateSource, public GUIReporter
{
public:
	RenderManager()
	{
		//thread -> RenderManager::Run()
	}
	~RenderManager()
	{
		Shutdown();
		for (int i=0; i<renderers.GetCount(); ++i)
			renderers[i].Wait();
		managerThread.Wait();
	}
	void Shutdown()
	{
		managerThread.Shutdown();
		for (int i=0; i<renderers.GetCount(); ++i)
			renderers[i].Shutdown();
	}
	
	//thread: manager
	void Run()
	{
		//...
		Renderer &newRenderer = renderers.Add(new Renderer(this));
		//...
	}
	
	//thread: renderer[i]
	virtual const IntermediateData &GetSource(const String &k)
	{
		intermediateDataMutex.Enter();
		const IntermediateData &out = intermediateData.GetAdd(k);
		intermediateDataMutex.Leave();
		return out;
	}
	
	//thread: main
	virtual GUIData GetCurrentState()
	{
		//...
	}
private:
	Thread                            managerThread;
	Vector<Renderer>                  renderers;
	Mutex                             intermediateDataMutex;
	ArrayMap<String,IntermediateData> intermediateData;
};

class GUI()
{
public:
	void OnTick() //OnTick() - если по таймеру, либо что-то вроде OnIdle()
	{
		GUIData guiData = guiReporter->GetCurrentState();
		UpdateGUI(guiData);
	}
private:
	GUIReporter *guiReporter;
};

int main()
{
	RenderManager manager;
	GUI           gui(&manager);
	
	gui.Run();
}
В статье и примерах нет никаких счётчиков ссылок — уточняю на всякий случай.

Что касается Явы, то я отлично помню и захватил её зарождение. К моменту выхода JDK 1.2, у меня как раз появилась возможность сравнить её с С++. Хвалёная стабильность, которую якобы должны были обеспечить счётчики ссылок и мусоросборщик, на деле оказалась если и не маркетинговым ходом, то, будем более осторожны, решением, работающим далеко не всегда.

Потом я попал в одну достаточно крупную контору, затем другую — и там с головой окунулся с большие проекты на умных указателях. Довольно скоро выяснилось, что в сложных случаях они не только вызывают известные проблемы — это ещё пол беды. Самое неприятное, что эти ситуации оказывалось очень сложно повторить, а значит отладить. Так, на западе уже достаточно давно и правильно считают, что умные указатели — вовсе не «серебряная пуля», как это принято считать у некоторых.

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

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

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

Не понял по поводу контейнеров со счётчиком ссылок. Вы точно читали статью?
Этому «велосипеду» лет ничуть не меньше, чем intrusive_ptr, просто вы о нём только что узнали и судите по принципу: «это плохо, потому что я привык по-другому».
А вопросы мои к вам всё ещё актуальны. Не ответив на них, обосновать объективную необходимость применения вашего велосипеда, вам будет трудновато. Но я всё ещё надеюсь получить от вас серьёзные, респектабельные ответы.
Собираетесь писать статью по теме?
Встречный вопрос: зачем использовать то, без чего можно обойтись? Зачем переносить проблемы владения с высокого уровня (где известна семантика) на низкий (за счёт перестраховки и снижения производительности)?
Наконец, зачем проблемы циклических ссылок, микширования с обычными указателями?
Зачем отказываться от детерминированности этапа уничтожения объектов, особенно в случаях, когда нужно гарантировать определённый порядок их уничтожения (опять же исходя из семантики отношений)?
Я пишу существенно многопоточные программы (10+ потоков с разным функционалом, которые активно взаимодействуют друг с другом, а также, зачастую, число потоков заранее неизвестно на этапе компиляции и зависит от настроек — в зависимости от режима работы и т.д.) И этот подход себя прекрасно зарекомендовал.

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

Information

Rating
Does not participate
Location
Москва и Московская обл., Россия
Registered
Activity

Specialization

Chief Technology Officer (CTO)
Optimization of business processes
Development management
Mentoring
FullStack
Agile