The article's "soft" pointer does not own its contents and depends on an owning pointer, so the semantics are much closer to Rust's references. In fact, the article draws an analogy between soft pointers and weak_ptr. And of course dereferencing "soft" pointers can fault.
> Whether C++ or Rust or whatever-else, mutexes at app-level are evil ;-) (it can lead to a very long discussion, but long story short - finally, by 2017, most of the opinion leaders started to converge to this IMO-very-obvious observation: ASYNC RULEZZ! <wink />).
Async does jack shit for concurrent safety. You can have either shared-memory concurrency or isolated concurrency.
And explicit asynchronous API (à la JS or C#) are dreadful.
Not really; I see Rust references (enforced in compile-time) ~= OP's "naked pointers" with limitations on scope. 'soft pointer' is an alternative to long-living pointers (can be replaced with a refcounted ptr a-la RC<T>, but TBH I don't like refcounted stuff for several reasons).
> You can have either shared-memory concurrency
You can, but it doesn't work, suffering from all kinds of problems (from being _crazily_ error-prone, via being _fundamentally untestable_!, and all the way to being fundamentally unscalable, and sucking Big Time performance-wise - the last one unless we're speaking about RCU etc., but probably we aren't).
> And explicit asynchronous API (à la JS or C#) are dreadful.
Did you see C#'s await? And BTW, as practice shows, synchronous alternatives are MUCH more dreadful than even OO-style async handling (fundamental non-testability of shared-memory stuff, even if taken alone, is already enough to rule shared-memory stuff out for good - which BTW is already happening; there is a Really Good Reason for Go's philosophy of "share memory by communicating, not communicating by sharing memory").
Sure doesn't, I mean it's only the vast majority of concurrent systems which are built on shared-memory concurrency.
> Did you see C#'s await?
Yes, it sucks. Also, it's shared-memory concurrency.
> synchronous alternatives are MUCH more dreadful than even OO-style async handling (fundamental non-testability of shared-memory stuff, even if taken alone, is already enough to rule shared-memory stuff out for good
Async does not make things more testable.
> BTW is already happening; there is a Really Good Reason for Go's philosophy of "share memory by communicating, not communicating by sharing memory").
Go only pays lip service to that, Go is shared-memory concurrency to and through, it barely allows and doesn't enforce shared-nothing concurrency.
Shared-nothing concurrency definitely is already happening. In unices (where processes are historically the standard unit of concurrency) or Erlang (where you can't share memory) or Clojure or Haskell (where you do share memory but almost everything is immutable).
...which doesn't mean they work (~="they pretend to work, but happen to fail much more often than they should"). Just one example - one system which has 50% of one multi-billion-dollar industry and was built as shared-nothing concurrency (not Clojure or Erlang FWIW), has 5x lower downtimes that industry average; and I don't even remember how many times I've run into all kinds of shared-memory bugs in standard! libraries (my first article on such bugs was back in 1998, the last one was about a standard proposal made in 2015 IIRC); and so on and so forth.
>> Did you see C#'s await? > Also, it's shared-memory concurrency.
Nope; await (and C++ co_await BTW too) is single-threaded concurrency (nothing is shared between threads, and overall the concept is close to fibers with a bit more intuitive semantics), which makes it an extremely good building block to build a shared-nothing concurrency (the one which doesn't suffer from all the troubles of shared-memory one).
> Go only pays lip service to that, Go is shared-memory concurrency
You're somewhat right, but actually there are two different things there - one is language as such (and indeed, goroutines are shared-memory :-( ); however, Go "best practices" effectively say "don't use it", and LOTS of ppl from different projects were telling me that they do work in shared-nothing way (enforcing it is a different story though <sigh />).
> Shared-nothing concurrency definitely is already happening.
...in particular, with Node.js (which is ugly but still better than synchronized nightmare), C# await, and C++ co_await. As I told in one of my presentations (I think it was the CPPCON one on "8 different ways to do non-blocking"): you don't need to use Erlang to have reasonably-good concurrency :-). Overall, this sync-vs-async question is rather orthogonal to the programming language (heck, out of those 8 ways - which are largely equivalent to each other differing only in syntactic sugar - at least 2 will work even in asm).
> Async does not make things more testable.
It does - and very strictly too. Very briefly, async can be made reproducible, and whatever-is-reproducible, can be made testable; OTOH, making a non-trivial shared-memory program reproducible is next to impossible in any realistic environment (reproducibility ~= determinism, and thread context switches are non-deterministic at least for our purposes; heck, even VM guys weren't able to make them deterministic - which got lots of interesting implications which won't fit here). For discussion on determinism and testability - see my other presentation (ACCU 2017 one, on deterministic distributed systems or something).
"Volta and Cuda C++" - http://cppcast.com/2017/09/olivier-giroux/
CppCon 2017: Olivier Giroux "Designing (New) C++ Hardware”
I'd argue that use cases for 'soft pointers' are about the same as that of Rust's RC<T>, which also incurs runtime costs (very briefly - there is no magic here, neither with Rust).
> The key idea and massive difference from standard C++ is that object destruction is delayed until a "quiescient state" happens
If you're speaking about OP - clarification: it is not "object destruction" which is delayed (destructor is still called synchronously when the variable goes out of scope, so all the crazy finalize()-like problems don't occur), it is memory deallocation which is delayed (and this is generally ok as deallocation is not observable, or at least garbage-collected languages tell us so <wink />).
> things like mutexes can only be safe
Whether C++ or Rust or whatever-else, mutexes at app-level are evil ;-) (it can lead to a very long discussion, but long story short - finally, by 2017, most of the opinion leaders started to converge to this IMO-very-obvious observation: ASYNC RULEZZ! <wink />).
> since that allows to statically check for correctness,
The idea behind OP is to have a tool which will do the same thing (where possible, see above re. 'soft pointers' and RC<T>). Whether such a tool materializes - is a different story, but well - first we have to agree that such a tool is a Good Thing(tm).
> have to delay freeing memory
In practice, it is never an observable problem in (Re)Actor-like contexts ((Re)Actor use cases are about highly interactive systems ranging from games to stock exchanges, where typical input is processed in milliseconds, and amount of allocated memory until the 'quiescient state' is reached, is single-digit kilos; in extreme cases, it goes up to single-digit megabytes, still nothing by modern standards).
> you are much better off using Rust
Really really depends. It is still C++, and being C++ has its own virtues (alongside with its own quirks); just two things to illustrate this point - (i) recently it was revealed that modern GPUs are designed with ISO C++ standard in mind (specifically C++, not Rust or anything else); (ii) developer availability is also a major factor for real-world projects, and so on, and so forth. In an ideal world - well, probably Rust does look as a more to-the-point language (though even with Rust I'd create an own dialect, in particular, outlawing thread sync to simplify things), but given real-world considerations - the choice is certainly not that black-and-white.