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.
A Defer Mechanism for C
221–230 of 248 posts
Re: A Defer Mechanism for C
#222Earlier 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?
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
#223Earlier 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,…
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
#224Despite 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…
Re: A Defer Mechanism for C
#225Earlier 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…
Re: A Defer Mechanism for C
#226Earlier 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.
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
#227Earlier 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).
Re: A Defer Mechanism for C
#228Earlier 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.
Re: A Defer Mechanism for C
#229Earlier 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…
With lock() being a function taking a lambda.
lock([]{
// code locked with anonymous mutex
});Re: A Defer Mechanism for C
#230If you want these sort of services, why use C?