tags:

views:

201

answers:

4

I'm working on a class library and have opted for a route with my design to make implementation and thread safety slightly easier, however I'm wondering if there might be a better approach.

A brief background is that I have a multi-threaded heuristic algorithm within a class library, that once set-up with a scenario should attempt to solve it. However I obviously want it to be thread safe and if someone makes a change to anything while it is solving for that to causes crashes or errors.

The current approach I've got is if I have a class A, then I create a number InternalA instances for each A instance. The InternalA has many of the important properties from the A class, but is internal an inaccessible outside the library.

The downside of this, is that if I wish to extend the decision making logic (or actually let someone do this outside the library) then it means I need to change the code within the InternalA (or provide some sort of delegate function).

Does this sound like the right approach?

+1  A: 

It's hard to really say from just that - but I can say that if you can make everything immutable, your life will be a lot easier. Look at how functional languages approach immutable data structures and collections. The less shared mutable data you have, the simple threading will be.

Jon Skeet
Unfortunately I don't think I can make things immutable. I've added more info in another answer.
Ian
+1  A: 

Why Not? Create generic class, that accepts 2 members class (eg. Lock/Unlock) - so you could provide

  • Threadsafe impl (implmenetation can use Monitor.Enter/Exit inside)
  • System-wide safe impl (using Mutex)
  • Unsafe, but fast (using empty impl).
Dewfy
This would be pretty cool. Do you know if there is sample code anywhere demonstrating this kind of things?
Klerk
it is very simple - each implementation will not exceed 10 lines of code. Generic class accepts "Protector" - it can be derived from some Interface IProtector with 2 method:Enter()Exit()Implement for your cases. And in your code surround sensitive code with pair:try{ MyProtector.Enter();......} finally{ MyProtector.Exit(); }Or do the same with IDisposableIf you stacked with this write me to mvoronoy (*) yahoo (.) com
Dewfy
Dewfy, thanks for the response. I might email you at some point to get a more in depth example as I'm not quite sure I follow 100%.
Ian
A: 

another way i have had some success with is by using interfaces to achieve functional separation. the cost of this approach is that you end up with some fields 'repeated' because each interface requires total separation from the others fields.

In my case I had 2 threads that need to pass over a set of data that potentially is large and needs as little garbage collection as possible. Ie I only want to pass change information from the first stage to the second. And then have the first process the next work unit.

this was achieved by the use of change buffers to pass changes from one interface to the next.

this allows one thread to work away at one interface, make all its changes and then publish a struct containing the changes that the other interface (thread) needs to apply prior to its work.

by doing this You have a double buffer ... (thread 1 produces a change report whilst thread 2 consumes the last report). If you add more interfaces (and threads) it appears like there are pulses of work moving through the threads.

This was based on my research and I have no doubt that there are better methods available now.

My aim when coming up with this however was to avoid the need for locks in the vast majority of code by designing out race conditions. the other major consideration is performance in garbage collection - which may not be an issue for you.

this way is all good until you need complex interactions between threads ... then you find that you start forcing the layout of your buffer structures for reuse to get around inheritance which in turn has an upkeep overhead.

John Nicholas
A: 

A little more information on the problem to help...

The heuristic I'm using is to solve TSP like problems. What happens right at the start of each calculation is that all the aspects that form the problem (sales man/places to visit) are cloned so they aren't affected across threads.

This means each thread can change data (such as stock left on a sales man etc) as there are a number of values that change during the calculation as things progress. What I'd quite like to do is allow the checked such as HasSufficientStock() for a simple example to be override by a developer using the library.

Unforutantely at present however to add further protection across threads and makings some simplier/lightweight classes I convert them to these internal classes, and these are the things that are actually used and cloned.

For example

class A
{
   public double Stock { get; }

   // Processing and cloning actually works using these InternalA's
   internal InternalA ConvertToInternal() {}
}

internal class InternalA : ICloneable
{
   public double Stock { get; set; }

   public bool HasSufficientStock() {}
}
Ian