Shared

2010-08-01 Thread dsimcha
I've reread the relevant TDPL chapter and I still don't quite understand the
following:

1.  What is shared?  Is it simply a piece of syntactic salt to make it hard to
share data across threads by accident, or is there more to it?

2.  Is it fully or mostly implemented?


Shared Hell

2009-10-27 Thread Denis Koroskin
I've recently updated to DMD2.035 (from DMD2.031 because all the later  
versions had issues with imports) and for the first time faced problems  
with shared modifier.


I don't need shared and all my globals are __gshared (they are globally  
unique instances that don't need per-thread copies).


Yet some of methods of the class hierarchy (a root singleton class and  
everything which is accessible through it) are synchronized (well, you  
know why). That's where the problems begin.


Marking a method as synchronized automatically makes it shared (more or  
less obvious). And marking the method shared makes it unable to invoke  
with non-shared instance (and __gshared != shared), meaning that I'm  
unable to use my __gshared variables anymore, making this attribute  
useless for any serious safe programming.


So I started with replacing __gshared with shared and quickly understood  
how viral it is. Not only you mast mark all the members shared (methods  
and field), instantiate classes with shared attribute, you also have to  
create a duplicate all the methods to make them accessible with both  
shared and non-shared (thread-local) instances:


class Array(T)
{
const(T) opIndex(uint index) const
{
return data[index];
}

T opIndex(uint index)
{
return data[index];
}

const(T) opIndex(uint index) shared const
{
return data[index];
}

shared(T) opIndex(uint index) shared
{
return data[index];
}

private T[] data;
}

And that's just opIndex. Ooops...

But not only that, every interface now have to specify the same method  
twice, too:


interface Target
{
bool build();
bool build() shared;
void clean();
void clean() shared;
bool ready();
bool ready() shared;
void setBuildListener(BuildListener buildListener);
    void setBuildListener(shared BuildListener buildListener) shared;
}

That's a bit frustrating. Most importantly, I don't even need shared  
(__gshared was more than enough for me), yet I'm imposed on using it.


Oh, I can't use any of the druntime/Phobos classes (e.g. create an  
instance of shared(Thread)), because none of them are shared-aware.


I think the design needs to be given a second thought before the plane  
takes off because I'm afraid it may painfully crash.


shared library

2010-03-05 Thread Igor Lesik
I was able to build D runtime shared library (.so). The test app dies with 
segmentation fault, I am debugging it; decided to share.

To reproduce my results one can load makefile from here:
http://www.curoles.com/j/dso/so.mak
(drop it into the runtime directory and call make -f so.mak)

The problem happens in main() (defined in src/rt/dmain2.d) when first time a 
library function is called.
The PLT entry look good, but jump to GOT seems to be wrong. I expect to see 
address of got.plt section
(readelf -S ./test), instead the address for indirect jump is taken from 
some stack variable, the address
is invalid and segmentation fault happens.

I have written some notes here (gdb session):
http://www.curoles.com/j/dso/dso.html

Igor





Shared Memory

2009-04-16 Thread sesteel
I just wanted to float an idea out there.  I have been using technologies such 
as Terracotta and Memcache at work.  Terracotta, has left me wondering about 
the applicability of integrating shared objects (memory) directly into a 
programming language.  Is this anything anybody else here has thought of?  
Additionally, I was thinking about the concept of services vs libraries, and 
how shared objects might be a way to provide fast IPC while getting rid of the 
library concept.  Thus, each service would have it's own memory space to manage 
and GC.  One hinderence would be the versioning of the shared object, but if 
that object could be viewed through an interface...   

Just brainstorming. 


Re: Shared

2010-08-01 Thread dsimcha
== Quote from dsimcha (dsim...@yahoo.com)'s article
> I've reread the relevant TDPL chapter and I still don't quite understand the
> following:
> 1.  What is shared?  Is it simply a piece of syntactic salt to make it hard to
> share data across threads by accident, or is there more to it?
> 2.  Is it fully or mostly implemented?

Sorry, accidentally submitted the post before I was done.

3.  How does casting to and from shared work?  Under what circumstances can
unshared data be cast to shared?  Under what circumstances can shared data
implicitly be cast to unshared?


Re: Shared

2010-08-02 Thread Graham St Jack

On 02/08/10 02:16, dsimcha wrote:

== Quote from dsimcha (dsim...@yahoo.com)'s article
   

I've reread the relevant TDPL chapter and I still don't quite understand the
following:
1.  What is shared?  Is it simply a piece of syntactic salt to make it hard to
share data across threads by accident, or is there more to it?
2.  Is it fully or mostly implemented?
 

Sorry, accidentally submitted the post before I was done.

3.  How does casting to and from shared work?  Under what circumstances can
unshared data be cast to shared?  Under what circumstances can shared data
implicitly be cast to unshared?
   


I too have had a lot of trouble using shared, but I am currently giving 
it another serious try.


My observations so far are that the compiler's handling of it is a bit 
buggy, but that it seems to more-or-less work, and will be usable when 
the necessary library code is updated to use it - specifically Mutex, 
Condition and concurrency's Mailbox.


You are not supposed to need to routinely cast to-and-from shared. Value 
and immutable types should implicitly convert to/from shared, and 
synchronized types should implicitly convert to shared. So for example, 
a string is ok because it is a value and a pointer to immutable data.


I have found the following approach to work ok:

import std.stdio;
import std.traits;
import std.conv;


synchronized class Channel(T) if (!hasAliasing!T)
{
void add(T t) { }
}

alias Channel!string MyChannel1;
alias shared MyChannel1 MyChannel;

void main() {
auto channel = new MyChannel();

channel.add("hello");
}


The key trick for me was to use an alias to wrap the shared up with the 
data type. For some reason the compiler didn't like it when I used a 
templated type, but the second layer of aliases placated it - hopefully 
that is a bug that will be fixed soon.


I hope that helps.

--
Graham St Jack



Re: Shared

2010-08-02 Thread Steven Schveighoffer

On Sun, 01 Aug 2010 12:46:58 -0400, dsimcha  wrote:


== Quote from dsimcha (dsim...@yahoo.com)'s article
I've reread the relevant TDPL chapter and I still don't quite  
understand the

following:
1.  What is shared?  Is it simply a piece of syntactic salt to make it  
hard to

share data across threads by accident, or is there more to it?
2.  Is it fully or mostly implemented?


Sorry, accidentally submitted the post before I was done.

3.  How does casting to and from shared work?  Under what circumstances  
can
unshared data be cast to shared?  Under what circumstances can shared  
data

implicitly be cast to unshared?


Let me preface this by saying I don't actually use shared on a daily  
basis, but I'll try and respond how I think it works:


1. It indicates to the compiler that multiple threads have direct access  
to the data.  But more importantly, the *lack* of shared means that  
exactly one thread has direct access to the data.  I see shared not as  
great a feature as unshared is.  For an example of optimizations that can  
be had with unshared data, see the LRU cache for lock-free array appending.


I think in terms of technical details, reading from/writing to a shared  
piece of data requires either a lock, or the compiler will insert a memory  
barrier around the write to ensure the write is atomic as long as the data  
written is small enough (I'm very fuzzy on these details, I use the term  
memory barrier in complete ignorance).  Declaring a global variable shared  
also makes it a true global (not thread-local).  I don't know what was  
decided on for shared classes/structs, I vaguely remember that the  
consensus was to require declaring the entire class shared at class  
definition, but I could be wrong.


2. I do not think it's fully implemented, but I think the intention is  
that it's fully implemented, so submit bugs against what it doesn't do if  
you find any.


3. *NO* implicit casting of shared<->unshared is allowed for references.   
To do so would violate the shared transitivity.  It is ok to copy  
value-types to/from shared.  Think of the relationship between unshared  
and shared in the same way as the relationship between mutable and  
immutable.


I think you can cast shared to unshared if you *know* that no other thread  
will be able to access the data pointed at by the shared value.  For  
instance, you can never take a reference to a shared global and cast that  
reference to unshared, because globals are always available to all threads.


You can cast unshared to shared if you know that you have no other  
unshared references to the same data in your local thread.  This one can  
be much easier to prove.


Neither cast is statically checked or verified, it's up to you as the  
programmer to ensure these properties.


-Steve


Shared pain

2010-11-18 Thread Steve Teale
I had D code that provided a basis for creation of Windows services, 
which I have just tried to get working with the latest D2.

No dice.

The point of failure was in this method

static void StartService()
{
   if (!StartServiceCtrlDispatcherA(cast(SERVICE_TABLE_ENTRY *) &_sta[0]))
   {
  ...
   }
}

Where _sta is an array of SERVICE_TABLE_ENTRY structs. The bits of code 
that install and remove the service worked fine, but the service control 
dispatcher was clearly not happy about these structs being in TLS, and 
the service crashed immediately when I tried to start it.

The class also has a couple of methods with signatures like:

extern (Windows) static export void service_ctrl(uint dwCtrlCode) {...}

That's probably not relevant, but I think it contributed to a host of 
errors that finally made be take a big step back.

I re-implemented the thing in the style used for OOP in C.

struct ServiceBase
{
   SERVICE_TABLE_ENTRY[2] _sta;
   ...
}

__gshared ServiceBase __sb;

void initialize(ServiceBase* sb) { ... }
void whatever(ServiceBase* sb ...) { ... }

and used the __sb global within the functions with the Windows signature, 
which just became

extern (Windows) export void service_ctrl(uint dwCtrlCode) {...}

Now it's working again, but I want to change it into idiomatically sound 
D code.

Style suggestions please!

Steve


Migrating to Shared

2009-05-12 Thread Walter Bright

I wrote a brief article which should help:

http://www.digitalmars.com/d/2.0/migrate-to-shared.html


Semantics of shared

2009-05-13 Thread Matt
[from reddit]

There was just a post to reddit announcing that thread local storage would be 
the default for global variables and that the 'shared' qualifier would make 
this happen.   What I can't find is a description of typing rules surrounding 
'shared'.   From the discussion at reddit, it sounded like 'shared' was 
intended to mean 'possibly shared', with the implication that thread local 
objects can be treated as 'possibly shared'.  

The problem I see with this is that it implies that it is not safe to assign 
one shared reference to another, because the former may actually be thread 
local while the latter is actually global.  This would seem to make the "maybe 
shared" concept pretty useless.  Is this not a problem?   Or if not, can 
someone clarify to me what the actual semantics & typing rules are?

Thanks,
Matt






shared class constructor

2009-08-13 Thread Jeremie Pelletier
Just came across this while porting my code to enforce the use of shared.

---
module test;
shared class Foo {
   this() {}
}
---
Error: cannot implicitly convert expression (this) of type shared(Foo) to 
test.Foo

Of course I could just use new shared(Foo) but that would allow non-shared 
instances of Foo to be created as well, which I do not want.

Shouldn't "this" resolve to the fully qualified class?


Re: Shared Hell

2009-10-28 Thread #ponce
Denis Koroskin Wrote:

> I've recently updated to DMD2.035 (from DMD2.031 because all the later  
> versions had issues with imports) and for the first time faced problems  
> with shared modifier.
> 
> I don't need shared and all my globals are __gshared (they are globally  
> unique instances that don't need per-thread copies).
> 
> Yet some of methods of the class hierarchy (a root singleton class and  
> everything which is accessible through it) are synchronized (well, you  
> know why). That's where the problems begin.
> 
> Marking a method as synchronized automatically makes it shared (more or  
> less obvious). And marking the method shared makes it unable to invoke  
> with non-shared instance (and __gshared != shared), meaning that I'm  
> unable to use my __gshared variables anymore, making this attribute  
> useless for any serious safe programming.
> 
> So I started with replacing __gshared with shared and quickly understood  
> how viral it is. Not only you mast mark all the members shared (methods  
> and field), instantiate classes with shared attribute, you also have to  
> create a duplicate all the methods to make them accessible with both  
> shared and non-shared (thread-local) instances:
> 
> class Array(T)
> {
>  const(T) opIndex(uint index) const
>  {
>  return data[index];
>  }
> 
>  T opIndex(uint index)
>  {
>  return data[index];
>  }
> 
>  const(T) opIndex(uint index) shared const
>  {
>  return data[index];
>  }
> 
>  shared(T) opIndex(uint index) shared
>  {
>  return data[index];
>  }
> 
>  private T[] data;
> }
> 
> And that's just opIndex. Ooops...
> 
> But not only that, every interface now have to specify the same method  
> twice, too:
> 
> interface Target
> {
>  bool build();
>  bool build() shared;
>  void clean();
>  void clean() shared;
>  bool ready();
>  bool ready() shared;
>  void setBuildListener(BuildListener buildListener);
>  void setBuildListener(shared BuildListener buildListener) shared;
> }
> 
> That's a bit frustrating. Most importantly, I don't even need shared  
> (__gshared was more than enough for me), yet I'm imposed on using it.
> 
> Oh, I can't use any of the druntime/Phobos classes (e.g. create an  
> instance of shared(Thread)), because none of them are shared-aware.
> 
> I think the design needs to be given a second thought before the plane  
> takes off because I'm afraid it may painfully crash.

Wow.
I certainly won't switch to D2 if every getter must be written 4 times (and 4 
times more with immutable(T) ?).

I don't even understand the fundamental difference between __gshared 
and shared : is this only transitivity ?




Re: Shared Hell

2009-10-28 Thread Walter Bright

Denis Koroskin wrote:
I've recently updated to DMD2.035 (from DMD2.031 because all the later 
versions had issues with imports) and for the first time faced problems 
with shared modifier.


I don't need shared and all my globals are __gshared (they are globally 
unique instances that don't need per-thread copies).


I don't understand. Are you running multiple threads? Are those threads 
accessing globals?


A function that accesses shared data has to put in fences. There's no 
way to have the same code deal with shared and unshared code.


As an escape from the type system, you can always cast away the 
shared-ness. But I wonder about code that both uses global variables 
shared across threads that don't need synchronization?


Re: Shared Hell

2009-10-28 Thread Christopher Wright

Denis Koroskin wrote:
I've recently updated to DMD2.035 (from DMD2.031 because all the later 
versions had issues with imports) and for the first time faced problems 
with shared modifier.


I don't need shared and all my globals are __gshared (they are globally 
unique instances that don't need per-thread copies).


Yet some of methods of the class hierarchy (a root singleton class and 
everything which is accessible through it) are synchronized (well, you 
know why). That's where the problems begin.


Marking a method as synchronized automatically makes it shared (more or 
less obvious). And marking the method shared makes it unable to invoke 
with non-shared instance (and __gshared != shared), meaning that I'm 
unable to use my __gshared variables anymore, making this attribute 
useless for any serious safe programming.


So I started with replacing __gshared with shared and quickly understood 
how viral it is. Not only you mast mark all the members shared (methods 
and field), instantiate classes with shared attribute, you also have to 
create a duplicate all the methods to make them accessible with both 
shared and non-shared (thread-local) instances:


Why can't you use a non-shared method on a shared object? The compiler 
could insert locking on the caller side.


Why can't you use a shared method on a non-shared object? The compiler 
could, as an optimization, duplicate the method, minus the 
synchronization. Or it could leave in the locking, which is expensive 
but correct.


Re: Shared Hell

2009-10-28 Thread Christopher Wright

Walter Bright wrote:

Denis Koroskin wrote:
I've recently updated to DMD2.035 (from DMD2.031 because all the later 
versions had issues with imports) and for the first time faced 
problems with shared modifier.


I don't need shared and all my globals are __gshared (they are 
globally unique instances that don't need per-thread copies).


I don't understand. Are you running multiple threads? Are those threads 
accessing globals?


A function that accesses shared data has to put in fences. There's no 
way to have the same code deal with shared and unshared code.


Acquiring a lock on a non-shared instance is safe, just an unnecessary 
expense. I would have looked into optimizing this expense away rather 
than punting the problem to the programmer.


As an escape from the type system, you can always cast away the 
shared-ness. But I wonder about code that both uses global variables 
shared across threads that don't need synchronization?


Maybe the methods are mostly inherently threadsafe. Only a small portion 
requires locking, so it's more efficient to handle it manually.


Re: Shared Hell

2009-10-28 Thread Denis Koroskin
On Wed, 28 Oct 2009 13:17:43 +0300, Walter Bright  
 wrote:



Denis Koroskin wrote:
I've recently updated to DMD2.035 (from DMD2.031 because all the later  
versions had issues with imports) and for the first time faced problems  
with shared modifier.
 I don't need shared and all my globals are __gshared (they are  
globally unique instances that don't need per-thread copies).


I don't understand. Are you running multiple threads? Are those threads  
accessing globals?




Yes.

A function that accesses shared data has to put in fences. There's no  
way to have the same code deal with shared and unshared code.




That's frustrating. I'd like to use the same class for both cases.

But I wonder about code that both uses global variables shared across  
threads that don't need synchronization?


You missed the point. I do the synchronization myself and I'm fine with  
switching to shared (I do believe it is a nice concept). The reason I use  
__gshared is because shared object were garbage-collected while still  
being in use a few versions of DMD back and I had no choice but to switch  
to __gshared. I hope it is fixed by now.


But I still can't make my data shared, since shared is transitive (viral).  
After a few hours or work I still can't even compile my code.


As an escape from the type system, you can always cast away the  
shared-ness.


That's the only way I have now. Casts from shared to unshared *everywhere*:

class BuildManager : BuildListener
{
synchronized void build(shared Target target)
{
// ...

_buildingThread = new shared(Thread)(&_startBuild); // creating a  
new shared Thread. Yes, shared Thread, because BuildManager is global.


//_buildingThread.start(); // Error: function  
core.thread.Thread.start () is not callable using argument types () shared
(cast(Thread)_buildingThread).start(); // works, but ugly, and I  
don't have a reason to hijack the type system in this case


// ...
}
}

Andrei would suggest a Shared!(T) template that would wrap an unshared  
type and make all methods shared. This would work, but requires full AST  
manipulation capabilities (it's clearly not enough to just mark all the  
members shared). What should we do until then?


Re: Shared Hell

2009-10-28 Thread Jason House
Denis Koroskin Wrote:

> I've recently updated to DMD2.035 (from DMD2.031 because all the later  
> versions had issues with imports) and for the first time faced problems  
> with shared modifier.

A quick trip over to bugzilla is all you need to see that shared is completely 
broken. Here's what I see as basic functionality that is broken: 3035, 3089, 
3090, 3091, 3102, 3349.

Half of those are bugs I created within an hour of trying to use shared for 
real. I also have a bug in druntime as well, but Batosz's rewrite should 
address that issue. Interestingly, even though I reported that bug long ago, it 
still bit me. It was the source of a segfault that took me 3 months to track 
down (mostly due to an inability to use gdb until recently).

My code is littered with places that cast away shared since it was so utterly 
unusable when I tried. I'm still waiting for basic bugs to be closed before I 
try again. 


Re: Shared Hell

2009-10-28 Thread Jason House
Christopher Wright Wrote:

> Denis Koroskin wrote:
> > I've recently updated to DMD2.035 (from DMD2.031 because all the later 
> > versions had issues with imports) and for the first time faced problems 
> > with shared modifier.
> > 
> > I don't need shared and all my globals are __gshared (they are globally 
> > unique instances that don't need per-thread copies).
> > 
> > Yet some of methods of the class hierarchy (a root singleton class and 
> > everything which is accessible through it) are synchronized (well, you 
> > know why). That's where the problems begin.
> > 
> > Marking a method as synchronized automatically makes it shared (more or 
> > less obvious). And marking the method shared makes it unable to invoke 
> > with non-shared instance (and __gshared != shared), meaning that I'm 
> > unable to use my __gshared variables anymore, making this attribute 
> > useless for any serious safe programming.
> > 
> > So I started with replacing __gshared with shared and quickly understood 
> > how viral it is. Not only you mast mark all the members shared (methods 
> > and field), instantiate classes with shared attribute, you also have to 
> > create a duplicate all the methods to make them accessible with both 
> > shared and non-shared (thread-local) instances:
> 
> Why can't you use a non-shared method on a shared object? The compiler 
> could insert locking on the caller side.
> 
> Why can't you use a shared method on a non-shared object? The compiler 
> could, as an optimization, duplicate the method, minus the 
> synchronization. Or it could leave in the locking, which is expensive 
> but correct.

The caller would have to acquire locks for all the data accessed by the 
non-shared method and all non-shared methods it calls. Additionally, non-shared 
functions can access thread-local data. Neither of those issues are easily 
solved. Bartosz's scheme would solve the first one due to implied ownership.  


Re: Shared Hell

2009-10-28 Thread dsimcha
== Quote from Walter Bright (newshou...@digitalmars.com)'s article
> Denis Koroskin wrote:
> > I've recently updated to DMD2.035 (from DMD2.031 because all the later
> > versions had issues with imports) and for the first time faced problems
> > with shared modifier.
> >
> > I don't need shared and all my globals are __gshared (they are globally
> > unique instances that don't need per-thread copies).
> I don't understand. Are you running multiple threads? Are those threads
> accessing globals?
> A function that accesses shared data has to put in fences. There's no
> way to have the same code deal with shared and unshared code.
> As an escape from the type system, you can always cast away the
> shared-ness. But I wonder about code that both uses global variables
> shared across threads that don't need synchronization?

I have at least one use case for __gshareds in multithreaded code.  I often use
__gshared variables to hold program parameters that are only set using getopt at
program startup and never modified after the program becomes multithreaded.

That said, although I use D2 regularly, I basically have ignored shared's
existence up to this point.  The semantics aren't fully implemented, so right 
now
you get all the bondage and discipline of it without any of the benefits.  As 
far
as the problem of synchronized methods automatically being shared, here's an 
easy
workaround until the rough edges of shared are worked out:

//Instead of this:
synchronized SomeType someMethod(Foo args) {
// Do stuff.
}

// Use this:
SomeType someMethod(Foo args) {
synchronized(this) {
// Do stuff.
}
}


Re: Shared Hell

2009-10-28 Thread Kagamin
Denis Koroskin Wrote:

> > As an escape from the type system, you can always cast away the  
> > shared-ness.
> 
> That's the only way I have now. Casts from shared to unshared *everywhere*:
> 
> class BuildManager : BuildListener
> {
>  synchronized void build(shared Target target)
>  {
>  // ...
> 
>  _buildingThread = new shared(Thread)(&_startBuild); // creating a  
> new shared Thread. Yes, shared Thread, because BuildManager is global.
> 
>  //_buildingThread.start(); // Error: function  
> core.thread.Thread.start () is not callable using argument types () shared
>  (cast(Thread)_buildingThread).start(); // works, but ugly, and I  
> don't have a reason to hijack the type system in this case
> 
>  // ...
>  }
> }

you can use local variables to not have to cast in every statement.

class BuildManager : BuildListener
{
 synchronized void build(shared Target target)
 {
     // ...
 bt = new Thread(&_startBuild);
 _buildingThread = cast(shared Thread)bt; //store as shared
 bt.start(); //work with non-shared variable normally
 // ...
 }
}


Re: Shared Hell

2009-10-28 Thread Walter Bright

Denis Koroskin wrote:
On Wed, 28 Oct 2009 13:17:43 +0300, Walter Bright 
 wrote:



Denis Koroskin wrote:
I've recently updated to DMD2.035 (from DMD2.031 because all the 
later versions had issues with imports) and for the first time faced 
problems with shared modifier.
 I don't need shared and all my globals are __gshared (they are 
globally unique instances that don't need per-thread copies).


I don't understand. Are you running multiple threads? Are those 
threads accessing globals?




Yes.

A function that accesses shared data has to put in fences. There's no 
way to have the same code deal with shared and unshared code.




That's frustrating. I'd like to use the same class for both cases.

But I wonder about code that both uses global variables shared across 
threads that don't need synchronization?


You missed the point. I do the synchronization myself and I'm fine with 
switching to shared (I do believe it is a nice concept). The reason I 
use __gshared is because shared object were garbage-collected while 
still being in use a few versions of DMD back and I had no choice but to 
switch to __gshared. I hope it is fixed by now.


Which OS are you using? This is definitely a bug. If it's still there, 
you can work around by adding the tls data as a "root" to the gc.



But I still can't make my data shared, since shared is transitive 
(viral). After a few hours or work I still can't even compile my code.


As an escape from the type system, you can always cast away the 
shared-ness.


That's the only way I have now. Casts from shared to unshared *everywhere*:

class BuildManager : BuildListener
{
synchronized void build(shared Target target)
{
// ...

_buildingThread = new shared(Thread)(&_startBuild); // creating 
a new shared Thread. Yes, shared Thread, because BuildManager is global.


//_buildingThread.start(); // Error: function 
core.thread.Thread.start () is not callable using argument types () shared
(cast(Thread)_buildingThread).start(); // works, but ugly, and I 
don't have a reason to hijack the type system in this case


// ...
}
}

Andrei would suggest a Shared!(T) template that would wrap an unshared 
type and make all methods shared. This would work, but requires full AST 
manipulation capabilities (it's clearly not enough to just mark all the 
members shared). What should we do until then?


shared(T) should transitively make a new type where it's all shared.


Re: Shared Hell

2009-10-28 Thread Denis Koroskin

On Wed, 28 Oct 2009 16:19:11 +0300, dsimcha  wrote:


== Quote from Walter Bright (newshou...@digitalmars.com)'s article

Denis Koroskin wrote:
> I've recently updated to DMD2.035 (from DMD2.031 because all the later
> versions had issues with imports) and for the first time faced  
problems

> with shared modifier.
>
> I don't need shared and all my globals are __gshared (they are  
globally

> unique instances that don't need per-thread copies).
I don't understand. Are you running multiple threads? Are those threads
accessing globals?
A function that accesses shared data has to put in fences. There's no
way to have the same code deal with shared and unshared code.
As an escape from the type system, you can always cast away the
shared-ness. But I wonder about code that both uses global variables
shared across threads that don't need synchronization?


I have at least one use case for __gshareds in multithreaded code.  I  
often use
__gshared variables to hold program parameters that are only set using  
getopt at
program startup and never modified after the program becomes  
multithreaded.


That said, although I use D2 regularly, I basically have ignored shared's
existence up to this point.  The semantics aren't fully implemented, so  
right now
you get all the bondage and discipline of it without any of the  
benefits.  As far
as the problem of synchronized methods automatically being shared,  
here's an easy

workaround until the rough edges of shared are worked out:

//Instead of this:
synchronized SomeType someMethod(Foo args) {
// Do stuff.
}

// Use this:
SomeType someMethod(Foo args) {
synchronized(this) {
// Do stuff.
}
}


Yes, I've though about it. That's probably the only workaround for now and  
I'll give it. Thanks.


Re: Shared Hell

2009-10-28 Thread Denis Koroskin
On Wed, 28 Oct 2009 20:30:45 +0300, Walter Bright  
 wrote:


 Andrei would suggest a Shared!(T) template that would wrap an unshared  
type and make all methods shared. This would work, but requires full  
AST manipulation capabilities (it's clearly not enough to just mark all  
the members shared). What should we do until then?


shared(T) should transitively make a new type where it's all shared.


Type, yes, but not the methods. It will make a type with *no* methods  
usable (because they still accept and operate on thread-local variables).


I was hinting about template that would create a separate fully  
shared-aware type so that there would be no need for code duplication.  
I.e. it would transform the following class:


class Float
{
this(float value) { this.value = value; }

Float opAdd(Float other)
{
return new Vector(this.value + other.value);
}

private float value;
}

into the following:

class SharedFloat
{
this(float value) shared { this.value = value; }

shared Float opAdd(shared Float other) shared
{
return new shared Vector(this.value + other.value);
}

    private shared float value;
}

This obviously requires techniques not available in D currently (AST  
manipulation).


Re: Shared Hell

2009-10-29 Thread Kagamin
Walter Bright Wrote:

> A function that accesses shared data has to put in fences. There's no 
> way to have the same code deal with shared and unshared code.

Shared code perfectly deals with unshared data (it's not guaranteed that shared 
data is accessed by more than one thread). In other words unshared data is 
implicitly castable to shared.


Re: Shared Hell

2009-10-29 Thread Kagamin
Kagamin Wrote:

> Walter Bright Wrote:
> 
> > A function that accesses shared data has to put in fences. There's no 
> > way to have the same code deal with shared and unshared code.
> 
> Shared code perfectly deals with unshared data (it's not guaranteed that 
> shared data is accessed by more than one thread). In other words unshared 
> data is implicitly castable to shared.

Uh... this post was a little fast, ignore it, please.


Re: Shared Hell

2009-10-29 Thread Kagamin
Christopher Wright Wrote:

> > A function that accesses shared data has to put in fences. There's no 
> > way to have the same code deal with shared and unshared code.
> 
> Acquiring a lock on a non-shared instance is safe, just an unnecessary 
> expense. I would have looked into optimizing this expense away rather 
> than punting the problem to the programmer.

Shared code can put data into *really* shared environment, which must not 
happen for unshared data.


Re: Shared Hell

2009-10-29 Thread Christopher Wright

Kagamin wrote:

Christopher Wright Wrote:

A function that accesses shared data has to put in fences. There's no 
way to have the same code deal with shared and unshared code.
Acquiring a lock on a non-shared instance is safe, just an unnecessary 
expense. I would have looked into optimizing this expense away rather 
than punting the problem to the programmer.


Shared code can put data into *really* shared environment, which must not 
happen for unshared data.


Okay, but the compiler can try copying the method, removing the 'shared' 
storage class, and running semantic on the result. If that succeeds, 
you're guaranteed not to be doing anything that would be unsafe unless 
you're casting, and you can call the shared method on a local instance.


This lets you avoid whole program analysis and blacklisting unsafe 
operations.


In this case, the compiler can also point to the line of code that 
prevents the method from being marked not shared.


Re: Shared Hell

2009-10-29 Thread Steven Schveighoffer
On Thu, 29 Oct 2009 07:25:20 -0400, Christopher Wright  
 wrote:



Kagamin wrote:

Christopher Wright Wrote:

A function that accesses shared data has to put in fences. There's no  
way to have the same code deal with shared and unshared code.
Acquiring a lock on a non-shared instance is safe, just an unnecessary  
expense. I would have looked into optimizing this expense away rather  
than punting the problem to the programmer.
 Shared code can put data into *really* shared environment, which must  
not happen for unshared data.


Okay, but the compiler can try copying the method, removing the 'shared'  
storage class, and running semantic on the result. If that succeeds,  
you're guaranteed not to be doing anything that would be unsafe unless  
you're casting, and you can call the shared method on a local instance.


This lets you avoid whole program analysis and blacklisting unsafe  
operations.


In this case, the compiler can also point to the line of code that  
prevents the method from being marked not shared.


Let's say your shared method your attempting to analyze calls an obscure  
shared method:


int foo(shared C c);

How do you determine if it can be called without the 'shared' qualifier?   
This is one of the problems with not importing from compiled interface  
files.


-Steve


Re: Shared Hell

2009-10-29 Thread Walter Bright

Kagamin wrote:

Walter Bright Wrote:

A function that accesses shared data has to put in fences. There's
no way to have the same code deal with shared and unshared code.


Shared code perfectly deals with unshared data (it's not guaranteed
that shared data is accessed by more than one thread). In other words
unshared data is implicitly castable to shared.


Unfortunately, there is a subtle problem with that that makes such 
implicit casts unsafe. Shared data can be handed off to other threads. 
So if thread local data is implicitly cast to shared, then it can be 
handed off to other threads. Meaning it is no longer guaranteed to be 
thread local.


Various shared bugs

2009-12-07 Thread Jason House
So, after months of avoiding shared, I decided to see if I could remove all 
my casting away of shared.  It looks like things are still pretty buggy (or 
at least not particularly easy to use).

"is(T : shared)" gives a parse error
"alias shared T U" silently does the wrong thing.  
   (Use "alias shared(T) U" instead)
" is not callable using argument types ()" is just awful.  Typically, it 
means you're calling a non-shared function with a shared type or a shared 
function with a non-shared type.  I hit into a case where I got that message 
with a shared type and a shared method, but I have mad no attempt to 
reproduce.
The error "Can not implicitly convert expression of type(this) of type 
shared(xxx) to full.name.xxx" can pop up when defining shared this() 
constructor gives no line number where the offending usage occurs.

I've backed out most of my pro-shared changes and will try again in a few 
months :(


Re: shared library

2010-03-06 Thread Igor Lesik
Walter, Don, and All

Function codgen() in dmd/backend/cgcod.c has lines like:
if (0 && config.flags3 & CFG3pic)
so the PIC flag is ignored (2.040)
Do I understand it right?

I look on this code because value in %ebx (PIC register) does not look right 
when I debug
application that is dynamically linked with runtime shared library.

Also 




Re: shared library

2010-03-06 Thread Igor Lesik
Walter, Don, and All

Function codgen() in dmd/backend/cgcod.c has lines like:
if (0 && config.flags3 & CFG3pic)
so the PIC flag is ignored (2.040)

Do I understand it right?

I look on this code because value in %ebx (PIC register) does not look
right when I debug application that is dynamically linked with runtime
shared library.

Thanks,
Igor

"Igor Lesik"  wrote in message 
news:hmujil$nt...@digitalmars.com...
> Walter, Don, and All
>
> Function codgen() in dmd/backend/cgcod.c has lines like:
> if (0 && config.flags3 & CFG3pic)
> so the PIC flag is ignored (2.040)
> Do I understand it right?
>
> I look on this code because value in %ebx (PIC register) does not look 
> right when I debug
> application that is dynamically linked with runtime shared library.
>
> Also
> 




Re: Shared Memory

2009-04-16 Thread Robert Jacques

On Thu, 16 Apr 2009 17:20:47 -0400, sesteel  wrote:

I just wanted to float an idea out there.  I have been using  
technologies such as Terracotta and Memcache at work.  Terracotta, has  
left me wondering about the applicability of integrating shared objects  
(memory) directly into a programming language.  Is this anything anybody  
else here has thought of?


Yes. D2 has introduced the shared storage type (though it doesn't do  
anything yet) and there's also Bartosz's blog  
(http://bartoszmilewski.wordpress.com/feed/).


Additionally, I was thinking about the concept of services vs libraries,  
and how shared objects might be a way to provide fast IPC while getting  
rid of the library concept.  Thus, each service would have it's own  
memory space to manage and GC.  One hinderence would be the versioning  
of the shared object, but if that object could be viewed through an  
interface...


Just brainstorming.


This sounds like you're proposing the actor model, (at a coarser level  
than objects) and possibly also thread-local heaps.
Also, for those who don't know (I didn't) Terracotta is an open-source  
Java clustering package, which essentially transparently converts a  
multi-threaded application into a cluster application. Neat.


Shared Class Variables

2010-05-27 Thread sybrandy

Evening.

I'm having a bit of a problem and I'm hoping someone can help.  I'm 
trying to create a class that is shared across threads.  The only 
purpose of this class is to write data to somewhere, though currently a 
file.  A single-threaded version of this works fine, however I can't 
seem to get the code to work correctly when dealing with multiple 
threads.  I've gotten sharing issues, compilation issues trying to 
figure out how to use a shared class correctly, and currently an 
exception occurring during class finalization.


So, my question is, what is the correct way to do this?  Would a class 
work or would a struct be better?  Perhaps a singleton?


Thanks.

Casey


Re: Shared pain

2010-11-18 Thread Jason House
I'm not familiar with the API, but are you able to declare your original _sta 
as immutable and call it a day? Immutable data should have the same protection 
as __gshared but with no implications of bypassing the type system.

If that's not helpful, can you give more details like calling patterns? Is the 
function called from one thread or from many? My quick read of the windows 
documentation makes it seem like that's true. Probably unimportant, but I'd use 
_sta.ptr instead of &_sta[0] because the former more clearly implies array 
pointer to me, but that may be my own quirky style. 

Steve Teale Wrote:

> I had D code that provided a basis for creation of Windows services, 
> which I have just tried to get working with the latest D2.
> 
> No dice.
> 
> The point of failure was in this method
> 
> static void StartService()

> {

>if (!StartServiceCtrlDispatcherA(cast(SERVICE_TABLE_ENTRY *) &_sta[0]))

>{
>   ...

>}

> }
> 
> Where _sta is an array of SERVICE_TABLE_ENTRY structs. The bits of code 
> that install and remove the service worked fine, but the service control 
> dispatcher was clearly not happy about these structs being in TLS, and 
> the service crashed immediately when I tried to start it.
> 
> The class also has a couple of methods with signatures like:
> 
> extern (Windows) static export void service_ctrl(uint dwCtrlCode) {...}
> 
> That's probably not relevant, but I think it contributed to a host of 
> errors that finally made be take a big step back.
> 
> I re-implemented the thing in the style used for OOP in C.
> 
> struct ServiceBase
> {
>SERVICE_TABLE_ENTRY[2] _sta;
>...
> }
> 
> __gshared ServiceBase __sb;
> 
> void initialize(ServiceBase* sb) { ... }
> void whatever(ServiceBase* sb ...) { ... }
> 
> and used the __sb global within the functions with the Windows signature, 
> which just became
> 
> extern (Windows) export void service_ctrl(uint dwCtrlCode) {...}
> 
> Now it's working again, but I want to change it into idiomatically sound 
> D code.
> 
> Style suggestions please!
> 
> Steve




Re: Shared pain

2010-11-18 Thread Steven Schveighoffer
On Thu, 18 Nov 2010 06:26:39 -0500, Steve Teale  
 wrote:



I had D code that provided a basis for creation of Windows services,
which I have just tried to get working with the latest D2.

No dice.

The point of failure was in this method

static void StartService()

{

   if (!StartServiceCtrlDispatcherA(cast(SERVICE_TABLE_ENTRY *)  
&_sta[0]))


   {
  ...

   }

}

Where _sta is an array of SERVICE_TABLE_ENTRY structs. The bits of code
that install and remove the service worked fine, but the service control
dispatcher was clearly not happy about these structs being in TLS, and
the service crashed immediately when I tried to start it.


I think this has something to do with how services start.  From this page:  
http://msdn.microsoft.com/en-us/library/ms685990(v=VS.85).aspx
I see that StartServiceCtrlDispatcher creates its own thread to run  
ServiceMain, which most likely does not call the D thread initialization  
routines (not sure).  TLS may not be properly set up inside your thread  
that is running ServiceMain, and probably the static this() module  
functions have not been called.




The class also has a couple of methods with signatures like:

extern (Windows) static export void service_ctrl(uint dwCtrlCode) {...}

That's probably not relevant, but I think it contributed to a host of
errors that finally made be take a big step back.

I re-implemented the thing in the style used for OOP in C.

struct ServiceBase
{
   SERVICE_TABLE_ENTRY[2] _sta;
   ...
}

__gshared ServiceBase __sb;

void initialize(ServiceBase* sb) { ... }
void whatever(ServiceBase* sb ...) { ... }

and used the __sb global within the functions with the Windows signature,
which just became

extern (Windows) export void service_ctrl(uint dwCtrlCode) {...}

Now it's working again, but I want to change it into idiomatically sound
D code.

Style suggestions please!


I think using a class in D is a good idea.  But what you may need is  
global functions which forward to your class methods.  This is how I would  
probably do it.


-Steve


Re: Shared pain

2010-11-18 Thread Steve Teale
On Thu, 18 Nov 2010 08:33:12 -0500, Steven Schveighoffer wrote:

> 
> I think using a class in D is a good idea.  But what you may need is
> global functions which forward to your class methods.  This is how I
> would probably do it.
> 
> -Steve

Steve,

Thanks. I kind of went that way. Having done the laborious C OOP style 
thing, I put most of the methods back into the struct, just leaving the 
extern(Windows) functions at global scope - they referred to the 
__gshare'd object explicitly - I hate that.

Then I hid all of the crap behind a class that sneakily referred to the 
__gshared struct, but at least now to an external user of the module the 
interface looks much the same as it did before.

Now it works OK with the test case example - a service that just writes 
entries in the event log. However, the real service I'm trying to update 
works fine if I run it in debug mode (i.e. basically as just an 
executable), but if I run it as a service it seems to crash the first 
time I use a RegExp.find().

As you can imagine, this is terrible to debug - printf or similar is bad 
enough, but for the service I'm pushing entries into the Windows event 
logger system. Fortunately my D class for doing that has survived the D2 
changes. I'm going to try tweaking the service so it will interact with 
the desktop, then at least I can revert to printf.

But first I think I'll stop and do some carpentry for a couple of days. 
Then eventually something might dawn on me.

Steve



Re: Shared pain

2010-11-18 Thread Steven Schveighoffer
On Thu, 18 Nov 2010 13:53:53 -0500, Steve Teale  
 wrote:



On Thu, 18 Nov 2010 08:33:12 -0500, Steven Schveighoffer wrote:



I think using a class in D is a good idea.  But what you may need is
global functions which forward to your class methods.  This is how I
would probably do it.

-Steve


Steve,

Thanks. I kind of went that way. Having done the laborious C OOP style
thing, I put most of the methods back into the struct, just leaving the
extern(Windows) functions at global scope - they referred to the
__gshare'd object explicitly - I hate that.

Then I hid all of the crap behind a class that sneakily referred to the
__gshared struct, but at least now to an external user of the module the
interface looks much the same as it did before.

Now it works OK with the test case example - a service that just writes
entries in the event log. However, the real service I'm trying to update
works fine if I run it in debug mode (i.e. basically as just an
executable), but if I run it as a service it seems to crash the first
time I use a RegExp.find().


As I said before, I don't know if the thread being created by the windows  
service procedure is properly initializing the D modules of the  
library/runtime.  Try as the first line of ServiceMain to initialize the  
current thread:


auto mythread = thread_attachThis();

see http://www.digitalmars.com/d/2.0/phobos/core_thread.html

-Steve


Re: Shared pain

2010-11-18 Thread Steve Teale

> As I said before, I don't know if the thread being created by the
> windows service procedure is properly initializing the D modules of the
> library/runtime.  Try as the first line of ServiceMain to initialize the
> current thread:
> 
> auto mythread = thread_attachThis();
> 
> see http://www.digitalmars.com/d/2.0/phobos/core_thread.html
> 
> -Steve

Steve,

I don't think it gets as far as ServiceMain. Anyway, I tried it there, 
and at the point just before the first WINAPI call, but it still crashes.

I can fix it, by making my statically initialized RegExp objects __gshared 
or immutable, but the latter involves inserting a slew of tedious casts 
into my XML parser, since RexExp calls are used all over the place.

See my separate post for my thoughts on that.

Thanks
Steve



Re: Shared pain

2010-11-18 Thread Steve Teale
On Thu, 18 Nov 2010 11:26:39 +, Steve Teale wrote:

> I had D code that provided a basis for creation of Windows services,
> which I have just tried to get working with the latest D2.
> 
> No dice.
> 
I have made some progress in understanding this. It appears that any D 
static data structures containing function pointers will now cause a 
Windows service to crash.

For happiness, these must be forced into the global data segment.

I have demonstrated this within a vestigial service for a couple of cases 
- plain old struct containing an int and a function pointer, and for 
Regexp objects by using and not using __gshared on the offending objects.

Now that I'm reasonably sure what's happening, I ought to be able to make 
these things work by making such static members immutable, and 
initializing them in static this().

However, I then run into a slew of complier errors. Lets start with this 
simple framework:

import std.stdio;
import std.regexp;

class ThingWithStatic
{
   static RegExp rex;
   string ns;

   static this()
   {
  rex = RegExp("ab+a");
   }

   this()
   {
  ns = "abbaabba";
   }

   int getFromStatic() { return rex.find(ns); }
}

void main()
{
   ThingWithStatic tws = new ThingWithStatic();
   writefln("%d", tws.getFromStatic());
}

This compiles fine, but if I include this class in a service, and call 
getFromStatic(), the service will crash. If I change to:

__gshared RegExp rex;

It compiles fine, and the service does not crash.

If I change to:

   static immutable RegExp rex;

Then I get errors:

triv.d(11): Error: cannot implicitly convert expression (opCall("ab
+a",null)) of type std.regexp.RegExp to immutable(RegExp)
triv.d(19): Error: function std.regexp.RegExp.find (string string) is not 
callable using argument types (string) immutable
st...@ubuntu:~/scratch$

So then I use a cast:

rex = cast(immutable(RegExp)) RegExp("ab+a");

and get down to:

triv.d(19): Error: function std.regexp.RegExp.find (string string) is not 
callable using argument types (string) immutable

as somewhat wierd message in itself. So I use a cast in the call to find
():

 return (cast(RegExp) rex).find(ns);
 
 At this point it compiles, and if it's used in the service, the service 
does not crash.
 
 BUT - all these complicated casts will be extremely tedious to 
administer to code that uses RexExp methods all  over the place, so 
__gshared is a great temptation. The compiler should try to eliminate 
such temptations in the interests of safety.
 
Also why are these casts necessary. If I am assigning to something that 
is the same type and was declared as immutable should not at least the 
first cast be done implicitly. In the second case, I'm using a Regexp 
object, wherever it may be stored, so why the cast? If find was pure 
would the cast still be required?

Thanks
Steve


Re: Shared pain

2010-11-19 Thread Steven Schveighoffer
On Fri, 19 Nov 2010 01:49:30 -0500, Steve Teale  
 wrote:





As I said before, I don't know if the thread being created by the
windows service procedure is properly initializing the D modules of the
library/runtime.  Try as the first line of ServiceMain to initialize the
current thread:

auto mythread = thread_attachThis();

see http://www.digitalmars.com/d/2.0/phobos/core_thread.html

-Steve


Steve,

I don't think it gets as far as ServiceMain. Anyway, I tried it there,
and at the point just before the first WINAPI call, but it still crashes.

I can fix it, by making my statically initialized RegExp objects  
__gshared

or immutable, but the latter involves inserting a slew of tedious casts
into my XML parser, since RexExp calls are used all over the place.

See my separate post for my thoughts on that.


OK, I'm out of ideas, sorry :(

It certainly looks like there is an issue with TLS.  I wouldn't suggest  
band-aiding things how you are doing, because some modules in  
phobos/druntime use TLS also.  It's reasonable to assume that if your uses  
of TLS are failing, those may fail as well.


-Steve


Re: Shared pain

2010-11-19 Thread Jason House
A cast to immutable is required when constructing immutable objects. The type 
system can't prove that's safe. It's a design limitation to keep complexity low.

http://www.digitalmars.com/d/2.0/phobos/std_regexp.html
Looking at the Regexp docs, find isn't marked const or pure. If that's an 
oversite, file it in bugzilla. If it can't be const, then you should find 
another approach.

When this stuff crashes for you, is it accessing a different thread's TLS or is 
it simply unable to handle TLS at all?

Steve Teale Wrote:

> On Thu, 18 Nov 2010 11:26:39 +, Steve Teale wrote:
> 
> > I had D code that provided a basis for creation of Windows services,
> > which I have just tried to get working with the latest D2.
> > 
> > No dice.
> > 
> I have made some progress in understanding this. It appears that any D 
> static data structures containing function pointers will now cause a 
> Windows service to crash.
> 
> For happiness, these must be forced into the global data segment.
> 
> I have demonstrated this within a vestigial service for a couple of cases 
> - plain old struct containing an int and a function pointer, and for 
> Regexp objects by using and not using __gshared on the offending objects.
> 
> Now that I'm reasonably sure what's happening, I ought to be able to make 
> these things work by making such static members immutable, and 
> initializing them in static this().
> 
> However, I then run into a slew of complier errors. Lets start with this 
> simple framework:
> 
> import std.stdio;

> import std.regexp;

> 

> class ThingWithStatic

> {

>static RegExp rex;

>string ns;

> 

>static this()

>{

>   rex = RegExp("ab+a");

>}

> 

>this()

>{

>   ns = "abbaabba";

>}

> 

>int getFromStatic() { return rex.find(ns); }

> }

> 

> void main()

> {

>ThingWithStatic tws = new ThingWithStatic();

>writefln("%d", tws.getFromStatic());

> }
> 
> This compiles fine, but if I include this class in a service, and call 
> getFromStatic(), the service will crash. If I change to:
> 
> __gshared RegExp rex;
> 
> It compiles fine, and the service does not crash.
> 
> If I change to:
> 
>static immutable RegExp rex;
> 
> Then I get errors:
> 
> triv.d(11): Error: cannot implicitly convert expression (opCall("ab
> +a",null)) of type std.regexp.RegExp to immutable(RegExp)
> triv.d(19): Error: function std.regexp.RegExp.find (string string) is not 
> callable using argument types (string) immutable
> st...@ubuntu:~/scratch$
> 
> So then I use a cast:
> 
> rex = cast(immutable(RegExp)) RegExp("ab+a");
> 
> and get down to:
> 
> triv.d(19): Error: function std.regexp.RegExp.find (string string) is not 
> callable using argument types (string) immutable
> 
> as somewhat wierd message in itself. So I use a cast in the call to find
> ():
> 
>  return (cast(RegExp) rex).find(ns);
>  
>  At this point it compiles, and if it's used in the service, the service 
> does not crash.
>  
>  BUT - all these complicated casts will be extremely tedious to 
> administer to code that uses RexExp methods all  over the place, so 
> __gshared is a great temptation. The compiler should try to eliminate 
> such temptations in the interests of safety.
>  
> Also why are these casts necessary. If I am assigning to something that 
> is the same type and was declared as immutable should not at least the 
> first cast be done implicitly. In the second case, I'm using a Regexp 
> object, wherever it may be stored, so why the cast? If find was pure 
> would the cast still be required?
> 
> Thanks
> Steve



Re: Shared pain

2010-11-19 Thread Steve Teale
On Fri, 19 Nov 2010 08:25:17 -0500, Jason House wrote:

> A cast to immutable is required when constructing immutable objects. The
> type system can't prove that's safe. It's a design limitation to keep
> complexity low.
> 
Jason,

But design limitations like that will force programmers who are on a 
tight schedule to just say __gshared, and to hell with it.

Languages can't be designed just on theory - some recognition of 
practicality is also required.

As to the thread - I don't think that is under my control. I believe the 
Windows service dispatcher does its own thing.

Thanks for taking the trouble
Steve


Re: Shared pain

2010-11-19 Thread bearophile
Steve Teale:

> Languages can't be designed just on theory - some recognition of 
> practicality is also required.

In the case of creation of immutable data structures it looks the opposite to 
me: DMD is too much pragmatic and there isn't enough theory behind it :-)


> But design limitations like that will force programmers who are on a 
> tight schedule to just say __gshared, and to hell with it.

Regarding the creation of immutable data structures, there is a proposal that 
is probably able to remove some of the pain: the result of strongly pure 
functions may become implicitly castable to immutable.

Bye,
bearophile


Re: Shared pain

2010-11-19 Thread Steve Teale
On Fri, 19 Nov 2010 11:23:44 -0500, bearophile wrote:

> Regarding the creation of immutable data structures, there is a proposal
> that is probably able to remove some of the pain: the result of strongly
> pure functions may become implicitly castable to immutable.
> 
> Bye,
> bearophile

BP,

I admire your dedication to language theory and purity, but there are 
many who'd translate that to impracticality and obscurity.

I came to D in the first place because I found it refreshingly clear and 
easy to use after C++ and Java. But now it's getting painful.

I've bailed out several times, just keep coming back to see how it is 
doing. I have a bunch of code that worked with D1 and D2 at one time. 
I've given up on D1, since it is now obviously legacy, but even without 
the complexity of supporting both, It's been real hard this visit to get 
things working again.

What's your estimate of how long it will be before D is a stable language?

Thanks
Steve




Re: Shared pain

2010-11-19 Thread Fawzi Mohamed


On 19-nov-10, at 17:42, Steve Teale wrote:


On Fri, 19 Nov 2010 11:23:44 -0500, bearophile wrote:

Regarding the creation of immutable data structures, there is a  
proposal
that is probably able to remove some of the pain: the result of  
strongly

pure functions may become implicitly castable to immutable.

Bye,
bearophile


BP,

I admire your dedication to language theory and purity, but there are
many who'd translate that to impracticality and obscurity.

I came to D in the first place because I found it refreshingly clear  
and

easy to use after C++ and Java. But now it's getting painful.

I've bailed out several times, just keep coming back to see how it is
doing. I have a bunch of code that worked with D1 and D2 at one time.
I've given up on D1, since it is now obviously legacy, but even  
without
the complexity of supporting both, It's been real hard this visit to  
get

things working again.

What's your estimate of how long it will be before D is a stable  
language?


well D1 is pretty stable I think, if you are interested in stability  
that is a good choice, has worked well for me.
This does not mean that I will not consider D2, but D1 is my main  
workhorse.


Fwzi



Thanks
Steve






Re: Shared pain

2010-11-19 Thread bearophile
Steve Teale:

> I admire your dedication to language theory and purity, but there are 
> many who'd translate that to impracticality and obscurity.

I like that idea about immutables & strong pure functions, but it was not an 
idea of mine :-) That enhancement request in Bugzilla is not written by me.


> I came to D in the first place because I found it refreshingly clear and 
> easy to use after C++ and Java. But now it's getting painful.

But strongly pure functions are already present in D. So it's morally good to 
push its usages and implications as far as possible, otherwise we are wasting 
possibilities. That implicit cast idea is another implication of purity. It's a 
clean thing, it's not a hack or workaround or a dangerous thing or something 
like that, it comes from a clean & logical reasoning about consequences of 
purity. So it can't be compared to many other dirty things present in D2. It 
actually helps to clean the programs a little, because removes the need for one 
important use case of casts. So I can't agree. There is a large complexity 
difference between extending the logical implications of an already present 
feature, and adding a true special case.


> What's your estimate of how long it will be before D is a stable language?

I have no idea, I am not that expert, and probably no one knows. D is developed 
by a small group of devs, and despite in life you seem to "need" to be fast 
everything you do (for example because otherwise others do it before you and 
you miss the train), D is not a commercial project, so it has less timing 
pressures. Often commercial software projects produce a worse result, despite 
having more resources, because of the strict development timing requirements.

If you look at the PyPy Python project it's may years out of schedule, it was 
started by lot of money coming from European Union, but in the end it may 
deliver something good any way. Open Source projects too need to respect some 
timing schedules, but in OS you are sometimes able to say "it will be done when 
it will be done," while in most commercial software projects you can't say that.

The "feature" we are describing here probably needs only few lines of code to 
be implemented in the compiler (but I can't be sure) and it's 
backward-compatible (because it removes the need of a cast in some cases), so 
it's a kind of additive change.

Bye,
bearophile


Re: Shared pain

2010-11-19 Thread Jason House
Steve Teale Wrote:

> On Fri, 19 Nov 2010 08:25:17 -0500, Jason House wrote:
> 
> > A cast to immutable is required when constructing immutable objects. The
> > type system can't prove that's safe. It's a design limitation to keep
> > complexity low.
> > 
> Jason,
> 
> But design limitations like that will force programmers who are on a 
> tight schedule to just say __gshared, and to hell with it.
> 
> Languages can't be designed just on theory - some recognition of 
> practicality is also required.

I didn't say I liked the need for the cast or even that I think D has the 
proper design! IIRC, the cast with object creation was in lieu of adding 
"unique" tepe qualifier and the extra complexity to get that right. In your 
example, I believe the object was created once, so a cast really isn't that 
bad. The bad part to me was the need to cast away immutability with every use. 
That's why I encouraged a bugzilla entry. I did't check this case, but Phobos 
had a bad track record with adopting type qualifiers after they were added to 
D2.


Re: Shared pain

2010-11-19 Thread Steve Teale
On Fri, 19 Nov 2010 16:21:41 -0500, Jason House wrote:

> Steve Teale Wrote:
> 
>> On Fri, 19 Nov 2010 08:25:17 -0500, Jason House wrote:
>> 
>> > A cast to immutable is required when constructing immutable objects.
>> > The type system can't prove that's safe. It's a design limitation to
>> > keep complexity low.
>> > 
>> Jason,
>> 
>> But design limitations like that will force programmers who are on a
>> tight schedule to just say __gshared, and to hell with it.
>> 
>> Languages can't be designed just on theory - some recognition of
>> practicality is also required.
> 
> I didn't say I liked the need for the cast or even that I think D has
> the proper design! IIRC, the cast with object creation was in lieu of
> adding "unique" tepe qualifier and the extra complexity to get that
> right. In your example, I believe the object was created once, so a cast
> really isn't that bad. The bad part to me was the need to cast away
> immutability with every use. That's why I encouraged a bugzilla entry. I
> did't check this case, but Phobos had a bad track record with adopting
> type qualifiers after they were added to D2.

I'm a bit calmer now I have got most of my utility modules working again.

There were two circumstances where I found the casts particularly irksome.

I had at one point an immutable char* that I would be passing to Win32 
functions. I was assigning to it the address of a plain static character 
array, and I had to use a cast to do it. I could not see what harm such 
an assignment could do.

Then I had a slew of cases where I had created immutable RegExp objects, 
and I had to do (cast(RegExp) rexobj).find(...). I could not see what the 
cast was protecting here either.

I think these are bugs, if you agree I will put them in bugzilla.


Phobos and shared

2011-03-15 Thread d coder
Greetings

I am trying to create a multithreaded application. Right now I am finding it
difficult to work with "shared" qualifier. One of the reasons is that Phobos
library does not seem compatible with "shared" data-structures. For example:

import std.bitmanip;
shared BitArray foo;
void main() {
  foo ~= true; // this does not work
  (cast(BitArray)foo) ~= true; // Even casting does not help
}


I know that "shared" is a relatively new qualifier in D2. Are there plans to
make Phobos "shared" compatible?
Are there any workarounds that I am missing.

Regards
- Puneet


Re: Migrating to Shared

2009-05-12 Thread The Anh Tran

Walter Bright wrote:

I wrote a brief article which should help:

http://www.digitalmars.com/d/2.0/migrate-to-shared.html


Sir,

So immutable is an alias of invariant?
D now has 3 keywords that have somewhat similar meaning: const invariant 
immutable.


Thx.


Re: Migrating to Shared

2009-05-12 Thread Walter Bright

The Anh Tran wrote:

So immutable is an alias of invariant?
D now has 3 keywords that have somewhat similar meaning: const invariant 
immutable.


By popular demand, the invariant keyword was replaced with immutable. 
Invariant will eventually go away.


Re: Migrating to Shared

2009-05-12 Thread Leandro Lucarella
Walter Bright, el 12 de mayo a las 10:59 me escribiste:
> The Anh Tran wrote:
> >So immutable is an alias of invariant?
> >D now has 3 keywords that have somewhat similar meaning: const invariant 
> >immutable.
> 
> By popular demand, the invariant keyword was replaced with immutable.
> Invariant will eventually go away.

Better sooner than later. At least it would be nice if a deprecation
warning is issued if invariant is used when immutable should go.

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/

GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)



Re: Migrating to Shared

2009-05-12 Thread Walter Bright

Leandro Lucarella wrote:

At least it would be nice if a deprecation
warning is issued if invariant is used when immutable should go.


That'll happen.


Re: Migrating to Shared

2009-05-12 Thread Jarrett Billingsley
On Tue, May 12, 2009 at 1:47 PM, Walter Bright
 wrote:
> I wrote a brief article which should help:
>
> http://www.digitalmars.com/d/2.0/migrate-to-shared.html
>

A couple typos:

// should be immutable int[3], no?
immutable table[3] x = [6, 123, 0x87];

// no type
__gshared x;


Re: Migrating to Shared

2009-05-12 Thread Walter Bright

Jarrett Billingsley wrote:

A couple typos:


Fixed.


Re: Migrating to Shared

2009-05-12 Thread Brian Palmer
Walter Bright Wrote:

> I wrote a brief article which should help:
> 
> http://www.digitalmars.com/d/2.0/migrate-to-shared.html

I like this development, the only thing that makes me wary is the implied TLS 
behavior. I think I'd personally prefer it if tls was a keyword as well, and 
all globals had to have either tls or shared (or __gshared) in their type, 
rather than defaulting to tls if none is specified. So we'd force the 
programmer to explicitly define the level of sharing. 

Some might view that as too verbose though?


Re: Migrating to Shared

2009-05-12 Thread BCS

Hello Brian,



I like this development, the only thing that makes me wary is the
implied TLS behavior. I think I'd personally prefer it if tls was a
keyword as well, and all globals had to have either tls or shared (or
__gshared) in their type, rather than defaulting to tls if none is
specified. So we'd force the programmer to explicitly define the level
of sharing.



I'm fine with the implicit but I'd like to see the explicit form as well 
(so they wouldn't pop up from -vtls).





Re: Migrating to Shared

2009-05-12 Thread Walter Bright

BCS wrote:
I'm fine with the implicit but I'd like to see the explicit form as well 
(so they wouldn't pop up from -vtls).


You can do it explicitly with ___thread, though I was planning on 
deprecating that.


Re: Migrating to Shared

2009-05-12 Thread Leandro Lucarella
Walter Bright, el 12 de mayo a las 11:19 me escribiste:
> Leandro Lucarella wrote:
> >At least it would be nice if a deprecation
> >warning is issued if invariant is used when immutable should go.
> 
> That'll happen.

Great! =)

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/

GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)



Re: Migrating to Shared

2009-05-12 Thread BCS

Hello Walter,


BCS wrote:


I'm fine with the implicit but I'd like to see the explicit form as
well (so they wouldn't pop up from -vtls).


You can do it explicitly with ___thread, though I was planning on
deprecating that.



not soon I hope.




Re: Migrating to Shared

2009-05-12 Thread Derek Parnell
On Tue, 12 May 2009 10:47:02 -0700, Walter Bright wrote:

> I wrote a brief article which should help:
> 
> http://www.digitalmars.com/d/2.0/migrate-to-shared.html

Good article. This is an exciting enhancment to an already exciting
programming language. 

-- 
Derek Parnell
Melbourne, Australia
skype: derek.j.parnell


Re: Migrating to Shared

2009-05-12 Thread Robert Fraser

Jarrett Billingsley wrote:

// should be immutable int[3], no?
immutable table[3] x = [6, 123, 0x87];


Really shouldn't that be enum, unless you mysteriously needed to take 
the address of it?


Re: Migrating to Shared

2009-05-13 Thread Kagamin
And shared(int) is neither subtype nor supertype of int?


Re: Migrating to Shared

2009-05-13 Thread Simen Kjaeraas

Robert Fraser wrote:


Jarrett Billingsley wrote:

// should be immutable int[3], no?
immutable table[3] x = [6, 123, 0x87];


Really shouldn't that be enum, unless you mysteriously needed to take  
the address of it?


Seeing as how the example is for immutable, I'd say enum wouldn't be
quite right.

--
 Simen


Re: Migrating to Shared

2009-05-13 Thread Walter Bright

Kagamin wrote:

And shared(int) is neither subtype nor supertype of int?


It's like const(int) and immutable(int).


Re: Semantics of shared

2009-05-13 Thread Robert Jacques

On Wed, 13 May 2009 23:44:32 -0400, Matt  wrote:

[from reddit]

There was just a post to reddit announcing that thread local storage  
would be the default for global variables and that the 'shared'  
qualifier would make this happen.   What I can't find is a description  
of typing rules surrounding 'shared'.   From the discussion at reddit,  
it sounded like 'shared' was intended to mean 'possibly shared', with  
the implication that thread local objects can be treated as 'possibly  
shared'.
The problem I see with this is that it implies that it is not safe to  
assign one shared reference to another, because the former may actually  
be thread local while the latter is actually global.  This would seem to  
make the "maybe shared" concept pretty useless.  Is this not a  
problem?   Or if not, can someone clarify to me what the actual  
semantics & typing rules are?


Thanks,
Matt


I'm posting Walter's reply from reddit:

WalterBright 4 points 6 hours ago[-]

You're right about the return types of accessors, though we plan to  
address this. But if I may make some corrections, C++ has four versions  
(none, const, volatile, and const volatile), while D has five (none,  
const, immutable, shared, and shared const). The shared immutable is not  
counted since is the same as immutable.


I don't see a place for "maybe shared" that isn't already handled by  
simply "shared".


Re: Semantics of shared

2009-05-13 Thread Walter Bright

Matt wrote:

There was just a post to reddit announcing that thread local storage
would be the default for global variables and that the 'shared'
qualifier would make this happen.   What I can't find is a
description of typing rules surrounding 'shared'.   From the
discussion at reddit, it sounded like 'shared' was intended to mean
'possibly shared', with the implication that thread local objects can
be treated as 'possibly shared'.

The problem I see with this is that it implies that it is not safe to
assign one shared reference to another, because the former may
actually be thread local while the latter is actually global.  This
would seem to make the "maybe shared" concept pretty useless.  Is
this not a problem?   Or if not, can someone clarify to me what the
actual semantics & typing rules are?


The addresses of thread local data cannot be implicitly cast to shared. 
If they could, then they could be accessed by other threads, and the 
whole safety of them being thread local is compromised.


Shared data must be created as shared, or cast to be shared. Casting to 
shared is an implicitly unsafe operation, relying on the user ensuring 
that it is safe to do so.


Thread local data can point to shared data, but cannot be implicitly 
cast to shared.


Re: Semantics of shared

2009-05-13 Thread Walter Bright

Robert Jacques wrote:
I don't see a place for "maybe shared" that isn't already handled by 
simply "shared".


I gave a flip and incomplete answer there.

I'm not sure there is even a point to a function that could handle both 
shared and unshared with the same code. First of all, sharing is going 
to need some sort of synchronization; you're going to try and minimize 
the amount of code that has to deal with shared. I can't see trying to 
run an in-place sort on a shared array, for example. Can you imagine two 
threads trying to sort the same array?


You're going to want to approach manipulating shared data differently 
than unshared.


Re: Semantics of shared

2009-05-13 Thread Robert Jacques
On Thu, 14 May 2009 01:27:15 -0400, Walter Bright  
 wrote:



Robert Jacques wrote:
I don't see a place for "maybe shared" that isn't already handled by  
simply "shared".


I gave a flip and incomplete answer there.

I'm not sure there is even a point to a function that could handle both  
shared and unshared with the same code. First of all, sharing is going  
to need some sort of synchronization; you're going to try and minimize  
the amount of code that has to deal with shared. I can't see trying to  
run an in-place sort on a shared array, for example. Can you imagine two  
threads trying to sort the same array?


You're going to want to approach manipulating shared data differently  
than unshared.


I agree for POD, but what classes where the synchronization is  
encapsulated behind a virtual function call?


Also, does this mean 'scope' as a type is going away?


Re: Semantics of shared

2009-05-13 Thread Walter Bright

Robert Jacques wrote:
I agree for POD, but what classes where the synchronization is 
encapsulated behind a virtual function call?


synchronization can make a shared reference "tail shared".


Also, does this mean 'scope' as a type is going away?


Scope never was a type, it's a storage class.


Re: Semantics of shared

2009-05-14 Thread Matt
Walter Bright Wrote:

> Robert Jacques wrote:
> > I don't see a place for "maybe shared" that isn't already handled by 
> > simply "shared".
> 
> I gave a flip and incomplete answer there.
> 
> I'm not sure there is even a point to a function that could handle both 
> shared and unshared with the same code. [...]
> You're going to want to approach manipulating shared data differently 
> than unshared.

Ok, so there is no cast from 'shared' to 'not shared' or vice-versa, so it's 
sound.  Sorry, quotes like the above from Robert confused me.

But now I'm confused by the idea that you wouldn't want to use the same code on 
shared and unshared data.  The usual approach in C or C++ in dealing with 
shared data is to first acquire a lock and then to run code that would have 
been otherwise safe on the data.  Is there some way to cast shared to thread 
local when a local has been acquired?

>  Can you imagine two threads trying to sort the same array?

Not at the same time, but yes.



Re: Semantics of shared

2009-05-14 Thread Matt
Matt Wrote:

> Is there some way to cast shared to thread local when a local has been 
> acquired?

It occurs to me that your plan is probably: with an explicit cast when the lock 
is acquired.   So in practice 'unshared' is really going to mean something more 
like 'exclusively owned' and these modifiers aren't really going to help with 
managing what data is actually thread local vs. in the global heap.  The 
purpose of the 'shared' annotation is then just to warn you about unlocked data 
and to serve a similar purpose as 'volatile' for code generation.

Is this about right?




Re: Semantics of shared

2009-05-14 Thread Robert Jacques
On Thu, 14 May 2009 02:13:37 -0400, Walter Bright  
 wrote:



Robert Jacques wrote:
I agree for POD, but what classes where the synchronization is  
encapsulated behind a virtual function call?


synchronization can make a shared reference "tail shared".


I agree, but that doesn't seem answer my question. Put another way, if I  
have an interface I which is implemented by both a thread local class L  
and a shared class S, then does some function F need to know about whether  
the implementor of I is S or L?


P.S. There will obviously be some interfaces S can't implement, but that a  
separate issue.



Also, does this mean 'scope' as a type is going away?


Scope never was a type, it's a storage class.


Sorry for the confusion of terminology. However, you talk blog about using  
the 'scope' keyword to support escape analysis, ettc. i.e. 'scope' would  
become the 'const' of the shared-thread local-stack storage type system.  
Is this still the plan?


Re: Semantics of shared

2009-05-14 Thread Jason House
Robert Jacques Wrote:

> On Thu, 14 May 2009 02:13:37 -0400, Walter Bright  
>  wrote:
> 
> > Robert Jacques wrote:
> >> I agree for POD, but what classes where the synchronization is  
> >> encapsulated behind a virtual function call?
> >
> > synchronization can make a shared reference "tail shared".
> 
> I agree, but that doesn't seem answer my question. Put another way, if I  
> have an interface I which is implemented by both a thread local class L  
> and a shared class S, then does some function F need to know about whether  
> the implementor of I is S or L?

Shared data needs fundamentally different handling than thread local data. I 
expect "shared I" and "__thread I" to be handled differently. You can't store 
an S where an L is expected... It can break code.
 
> P.S. There will obviously be some interfaces S can't implement, but that a  
> separate issue.
> 
> >> Also, does this mean 'scope' as a type is going away?

Of course not. Scope storage class will remain.
> > Scope never was a type, it's a storage class.
> 
> Sorry for the confusion of terminology. However, you talk blog about using  
> the 'scope' keyword to support escape analysis, ettc. i.e. 'scope' would  
> become the 'const' of the shared-thread local-stack storage type system.  
> Is this still the plan?



Re: Migrating to Shared

2009-05-14 Thread Steven Schveighoffer
On Tue, 12 May 2009 13:47:02 -0400, Walter Bright  
 wrote:



I wrote a brief article which should help:

http://www.digitalmars.com/d/2.0/migrate-to-shared.html


Regarding making globals immutable, one other option that was not  
identified was making it an enum.


Most of the time, I would think you'd want manifest constants versus  
immutable globals, as they take up no static space.


(not any more comments yet, still reading...)

-Steve


Re: Semantics of shared

2009-05-14 Thread Jason House
Matt Wrote:

> Matt Wrote:
> 
> > Is there some way to cast shared to thread local when a local has been 
> > acquired?
> 
> It occurs to me that your plan is probably: with an explicit cast when the 
> lock is acquired.   So in practice 'unshared' is really going to mean 
> something more like 'exclusively owned' and these modifiers aren't really 
> going to help with managing what data is actually thread local vs. in the 
> global heap.  The purpose of the 'shared' annotation is then just to warn you 
> about unlocked data and to serve a similar purpose as 'volatile' for code 
> generation.
> 
> Is this about right?

I don't think so. What happens when the lock is released? Any residual use of 
the cast data is going to be incorrect (lacks a lock). What that means is that 
the cast is unsafe even when the data is locked! Casting is a back door that 
should be used with extreme care.


Re: Migrating to Shared

2009-05-14 Thread Steven Schveighoffer
On Thu, 14 May 2009 08:54:21 -0400, Steven Schveighoffer  
 wrote:


On Tue, 12 May 2009 13:47:02 -0400, Walter Bright  
 wrote:



I wrote a brief article which should help:

http://www.digitalmars.com/d/2.0/migrate-to-shared.html


Regarding making globals immutable, one other option that was not  
identified was making it an enum.


Most of the time, I would think you'd want manifest constants versus  
immutable globals, as they take up no static space.


(not any more comments yet, still reading...)



OK, I think there's another thread talking about this, but I was looking  
for the same thing...


There doesn't seem to be a way to convert shared data into a form (call it  
"locked-shared") that then can be used in a function as if it were local  
data.


For example, given that shared is a type constructor, I have to mark  
methods on a class shared in order to call them on a shared class  
instance.  But if there was a way to lock the instance so it temporarly  
became local, then I could call any method (as long as it didn't squirrel  
away a pointer to this).  Are there plans to be able to do something like  
this?  It couldn't be simply marked local, because you don't want to be  
able to squirrel away a pointer to it.  It would have to be marked  
something else...


Then comes the notion of deep locking: if you lock simply the this  
pointer, then it becomes tail-shared as you mentioned -- all the  
references the object contains are still shared.  You'd almost have to  
recursively lock everything, and then what if something has a cycle...


I'm thinking this shared thing is going to be only good for small POD, as  
it's going to be almost untennable to deal with repeating all  
implementation just because something is shared or not.  And even then,  
you probably want to copy the POD to non-shared form so you can pass it  
around.  I don't anticipate anyone making much more than a shared int.


-Steve


Re: Semantics of shared

2009-05-14 Thread Robert Jacques
On Thu, 14 May 2009 08:51:37 -0400, Jason House  
 wrote:



Robert Jacques Wrote:


On Thu, 14 May 2009 02:13:37 -0400, Walter Bright
 wrote:

> Robert Jacques wrote:
>> I agree for POD, but what classes where the synchronization is
>> encapsulated behind a virtual function call?
>
> synchronization can make a shared reference "tail shared".

I agree, but that doesn't seem answer my question. Put another way, if I
have an interface I which is implemented by both a thread local class L
and a shared class S, then does some function F need to know about  
whether

the implementor of I is S or L?


Shared data needs fundamentally different handling than thread local  
data. I expect "shared I" and "__thread I" to be handled differently.  
You can't store an S where an L is expected... It can break code.


P.S. There will obviously be some interfaces S can't implement, but  
that a

separate issue.

>> Also, does this mean 'scope' as a type is going away?


Of course not. Scope storage class will remain.


The use of scope I'm talking about (see below) isn't even implemented yet,  
so how can it remain? It was Walter bogged a while ago about using the  
scope keyword to aid escape analysis, which would provide a common type  
for shared-local-stack allocation. I'm not referring to the use of 'scope'  
to stack allocate a class.



> Scope never was a type, it's a storage class.

Sorry for the confusion of terminology. However, you talk blog about  
using

the 'scope' keyword to support escape analysis, ettc. i.e. 'scope' would
become the 'const' of the shared-thread local-stack storage type system.
Is this still the plan?






Re: Migrating to Shared

2009-05-14 Thread Sean Kelly

Steven Schveighoffer wrote:


I'm thinking this shared thing is going to be only good for small POD, 
as it's going to be almost untennable to deal with repeating all 
implementation just because something is shared or not.  And even then, 
you probably want to copy the POD to non-shared form so you can pass it 
around.  I don't anticipate anyone making much more than a shared int.


Personally, I anticipate using shared for large global containers almost 
exclusively.  I've never considered the "interconnected web of shared 
objects" idea to be a good one, and building shared into the language 
doesn't change that.  For containers, a range returned by a shared 
container will probably have to hold the lock on that container until it 
is destroyed or shared won't be terribly useful.  I haven't thought 
about this very thoroughly, but that's my initial take on the idea.


Re: Semantics of shared

2009-05-14 Thread Matt
Jason House Wrote:

> Matt Wrote:
> > Is this about right?
> 
> I don't think so. What happens when the lock is released? Any residual use of 
> the cast data is going to be incorrect (lacks a lock). What that means is 
> that the cast is unsafe even when the data is locked! Casting is a back door 
> that should be used with extreme care.

You're right - it's a big departure from C++ where casting is to be avoided if 
possible, and you're right that the cast isn't safe in general.  It's 
semi-reasonable because it's safe unless you cast somewhere and the C++ 
multi-threaded programming model is unsafe anyway.  But it's bad that the bugs 
introduced can be quite far from the casts (e.g. if cast-to-unshared data is 
placed in a global thread-local somewhere).

But I don't see how you can do much of anything useful with shared data if 
something like this isn't the plan.  Tracking what data is protected by lock 
and when is going to be outside of the scope of any type system you're going to 
want for D (and is going to be undecidable in general).




Re: Semantics of shared

2009-05-14 Thread Jason House
Matt Wrote:

> Jason House Wrote:
> 
> > Matt Wrote:
> > > Is this about right?
> > 
> > I don't think so. What happens when the lock is released? Any residual use 
> > of the cast data is going to be incorrect (lacks a lock). What that means 
> > is that the cast is unsafe even when the data is locked! Casting is a back 
> > door that should be used with extreme care.
> 
> You're right - it's a big departure from C++ where casting is to be avoided 
> if possible, and you're right that the cast isn't safe in general.  It's 
> semi-reasonable because it's safe unless you cast somewhere and the C++ 
> multi-threaded programming model is unsafe anyway.  But it's bad that the 
> bugs introduced can be quite far from the casts (e.g. if cast-to-unshared 
> data is placed in a global thread-local somewhere).
> 
> But I don't see how you can do much of anything useful with shared data if 
> something like this isn't the plan.  Tracking what data is protected by lock 
> and when is going to be outside of the scope of any type system you're going 
> to want for D (and is going to be undecidable in general).
> 

We're all still waiting to hear how D will handle locking under the covers. I 
don't think locking will be used to change types. A shared variable will always 
be shares, even if you have the lock.


Re: Migrating to Shared

2009-05-14 Thread bobef
Walter Bright Wrote:

> I wrote a brief article which should help:
> 
> http://www.digitalmars.com/d/2.0/migrate-to-shared.html


__gshared, __etc. These look ugly IMHO. :)


Re: Migrating to Shared

2009-05-14 Thread BCS

Hello bobef,


Walter Bright Wrote:


I wrote a brief article which should help:

http://www.digitalmars.com/d/2.0/migrate-to-shared.html


__gshared, __etc. These look ugly IMHO. :)



I think that's the point: they look ugly because they are ugly.




Re: Semantics of shared

2009-05-14 Thread Walter Bright

Robert Jacques wrote:
On Thu, 14 May 2009 02:13:37 -0400, Walter Bright 
 wrote:



Robert Jacques wrote:
I agree for POD, but what classes where the synchronization is 
encapsulated behind a virtual function call?


synchronization can make a shared reference "tail shared".


I agree, but that doesn't seem answer my question. Put another way, if I 
have an interface I which is implemented by both a thread local class L 
and a shared class S, then does some function F need to know about 
whether the implementor of I is S or L?


Since a reference to thread local cannot be implicitly cast to shared, 
then this scenario cannot happen - i.e. a shared function is not 
covariant with an unshared one.



P.S. There will obviously be some interfaces S can't implement, but that 
a separate issue.



Also, does this mean 'scope' as a type is going away?


Scope never was a type, it's a storage class.


Sorry for the confusion of terminology. However, you talk blog about 
using the 'scope' keyword to support escape analysis, ettc. i.e. 'scope' 
would become the 'const' of the shared-thread local-stack storage type 
system. Is this still the plan?


I'm not sure what you mean by that.


Re: Semantics of shared

2009-05-14 Thread Walter Bright

Matt wrote:

But now I'm confused by the idea that you wouldn't want to use the
same code on shared and unshared data.  The usual approach in C or
C++ in dealing with shared data is to first acquire a lock and then
to run code that would have been otherwise safe on the data.  Is
there some way to cast shared to thread local when a local has been
acquired?


Shared data becomes unshared for the duration of a lock on it. The 
problem with this is:


1. determining that there are no other shared references into that data.

2. determining that the code operating on that data doesn't squirrel 
away a thread local reference to it.


Currently, Bartosz is working on these problems. There is no solution 
yet other than using an (unsafe) cast and relying on the user not to 
screw it up.



Can you imagine two threads trying to sort the same array?

Not at the same time, but yes.


That's why there's no way one would do this with simply shared data. 
Locks would be needed, too.




Re: Semantics of shared

2009-05-14 Thread Walter Bright

Matt wrote:

You're right - it's a big departure from C++ where casting is to be
avoided if possible, and you're right that the cast isn't safe in
general.  It's semi-reasonable because it's safe unless you cast
somewhere and the C++ multi-threaded programming model is unsafe
anyway.  But it's bad that the bugs introduced can be quite far from
the casts (e.g. if cast-to-unshared data is placed in a global
thread-local somewhere).


It's not all bad. The huge advantage with "shared" is when you do a code 
review, it points you to where the potential trouble spots are. With the 
implicit sharing in C/C++, the whole program is a trouble spot.


Re: Semantics of shared

2009-05-14 Thread Robert Jacques
On Thu, 14 May 2009 13:12:46 -0400, Walter Bright  
 wrote:



Robert Jacques wrote:
On Thu, 14 May 2009 02:13:37 -0400, Walter Bright  
 wrote:



Robert Jacques wrote:
I agree for POD, but what classes where the synchronization is  
encapsulated behind a virtual function call?


synchronization can make a shared reference "tail shared".
 I agree, but that doesn't seem answer my question. Put another way, if  
I have an interface I which is implemented by both a thread local class  
L and a shared class S, then does some function F need to know about  
whether the implementor of I is S or L?


Since a reference to thread local cannot be implicitly cast to shared,  
then this scenario cannot happen - i.e. a shared function is not  
covariant with an unshared one.
P.S. There will obviously be some interfaces S can't implement, but  
that a separate issue.



Also, does this mean 'scope' as a type is going away?


Scope never was a type, it's a storage class.
 Sorry for the confusion of terminology. However, you talk blog about  
using the 'scope' keyword to support escape analysis, ettc. i.e.  
'scope' would become the 'const' of the shared-thread local-stack  
storage type system. Is this still the plan?


I'm not sure what you mean by that.


I'm asking about the use of scope you blogged about:

http://dobbscodetalk.com/index.php?option=com_myblog&show=Escape-Analysis.html&Itemid=29

[...]

For D, we are looking at a design that creates a parameter storage class  
called scope:


T foo(scope int* p);

The presence of scope means that the function will not allow the  
parameter, or anything reachable through that parameter, to escape from  
the scope of the function. The scope storage class can be applied to the  
parameters or the 'this' reference (for member functions). Initially, this  
will be a promise by the implementor of foo(), but it should be entirely  
possible for the compiler to perform escape analysis using data flow  
analysis techniques on the implementation of foo() to ensure it. The  
caller of the function will know that a reference to a local variable can  
be safely passed as a scope parameter. A million line program can be  
automatically verified as being free of escaping reference bugs.


Re: Semantics of shared

2009-05-14 Thread Walter Bright

Robert Jacques wrote:
 Sorry for the confusion of terminology. However, you talk blog about 
using the 'scope' keyword to support escape analysis, ettc. i.e. 
'scope' would become the 'const' of the shared-thread local-stack 
storage type system. Is this still the plan?


I'm not sure what you mean by that.


I'm asking about the use of scope you blogged about:

http://dobbscodetalk.com/index.php?option=com_myblog&show=Escape-Analysis.html&Itemid=29 



[...]

For D, we are looking at a design that creates a parameter storage class 
called scope:


T foo(scope int* p);

The presence of scope means that the function will not allow the 
parameter, or anything reachable through that parameter, to escape from 
the scope of the function. The scope storage class can be applied to the 
parameters or the 'this' reference (for member functions). Initially, 
this will be a promise by the implementor of foo(), but it should be 
entirely possible for the compiler to perform escape analysis using data 
flow analysis techniques on the implementation of foo() to ensure it. 
The caller of the function will know that a reference to a local 
variable can be safely passed as a scope parameter. A million line 
program can be automatically verified as being free of escaping 
reference bugs.


We've talked about it, but am unsure as to whether it will work or not.


Re: Migrating to Shared

2009-05-14 Thread Walter Bright

bobef wrote:

__gshared, __etc. These look ugly IMHO. :)


They're only allowed in safe mode, and are meant to inspire people to 
use them only when there's no other choice. Hence the unattractiveness 


Re: Semantics of shared

2009-05-14 Thread Jason House
Walter Bright Wrote:

> Matt wrote:
> 
> Shared data becomes unshared for the duration of a lock on it. 

Is that a statement of fact? Or is it just speculation leading to the issues 
below? Even if this was changed to "scope unshared", that still is really hairy 
since scope is a storage class.

> The problem with this is:
> 
> 1. determining that there are no other shared references into that data.
> 
> 2. determining that the code operating on that data doesn't squirrel 
> away a thread local reference to it.
> 
> Currently, Bartosz is working on these problems. There is no solution 
> yet other than using an (unsafe) cast and relying on the user not to 
> screw it up.

His last blog implied he was further. I thought the recent shift to use TLS and 
shared inside dmd was because a design had been worked out. Without that, D 
hardly helps writing correct multi-threaded code :( It may be that I'm being 
overly pessimistic...
 
> >> Can you imagine two threads trying to sort the same array?
> > Not at the same time, but yes.
> 
> That's why there's no way one would do this with simply shared data. 
> Locks would be needed, too.
> 



Re: Semantics of shared

2009-05-14 Thread Walter Bright

Jason House wrote:

His last blog implied he was further. I thought the recent shift to
use TLS and shared inside dmd was because a design had been worked
out. Without that, D hardly helps writing correct multi-threaded code
:( It may be that I'm being overly pessimistic...


Even if D goes *no further* with shared than where it is now, it still 
helps a *lot* in writing correct multi-threaded code.


It does this by making the points where threads communicate obvious, 
instead of inadvertent and hidden.


Re: Migrating to Shared

2009-05-14 Thread Leandro Lucarella
BCS, el 14 de mayo a las 16:48 me escribiste:
> Hello bobef,
> 
> >Walter Bright Wrote:
> >>I wrote a brief article which should help:
> >>http://www.digitalmars.com/d/2.0/migrate-to-shared.html
> >__gshared, __etc. These look ugly IMHO. :)
> 
> I think that's the point: they look ugly because they are ugly.

I prefer normal keywords for standard things (keywords or symbols starting
with __ are historically reserved for compiler specific features or even
private stuff in Python). For __gshared I agree that it's something ugly
and it's fine if it looks ugly.

But __traits?! Come on! __traits is beutiful, it deserves a beutiful
keyword ;)

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/

GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)



Re: Migrating to Shared

2009-05-14 Thread dsimcha
== Quote from Leandro Lucarella (llu...@gmail.com)'s article
> BCS, el 14 de mayo a las 16:48 me escribiste:
> > Hello bobef,
> >
> > >Walter Bright Wrote:
> > >>I wrote a brief article which should help:
> > >>http://www.digitalmars.com/d/2.0/migrate-to-shared.html
> > >__gshared, __etc. These look ugly IMHO. :)
> >
> > I think that's the point: they look ugly because they are ugly.
> I prefer normal keywords for standard things (keywords or symbols starting
> with __ are historically reserved for compiler specific features or even
> private stuff in Python). For __gshared I agree that it's something ugly
> and it's fine if it looks ugly.
> But __traits?! Come on! __traits is beutiful, it deserves a beutiful
> keyword ;)

True.  I think I subconsciously avoid anything with an __ in front of it because
to me the connotation of an __ is "Only works if the stars align just right.
We're trying to scare you away from this feature for a reason.  Here be 
monsters."
 If traits, excuse me, __traits, is stable enough not to deserve this 
connotation,
then it absolutely deserves its own keyword.


Re: Migrating to Shared

2009-05-14 Thread BCS

Reply to dsimcha,


True.  I think I subconsciously avoid anything with an __ in front of
it because to me the connotation of an __ is "Only works if the stars
align just right. We're trying to scare you away from this feature for 
a reason.  Here be monsters."


like __gshared? 


If traits, excuse me, __traits, is stable enough not to deserve this
connotation, then it absolutely deserves its own keyword.


I think traits should get first class treatment as it really isn't being 
used as the backdoor hack that the __ implies.





Re: Migrating to Shared

2009-05-14 Thread dsimcha
== Quote from BCS (a...@pathlink.com)'s article
> Reply to dsimcha,
> > True.  I think I subconsciously avoid anything with an __ in front of
> > it because to me the connotation of an __ is "Only works if the stars
> > align just right. We're trying to scare you away from this feature for
> > a reason.  Here be monsters."
> like __gshared? 

Exactly, except __gshared deserves this treatment.


Re: Migrating to Shared

2009-05-14 Thread Rainer Deyke
Leandro Lucarella wrote:
> I prefer normal keywords for standard things (keywords or symbols starting
> with __ are historically reserved for compiler specific features or even
> private stuff in Python). For __gshared I agree that it's something ugly
> and it's fine if it looks ugly.
> 
> But __traits?! Come on! __traits is beutiful, it deserves a beutiful
> keyword ;)

I like the idea of using __ for temporary, transitional, and
experimental keywords.  Using __ has several advantages here:
  - It's unlikely to collide with existing identifiers.
  - You can create as many of them as you want without worrying about
namespace pollution.
  - It's ugly as a reminder that the feature is temporary, transitional,
or experimental.
  - It's easy to search for and easy to globally replace with a real
keyword.

Eventually all features using __ keywords should be removed, renamed, or
modified in such as way that they do not require a keyword at all.


-- 
Rainer Deyke - rain...@eldwood.com


Re: Migrating to Shared

2009-05-15 Thread Don

Walter Bright wrote:

bobef wrote:

__gshared, __etc. These look ugly IMHO. :)


They're only allowed in safe mode, and are meant to inspire people to 
use them only when there's no other choice. Hence the unattractiveness 


Agreed. Yet as others have said, __traits deserves a beautiful keyword.


Re: shared class constructor

2009-08-13 Thread Robert Jacques
On Thu, 13 Aug 2009 09:34:50 -0700, Jeremie Pelletier   
wrote:



Just came across this while porting my code to enforce the use of shared.

---
module test;
shared class Foo {
   this() {}
}
---
Error: cannot implicitly convert expression (this) of type shared(Foo)  
to test.Foo


Of course I could just use new shared(Foo) but that would allow  
non-shared instances of Foo to be created as well, which I do not want.


Shouldn't "this" resolve to the fully qualified class?


In general, shared classes right now are broken. For example, you can't  
actually write any shared methods yet, (bug 3089) amoung other things.  
This does look like something new, and should be added.


As for your question: given that immutable classes work the same way, I  
assume it should.


Re: Various shared bugs

2009-12-08 Thread Graham St Jack
On Mon, 07 Dec 2009 22:45:17 -0500, Jason House wrote:

> So, after months of avoiding shared, I decided to see if I could remove
> all my casting away of shared.  It looks like things are still pretty
> buggy (or at least not particularly easy to use).
> 
> "is(T : shared)" gives a parse error
> "alias shared T U" silently does the wrong thing.
>(Use "alias shared(T) U" instead)
> " is not callable using argument types ()" is just awful. 
> Typically, it means you're calling a non-shared function with a shared
> type or a shared function with a non-shared type.  I hit into a case
> where I got that message with a shared type and a shared method, but I
> have mad no attempt to reproduce.
> The error "Can not implicitly convert expression of type(this) of type
> shared(xxx) to full.name.xxx" can pop up when defining shared this()
> constructor gives no line number where the offending usage occurs.
> 
> I've backed out most of my pro-shared changes and will try again in a
> few months :(

I have also given up on shared and am also adopting a waiting strategy.

I would love to get some tips from anyone (like Walter, for example) who 
thinks they have a way of using shared successfully.

My recent post on the subject got no meaningful responses - just one from 
bearophile that was supportive, but alas not helpful.


  1   2   3   >