On Fri, May 26, 2023 at 8:23 AM Peter Zijlstra <peterz@xxxxxxxxxxxxx> wrote: > > The CPP is rather impenetrable -- but I'll attempt to write proper > comments if/when people think this is worth pursuing. Ugh. It's not only impenetrable, it seems _unnecessarily_ so. Yes, yes, 'for()' loops can only declare one type, and if you want multiple typed variables you declare a struct that contains all the types. But you don't actually *need* multiple types. Yes, you think you do, because you want to use that 'bool done' to make the for-loop only execute once. Nasty limitation of the for syntax. But you can actually do the 'bool done' using the exact same type you have for the guard - just make it a pointer instead, and use NULL for "not done" and non-NULL for "done". It ends up acting exactly like a boolean. But that extra structure is only a detail. The real ugliness comes from using different scoping macros. And I think you don't actually need to have those different forms of "scoped()" macros for different cases. I think you can just use variable macro arguments. IOW, something like this: #define variable_scope(type, enter, exit) \ for (type *_done = NULL, _scope __cleanup(exit) = enter; !_done; _done = (void *)8) #define scoped(type, init...) \ variable_scope(scope_##type##_t, scope_##type##_init(init), scope_##type##_cleanup) and then you can do scoped (rcu) { ... } and it will call "scope_rcu_init()" on entry, and "scope_rcu_exit(_scope)" on exit. And just doing scoped (mutex, mymutex) { ... } will call "scope_mytex_init(mymutex)" on entry, and "scope_mytex_exit(_scope)" on exit. And if you just make the scope_##type##_init() functions return the right values, it all works very naturally. I think you can also do things like scoped(irqsave) { ... } scoped(irqoff) { ... } scoped(preempt) { ... } very naturally. No need for that odd "one scope for 'void', one scope for 'lock'" nonsense. I dunno. I didn't *test* the above. Maybe you already tried something like the above, and there's a reason why it doesn't work. Linus