patterncsharpMinor
Allow changing the properties of a mutable controller in a thread safe way
Viewed 0 times
thepropertieswaycontrollerallowthreadsafechangingmutable
Problem
I have a (control engineering) controller. These controllers usually need several parameters to do their thing, and in my application it is desirable that these parameters can be changed while the controller is running - in a thread safe and well defined manner.
I came up with this design (extremely simplified):
Usage example:
```
var controller = new Controller();
controller.Info = new ControllerInfo(/ values /);
controller.Start();
// later:
controller.Info = new ControllerInfo(/ new values /);
// Application is done:
co
I came up with this design (extremely simplified):
// This is the class that the user instanciates.
public class Controller
{
public ControllerInfo Info { get; set; }
public void Start() { ... }
public void Stop() { ... }
private ControllerBody body = new ControllerBody();
private void ControllerThreadProc()
{
while (true)
{
var elapsedTime_ms = ...;
var currentInfo = this.Info;
// the actual calculation is done in another class
this.body.SingleStep(currentInfo, elapsedTime_ms);
Thread.Sleep(currentInfo.SampleTime_ms);
}
}
}
// This exists as a separate class so it is possible to test the
// mathematical model without having to do it in real-time.
public class ControllerBody
{
public void SingleStep(ControllerInfo info, long elapsedTime_ms)
{
var referenceValue = info.ReferenceValueGetter();
var calculationResult = math;
info.ControlValueSetter(calculationResult);
}
}
// Immutable class that contains all the info necessary to do stuff.
public class ControllerInfo
{
public Func ReferenceValueGetter { get; private set; }
public Action ControlValueSetter { get; private set; }
public int SampleTime_ms { get; private set; }
public double SomeConstant { get; private set; }
public double OtherConstant { get; private set; }
...
public ControllerInfo(/* 1 argument per property :( */) { /* many assignments */ }
}Usage example:
```
var controller = new Controller();
controller.Info = new ControllerInfo(/ values /);
controller.Start();
// later:
controller.Info = new ControllerInfo(/ new values /);
// Application is done:
co
Solution
Another option is to create ControllerInfo with mutable properties and a Clone method which would return a copy of the instance.
Then on the ControllerInfo Info set, simply call the Clone method and set _info to the clone of the object passed in.
To be clearer you can do away with Info as a property and instead code a method
Doing away with "get" semantics for Info, is a good idea, as you do not want the interface to suggest that a get followed by mutating the Info object would reflect the changes in the Controller.
Then on the ControllerInfo Info set, simply call the Clone method and set _info to the clone of the object passed in.
private ControllerInfo _info;
public Info
{
get { return _info; }
set { _info = value.Clone(); }
}To be clearer you can do away with Info as a property and instead code a method
public Controller SetInfo(ControllerInfo info)
{
_info = info.Clone();
return this;
}Doing away with "get" semantics for Info, is a good idea, as you do not want the interface to suggest that a get followed by mutating the Info object would reflect the changes in the Controller.
Code Snippets
private ControllerInfo _info;
public Info
{
get { return _info; }
set { _info = value.Clone(); }
}public Controller SetInfo(ControllerInfo info)
{
_info = info.Clone();
return this;
}Context
StackExchange Code Review Q#40096, answer score: 3
Revisions (0)
No revisions yet.