Here, only one data member is meant to be serialized. The others members are there to accelerate lookups into the first data member. (Full disclosure: that structure isn't actually serialized yet, but the Arc80 Engine which uses Plywood has similar examples.)
The biggest advantage I find with runtime reflection it that it's possible to load and manipulate data that has no C++ definition at all. This is actually handy when working with 3D geometry consumed by a GPU.
Perhaps, but it's easily overlooked because every project that needs runtime reflection badly enough has already rolled their own. (Some game engines have multiple reflection systems, eg. shader parameters vs. serialization.) This framework takes a particular approach and makes it an (almost) standalone component.
This might come true some day, but it seems not in C++20 and in recent static reflection proposals there was no way to distinguish reflected from non-reflected members in the same class.
It's the latter: A standalone framework that can be used by other projects. It's like a library (or suite of libraries) with separate modules for platform abstraction, containers, JSON, etc. A bit more "batteries included" than vanilla C++, and you only link with what you use. These modules are organized into a workspace that helps set up new build pipelines, to compensate for the lack of a standard build system in C++.
I think you might be right. Maybe I should edit the post and not call it "more scalable", since I only have six cores to test on. But if it does top out at a higher core count, there are several ways it could be optimized.
Either way, Junction is BSD-licensed while TBB is GPL/$, so I hope it'll find a use somewhere.
> you've moved the fast path of the semaphore implementation into user space.
I see now why your original comment was a bit inflammatory. I should have been more clear in the post that by "lightweight", I meant exactly that: "fast path in user space". I guess not everyone shares this vocabulary. I'll improve the post.
You're right that this lightweight mutex is a semaphore, of course. But not every semaphore is a lightweight mutex. So the technique isn't pointless.
If I implement the mutex as you suggest -- by using the native semaphore directly, with no separate counter -- the running time of "testBenaphore" increases from 375 ms to 3 seconds on my Windows PC.
As mentioned in the article, most mutex implementations already use this trick. So you can just use std::mutex, and things are fine.
> It may just be poor wording, but I don't think this sentence makes sense
I can see how you could might have interpreted that sentence differently. I just tweaked it a little in the post, mainly changing "the sample" to "this sample". Hopefully it's precise enough for most now.
There's no contradiction. Normally, the x86/64 memory model is quite strong, preserving LoadLoad, LoadStore, and StoreStore ordering. But doesn't preserve StoreLoad ordering; eg. stores can be reordered after loads, as you point out. As I understand it, that's mainly because there's a limit to how quickly each store can be seen by other processors.
Based on your comment, I should probably be more precise and say: "the possibility of 'locking up' the entire application in some way". I'll update the post. There's nothing about this definition that prohibits a single thread from starving.
I totally agree with you about the dangers of lock-free programming, and that every programmer will certainly make mistakes. I feel strongly enough about it that I actually wrote several paragraphs about the importance of stress testing lock-free algorithms, which I eventually decided to break off into a separate post... I might get around to publishing that, we'll see. We're not the first to feel this way :)
It's true, and I had a hard time reconciling that Wikipedia page with how others had been describing lock-free programming, which is why I spent so much of the post on semantics.
> One benefit of load-linked/store-conditional (often abbreviated LL/SC) is that it avoids the ABA problem
Good point. Though I suspect if you access other cache lines between the LL & SC, it may invalidate the reservation.
> I don't think this is true about x86/64.
It is true about x86/64, at least for the most common, non-SSE instructions and normal, non-write-combined memory. I'll update the post to be more specific. See volume 3, section 8.2.2 of the Intel 64 and IA-32 Developer's Manuals: (http://www.intel.com/content/www/us/en/processors/architectu...)
- Reads are not reordered with other reads.
- Writes are not reordered with older reads.
- Writes to memory are not reordered with other writes (with a few exceptions for special instructions)
Actually, I thought it was pretty clear in the article that it's not ok to use locks (mutexes) under the definition given. I tried pretty hard to use the most widely accepted definition of lock-free, even exchanging e-mails with Maurice Herlihy about it.
Actually, it's not because the PPU executes in-order, which has only to do with the way the CPU orders instructions internally and says nothing about memory ordering. For example, the Xbox 360 has in-order processors too, yet you can observe memory reordering all over the place. Both consoles use the PowerPC architecture, which is well-known to provide weak memory ordering.
Here, only one data member is meant to be serialized. The others members are there to accelerate lookups into the first data member. (Full disclosure: that structure isn't actually serialized yet, but the Arc80 Engine which uses Plywood has similar examples.)