www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Overhead of synchronized class used in unshared situation

reply breezes <Wangyuanzju gmail.com> writes:
I have several cumtermized data structures which will be used both in shared
and unshared situations. Because un-synchronized classes can not be used in
shared situation, I think i have to
define these classes as synchronized classes, because otherwise i will have to
write the same class twice. However, if those classes are used in unshared
situations, such as local variable or
unshared global variable, does the overhead of synchronized still remain? I'm
writing database in which performance is critical.
Nov 27 2011
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, November 27, 2011 13:53:49 breezes wrote:
 I have several cumtermized data structures which will be used both in shared
 and unshared situations. Because un-synchronized classes can not be used in
 shared situation, I think i have to define these classes as synchronized
 classes, because otherwise i will have to write the same class twice.
 However, if those classes are used in unshared situations, such as local
 variable or unshared global variable, does the overhead of synchronized
 still remain? I'm writing database in which performance is critical.

If your class is synchronized, then you get the overhead. If you really want to use a class both in a situation which is shared and one which is not and only synchronize the shared case, then you need two separate classes. An alternative would be to use a wrapper class which is synchronized and use the wrapper when you care about synchronization and not use it otherwise. - Jonathan M Davis
Nov 27 2011
parent reply breezes <wangyuanzju gmail.com> writes:
Thanks. It seems that I have to write two classes, one synchronized and one is
not. Of course the
synchronized one should be the wrapper.

However, all members of a synchronized class are also shared. So I can not use
the un-synchronized class
in the synchronized wrapper class directly. I found two ways to overcome this
problem:
1. Cast away shared whenever using the wrapped un-synchronized object.
2. Define the wrapped un-synchronized object as __gshared.

Which way if more preferred?
Nov 27 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 11/28/2011 07:37 AM, breezes wrote:
 Thanks. It seems that I have to write two classes, one synchronized and one is
not. Of course the
 synchronized one should be the wrapper.

 However, all members of a synchronized class are also shared. So I can not use
the un-synchronized class
 in the synchronized wrapper class directly. I found two ways to overcome this
problem:
 1. Cast away shared whenever using the wrapped un-synchronized object.
 2. Define the wrapped un-synchronized object as __gshared.

 Which way if more preferred?

The first one. You manually ensure, by locking, that the object is actually unshared during that particular time frame and that there are memory fences. Casting away shared makes that information available to the compiler.
Nov 28 2011
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, November 28, 2011 06:37:39 breezes wrote:
 Thanks. It seems that I have to write two classes, one synchronized and one
 is not. Of course the synchronized one should be the wrapper.
 
 However, all members of a synchronized class are also shared. So I can not
 use the un-synchronized class in the synchronized wrapper class directly. I
 found two ways to overcome this problem: 1. Cast away shared whenever using
 the wrapped un-synchronized object. 2. Define the wrapped un-synchronized
 object as __gshared.
 
 Which way if more preferred?

Neither is exactly good, but casting away shared would probably be better - just be aware that in doing so you are then losing any guarantees that shared gives you with regards to threads. _You_ must guarantee that a shared object which has been cast to non-shared isn't actually shared between threads, since as soon as you cast away shared, the compiler is free to assume that the object is thread-local. __gshared basically makes something act like it would in C or C++, so the compiler really doesn't give any guarantees with regards to it, and it should generally only be used when interacting with C or C++ code. As I understand it, however, you _should_ be able to have object as a member variable in a synchronized class and still be able to use it without it being shared. The problem is IIRC that you have to mark an functions on it that you intend to be able to use when it's shared as shared and will probably have to duplicate those functions. So, you could essentially end up duplicating the entire class anyway (though mixin templates and string mixins would make it easy enough to avoid actually having to duplicate the code as far as what you maintain goes). A _class_ isn't shared or not. It's an instantiated object which is shared or not, and shared objects can only call shared functions. So, that may be part of what's throwing you off. But as I said, the situation does risk more code duplication than would be desirable (or force you to use mixins of some variety to avoid such duplication). If you're running into major problems with shared, I'd advise bringing it up in the main D newsgroup. There have been a variety of discussions about it lately - including some possible adjustments to how it works - since a number of people have been running into issues when trying to use it on anything other than a fairly small scale. - Jonathan M Davis
Nov 27 2011