LINUX.ORG.RU

Попытка номер 5(2)

 ,


3

4

Это моя вторая попытка написать клиент-серверное приложение в качестве теста для одной конторы. Меня послали и на этот раз. Внятных аргументов снова не дали, сказали что недостаточно опыта для их задач. В общем выкладываю на общее обозрение мою вторую поделку. В этот раз я подошел, с моей точки зрения, более обстоятельно. Сервер и клиент асинхронные. Компилируются и работают под x86 и amd64. Конвертация порядка байт есть. readme есть хоть и вордовый. Система сборки cmake. Зависимости: boost(вычитка/пересылка всех байт реализована автоматически) и poco. Есть небольшие недочеты: вызывается sleep в основных потоках, но это пофиксить очень просто и не думаю, что это должно как-то влиять на оценку. Использовал пару шаблонов проктирования: медиатор и шаблонный метод. Есть один модульный тест. В общем с моей точки зрения в этот раз все намного лучше, но снова чего-то нехватает, прошу посмотреть и оценить. Прошу в этот раз воздержаться от перехода на личности, особенно это касается анонов.

Ссылка

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

Не догадаться, что это отмена задачи? Там коммент между прочим есть.

Не догадаться, кто и каким образом у тебя должен взводить этот флажок. Обработчик сигнала? Просто другой поток? Или в твоей программе поток только один, сигналов нет, а флажок может быть взведен только ДО вызова GetFactors() ? От этого зависит, что дальше делать с твоим кодом.

Manhunt ★★★★★
()
Последнее исправление: Manhunt (всего исправлений: 1)
Ответ на: комментарий от Booster

Не беспокойся. Причины отказа действительно были технические.

У тебя немного неверные сведения. Самое забавное тут то, что формально ты правильные вещи написал, чтение bool может быть атомарно. Только всё равно всё вместе будет работать не так, как ты себе представляешь.

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

i-rinat ★★★★★
()
Последнее исправление: i-rinat (всего исправлений: 1)

Выкладывать сорцы на гугл диск... еще и с запросом на разрешение.. это просто... Есть же github, bitbucket...

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

Зачем?

Например затем, что в нынешнем виде компилятор может вынести проверку твоего флажка за тело цикла. Если у него хватит мозгов доказать, что factors.push_back() в этот флажок не пишет. Примерно так, как описано тут: https://en.wikipedia.org/wiki/Volatile_(computer_programming)#Example_of_memo...

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

Скажу только про Java, вряд ли ц-п-п отличается.

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

Другое дело, что самому прописывать синхронизации-мютексы нафиг не сдалось, лучше взять библиотечные вещи. Для флагов решает AtomicBoolean (он не только атомарен, как простой boolean, но и даст защиту от кэша), в Java пойдет объявление volatile, как в плюсах - не знаю.

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

в Java пойдет объявление volatile, как в плюсах - не знаю.

В плюсах, если только это не код драйвера, никаких volatile быть не должно. Слово одно и то же, а смысл у него совсем не такой, как в java.

Manhunt ★★★★★
()
Последнее исправление: Manhunt (всего исправлений: 1)
Ответ на: комментарий от Manhunt

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

Только вспоминается вопрос: если есть тот же синхронизированный boolean, может ли компилятор его в цикле заоптимизировать, если нету квалификатора volatile? Или есть гарантия, что этого не произойдет?

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

Да потому что компилятор оптимизирует (и, к слову, совершенно законно) твой код так, что переданный bool* ляжет в регистр. И проверяться будет значение в регистре, и даже если ты из другого потока изменишь свой bool (который, однако, const!), этот поток, который разложением занимается, это изменение не увидит. man volatile.

А может быть еще хуже: т. к. у тебя на входе const bool cancellation = 0 (ну, я код не смотрел, но я надеюсь, что ты все-таки был в сознании, когда писал код), очевидно, что проверку и лишний параметр у функции вообще можно выкинуть, и реально в ассемблерном коде функции его вообще не будет.

Ну и наконец, разложение на множители выполнено неэффективно. Зачем нужен шаблон? Зачем нужна переменная tmpNumber? И еще есть одна оптимизация, но это уже для математиков. Не нужно сбрасывать переменную i, вместо этого следует написать цикл

while ( tmpNumber % i == 0 ) {
    factors.push_back(i);
    tmpNumber /= i;
}

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

Веселишь однако.

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

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

«Каждая атомизировання инструкция полностью выполняется ...».

Спасибо, теперь ясно.

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

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

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

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

На самом деле всё проще, возращаемся в начало темы и смотрим:

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

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

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

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

torvn77 ★★★★★
()
Последнее исправление: torvn77 (всего исправлений: 1)

Аффтар лох. Язабан

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

Воткнуть конечно не помешает, но ты же понимаешь, что нет там проблем с регистром. Этот флаг член класса.

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

Я конечно согласен, сгоряча написал. Но с другой стороны вскому терпению есть предел. Многие анонимы чувствуют безнаказанность. Или взять первый пост который меня взбесил. Зачем было писать - «вау. ОДИН модульный тест»? Человек даже не разобрался нужны там тесты или нет. Тестировать тривиальную логику не обязательно.

Booster ★★
() автор топика
Последнее исправление: Booster (всего исправлений: 1)
Ответ на: комментарий от Booster
#include <thread>
#include <iostream>
#include <chrono>

void
worker(const bool &cancel)
{
    unsigned int i = 0;
    while (!cancel) {
        i++;
    }
}

int
main()
{
    bool cancel = false;

    auto t = std::thread([&cancel] {
        std::cout << "worker thread starting" << std::endl;
        worker(cancel);
        std::cout << "worker thread stopping" << std::endl;
    });

    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "trying to cancel worker thread" << std::endl;
    cancel = true;

    t.join();
    std::cout << "joined" << std::endl;
}
i-rinat ★★★★★
()
Ответ на: комментарий от Booster

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

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

Хочешь сказать, что члены класса могут могут оптимизироваться в регистр?

Ничего, что тело функции GetFactors() ничего об этом классе не знает?

Не слышал о таком.

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

Manhunt ★★★★★
()
Последнее исправление: Manhunt (всего исправлений: 1)

Какой-то верх неадекватности. Даже для ЛОРа, даже для C++-ника.

И никто еще не спросил, зачем в маленькую задачу тянется два здоровых фреймворка.

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

Хочешь сказать, что члены класса могут могут оптимизироваться в регистр? Не слышал о таком.

Все переменные когда-то попадают на регистры, и ничего не мешает кешировать любые из них (без volatile).

Вообще, писать надо по спекам, а не гадать, что сделает компилятор. В данном случае - никаких const (твоя проверка с большой вероятностью будет выоптимизирована), а volatile.

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

В плюсах, если только это не код драйвера, никаких volatile быть не должно.

Слишком сильное заявление для языка, который не понимает асинхронности. Если атомики (наконец!) попали в язык, то есть и другие расшариваемые типы данных. И еще есть сигналы unix.

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

Слишком сильное заявление для языка, который не понимает асинхронности.

Ты лучше разберись, что в этом языке на самом деле означает слово volatile. В нем какой-то смысл появляется только в сочетании со специальной настройкой MMU. https://www.kernel.org/doc/Documentation/volatile-considered-harmful.txt

Если атомики (наконец!) попали в язык

Попали

И еще есть сигналы unix.

Хм. Да, в случае сигналов следует использовать volatile sig_atomic_t

Manhunt ★★★★★
()
Последнее исправление: Manhunt (всего исправлений: 1)
Ответ на: комментарий от anonymous

+1

но до тестового задания или прочих бесед по существу

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

а что аноны?

код всё равно не почитать, а поговорить о чём-нибудь хочется :)

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

нет там проблем с регистром. Этот флаг член класса.

да ты ещё и шизофреник

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

https://www.kernel.org/doc/Documentation/volatile-considered-harmful.txt

знатный был когда-то давно бугурт у гражданина торвальдса, аж в документацию награфоманил. он ведь тоже volatile синхронизировал, пока разработчики gcc не объяснили ему что он лох :)

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

знатный был когда-то давно бугурт у гражданина торвальдса, аж в документацию награфоманил.

Да неужели...

Original impetus and research by Randy Dunlap

Written by Jonathan Corbet

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

В общем это мой тебе совет,

Сударь, вы уверены, что для своих советов вы выбрали того человека?

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

значит анонимус — Ъ

и больше ничего

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

Чо

Хули ты хамишь тут, чмо болотное? Иди уроки учи, урка.

anonymous
()

Документация небрежная. Нет описания архитектуры приложений. Нет тестов сервера, я не силен в терминологии QA, я имею в виду: запускаешь сервер и проверяешь ответы на эталонные запросы. Если есть отдельная логика заполнения буфера, ее можно и нужно модульно протестировать. Если она вхадкожена куда-то – минус. Почему клиент читает только 8 байт, когда в протоколе int64? Организация исходников какая-то чудная, почему не сделать два архива с нормальной структурой CMakelists.txt, src, include, tests? Кириллические имена файлов – кракозябры, я-то конечно лох и ниасилил, но в данном случае сделать клиенту заебись – твоя непосредственная задача. Два больших фреймворка на такую простую задачу – перебор.

Это за две минуты, даже не смотря в код. А зачем тратить время на код, если его архитектура не описана? Если позиция выше джуна, то и там могли подумать так же.

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

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

anonymous
()

Каменты не читал.

Исходники - непонятная, неописанная каша. Что, где, куда.

Зачем буст и поко вместе? Можно все сделать или на том, или на другом.

Запись реализована неверно, потому как async_read может записать не все сразу. Тоже самое про async_read. Клиенту ничего не помешает писать по байту за раз. А у тебя получается одна операция чтения == одна операция протокола.

В общем архитектура - г..но. За такое жуниоры по головам получают.

Это только за 1 минуту посмотреть.

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

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

За буфером следит asio. Там нужно только не накосячить с параллельным вызовом такой же асинхронной функции. Или имеешь ввиду что-то другое?

Почему клиент читает только 8 байт, когда в протоколе int64?

Тут я сначала немного завис. Клиент читает 8 байтное число, а не 8 байт.

Кириллические имена файлов – кракозябры, я-то конечно лох и ниасилил

В смысле кодировка имен файлов в кирилице или что? Имена то не в кирилице.

А зачем тратить время на код, если его архитектура не описана?

А каким образом она описывается? UML диаграммы что-ли строить? Что же все так жирно нужно делать.

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

Запись реализована неверно, потому как async_read может записать не все сразу. Тоже самое про async_read. Клиенту ничего не помешает писать по байту за раз. А у тебя получается одна операция чтения == одна операция протокола.

Потрать больше минуты и поймешь, что гонишь.

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

async_write и async_read пишут и читают то количество байт которое у них прописано в параметре. Сделано это с помощью многократного вызова async_send и async_recv. В общем не рубишь ты в asio.

Booster ★★
() автор топика
Последнее исправление: Booster (всего исправлений: 2)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.