From: Michal on
Thanks Peter, that's quite interesting solution. But also quite lot of
writing. I know it's best to keep all the code for changing data inside
class. But like this the class will get huge. E.g. imagine class for Bezier
curve - to make all the operations like rotate, move, resize, ... inside it's
awful. I ended up with 3500 lines in one cpp file in one of my projects,
that's not acceptable.

My idea is to provide some kind of "editors" for class, which would change
it. Something similar to MVC pattern maybe(?). Like this the operation is in
once class and it does only what it has to. The only problem is this
synchronization.
From: Peter Duniho on
Michal wrote:
> Thanks Peter, that's quite interesting solution. But also quite lot of
> writing.

It's no more typing ("writing") than your proposed solution of having
separate lock/unlock methods that have to be called while you operate on
an instance. But I agree, it's not the best choice. I simply offer it
only in case you won't or can't make the best choice.

> I know it's best to keep all the code for changing data inside
> class. But like this the class will get huge. E.g. imagine class for Bezier
> curve - to make all the operations like rotate, move, resize, ... inside it's
> awful. I ended up with 3500 lines in one cpp file in one of my projects,
> that's not acceptable.

In general, classes like that are not thread-safe. Why do you think
yours should be?

> My idea is to provide some kind of "editors" for class, which would change
> it. Something similar to MVC pattern maybe(?). Like this the operation is in
> once class and it does only what it has to. The only problem is this
> synchronization.

As I mentioned before, typically you make access to a type thread-safe,
rather than making the type itself thread-safe. Every now and then, you
wind up with a type that is used _only_ in a threaded context, and where
every member or almost every member may be accessed by two or more
threads simultaneously. In those cases, making the type thread-safe
makes sense. But those are rare exceptions.

This is true for at least a couple of reasons: reusable types most
frequently do not need to be thread-safe, so making them thread-safe
causes client code using the class to suffer unneeded overhead when
thread-safe access is not needed; also, as you yourself describe, a
given class may have a large number of mutation points where thread
safety is needed in order to make the whole class thread-safe, but
client code may actually access the instance(s) of that class in only a
small number of places.

Rather than designing classes that are relatively inefficient, one can
limit the implementation of thread-safety to the few places where the
class instance(s) are actually used by client code, saving work and
program overhead.

Pete
From: Patrice on
Michal, perhaps unrelated but FYI, I remember to have noticed once
http://msdn.microsoft.com/en-us/library/ms668265(v=VS.100).aspx
(SynchronizedCollection<T>) but I'm not sure now about the actual need...

Peter will likely provide better help if this collection could be of some
usefullness depending on what you are trying to do. Interesting design
thread...
--
Patrice



From: Michal on
Thanks for info Patrice, but it's not only about some List<> data, is about
any data class might contain - and Editor class might also require access to
more members. Anyway, I've solved this, but it's far from being nice ...

I've made one class:

public void AddObject(string name, object newObj)
{
objects.Add(name, newObj);
}

public object Get(string name)
{
Debug.Assert(objects.ContainsKey(name));
return objects[name];
}

Dictionary<string, object> objects = new Dictionary<string, object>();

and one interface:

public interface ILockableDataAccess
{
DataAccess LockAndGetData();
void Unlock();
}

So every class with lockable access to data provides LockAndGetData and
Unlock functions and in DataAccess object it returns required objects. It's
boring, not safe and requires lot of TYPING (sorry for my English in last
post) and converting between object and my types. But only solution I have
now ...

To answer Peter's question:
>>In general, classes like that are not thread-safe. Why do you think
yours should be?

Generally my program constantly generates some graphical data for other
input devices in separate thread and it allows user to change them anytime.
So I need thread safe access to edit and generate methods of different
classes.

From: Michal on
Sorry, here is the DataAccess class complete:

public class DataAccess
{
public void AddObject(string name, object newObj)
{
objects.Add(name, newObj);
}

public object Get(string name)
{
Debug.Assert(objects.ContainsKey(name));
return objects[name];
}

Dictionary<string, object> objects =
new Dictionary<string, object>();
}