shared - i need it to be useful
Manu
turkeyman at gmail.com
Fri Oct 19 00:54:45 UTC 2018
On Thu, Oct 18, 2018 at 3:40 PM Steven Schveighoffer via Digitalmars-d
<digitalmars-d at puremagic.com> wrote:
>
> On 10/18/18 5:22 PM, Manu wrote:
> > On Thu, Oct 18, 2018 at 12:15 PM Steven Schveighoffer via
> > Digitalmars-d <digitalmars-d at puremagic.com> wrote:
> >>
> >> On 10/18/18 2:55 PM, Manu wrote:
> >>> On Thu, Oct 18, 2018 at 7:20 AM Steven Schveighoffer via Digitalmars-d
> >>> <digitalmars-d at puremagic.com> wrote:
> >>>>
> >>>> On 10/18/18 10:11 AM, Simen Kjærås wrote:
> >>>>> On Thursday, 18 October 2018 at 13:35:22 UTC, Steven Schveighoffer wrote:
> >>>>>> struct ThreadSafe
> >>>>>> {
> >>>>>> private int x;
> >>>>>> void increment()
> >>>>>> {
> >>>>>> ++x; // I know this is not shared, so no reason to use atomics
> >>>>>> }
> >>>>>> void increment() shared
> >>>>>> {
> >>>>>> atomicIncrement(&x); // use atomics, to avoid races
> >>>>>> }
> >>>>>> }
> >>>>>
> >>>>> But this isn't thread-safe, for the exact reasons described elsewhere in
> >>>>> this thread (and in fact, incorrectly leveled at Manu's proposal).
> >>>>> Someone could write this code:
> >>>>>
> >>>>> void foo() {
> >>>>> ThreadSafe* a = new ThreadSafe();
> >>>>> shareAllOver(a);
> >>>>
> >>>> Error: cannot call function shareAllOver(shared(ThreadSafe) *) with type
> >>>> ThreadSafe *
> >>>
> >>> And here you expect a user to perform an unsafe-cast (which they may
> >>> not understand), and we have no language semantics to enforce the
> >>> transfer of ownership. How do you assure that the user yields the
> >>> thread-local instance?
> >>
> >> No, I expect them to do:
> >>
> >> auto a = new shared(ThreadSafe)();
> >
> > I don't have any use for this design in my application.
> > I can't use the model you prescribe, at all.
>
> Huh? This is the same thing you are asking for. How were you intending
> to make a thread-safe thing sharable? Surely it will be typed as shared,
> right? How else will you pass it to multiple threads?
Things get promoted to shared and distributed on occasion, but there
is only one owner, and he's the only guy with thread-local access.
> >>> I think requiring the cast is un-principled in every way that D values.
> >>
> >> No cast is required. If you have shared data, it's shared. If you have
> >> thread local data, it's unshared. Allocate the data the way you expect
> >> to use it.
> >
> > All data is thread-local, and occasionally becomes shared during periods.
> > I can't make use of the model you describe.
>
> If data is shared, it is shared. Once it is shared, it never goes back.
I'm suggesting that; data *may be shared* (ie, has valid threadsafe
interaction), or it may not (has no access).
NOT that data "is shared", or "is not". I don't see value in that
proposition. I don't know how to make that useful to me. It's
impossible for me to interact with that model safely.
The ONLY way to interact with that model safely is to allocate objects
shared, or not... there is no safe transition, and I am totally
concerned with the transition.
> In your model, everything is *assumed* shared, so that's what you need
> to do, initialize it as shared. It still works just as you like. Even if
> you never actually share it, or share it periodically.
You can't do that... cus you can't call anything's unshared methods.
> > My proposal is more permissive, and allows a wider range of
> > application designs. What are the disadvantages?
>
> The opposite is true. More designs are allowed by restricting casting as
> I have demonstrated many times.
No you haven't.
What design is enabled by it that is inhibited by my design? I can't see this...
Your demonstrated design if fundamentally unsafe, unless you
*allocate* things as shared, and accept that no transition is
possible.
This is not a flexible design. My design also allows that if that's
what you want. Under my proposal, you can equally allocate things
shared to the exact same effect; I haven't taken anything away.
> >> It's only if you intend to turn unshared data into shared data where you
> >> need an unsafe cast.
> >
> > It's unnecessary though, because threadsafe functions are threadsafe!
> > You're pointlessly forcing un-safety. Why would I prefer a design that
> > forces unsafe interactions to perform safe operations?
>
> No unsafe interactions are required for a type that defensively is
> shared. Just make it always shared, and you don't have any problems.
Then you completely lose access to the unshared API. This is not workable.
> >> It's not even as difficult as immutable, because you can still modify
> >> shared data. For instance, the shared constructor doesn't have to have
> >> special rules about initialization, it can just assume shared from the
> >> beginning.
> >
> > Your design us immutable, mine is const.
>
> No, your design is not const, const works on normal types. It's
> applicable to anything.
But... that's the same here.
const restricts you to calling const methods... shared restricts you
to calling shared methods.
> > Tell me, how many occurrences of 'immutable' can you find in your
> > software? ... how about const?
>
> I generally use inout whenever possible, or const when that is more
> appropriate. But that is for methods.
>
> For data, I generally use immutable when I want a constant.
You're dodging the question... I think you know that nothing can work
without const, but we could live without immutable.
Certainly, immutable wouldn't work without const!
The exact same connundrum applies here. Imagine that we only had
immutable, and any time you wanted to call a const method, you had to
cast to immutable...
> But like I said, something can't be both shared and unshared. So having
> shared pointers point at unshared data makes no sense -- once it's
> shared, it's shared. So shared really can't be akin to const.
Yes, but I'm saying the mutually-exclusive state isn't useful. No
transition is possible, and necessitates unsafety to do anything (that
I want to do).
I'm trying to create a world where the mutual-exclusion is effected in
practise (can define and perform threadsafe interaction), but not in
strict terms, such that transition is impossible... I'm very carefully
designing a solution where the worlds aren't isolated, and that world
is 100% more useful to me and my entire ecosystem.
I don't know how to use shared safely if it's not designed that way,
just like I don't know how to generally use immutable in lieu of
const. immutable wouldn't be practical without const.
> > Which is more universally useful? If you had to choose one or the
> > other, which one could you live without?
>
> I would hate to have a const where you couldn't read the data, I
> probably would rather have immutable.
If an object has no const methods, you can't do anything with it. The
usefulness of const depends on people recognising and support const.
> I said I would stop commenting on this thread, and I didn't keep that
> promise. I really am going to stop now. I'm pretty sure Walter will not
> agree with this mechanism, so until you convince him, I don't really
> need to be spending time on this.
>
> We seem to be completely understanding each others mechanisms, but not
> agreeing which one is correct, based on (from both sides) hypothetical
> types and usages.
I'm still not at all clear on how I'm excluding any interesting use
cases... I have deliberately tried to preserve all the valuable use
cases I'm aware of.
I don't understand your perspective, because I don't understand your
sense of loss.
More information about the Digitalmars-d
mailing list