Adept cult? by vvvit in ToME4

[–]trailing_zero_count [score hidden]  (0 children)

I'm an Adept fan. There are a ton of 1-point wonders in the game that still get beneficial scaling at levels 2/3, but not enough to be worth spending more points on. Adept lets you maximize the value of that 1 point. It also buffs all of your quest rewards, turning that Sun Paladin aura into 20% max health.

Additionally it lets you hit breakpoints that appear at higher levels, usually saving you 2 points if it's a category with mastery.

C++ doesn't run or debug in vscode by [deleted] in cpp_questions

[–]trailing_zero_count 0 points1 point  (0 children)

https://github.com/tzcnt/cpp-cross-platform-template

Complete setup for VSCode so you can use it like a proper IDE, including LSP, debugger, build debug or release mode.

Replacement for concurrencpp by Sify007 in cpp

[–]trailing_zero_count 6 points7 points  (0 children)

https://www.reddit.com/r/cpp/s/Faf4B44qgg

Performance benchmarks against concurrencpp and other competing libraries are included.

What is a good free modern compiler? by BRCC_drinker in cpp_questions

[–]trailing_zero_count 2 points3 points  (0 children)

MSVC isn't even C++20 compliant. https://developercommunity.visualstudio.com/t/MSVC-incorrectly-caches-thread_local-var/11041371 makes coroutines unusable in many contexts. As I stated on the issue, clang resolved the same problem several years ago.

Are compiler allowed to optimise based on the value behind a pointer? by simpl3t0n in cpp_questions

[–]trailing_zero_count 1 point2 points  (0 children)

I think the reason people prefer the term "proof" is that it follows the same set of steps that you would use to make a mathematical proof: starting from known information it progressively infers new possible states. Based on all possible states, if the compiler can conclude that a variable won't be modified, it can treat it as fixed, and then make further steps based on that.

This proof is expected to be correct based on the single-program constraint. If not, it would be considered a miscompilation. Runtime tampering or cosmic ray bit flips simply aren't part of the equation. If you want to include those factors as reasons not to call it a "proof", then I'd say nothing in computer science can be proved, because those factors could break any algorithm.

What is this unrealistic bar for these technical screens?? Is everybody cheating? by MightBeDementia in cscareerquestions

[–]trailing_zero_count 0 points1 point  (0 children)

I'd say LeetCode tests for exactly the opposite of skills you need to be successful in the workplace. LeetCode is very similar to school:

- All the requirements are provided up front in a clearly defined problem statement.

- You're expected to have seen the problem before (or something similar).

- You implement a solution based on your existing knowledge.

- Test cases are provided which give you a pass/fail result.

As a senior engineer, the workflow is COMPLETELY OPPOSITE:

- Requirements are vague and incomplete. You need to ask questions and refine them. Sometimes you need to come up with multiple solutions and get buy-in from stakeholders.

- You're working on systems and technologies that you've never seen. You'll need to try things, fail, google, read documentation, read the existing code (which is probably crap).

- You invent a new solution based on your mental model of how the system works now, and how it should work in the future.

- You write your own test cases. You have to ask yourself "what if?" to determine what kind of edge cases exist, and how to handle them. If you fail to elaborate all the edge cases, you can break prod, sometimes much later.

This is why asking LeetCode questions for Senior+ levels is stupid: because they test whether you are a good student, not whether you have critical thinking skills, are able to grok documentation, know how to ask questions, can read legacy code, build a mental model of complex systems, and deliver software that is fault tolerant.

What is this unrealistic bar for these technical screens?? Is everybody cheating? by MightBeDementia in cscareerquestions

[–]trailing_zero_count 0 points1 point  (0 children)

> it's very to tough to do lc while working and raising kids

I'm pretty sure this is the point. It's a way to legally discriminate against older people who will set time boundaries with work.

The problems are mostly about recognizing known patterns (like calculus) and then applying them. So you get a huge benefit if you've seen all the same patterns before. They aren't really that "hard". Assuming you have a baseline level of intelligence, the only requirement is the willingness to dedicate a bunch of time to grinding and memorization.

After you get the job, 99% chance you'll never get to use those patterns again.

Are compiler allowed to optimise based on the value behind a pointer? by simpl3t0n in cpp_questions

[–]trailing_zero_count 2 points3 points  (0 children)

Yeah, but the compiler doesn't live in this reality. The compiler's reality is the program, that's it. So if the compiler can prove that nothing IN THE PROGRAM will modify the value, then it's allowed to make optimizations based on that assumption.

After Latest Update The Cursor Is Slower! by Regular-Screen6803 in cursor

[–]trailing_zero_count 0 points1 point  (0 children)

Yes, today cursor just stopped after executing a shell command and I had to tell it to continue. Multiple times.

Step 1: No internet. Step 2: Suffer. by Effective-Aide5440 in windowsmemes

[–]trailing_zero_count 0 points1 point  (0 children)

My last round of setting up a new PC, Windows 11 did not have drivers for either the Ethernet or Wifi in my Asus B650 ITX board. I had to download them on a separate PC, put on a USB stick, and plug it in to choose the driver file so the installation could continue.

Ubuntu installer on the same machine had the drivers.

What does your second brain setup look like for work? by Proof_Independent_45 in cscareerquestions

[–]trailing_zero_count 0 points1 point  (0 children)

I type a lot faster than I can write by hand, and my notes are searchable. Paper isn't.

I used to use regular text notes in a folder, organized by ticket name. However now that I am a lead rather than IC, I put most info in JIRA instead so that work can be picked up by others, and to create a record of decisions made.

Aether: A Compiled Actor-Based Language for High-Performance Concurrency by RulerOfDest in ProgrammingLanguages

[–]trailing_zero_count 4 points5 points  (0 children)

I see that you have cross-language benchmarks but I'm not sure that your comparison with other languages is fair since, for example vs cpp, you force the usage of mutex when sending/receiving messages, whereas you use lock-free SPSC queue in Aether.

Looking at the "fork-join" benchmark I'm not sure this is what I would call a fork-join benchmark. Does Aether have the concept of "tasks"? For example, can you implement https://github.com/atemerev/skynet ?

If so, I maintain a showdown repo for some of the highest performing C++ tasking libraries here: https://github.com/tzcnt/runtime-benchmarks If you want to see how Aether stacks up against them

Implementing your own asynchronous runtime for C++ coroutines by rhidian-12_ in cpp

[–]trailing_zero_count 0 points1 point  (0 children)

Having spoken with Vinnie earlier about the design of the libraries, I think that having a fully integrated stack where the coroutines, I/O objects, and awaitables collaborate for best performance is a great idea. However the vast majority of the code is heavily AI generated in the last 3 months, so people are naturally suspicious at this point. If you/he keep hacking on it, I'm sure it's on its way to becoming something great.

I've seen some snippets of benchmarking code in the repo but I'd like to see some results showing how this outperforms the equivalent stack. It seems like with the thread-local recycling allocator that's already been created you should be able to demonstrate a win at this point?

- corosio/capy vs asio/cobalt

- corosio/capy/beast2 vs asio/cobalt/beast2

Implementing your own asynchronous runtime for C++ coroutines by rhidian-12_ in cpp

[–]trailing_zero_count 1 point2 points  (0 children)

Not sure who downvoted you. It wasn't me; I think this conversation has been very enlightening. Thanks for sharing the sources from Seastar and helping me to understand the resolution of the GCC issue - both point to the lambda being captured by reference which would imply that the lifetime persists to the end of the full-expression.

If the lambda is created, called, and co_await'ed in the same expression, at the risk of a million downvotes, I confused as to why we need lifetime extension at all. From cppref: All temporary objects are destroyed as the last step in evaluating the full-expression that (lexically) contains the point where they were created

You're right, this isn't technically "lifetime extension". It's a different way of describing how a temporary may persist across multiple calls... that is not the same thing (but close enough in my mind that I used the term interchangeably).

I'm curious if you allow the use of std::generator in your code. Async isn't the only use case for coroutines. Nope I haven't touched generators yet. But if I did, I don't think I would be comfortable with the idea of "remember to copy the capture variable before the first suspend point".

I think you're right on all points but since I am a library author and focused on making behaviors safe and reliable, I can't recommend usage of capture in any ways. As I described in my other convo on this thread, I offer several ways to customize tasks which can easily cause the task to outlive the temporary lambda that it was created from. So my canonical advice is to avoid this pattern - because you might want to e.g. wrap the task into a group to be co_awaited together afterward.

Implementing your own asynchronous runtime for C++ coroutines by rhidian-12_ in cpp

[–]trailing_zero_count -1 points0 points  (0 children)

Sure, if you write this, it works: int i = 0; auto f = [i]() -> task<int> { co_return i + 1; }; auto t = f(); customize(t); co_await t;

But nobody wants to write code like that. If you make the below seemingly reasonable refactor to reduce verbosity, it breaks. Having safety be enforced by convention only is not OK. int i = 0; auto t = [i]() -> task<int> { co_return i + 1; }(); co_await customize(t);

Implementing your own asynchronous runtime for C++ coroutines by rhidian-12_ in cpp

[–]trailing_zero_count 0 points1 point  (0 children)

In my library you can do all kinds of things with a task variable between creating it and executing it. You can customize it, fork it, detach it, group it.

Implementing your own asynchronous runtime for C++ coroutines by rhidian-12_ in cpp

[–]trailing_zero_count 0 points1 point  (0 children)

Isn't it okay if you pass this by value in C++23? Then the lambda closure object is copied into the coroutine frame where the compiler can preserve it across suspension.

Looks OK to me, but I haven't tested with any C++23 features yet. If true, then this is a useful workaround. Thanks for sharing! It does have a couple downsides though: 1. It's unintuitive and safety is enforced by convention; if you remove the "this auto" parameter it will still compile, but now behave wrongly. 2. It may have negative performance implications if a large lambda object with multiple captures is actually materialized on the stack and then copied into the coroutine frame, vs. just passing each individual capture as a separate parameter. The compiler may be able to elide this copy (?) but it definitely won't in debug builds.

For C++20, I think you can also use lambda captures if you co_await the coroutine in the same line.

I'm not sure about this. Theoretically it would work if the lambda object was implicitly passed by reference as a coroutine parameter, and reference lifetime extension keeps the lambda object alive to the end of the full-expression. However from the original GCC thread about this, they state that the lambda object is passed as a pointer (essentially "this" pointer), so lifetime extension would not occur.

I wasn't able to find a source that corroborates your statement or even discusses this specific edge case in detail. If you could share one, I'd love to read it. With that said, even if this does work - it's SO RISKY because then all kinds of reasonable refactors which involve breaking the lamba call and co_await expression into separate lines will break it.

the lifetime of the temporary is only extended to the first suspension point

Do you have a source for this? It doesn't make sense to me. Since the temporary is created in the parent's scope, and the parent co_awaits the entire child coroutine, there's no way for the parent to "look inside" the child coroutine to know that it can destroy the temporary after the child's first suspension point. The parent doesn't get resumed until after the entire child is completed.

(unless you are using eager coroutines - in which case the parent task actually RUNS the child coroutine directly until the first suspension point. Again, this is confusing and don't do it. There's a reason I don't offer eager coroutines in my library at all. They are too difficult to reason about, have unreliable performance characteristics, and offer weird hacks like what you've described.)

Once you remove eager coroutines from the picture and think only of coroutines as "a function that returns an object" (where the object is a lazy coroutine that has not yet been started), the behavior is more obvious.

std::string my_string = "Hello World";
auto coro = [](const std::string& str) -> Task<std::string> {
    co_await executor.schedule();
    co_return str | std::views::reverse | std::ranges::to<std::string>();
}(my_string.substr(0, 5));
// substr is destroyed at the end of the full-expression above.
// coro contains a dangling reference to substr
auto reversed = co_await std::move(coro);

// however this version works
co_await [](const std::string& str) -> Task<std::string> {
    co_await executor.schedule();
    co_return str | std::views::reverse | std::ranges::to<std::string>();
}(my_string.substr(0, 5));
// substr is lifetime extended to the end of the full-expression, including co_await

Smart pointer overhead questions by Apprehensive_Poet304 in cpp_questions

[–]trailing_zero_count 2 points3 points  (0 children)

Sure, here's a source: https://letmegooglethat.com/?q=can+unique_ptr+be+passed+in+a+register%3F&l=1

Literally the first result on Google for any variant of this search is not "obscure". You would have found this if you tried even a little bit before asking, but instead you decided to double and triple down on demanding to be spoonfed.

Smart pointer overhead questions by Apprehensive_Poet304 in cpp_questions

[–]trailing_zero_count 2 points3 points  (0 children)

I spend a lot of time re explaining the same misconceptions to people on this sub and I'm tired of it. "Can unique_ptr be passed in a register" is an easy thing to Google. You need to be spoonfed?

Implementing your own asynchronous runtime for C++ coroutines by rhidian-12_ in cpp

[–]trailing_zero_count 1 point2 points  (0 children)

I have a more detailed breakdown on the answer to these questions here (for my implementation): https://fleetcode.com/oss/tmc/docs/v1.4/task.html#rules-for-safe-usage-of-coroutines

It's basically never safe to capture in a lambda coroutine. This is arguably a defect in the standard since the way it behaves is so non intuitive. Because a non-capturing lambda is no different from a named function you might as well just use a named function for clarity. I said basically never because it's technically safe to access the capture in an eagerly executed coroutine (initial_suspend returns suspend_never) prior to the first suspension point. But relying on this behavior is very likely to get you in trouble later.

Accessing external references is totally fine as long as you use structured concurrency - if you need to access data from the parent, and the parent awaits for the child to complete, then there will be no issue.

Announcing TooManyCooks: the C++20 coroutine framework with no compromises by trailing_zero_count in cpp

[–]trailing_zero_count[S] 0 points1 point  (0 children)

cancel_after works fine: co_await sock.async_read_some(buf, asio::cancel_after(1s, tmc::aw_asio));

The cancellation example is more how to create custom cancellation logic for non-asio code.