4 ms·
It would seem to be a failing of the C language that ultimately prevents us from coming up with re-useable recipes for this. Macros or generics of sufficient po
by eximius 6y ago
It would seem to be a failing of the C language that ultimately prevents us from coming up with re-useable recipes for this. Macros or generics of sufficient power in a language with an advanced type system should be able to accomplish this.
I wonder, if language is the primary barrier here, if this is a way to integrate another language for specific small pieces like this.
- imglorp 6y agoYou can do all this in C but it's super hard to get your brain around and do it right. It's probably better to use an abstraction. For example, the Pony language is written in C and guarantees no races or deadlocks without using locks or mutexes so it's faster than C with locking. The user defines intentions, similar to Rust's borrow checking, and strict compile time analysis makes it happen for you. https://www.ponylang.io/discover/#what-makes-pony-different https://www.ponylang.io/discover/#what-makes-pony-different
- lalaland1125 6y ago> For example, the Pony language is written in C and guarantees no races or deadlocks without using locks or mutexes so it's faster than C with locking. This claim is misleading. The reason why Pony is able to "guarantee" no races or deadlocks is because it doesn't support shared memory concurrency. If you are willing to give up shared memory concurrency in C you can achieve exactly the same performance. In fact, you often have the opposite: shared memory concurrency (implemented in languages like C) can often offer performance advantages that actor models like Pony can't provide.
- danappelxx 6y agoBut... give an example. When is shared-memory concurrency (with locks) faster?
- lalaland1125 6y agoOne good example would be writing a multi-threaded dictionary compression program. Dictionary compression is quite simple, you simply need to encode a bunch of strings to a series of integers and construct a dictionary that can perform the inverse mapping. The main trick is that you need a shared mutable dictionary to store the current list of string to integer mappings. Doing this with an actor model would be tricky to the point of impossible. Sending a message to the common "dictionary" actor is much, much, much less efficient than just holding the corresponding sharded lock.
- rurban 6y agoThis is wrong. The biggest advantage of Pony is to support pointers into shared memory and still guarantee all 3 safeties. It just doesn't support blocking IO if you need that. And pointers into shared memory have severe limitations, just as in the real world. But the advantage is that the compiler already guarantees safety.
- AnanasAttack 6y agoYou can totally have memory barriers in macros. It doesn't have much to do with the language at all
- anaphor 6y agoC actually had better support (than C++) for double-checked locking (which is a lockless algorithm) up until relatively recently https://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/ https://preshing.com/20130930/double-checked-locking-is-fixe...
- lalaland1125 6y agoHuh? Both C and C++ only added support for atomics and double-checked locking in the same year: 2011 (C11 for C and C++11 for C++). How did C support double checked locking before C++ when the standards were released contemporaneously?
- deleted 6y ago[deleted]
- jcranmer 6y agoFalse. The C standard had no consideration for thread semantics prior to C11, and C11's memory model is literally and explicitly derived from C++11's memory model (which itself is adapted from Java 5's memory model). All of the discussions about how the memory model semantics for C11 and C++11 actually work take place entirely within the C++ standards committee, as is true for most new C language features these days (with the C committee largely designing merely the spellings of the new features).
- bsder 6y agoPart of the problem is that "Who waits?" or less colloquially "Are you guaranteeing fairness, progress, or performance?" For example, in a network stack, I may want fairness. In that case, all of my packets should get through with equal probability so I want my threads to all make progress even if I lose some maximum bandwidth. However, in an audio stack, my thread feeding the audio hardware had better NEVER block. I don't care how long the threads feeding into it have to wait, but the thread feeding the audio hardware gets priority under ALL conditions and I never want it to have to wait more than a single instruction. Those are VERY different locking scenarios, and you can't automatically differentiate.
- eximius 6y agoThere seems to be confusion about what I'm saying. I'm not saying C can't have recipes for concurrency. I'm saying it can't abstract those recipes well.