digitalmars.D.learn - Static problem
- Bob Cowdery (29/29) Oct 07 2010 Can someone sort out what I'm doing wrong here please.
- Stanislav Blinov (4/42) Oct 07 2010 Could you please post the use case as well? It should matter not from
- Bob Cowdery (4/47) Oct 07 2010 I suspected that might be the case. Yes they are from separate threads.
- Stanislav Blinov (17/25) Oct 07 2010 I wouldn't be too quick to state that there is no conflict, as
- Steven Schveighoffer (9/31) Oct 07 2010 FWIW, the classinfo of a class is an object, and as such can be used as ...
- Stanislav Blinov (2/24) Oct 07 2010 Thanks. To my shame, I repeatedly keep forgetting about this.
- Bob Cowdery (13/37) Oct 08 2010 Thanks for the suggestions. I'm keen to avoid locks as everything so far
- Stanislav Blinov (29/68) Oct 08 2010 Yeah, it's like this:
Can someone sort out what I'm doing wrong here please. ------------- import std.concurrency, std.stdio; import Definitions.procNames; class CRegistry { static Tid[E_PROC] TidRegistry; static void register(E_PROC name, Tid tid) { writeln(TidRegistry); TidRegistry[name] = tid; } static Tid getTid(E_PROC name) { //writeln("Entries: ", TidRegistry); if(name in TidRegistry) { writeln ("Returning ,", TidRegistry[name], " for " , name); return TidRegistry[name]; } return thisTid(); } } -------------- I register TID's like so: CRegistry.register(E_PROC.HPSDR, hpsdr_tid); and get them like so: CRegistry.getTid(E_PROC.HPSDR); If I call getTid() from any another module other than the one than set the values, TidRegistry is empty. How do I share this registry between modules. Thanks bob
Oct 07 2010
Bob Cowdery wrote:Can someone sort out what I'm doing wrong here please. ------------- import std.concurrency, std.stdio; import Definitions.procNames; class CRegistry { static Tid[E_PROC] TidRegistry; static void register(E_PROC name, Tid tid) { writeln(TidRegistry); TidRegistry[name] = tid; } static Tid getTid(E_PROC name) { //writeln("Entries: ", TidRegistry); if(name in TidRegistry) { writeln ("Returning ,", TidRegistry[name], " for " , name); return TidRegistry[name]; } return thisTid(); } } -------------- I register TID's like so: CRegistry.register(E_PROC.HPSDR, hpsdr_tid); and get them like so: CRegistry.getTid(E_PROC.HPSDR); If I call getTid() from any another module other than the one than set the values, TidRegistry is empty. How do I share this registry between modules. Thanks bobCould you please post the use case as well? It should matter not from what module you make the calls, as long as those calls are from the same thread. Different threads get different copies of the registry.
Oct 07 2010
On 07/10/2010 20:33, Stanislav Blinov wrote:Bob Cowdery wrote:I suspected that might be the case. Yes they are from separate threads. No conflict as one writes all the tids and the others only read them. What's the best way to fix that?Can someone sort out what I'm doing wrong here please. ------------- import std.concurrency, std.stdio; import Definitions.procNames; class CRegistry { static Tid[E_PROC] TidRegistry; static void register(E_PROC name, Tid tid) { writeln(TidRegistry); TidRegistry[name] = tid; } static Tid getTid(E_PROC name) { //writeln("Entries: ", TidRegistry); if(name in TidRegistry) { writeln ("Returning ,", TidRegistry[name], " for " , name); return TidRegistry[name]; } return thisTid(); } } -------------- I register TID's like so: CRegistry.register(E_PROC.HPSDR, hpsdr_tid); and get them like so: CRegistry.getTid(E_PROC.HPSDR); If I call getTid() from any another module other than the one than set the values, TidRegistry is empty. How do I share this registry between modules. Thanks bobCould you please post the use case as well? It should matter not from what module you make the calls, as long as those calls are from the same thread. Different threads get different copies of the registry.
Oct 07 2010
Bob Cowdery wrote:I wouldn't be too quick to state that there is no conflict, as associative array access/lookup is most probably not an atomic operation. What I'd propose is either: 1) Create your own lock-free associative array (yup, reinvent the wheel to introduce AA to the world of 'shared') 2) In this small case it may seem best (though mind that often such cases do grow up to the point when you still need to rethink design): Make your associative array __gshared and perform synchronization by hand, i.e. create a static Mutex (from core.sync.mutex) variable and initialize it in your CRegistry's static ctor, and then enclose all access to associative array in synchronized(mutex) {} blocks. Maybe concurrent-programming-in-D guru may propose simpler solution, but I don't see another. P.S. You can get much useful info on this topic in TDPL, the chapter on concurrency is even available for free: http://www.informit.com/articles/article.aspx?p=1609144Could you please post the use case as well? It should matter not from what module you make the calls, as long as those calls are from the same thread. Different threads get different copies of the registry.I suspected that might be the case. Yes they are from separate threads. No conflict as one writes all the tids and the others only read them. What's the best way to fix that?
Oct 07 2010
On Thu, 07 Oct 2010 16:18:26 -0400, Stanislav Blinov <stanislav.blinov gmail.com> wrote:Bob Cowdery wrote:FWIW, the classinfo of a class is an object, and as such can be used as sort of a global lock without having to use a static constructor: synchronized(this.classinfo) { .... } -SteveI wouldn't be too quick to state that there is no conflict, as associative array access/lookup is most probably not an atomic operation. What I'd propose is either: 1) Create your own lock-free associative array (yup, reinvent the wheel to introduce AA to the world of 'shared') 2) In this small case it may seem best (though mind that often such cases do grow up to the point when you still need to rethink design): Make your associative array __gshared and perform synchronization by hand, i.e. create a static Mutex (from core.sync.mutex) variable and initialize it in your CRegistry's static ctor, and then enclose all access to associative array in synchronized(mutex) {} blocks. Maybe concurrent-programming-in-D guru may propose simpler solution, but I don't see another.Could you please post the use case as well? It should matter not from what module you make the calls, as long as those calls are from the same thread. Different threads get different copies of the registry.I suspected that might be the case. Yes they are from separate threads. No conflict as one writes all the tids and the others only read them. What's the best way to fix that?
Oct 07 2010
Steven Schveighoffer wrote:Thanks. To my shame, I repeatedly keep forgetting about this.What I'd propose is either: 1) Create your own lock-free associative array (yup, reinvent the wheel to introduce AA to the world of 'shared') 2) In this small case it may seem best (though mind that often such cases do grow up to the point when you still need to rethink design): Make your associative array __gshared and perform synchronization by hand, i.e. create a static Mutex (from core.sync.mutex) variable and initialize it in your CRegistry's static ctor, and then enclose all access to associative array in synchronized(mutex) {} blocks. Maybe concurrent-programming-in-D guru may propose simpler solution, but I don't see another.FWIW, the classinfo of a class is an object, and as such can be used as sort of a global lock without having to use a static constructor: synchronized(this.classinfo) { .... } -Steve
Oct 07 2010
On 07/10/2010 21:32, Stanislav Blinov wrote:Steven Schveighoffer wrote:Thanks for the suggestions. I'm keen to avoid locks as everything so far is message parsing and the system is real-time. Having lots of threads that all talk to each other I needed a place to keep the Tid's which is accessible to everyone. There is no conflict because the main thread creates all others and registers the Tid's. Once the threads go the registry is read only. Just setting __gshared makes the app work. This may not be good practice I know and I will come back to it when I have more time. I'm not sure how to use synchronized(this.classinfo). Is this in combination with __gshared to synchronise access at the method level. Is it like a wrapper that goes inside the method? bobThanks. To my shame, I repeatedly keep forgetting about this.What I'd propose is either: 1) Create your own lock-free associative array (yup, reinvent the wheel to introduce AA to the world of 'shared') 2) In this small case it may seem best (though mind that often such cases do grow up to the point when you still need to rethink design): Make your associative array __gshared and perform synchronization by hand, i.e. create a static Mutex (from core.sync.mutex) variable and initialize it in your CRegistry's static ctor, and then enclose all access to associative array in synchronized(mutex) {} blocks. Maybe concurrent-programming-in-D guru may propose simpler solution, but I don't see another.FWIW, the classinfo of a class is an object, and as such can be used as sort of a global lock without having to use a static constructor: synchronized(this.classinfo) { .... } -Steve
Oct 08 2010
Bob Cowdery wrote:On 07/10/2010 21:32, Stanislav Blinov wrote:Yeah, it's like this: static void register(E_PROC name, Tid tid) { synchronized(this.classinfo) { theRegistry[name] = tid; } } static Tid getTid(E_PROC name) { Tid* result; synchronized(this.classinfo) { result = name in TidRegistry; } //... } All Objects contain a 'monitor' which is a synchronization primitive. synchronized(some_object) { foo(); } is similar to { some_mutex.lock(); scope(exit) some_mutex.unlock(); // some code }Steven Schveighoffer wrote:Thanks for the suggestions. I'm keen to avoid locks as everything so far is message parsing and the system is real-time. Having lots of threads that all talk to each other I needed a place to keep the Tid's which is accessible to everyone. There is no conflict because the main thread creates all others and registers the Tid's. Once the threads go the registry is read only. Just setting __gshared makes the app work. This may not be good practice I know and I will come back to it when I have more time. I'm not sure how to use synchronized(this.classinfo). Is this in combination with __gshared to synchronise access at the method level. Is it like a wrapper that goes inside the method? bobThanks. To my shame, I repeatedly keep forgetting about this.What I'd propose is either: 1) Create your own lock-free associative array (yup, reinvent the wheel to introduce AA to the world of 'shared') 2) In this small case it may seem best (though mind that often such cases do grow up to the point when you still need to rethink design): Make your associative array __gshared and perform synchronization by hand, i.e. create a static Mutex (from core.sync.mutex) variable and initialize it in your CRegistry's static ctor, and then enclose all access to associative array in synchronized(mutex) {} blocks. Maybe concurrent-programming-in-D guru may propose simpler solution, but I don't see another.FWIW, the classinfo of a class is an object, and as such can be used as sort of a global lock without having to use a static constructor: synchronized(this.classinfo) { .... } -Steve
Oct 08 2010