October 10, 2013
On 2013-10-10 13:17, Michel Fortin wrote:

> http://michelf.ca/blog/2012/mutex-synchonization-in-d/

I think I like the idea, but won't you have the same problem as Jonathan described? You can't pass these variables to another function that doesn't expect it to be passed a synchronized variable. You can pass it to pure functions which mean you can probably pass it to a couple of more functions compared to using "shared".

-- 
/Jacob Carlborg
October 10, 2013
On 2013-10-10 13:17, Michel Fortin wrote:

> http://michelf.ca/blog/2012/mutex-synchonization-in-d/

This looks similar to what I described here:

http://forum.dlang.org/thread/bsqqfmhgzntryyaqrtky@forum.dlang.org?page=19#post-l35rql:24og2:241:40digitalmars.com

-- 
/Jacob Carlborg
October 10, 2013
On 2013-10-10 13:02:14 +0000, Jacob Carlborg <doob@me.com> said:

> On 2013-10-10 13:17, Michel Fortin wrote:
> 
>> http://michelf.ca/blog/2012/mutex-synchonization-in-d/
> 
> I think I like the idea, but won't you have the same problem as Jonathan described? You can't pass these variables to another function that doesn't expect it to be passed a synchronized variable. You can pass it to pure functions which mean you can probably pass it to a couple of more functions compared to using "shared".

Well, it's one piece of a puzzle. In itself it already is better than having to cast every time. Combined with a way to pass those variables to other functions safely, it should solve practically all the remaining problems that currently require a cast. But I don't have nice a solution for the later problem (short of adding more attributes).

-- 
Michel Fortin
michel.fortin@michelf.ca
http://michelf.ca

October 10, 2013
On 2013-10-10 13:03:37 +0000, Jacob Carlborg <doob@me.com> said:

> On 2013-10-10 13:17, Michel Fortin wrote:
> 
>> http://michelf.ca/blog/2012/mutex-synchonization-in-d/
> 
> This looks similar to what I described here:
> 
> http://forum.dlang.org/thread/bsqqfmhgzntryyaqrtky@forum.dlang.org?page=19#post-l35rql:24og2:241:40digitalmars.com

Somewhat 
> 
similar. I don't think it's a good practice to make a mutex part of the public interface of an object (or any public interface for that matter), which is why they're kept private inside the class in my examples. Public mutexes can be locked from anywhere in your program, they lack encapsulation and this makes them prone to deadlocks.

-- 
Michel Fortin
michel.fortin@michelf.ca
http://michelf.ca

October 10, 2013
On 09/10/13 06:25, Andrei Alexandrescu wrote:
> The way I see it we must devise a robust solution to that, NOT consider the
> state of the art immutable (heh, a pun).

Must say I have had a miserable experience with immutability and any kind of complex data structure, particularly when concurrency is involved.

As a practical fact I've often found it necessary to convert to immutable (not always via a cast or std.conv.to; sometimes via assumeUnique) to pass a complex data structure to a thread, but then to convert _away_ from immutable inside the thread in order for that data (which is never actually mutated) to be practically usable.

I'm sure there are things that I could do better, but I did not find a superior solution that was also performance-friendly.
October 10, 2013
On 10/10/2013 12:51 AM, Jacob Carlborg wrote:
> On 2013-10-10 09:18, Walter Bright wrote:
>
>> 1. Shared data cannot be passed to regular functions.
>
> That I understand.
>
>> 2. Functions that create data structures would have to know in advance
>> that they'll be creating a shared object. I'm not so sure this would not
>> be an invasive change.
>
> If the function doesn't know it creates shared data it will assume it's not and
> it won't use any synchronization. Then suddenly someone casts it to "shared" and
> you're in trouble.

Same comment as for immutable data - create the data structure as thread local, because of (1), and then cast to shared and hand it to another thread.

>
>> 3. Immutable data is implicitly shared. But it is not created immutable
>> - it is created as mutable data, then set to some state, then cast to
>> immutable.
>
> It should be possible to create immutable data in the first place. No cast
> should be required.
>

October 10, 2013
On Oct 9, 2013, at 9:24 PM, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> 
> And given that std.concurrency requires casting to and from shared or immutable in order to pass objects across threads, it seems ilke most of D's concurrency model requires casting to and/or from shared or immutable.

std.concurrency won't be this way forever though.  We could fake move semantics with something like assumeUnique!T, so send could be modified to accept a non-shared class that's marked as Unique.  The other option would be deep copying or serialization.
October 10, 2013
On Oct 9, 2013, at 11:34 PM, Jacob Carlborg <doob@me.com> wrote:

> On 2013-10-10 02:22, Sean Kelly wrote:
> 
>> Only that this would have to be communicated to the user, since moving data later is problematic. Today, I think it's common to construct an object as unshared and then cast it.
> 
> What is the reason to not create it as "shared" in the first place?

The same as immutable--you may not have all the shared functions available to establish the desired state.  But I'll grant that this is obviously way more common with immutable than shared.
October 10, 2013
On Thursday, October 10, 2013 19:23:14 Joseph Rushton Wakeling wrote:
> On 09/10/13 06:25, Andrei Alexandrescu wrote:
> > The way I see it we must devise a robust solution to that, NOT consider
> > the
> > state of the art immutable (heh, a pun).
> 
> Must say I have had a miserable experience with immutability and any kind of complex data structure, particularly when concurrency is involved.
> 
> As a practical fact I've often found it necessary to convert to immutable (not always via a cast or std.conv.to; sometimes via assumeUnique) to pass a complex data structure to a thread, but then to convert _away_ from immutable inside the thread in order for that data (which is never actually mutated) to be practically usable.
> 
> I'm sure there are things that I could do better, but I did not find a superior solution that was also performance-friendly.

std.concurrency's design basically requires that you cast objects to shared or immutable in order to pass them across threads (and using assumeUnique is still doing the cast, just internally). And then you have to cast them back to thread-local mutable on the other side to complete the pass and make the object useable again. There's really no way around that at this point, not without completely redesigning shared. Arguably, it's better to use shared when doing that rather than immutable, but at least in the past, shared hasn't worked right with std.concurrency even though it's supposed to (though that's an implementation issue rather than a design one, and it might be fixed by now - I haven't tried recently). And whether you're using shared or immutable, you're still having to cast.

I'm honestly surprised that Andrei is rejecting the idea of casting to/from shared or immutable being normal given how it's required by our current concurrency model. And changing that would be a _big_ change.

- Jonathan M Davis
October 10, 2013
On Oct 10, 2013, at 4:17 AM, Michel Fortin <michel.fortin@michelf.ca> wrote:

> On 2013-10-10 06:41:19 +0000, Jacob Carlborg <doob@me.com> said:
> 
>> On 2013-10-10 06:24, Jonathan M Davis wrote:
>>> So, it's my impression that being able to consider casting to or from shared as abnormal in code which uses shared is a bit of a pipe dream at this point. The current language design pretty much requires casting when doing much of anything with concurrency.
>> There must be a better way to solve this.
> 
> http://michelf.ca/blog/2012/mutex-synchonization-in-d/

Good article.  But why didn't you mention core.sync?  It has both a Mutex and a ReadWriteMutex (ie. shared_mutex).