Live data from Hacker News

A Defer Mechanism for C

gustedt.wordpress.com

221–230 of 248 posts

Re: A Defer Mechanism for C

#221
post #202

I’ve always considered “defer” an inelegant kludge in comparison to RAII for automatic cleanup of resources. It’s surprising that the C standards committee is considering adding that to the language. Then again, nearly none of the syntactic C features post-C89 have been very compelling or widely adopted.

RAII can be an anti-pattern for certain high performance applications. Yes a lot of times you want the assurance you're always dealing with properly initialized memory, but if you're really optimizing for memory performance (one of the jobs C is for) then a lot of times initializing and deinitializing small blocks of memory is exactly the opposite of what you want to do.

that's what arenas are for

Re: A Defer Mechanism for C

#222
post #200

Earlier quoted context omitted.

Every defer statement is ultimately pushing a lambda into some stack that is executed when the defer block is exited. With an exception of setjmp/longjmp, I can't think of an existing C construct with similar run-time complexity.

Is it actually a lambda, or is it just essentially appending statements to the end of the scope?

that depends for instance you can safely call free on NULL so you could just append.

However, for some things you can only free/return resources if you successfully created that resource. At which point you would need to use something like a stack.

Re: A Defer Mechanism for C

#223

Earlier quoted context omitted.

it is a bit annoying yes. There are some proposals to have a anonymous reusable placeholders like '_', but they haven't gone anywhere yet. You can do lock(mutex), some-lock-protected-expression; but it is a bit too cute and limited. On the other hand, being able to name the RAII object is often very useful for example if you need to dismiss them early, which happens often in transactional code (unlocking a mutex befo…

> On the other hand, being able to name the RAII object is often very useful I didn't say it wasn't. Being able is perfectly fine, being forced is not. As I mentioned in another comment, the problem isn't the extra typing, the problem is that it requires us, the programmer, to remember to name it even when we don't feel we need and to remember that "foo (bar)" isn't calling the constructor of foo and passing in bar,…

> Its also a rather insidious bug, because the code will run seemingly normally, just... it never actually locks anything.

Actually, I think it's worse than that; IIUC, it will block until the mutex is unlocked, then run. Under light load, it will get away with this, but if the load is heavy enough, it will either guarantee that every process waiting for the lock runs at once, trampling each other's work, or almost-serialize them, making the race condition even more intermittent than if they didn't lock at all. Which failure mode you hit depends on how your scheduler works.

Re: A Defer Mechanism for C

#224
post #2

Despite being convenient,I have the feeling that it might be a bad idea. One of the key interest of C compared to more recent languages is that everything is explicit. With a finger you can follow the code as it runs and know exactly what is going on and when exactly. At the opposite, there is c++ that does a lot of things automagically. And it is often hard to understand why you suddenly get a segfault out of blue,…

I've heard this comment more than once. What we are trying to accomplish is to collocate the resource acquisition code with the acquisition release code. This does mean that the release code is removed when where the release occurs (for example, at every location a function returns. However, this is not without precedence in C. For example, just look at the for loop: for (clause1; expression2; expression3) statement…

The nonlocality can be eliminated by replacing the `guard {}` block with a `resolve;` statement to be placed at the end of a block containing multiple `defer`s. This also reduces nesting and solves the question of where the `defer` is executed and makes it easy to grep to the location where the `defer` statement will be executed. Of course, it would be a syntax error to use `defer` without a following `resolve;`.

Re: A Defer Mechanism for C

#225

Earlier quoted context omitted.

> defer just changes the problem from forgetting to write free to forgetting to write defer. That's the case only the first time you write code: { foo *f = new_foo(); // step 1 /* lots of code */ // step 3 free(f); // step 2 } vs { foo *f = new_foo(); // step 1 defer free(f); // step 2 /* lots of code */ // step 3 } Sure, in both cases you can forget step 2. But what about review ? With defer, the init and cleanup co…

I think this example demonstrates the opposite of what you intended. Defer doesn't give you anything that you can't already do. In your last four code blocks, you demonstrated three alternate ways to implement the functionality you want without defer. Defer is just a slightly different, arguably nicer fourth way to implement the same code. Language features should be orthogonal. A new language feature should add some…

Of course. There should never be more than one way to do something in c, even if it makes things easier or less error prone. This is why the -> operator would never be included in c. You can already use (*x).y, it would be SILLY to introduce a whole operator which isn't orthogonal to all existing features of the language.

Re: A Defer Mechanism for C

#226

Earlier quoted context omitted.

I think this example demonstrates the opposite of what you intended. Defer doesn't give you anything that you can't already do. In your last four code blocks, you demonstrated three alternate ways to implement the functionality you want without defer. Defer is just a slightly different, arguably nicer fourth way to implement the same code. Language features should be orthogonal. A new language feature should add some…

Of course. There should never be more than one way to do something in c, even if it makes things easier or less error prone. This is why the -> operator would never be included in c. You can already use (*x).y, it would be SILLY to introduce a whole operator which isn't orthogonal to all existing features of the language.

I never said C's language features are orthogonal. I said they should be. C is far from a perfect language, as your example shows.

Look at it from the opposite direction: if x->y didn't exist today, and the billions of lines of existing C code all used (*x).y, would you support a proposal to add a new x->y operator to the language? I doubt it.

Re: A Defer Mechanism for C

#227
post #102
post #91

Earlier quoted context omitted.

searches codebase I'm working on... finds thousands and thousands of std::shared_ptr (many involve a typedef, so there are even more...) eep! Should I be alarmed?

If that codebase is older than C++0x, many of these std::shared_ptr could be taking the place of std::unique_ptr (which didn't exist back then; std::auto_ptr was a footgun). If you're in the mood for a refactoring, you could take a look at each one and see whether then can be replaced by std::unique_ptr, or whether they really have shared ownership semantics (which is what std::shared_ptr should be used for).

Neither std::unique_ptr nor std::shared_ptr existed prior to c++11. Perhaps you're thinking of boost::shared_ptr or boost::scoped_ptr, both of which have existed in one form or another for somewhere around 20 years.

Re: A Defer Mechanism for C

#228
post #137

Earlier quoted context omitted.

Still there is a life beyond UNIX clones and gcc/clang. The C compiler vendor for some embedded CPU with homegrown C compiler for their in-house OS also has a seat at ISO table. While people here might not care, ISO does.

The proposals generally exist so that compiler vendors can comment on them and try proof-of-concept implementations if they're interested.

Indeed, and the fact that this is being proposed instead of adopting gcc/clang extensions, it is a proof that not all ISO members would be happy adopting that extension.

Re: A Defer Mechanism for C

#229

Earlier quoted context omitted.

I would strongly disagree on RAII being a kludge in C++. The language feature that enables it is deterministic destructors, whose primary purpose is to ensure that allocated resources are deallocated. RAII is one particular use of destructors. The primary goal is to have the object be the thing that owns a resource, not the calling scope. In terms of usability, destructors allow for resource management that is far ea…

I do feel that RAII is a little bit ruined by the fact that you cannot declare anonymous object instances. For example, I cannot write: lock (mutex); Expecting to declare an anonymous lock with the mutex passed in, as this gets parsed as a declaration of a lock called mutex (hopefully lock doesn’t have a default constrictor and I at least get an error). Instead I have to bake my lock: lock l(mutex); Often I have obje…

Sure you can, it just requires a little bit more syntax and following FP patters by making use of lambdas.

With lock() being a function taking a lambda.

    lock([]{
       // code locked with anonymous mutex
    });
Post reply on HN