Pull to refresh
97
0
Борис Егоров @JIghtuse

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

Send message

Думаю, вам понравится Armikrog от тех же авторов. Сам не играл, но соглашусь, что выглядит мило.
Да, ещё есть Вангеры. Там, судя по всему, не только пластилин, но игрушка атмосферная.

Мне youtube-dl нравится своей всеядностью — я, кажется, от силы пару сайтов встречал, с которых он не умеет тянуть. Ну и целыми плейлистами умеет качать. Да и не сказать, что сильно сложнее =)


pushd ~/Downloads
youtube-dl http://...
popd
Разные процессоры реализуют сдвиг по-разному, поэтому комитет поступил, как поступает обычно в таких случаях — объявил поведение неопределённым. Цитата под спойлером насчёт сдвига на ширину, большую размеру типа, но со сдвигом отрицательных чисел история та же.

Скрытый текст
Shifting a uint32_t by 32 or more bits is undefined. My guess is that this originated because the underlying shift operations on various CPUs do different things with this: for example, X86 truncates 32-bit shift amount to 5 bits (so a shift by 32-bits is the same as a shift by 0-bits), but PowerPC truncates 32-bit shift amounts to 6 bits (so a shift by 32 produces zero). Because of these hardware differences, the behavior is completely undefined by C (thus shifting by 32-bits on PowerPC could format your hard drive, it is *not* guaranteed to produce zero). The cost of eliminating this undefined behavior is that the compiler would have to emit an extra operation (like an 'and') for variable shifts, which would make them twice as expensive on common CPUs.

What Every C Programmer Should Know About Undefined Behavior #1/3
У Мейерса в Effective Modern C++ об этом пишется (Item 37: Make std::threads unjoinable on all paths):

Скрытый текст
One reason a std::thread’s joinability is important is that if the destructor for a joinable thread is invoked, execution of the program is terminated. For example, suppose we have a function doWork that takes a filtering function, filter, and a maximum value, maxVal, as parameters. doWork checks to make sure that all conditions necessary for its computation are satisfied, then performs the computation with all the values between 0 and maxVal that pass the filter. If it’s time-consuming to do the filtering and it’s also time-consuming to determine whether doWork’s conditions are satisfied, it would be reasonable to do those two things concurrently.

Our preference would be to employ a task-based design for this (see Item 35), but let’s assume we’d like to set the priority of the thread doing the filtering. Item 35 explains that that requires use of the thread’s native handle, and that’s accessible only through the std::thread API; the task-based API (i.e., futures) doesn’t provide it. Our approach will therefore be based on threads, not tasks.

We could come up with code like this:

constexpr auto tenMillion = 10000000;          // see Item 15
                                               // for constexpr

bool doWork(std::function<bool(int)> filter,   // returns whether
            int maxVal = tenMillion)           // computation was
{                                              // performed; see
                                               // Item 2 for
                                               // std::function

    std::vector<int> goodVals;                 // values that
                                               // satisfy filter

    std::thread t([&filter, maxVal, &goodVals] // populate
                  {                            // goodVals
                    for (auto i = 0; i <= maxVal; ++i)
                    { if (filter(i)) goodVals.push_back(i); }
                  });

    auto nh = t.native_handle();               // use t's native
                                               // handle to set
                                               // t's priority

    ...
    if (conditionsAreSatisfied()) {
        t.join();                              // let t finish
        performComputation(goodVals);
        return true;                           // computation was
                                               // performed
    }
    return false;                              // computation was
}                                              // not performed


Before I explain why this code is problematic, I’ll remark that tenMillion’s initializing value can be made more readable in C++14 by taking advantage of C++14’s ability to use an apostrophe as a digit separator:

constexpr auto tenMillion = 10'000'000; // C++14


I’ll also remark that setting t’s priority after it has started running is a bit like closing the proverbial barn door after the equally proverbial horse has bolted. A better design would be to start t in a suspended state (thus making it possible to adjust its priority before it does any computation), but I don’t want to distract you with that code. If you’re more distracted by the code’s absence, turn to Item 39, because it shows how to start threads suspended.

But back to doWork. If conditionsAreSatisfied() returns true, all is well, but if it returns false or throws an exception, the std::thread object t will be joinable when its destructor is called at the end of doWork. That would cause program execution to be terminated.

You might wonder why the std::thread destructor behaves this way. It’s because the two other obvious options are arguably worse. They are:

  • An implicit join. In this case, a std::thread’s destructor would wait for its underlying asynchronous thread of execution to complete. That sounds reasonable, but it could lead to performance anomalies that would be difficult to track down. For example, it would be counterintuitive that doWork would wait for its filter to be applied to all values if conditionsAreSatisfied() had already returned false.
  • An implicit detach. In this case, a std::thread’s destructor would sever the connection between the std::thread object and its underlying thread of execution. The underlying thread would continue to run. This sounds no less reasonable than the join approach, but the debugging problems it can lead to are worse. In doWork, for example, goodVals is a local variable that is captured by reference. It’s also modified inside the lambda (via the call to push_back). Suppose, then, that while the lambda is running asynchronously, conditionsAreSatisfied() returns false. In that case, doWork would return, and its local variables (including goodVals) would be destroyed. Its stack frame would be popped, and execution of its thread would continue at doWork’s call site. Statements following that call site would, at some point, make additional function calls, and at least one such call would probably end up using some or all of the memory that had once been occupied by the doWork stack frame. Let’s call such a function f. While f was running, the lambda that doWork initiated would still be running asynchronously. That lambda could call push_back on the stack memory that used to be goodVals but that is now somewhere inside f’s stack frame. Such a call would modify the memory that used to be goodVals, and that means that from f’s perspective, the content of memory in its stack frame could spontaneously change! Imagine the fun you’d have debugging that.

The Standardization Committee decided that the consequences of destroying a joinable thread were sufficiently dire that they essentially banned it (by specifying that destruction of a joinable thread causes program termination).

This puts the onus on you to ensure that if you use a std::thread object, it’s made unjoinable on every path out of the scope in which it’s defined. But covering every path can be complicated. It includes flowing off the end of the scope as well as jumping out via a return, continue, break, goto or exception. That can be a lot of paths.


TLDR: альтернативы хуже.

Это всё с нуля делалось? CLion ведь Clang использует? Есть ведь ровно такой же инструмент — clang-format. И заготовленные стили там есть (LLVM, Google, Chromium, Mozilla, WebKit), на основе которых тоже можно свой конфиг делать.


@kloppspb, рекомендую взглянуть на инструмент, кстати. У него информации о структуре кода больше, чем у astyle/indent, поэтому чаще адекватнее форматирует.

Одна из особенностей Range — begin и end могут быть разными типами (в примере выше это можно увидеть). Без этой возможности реализация значительно усложняется. А при её наличии ломается совместимость с предыдущими версиями стандартной библиотеки.
Сразу скажу, что язык в глаза не видел. По статье и комментариям на Reddit сложилось впечатление, что нет там никакой простоты и удобства. Только за счёт легаси и живёт язык. Не сказать что это плохо — на момент рождения был крут, очевидно. Но понемногу устарел. Из ныне живущих только FORTRAN его старше, как я понимаю.

типа случая с забытой точкой в конце оператора IF, стоившей некой страховой компании миллиардов долларов, согласно легенде
В статье же об этом.
Что тебя больше всего шокировало?
— Мой коллега однажды забыл добавить точку в конце инструкции для программного модуля в самой важной части нашей системы, которую мы называем «кассой». Она отвечает за обработку всех денег. В результате на 16 часов остановилась работа всего банка, исключительно из-за модуля, который продолжал выполняться, хотя должен был остановиться после той инструкции. Это буквально повесило нашу систему, устроив, можно сказать, DoS-атаку самой себя.
Если можно завернуть поиск в функцию, можно (будет) использовать std::optional, у которого как раз семантика «значения может не быть».

Да, действительно. Я заставил пример собраться, но о семантике не подумал.

Был proposal с добавлением Cairo для 2D-графики. Он довольно низкоуровневый (GTK, Firefox его используют под капотом) и достаточно кросплатформенный. Но не знаю, как он там продвигается.

Делает, но вы не можете одновременно объявить переменную и проверить её на произвольное условие.
Здесь подобное обсуждалось.

"Стандартный" split должен быть эффективен и широко применим. Есть n3593 с довольно адекватной мотивацией. Ждёт как раз упоминаемых string_view и Ranges.

Отличный результат!


Спасибо за исходники бенчмарка, пробую повторить. Подскажите, как вы строили результат? CSV-файлы получились, хочется график.

В новостях о Rust обычно имеются в виду RFC для Rust.

EDX/cs50

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

Вопрос к JavaRush: почему не использовать stepic/edx/lektorium для курса?
Он [протагонист](http://winteriscoming.net/2016/04/01/math-proves-that-tyrion-is-the-main-character-on-game-of-thrones/), кто ж его грохнет.

Не то, чтобы это помешало кому-то грохнуть Эддарда..

Бывает ещё вот так: https://youtu.be/5Da6ZyQJjE0
Но это не для каждого, естественно =)

C/C++

Что это за язык?


В C++ используется не совсем rand(). Унылая функция, к слову, особенно для многопоточной среды.

Вот proposal довольно эффективного решения http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3510.html
Но без Ranges и string_view работать будет не очень.

Information

Rating
Does not participate
Location
Россия
Registered
Activity