People who bother to practice for coding interviews (using the same website) and successfully land an interview do similarly well on coding interviews... That's a lot of selection bias.
I'm sorry but you can't possibly be serious. There is no sane motivation for a *FactoryFactoryFactory class. No problem on earth is complex enough to benefit from that much abstraction.
The article is an okay start, but it wasn't written by an expert. It lists some real pitfalls but doesn't provide commonly accepted solutions. Some examples...
multiple lines:
wrap in do { } while (0)
- can use a multiline macro like a function call, terminated with ;
or ({foo; bar;})
- multiple lines evaluate to 'bar'...
Function calls:
- in general anything with side effects could be harmful if evaluated more than once.
- But possible to write MIN()/MAX() with single evaluation of 'a' and 'b'.
#define MAX(a, b) \
({typeof(a) _a = (a); typeof(b) _b = (b); _a > _b ? _a : _b;})
And other important things like stringify, variadics, etc...
The lock could still be faster. atomic ops are more expensive than regular opcodes even when there is zero contention. On x86, a lock requires only a single atomic opcode and can be released with a normal write (because of TSO). Since it's uncontended it won't spin at all. Therefore, any alternative lock-free algorithm that uses more than a single atomic op is actually more expensive.
Keep in mind lockless algorithms are not necessarily more scalable than lock-based algorithms, usually have higher constant overheads, and are significantly easier to get wrong.
However, this post is, in part, about how to implement locks.