I would like to implement lazy loading on properties with PostSharp.
To make it short, instead of writing
SomeType _field = null;
private SomeType Field
{
get
{
if (_field == null)
{
_field = LongOperation();
}
return _field;
}
}
I would like to write
[LazyLoadAspect]
private object Field
{
get
{
return LongOperation();
}
}
So, I identify that I need to emit some code in the class to generate the backing field, as well as inside the getter method in order to implement the test.
With PostSharp, I was considering overriding CompileTimeInitialize, but I am missing the knowledge to get a handle over the compiled code.
EDIT:
The question can be extended to any parameterless method like:
SomeType _lazyLoadedField = null;
SomeType LazyLoadableMethod ()
{
if(_lazyLoadedField ==null)
{
// Long operations code...
_lazyLoadedField = someType;
}
return _lazyLoadedField ;
}
would become
[LazyLoad]
SomeType LazyLoadableMethod ()
{
// Long operations code...
return someType;
}
After our comments, I think I know what you want now.
[Serializable]
public class LazyLoadGetter : LocationInterceptionAspect, IInstanceScopedAspect
{
private object backing;
public override void OnGetValue(LocationInterceptionArgs args)
{
if (backing == null)
{
args.ProceedGetValue();
backing = args.Value;
}
args.Value = backing;
}
public object CreateInstance(AdviceArgs adviceArgs)
{
return this.MemberwiseClone();
}
public void RuntimeInitializeInstance()
{
}
}
Test code
public class test
{
[LazyLoadGetter]
public int MyProperty { get { return LongOperation(); } }
}
Thanks to DustinDavis's answer and comments, I could work on my own implementation, and I just wanted here to share it to help other people.
The main differences from the original answer are:
Implement the suggested "only run the operation once" (purpose of the lock)
Made the initialization status of the backing field more reliable by passing this responsibility to a boolean.
Here is the code:
[Serializable]
public class LazyLoadAttribute : LocationInterceptionAspect, IInstanceScopedAspect
{
// Concurrent accesses management
private readonly object _locker = new object();
// the backing field where the loaded value is stored the first time.
private object _backingField;
// More reliable than checking _backingField for null as the result of the loading could be null.
private bool _hasBeenLoaded = false;
public override void OnGetValue(LocationInterceptionArgs args)
{
if (_hasBeenLoaded)
{
// Job already done
args.Value = _backingField;
return;
}
lock (_locker)
{
// Once the lock passed, we must check if the aspect has been loaded meanwhile or not.
if (_hasBeenLoaded)
{
args.Value = _backingField;
return;
}
// First call to the getter => need to load it.
args.ProceedGetValue();
// Indicate that we Loaded it
_hasBeenLoaded = true;
// store the result.
_backingField = args.Value;
}
}
public object CreateInstance(AdviceArgs adviceArgs)
{
return MemberwiseClone();
}
public void RuntimeInitializeInstance() { }
}
I think the requirement cannot be accurately described as 'lazy loading', but is a special case of a more general caching aspect with in-AppDomain storage but without eviction. A general caching aspect would be able to handle method parameters.
Related
Please look at the following code:
public sealed class Foo<T> : IDisposable
where T : IDisposable, new()
{
public T Bar
{
get { return _bar; }
}
public void Reset()
{
var oldBar = _bar;
using (oldBar)
{
_bar = new T();
}
}
public void Dispose()
{
// TODO:
}
private T _bar = new T();
}
Consider multithreaded environment. Bar getter and Reset method are being called from multiple threads. Is it guaranteed that client would never get a disposed T object via Bar property? Foo object is guaranteed not to be disposed at that moment. If not, how to get it right? I want to use low-lock techniques if possible.
Thank you in advance.
UPDATE
Thank you all guys for the help. The question need to be clarified. I want
Foo to manage Bar state;
to be sure that clients will not use disposed T object.
It seems that it is impossible with the code provided before. Here is the code that reflects my needs:
public sealed class Foo<T> : IDisposable
where T : class, IDisposable, new()
{
public bool TryExecute(Action<T> action)
{
lock (_sync)
{
if (_bar == null)
{
return false;
}
action(_bar);
return true;
}
}
public void Reset()
{
lock (_sync)
{
if (_bar == null)
{
throw new ObjectDisposedException(string.Empty);
}
Reset(new T());
}
}
public void Dispose()
{
lock (_sync)
{
if (_bar != null)
{
Reset(null);
}
}
}
private void Reset(T newBar)
{
var oldBar = _bar;
using (oldBar)
{
_bar = newBar;
}
}
private T _bar = new T();
private readonly object _sync = new object();
}
I beleive it is thread safe this time.
You can't get all of the requirements, but at least you can make Reset itself thread-safe without locks. As it is, it can fail because multiple concurrent calls could try to dispose the same object.
You can't prevent clients from storing a reference to a previous T instance.
What you can do, is ensure that only one Reset call can change the stored value at a time, using Interlocked.CompareExchange. This would also allow one of the calls to dispose the old value. The original code would fail because all concurrent calls could attempt to dispose the same old value. With CompareExchange we can swap new and old values atomically :
public void Reset()
{
var originalValue=_bar;
var replaced=Interlocked.CompareExchange(ref _bar,new T(),originalValue);
if(replaced!=_bar)
{
//We got to replace the value,
//we could dispose it safely if we wanted to
if (replaced!=null)
{
replaced.Dispose();
}
}
}
The comparison to oldValue means that even if two threads execute Reset concurrently, only one of them will be allowed to assign to _bar and be able to dispose the old value. The other will see that _bar has a new value.
This doesn't solve the problem of multiple temporary objects and anyway, we don't want to dispose.
It would be easier if Reset accepted a parameter with the replacement value so it didn't have to create the new objects itself.
public void Reset(T newValue)
{
var originalValue=_bar;
var replaced=Interlocked.CompareExchange(ref _bar,newValue,originalValue);
...
}
I would say use _bar variable via Bar property only, do not use it directly. Put a lock on set property on Bar. Code as follows:
public sealed class Foo<T> : IDisposable
where T : IDisposable, new()
{
private readOnly object key;
public Foo(){
key = new Object();
this.Bar = new T();
}
public T Bar
{
get { return _bar; }
private set {
lock(key){
_bar = value;
}
}
}
public void Reset()
{
var oldBar = _bar;
this.Bar = new T();
}
public void Dispose()
{
this.Bar = null;
}
private T _bar;
}
I have an object that only initializes itself with barebones data when constructed (fast), and loads itself for real (slow) when first accessed. The idea is that I'm creating a lot of these barebones objects at startup and hash them into a map, then fully load each object whenever it is individually accessed for the first time. The problem is that I cannot guarantee how clients will interact with this object, there are multiple public methods that might be invoked.
Is there a good pattern to support this kind of situation? The obvious (and my current) solution is to track state with an internal bool, check against that bool in every function that might be invoked, and load that way. But that requires code duplication of that behavior across all public functions, and is vulnerable to errors.
I can imagine a single point-of-entry method that then dishes out behaviors based on a client request type etc., but before I go consider going down that road I want to see if there's a commonly accepted approach/pattern that I might not be aware of. I'm doing this in C#, but any insight is appreciated.
If I understood what you want to achieve, you are looking for the Proxy Design Pattern, more specifically, a virtual Proxy.
Refer to http://www.dofactory.com/net/proxy-design-pattern
A small example would be something like:
public abstract class IObjectProvider
{
public abstract IObjectProvider Object{get;}
public abstract void doStuff();
}
public class RealObject : IObjectProvider
{
public RealObject()
{
//Do very complicated and time taking stuff;
}
public override IObjectProvider Object
{
get { return this; }
}
public override void doStuff()
{
//do this stuff that these objects normally do
}
}
public class ObjectProxy : IObjectProvider
{
private IObjectProvider objectInstance = null;
public override IObjectProvider Object
{
get
{
if (objectInstance == null)
objectInstance = new RealObject();
return objectInstance;
}
}
public override void doStuff()
{
if(objectInstance!=null)
objectInstance.doStuff();
}
}
public class SkeletonClass
{
public IObjectProvider Proxy1 = new ObjectProxy();
public IObjectProvider Proxy2 = new ObjectProxy();
}
static void Main(String[] args)
{
//Objects Not Loaded
SkeletonClass skeleton = new SkeletonClass();
//Proxy1 loads object1 on demand
skeleton.Proxy1.Object.doStuff();
//Proxy2 not loaded object2 until someone needs it
}
Here's an example of dynamic proxy approach.
using System;
using System.Diagnostics;
using Castle.DynamicProxy; //Remember to include a reference, too. It's nugettable package is Castle.Core
namespace ConsoleApp
{
public class ActualClass
{
//Have static instances of two below for performance
private static ProxyGenerator pg = new ProxyGenerator();
private static ActualClassInterceptor interceptor = new ActualClassInterceptor();
//This is how we get ActualClass items that are wrapped in the Dynamic Proxy
public static ActualClass getActualClassInstance()
{
ActualClass instance = new ActualClass();
return pg.CreateClassProxyWithTarget<ActualClass>(instance, interceptor);
}
//Tracking whether init has been called
private bool initialized = false;
//Will be used as evidence of true initialization, i.e. no longer null
private int? someValue = null;
public void Initialize()
{
if (!initialized)
{
//do some initialization here.
someValue = -1; //Will only get set to non-null if we've run this line.
initialized = true;
}
}
//Any methods you want to intercept need to be virtual!
public virtual int replaceValue(int value)
{
//below will blow up, if someValue has not been set to -1 via Initialize();
int oldValue = someValue.Value;
someValue = value;
return oldValue;
}
//block off constructor from public to enforce use of getActualClassInstance
protected ActualClass() { }
}
public class ActualClassInterceptor : ActualClass, IInterceptor
{
public void Intercept(IInvocation invocation)
{
//Call initialize before proceeding to call the intercepted method
//Worth noting that this is the only place we actually call Initialize()
((ActualClass)invocation.InvocationTarget).Initialize();
invocation.Proceed();
}
}
class Program
{
static void Main(string[] args)
{
ActualClass instance1 = ActualClass.getActualClassInstance();
ActualClass instance2 = ActualClass.getActualClassInstance();
int x1 = instance1.replaceValue(41);
int x2 = instance2.replaceValue(42);
int y1 = instance1.replaceValue(82);
Debug.Assert(y1 == 41);
int y2 = instance2.replaceValue(84);
Debug.Assert(y2 == 42);
var read = Console.ReadKey();
}
}
}
Please consider the following code
public class DataModel
{
public int a { get; set; }
}
public static class StaticAccess
{
private static _Data = new DataModel();
private static DataModel Data {
lock(_Data) {
return _Data;
}
}
}
Will an access to property a such us StaticAccess.Data.a = 3; will lock for the entire property value assignment or just for the _Data static field reference retrieval?
In other words, can I use the above implementation to synchronize the access to the properties of the underlying data model or do I have to implement the lock in every single property of it?
e.g.
public class DataModel
{
private int _a;
public int a {
get {
lock(this) {
return _a;
}
}
set {
lock(this) {
_a = value;
}
}
}
Thanks in advance.
The code in your first example will synchronize access to the instance of DataModel in the StaticAccess class (i.e.: to the _Data field), not to members of the instance of DataModel itself. For that you need your second example.
Side note: Avoid locking on this, and use a dedicated object to lock on, as you don't know who else might lock on the instance. Use something like
public class DataModel
{
private readonly object _lock= new object();
private int _a;
public int a {
get {
lock(_lock) {
return _a;
}
}
set {
lock(_lock) {
_a = value;
}
}
}
Edit based on comments:
The Data property of StaticAccess returns the instance of DataModel. So only thread at a time can obtain the reference to that instance. The goal, however, is to synchronize access to DataModel.a. Since access to DataModel.a is not synchronized any code that tries to either read or write to DataModel.a is not synchronized meaning that multiple threads accessing StaticAccess.Data.a is not synchronized:
void ThreadProc1()
{
// (might) block on "get StaticAccess.Data"
// will not block on "DataModel.a = 20"
StaticAccess.Data.a = 20;
}
void ThreadProc2()
{
// (might) block on "StaticAccess.Data"
// will not block on "DataModel.a = 10"
StaticAccess.Data.a = 10;
// (might) block on "StaticAccess.Data"
// will not block on "DataModel.a"
// "StaticAccess.Data.a" might be 10 or 20;
Console.WriteLine(StaticAccess.Data.a);
}
I have the following class with a nested private class and I would like to assign the value of NID to Context. I have used getters and setters however the value of NID (Sequencer.Context = value;) never gets assigned to ( SeqNode = Node.LoadNode(Context); ). What am I doing wrong?
//Instantiation
Increment.NID = "/Root/Dir/NodetoIncrement";
String getSequence = Convert.ToString(Increment.SID);
// The Class
public static class Increment
{
//Value of the node Context location in the tree to increment ( Increment.NID )
public static string NID
{
set { Sequencer.Context = value; } //The "/Root/Dir/NodetoIncrement";
}
//Get the sequence ID
public static int SID
{
get { return Sequencer.GetSeqId; }
}
//Nested sequencer class. This increments the node.
private class Sequencer
{
private Node SeqNode;
private static int SequenceNumber;
private volatile bool Run = true;
public static string Context { get; set; } //gets
public static int GetSeqId
{
get
{
return Interlocked.Add(ref SequenceNumber, 1);
}
}
public Sequencer() //Constructor Here!
{
SeqNode = Node.LoadNode(Context);
SequenceNumber = Convert.ToInt16(SeqNode["LastSequenceNo"]);
//NEVER DO THIS .. causes the system to lockup see comments.
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
while (Run)
{
Save();
Thread.Sleep(5000);
}
});
}
private void Save()
{
//optimistic concurrency recommended!!
var retryMaxCount = 3; // maximum number of attempts
var cycles = 0; // current attempt
Exception exception = null; // inner exception storage
while (cycles++ < retryMaxCount) // cycle control
{
try
{
SeqNode["LastSequenceNo"] = Convert.ToString(SequenceNumber);
SeqNode.Save();
// successful save, exit loop
exception = null;
break;
}
catch (NodeIsOutOfDateException e)
{
exception = e; // storing the exception temporarily
SeqNode = Node.LoadNode(Context);
}
}
// rethrow if needed
if (exception != null)
throw new ApplicationException("Node is out of date after 3 attempts.", exception);
}
~Sequencer() { Save(); }
}
}
public class XYHandler : Node
{
public override void Save(NodeSaveSettings settings)
{
base.Name = Convert.ToString(Increment.SID);
base.Save();
}
public override bool IsContentType
{
get { return true; }
}
}
What am I doing wrong?
You are waiting for another thread in a static initializer. NEVER DO THAT. I can't emphasize strongly enough how insanely dangerous that is.
For an explanation why, see this answer:
https://stackoverflow.com/a/8883117/88656
Is there some temporal coupling at play here?
SeqNode is set when the Sequencer is instantiated, but I can't see an instantiation in your sample.
The static constructor will run before the property setter is invoked the first time, and then try again 5s later - when is the property being set?
I can't see where Sequencer is being constructed (perhaps I missed it). Since it isn't a static constructor it will have to be called at least once for LoadNode to run. Did you intent to make that constructor static also?
Let's say I have two methods -
getCurrentValue(int valueID)
updateValues(int changedComponentID)
These two methods are called on the same object independently by separate threads.
getCurrentValue() simply does a database look-up for the current valueID.
"Values" change if their corresponding components change. The updateValues()method updates those values that are dependent upon the component that just changed, i.e. changedComponentID. This is a database operation and takes time.
While this update operation is going on, I do not want to return a stale value by doing a lookup from the database, but I want to wait till the update method has completed. At the same time, I don't want two update operations to happen simultaneously or an update to happen when a read is going on.
So, I'm thinking of doing it this way -
[MethodImpl(MethodImplOptions.Synchronized)]
public int getCurrentValue(int valueID)
{
while(updateOperationIsGoingOn)
{
// do nothing
}
readOperationIsGoingOn = true;
value = // read value from DB
readOperationIsGoingOn = false;
return value;
}
[MethodImpl(MethodImplOptions.Synchronized)]
public void updateValues(int componentID)
{
while(readOperationIsGoingOn)
{
// do nothing
}
updateOperationIsGoingOn = true;
// update values in DB
updateOperationIsGoingOn = false;
}
I'm not sure whether this is a correct way of doing it. Any suggestions? Thanks.
That's not the correct way. Like this you are doing an "active wait", effectively blocking your CPU.
You should use a lock instead:
static object _syncRoot = new object();
public int getCurrentValue(int valueID)
{
lock(_syncRoot)
{
value = // read value from DB
}
}
public void updateValues(int componentID)
{
lock(_syncRoot)
{
// update values in DB
}
}
Create a static object outside of both of these methods. Then use a lock statement on that object; when one method is accessing the protected code, the other method will wait for the lock to release.
private static object _lockObj = new object();
public int getCurrentValue(int valueID)
{
object value;
lock(_lockObj)
{
value = // read value from DB
}
return value;
}
public void updateValues(int componentID)
{
lock(_lockObj)
{
// update values in DB
}
}
private static readonly object _lock = new object();
public int getCurrentValue(int valueID)
{
try
{
Monitor.Enter(_lock);
value = // read value from DB
return value;
}
finally
{
Monitor.Exit(_lock);
}
}
public void updateValues(int componentID)
{
try
{
Monitor.Enter(_lock);
// update values in DB
}
finally
{
Monitor.Exit(_lock);
}
}