I would like one instance of a model in memory to serve as a template for creating other objects for performance reasons, so that duplicates look like the original object but otherwise share no common components with the object they are initialized from, as if they were loaded with Model.find(template_object.id). I've tried some of the available solutions but none seems to do what I need: .dup and .deep_dup will create a new object with nil id and .clone will make some of the fields common to both the initializer and the initialized.
Currently my API is giving out the original objects that I keep as class variables, but I discovered that it leads to obscure memory leaks when the code using the objects manipulates their associations - these are kept in memory indefinitely. I hope that by giving out copies the associations of the template objects will stay untouched and the leak will be gone.
This sounds like the use case for defining a class and just initializing instances. You can customize whatever properties you want shared in the MyClass#new method. Without knowing more about your needs I will add that if you must store a template in memory you could store it as a class variable perhaps MyClass##template but would need to hear more to opine further. 😄
What I found when browsing rails source is the .instantiate method:
MyModel.instantiate(#my_other_instance.attributes_before_type_cast.deep_dup)
I've got an object that encapsulates remote calls. It needs credentials to make the calls. I think the credentials should be passed into the constructor so that, once the object is created, a user doesn't have to keep passing them in every time they make a call to the object. This seems like a sensible factoring.
If I do this though I've got the added complexity of the clients that use this object needing to be passed a factory instead of the object itself because they credentials won't be known until run time. So given this extra work, I was wondering if credentials (being just string values and no code) count as a dependency or not?
Does this question even make sense? You see I've gotten it into my head after using IoC that anything being passed into a constructor counts as a dependency and thus should probably be an instance of some implementation of an interface.
I wouldn't see those strings as dependencies. Instead, create an IUserContext or IUserCredentials abstraction that you can inject.
I'm working on the verification of an interface formalised in the OMG's IDL, and am having problems finding a definitive answer on the semantics of getting an attribute value. In an interface, I have an entry...
interface MyInterface {
readonly attribute SomeType someName;
};
I need to know if it is acceptable for someObj.someName != someObj.someName to be true (where someObj is an instance of an object implementing MyInterface).
All I can find in OMG documentation in regards to attributes is...
(5.14) An attribute definition is logically equivalent to declaring a
pair of accessor functions; one to retrieve the value of the attribute
and one to set the value of the attribute.
...
The optional readonly keyword indicates that there is only a single
accessor function—the retrieve value function.
Ergo, I'm forced to conclude that IDL attributes need not be backed by a data member, and are free to return basically any value the interface deems appropriate. Can anyone with more experience in IDL confirm that this is indeed the case?
As we know, IDL interface always will be represented by a remote object. An attribute is no more then a syntatic sugar for getAttributeName() and setAttributeName(). Personally, i don't like to use attribute because it is hardly to understand than a simply get/set method.
CORBA also has valuetypes, object by value structure - better explaned here. They are very usefull because, different from struct, allow us inherit from other valuetypes, abstract interface or abstract valuetype. Usualy, when i'm modeling objects with alot of
get/set methods i prefer to use valuetypes instead of interfaces.
Going back to your question, the best way to understand 'attribute' is looking for C#. IIOP.NET maps 'attribute' to properties. A property simulates a public member but they are a get/set method.
Answering your question, i can't know if someObj.someName != someObj.someName will return true or false without see the someObj implementation. I will add two examples to give an ideia about what we can see.
Example 1) This implementation will always return false for the expression above:
private static i;
public string getSomeName() {
return "myName" i;
}
Example 2) This implementation bellow can return true or false, depending of concurrency or 'race condition' between clients.
public string getSomeName() {
return this.someName;
}
public setSomeName(string name) {
this.someName = name;
}
First client can try to access someObj.someName() != someObj.someName(). A second client could call setSomeName() before de second call from the first client.
It is perfectly acceptable for someObj.someName != someObj.someName to be true, oddly as it may seem.
The reason (as others alluded to) is because attributes map to real RPC functions. In the case of readonly attributes they just map to a setter, and for non-readonly attributes there's a setter and a getter implicitly created for you when the IDL gets compiled. But the important thing to know is that an IDL attribute has a dynamic, server-dictated, RPC-driven value.
IDL specifies a contract for distributed interactions which can be made at runtime between independent, decoupled entities. Almost every interaction with an IDL-based type will lead to an RPC call and any return value will be dependent on what the server decides to return.
If the attribute is, say, currentTime then you'll perhaps get the server's current clock time with each retrieval of the value. In this case, someObj.currentTime != someObj.currentTime will very likely always be true (assuming the time granularity used is smaller than the combined roundtrip time for two RPC calls).
If the attribute is instead currentBankBalance then you can still have someObj.currentBankBalance != someObj.currentBankBalance be true, because there may be other clients running elsewhere who are constantly modifying the attribute via the setter function, so you're dealing with a race condition too.
All that being said, if you take a very formal look at the IDL spec, it contains no language that actually requires that the setting/accessing of an attribute should result in an RPC call to the server. It could be served by the client-side ORB. In fact, that's something which some ORB vendors took advantage of back in the CORBA heyday. I used to work on the Orbix ORB, and we had a feature called Smart Proxies - something which would allow an application developer to overload the ORB-provided default client proxies (which would always forward all attribute calls to the server hosting the target object) with custom functionality (say, to cache the attribute values and return a local copy without incurring network or server overhead).
In summary, you need to be very clear and precise about what you are trying to verify formally. Given the dynamic and non-deterministic nature of the values they can return (and the fact that client ORBs might behave differently from each other and still remain compliant to the CORBA spec) you can only reliably expect IDL attributes to map to getters and setters that can be used to retrieve or set a value. There is simply no predictability surrounding the actual values returned.
Generally, attribute does not need to be backed by any data member on the server, although some language mapping might impose such convention.
So in general case it could happen that someObj.someName != someObj.someName. For instance attribute might be last access time.
I have a class which implements persistable and a transient boolean member in this class. I noticed that thought he variable is declared as transient its state is being persisted. How do i over come this issue. Kindly help. Thanks in advance.
Blackberry's persistence mechanism does not respect transient. Possible solutions are:
split the object into two parts, persistable and not, or
use a different object format (perhaps something generic like a Hashtable) only for persistance, copying out into the "real" object after it is loaded and then writing back into the dummy object for saving.
(See this forum thread)
Look at this code:
dic:=TObjectDictionary<Integer, TObject>.Create([doOwnsValues]);
testObject:=TObject.Create;
dic.AddOrSetValue(1,testObject);
dic.AddOrSetValue(1,testObject);
The code
Creates a Dictionary that owns the contained values
Adds a value
Adds the same value again, using the same key
The surprising thing is that the object is freed when you add it the second time.
Is this intended behaviour? Or a bug in the Delphi libraries?
The documentation simply says "If the object is owned, when the entry is removed from the dictionary, the key and/or value is freed". So it seems a little odd to Free an object that I have just asked it to Add!
Is there any way to tell the TObjectDictionary to not do this? Currently, each time I add a value I have to check first if that Key-Value combination is already in the Dictionary.
Delphi 2010
[EDIT:
After reading all the comments:
My conclusions (for what they are worth)]
This seems to be the intended behaviour
There is no way of modifying this behaviour
Don't use TObjectDictionary (or any of the other similar classes) for anything other than the common "Add these objects to the container. Leave them there. Do some stuff. Free the container and all the objects you added" usage. If you are doing anything more complicated, it's better to manage the objects yourself.
The behaviour is poorly documented and you should read the source if you want to really know what's going on
[/EDIT]
TObjectDictionary<TKey,TValue> is in fact just a TDictionary<TKey,TValue> which has some extra code in the KeyNotify and ValueNotify methods:
procedure TObjectDictionary<TKey,TValue>.ValueNotify(const Value: TValue;
Action: TCollectionNotification);
begin
inherited;
if (Action = cnRemoved) and (doOwnsValues in FOwnerships) then
PObject(#Value)^.Free;
end;
This is, IMO, a rather simple minded approach, but in the ValueNotify method, it is impossible to tell for which key this is, so it simply frees the "old" value (there is no way to check if this value is set for the same key).
You can either write your own class (which is not trivial), deriving from TDictionary<K,V>, or simply not use doOwnsValues. You can also write a simple wrapper, e.g. TValueOwningDictionary<K,V> that uses TDictionary<K,V> to do the brunt of the work, but handles the ownership issues itself. I guess I would do the latter.
Thats because with reusing the key youre replacing the object and since the dictionary owns the object it frees the old one. Dictionary doesn't compare the value, only key, so it doesn't detect that the value (object) is same. Not a bug, as designed (IOW user error).
On second thought - perhaps the designer of the dict should have taken more care to have both doOwnsValues and AddOrSetValue()... one can argue both ways... I suggest you file it in QC, but I wouldn't hold my breath - it has been so now in at least two releases so it's unlikely to change.
This behaviour is by design and the design is sound.
Were the class to take responsibility for not freeing duplicates, it would have to iterate over the whole container every time a modification was made, both adding and removing. The iteration would check for any duplicate values and check accordingly.
It would be disasterous to impose this diabolical performance drain on all users of the class. If you wish to put duplicates in the list then you will have to come up with a bespoke lifetime management policy that suits your specific needs. In this case it is unreasonable to expect the general purpose container to support your particular usage pattern.
In the comments to this answer, and many of the others, it has been suggested that a better design would have been to test in AddOrSetValue whether or not the value being set was already assigned to the specified key. If so, then AddOrSetValue could return immediately.
I think it's clear to anyone that checking for duplicates in full generality is too expensive to contemplate. However, I contend that there are good design reasons why checking for duplicate K and V in AddOrSetValue would also be poor design.
Remember that TObjectDictionary<K,V> is derived from TDictionary<K,V>. For the more general class, comparing equality of V is potentially an expensive operation because we have no constraints on what V is, it being generic. So for TDictionary<K,V> there are performance reasons why we should not include the putative AddOrSetValue test.
It could be argued that we make a special exception for TObjectDictionary<K,V>. That would certainly be possible. It would require a little re-engineering of the coupling between the two classes, but it is quite feasible. But now you have a situation where TDictionary<K,V> and TObjectDictionary<K,V> have different semantics. This is a clear downside and must be weighed against the potential benefit from the AddOrSetValue test.
These generic container classes are so fundamental that design decisions have to take into account a huge spread of use cases, consistency considerations and so on. It is not, in my view, reasonable to consider TObjectDictionary<K,V>.AddOrSetValue in isolation.
Since the Delphi TDictionary implementation doesn't allow for more than one of the same keys you could check the excellent Generic collections library from Alex Ciobanu. It comes with a TMultiMap or for your case TObjectMultiMap that allows for multiple values per key.
Edit:
If you don't want multiple values per key, but rather want to avoid adding duplicates to the Dictionary then you can try TDistinctMultiMap or a TObjectDistinctMultiMap from the same Collections library.
So it seems a little odd to Free an object that I have just asked it to Add!
You didn't ask the dictionary to add - you called 'AddorSet', and since the key was already found, your call was a 'set', not an 'add'. Regardless, I see nothing odd here in terms of Delphi's behavior: In Delphi, objects are only object references, and there is no reference counting or ownership for simple objects.
Since in this case the dictionary owns the objects, it is doing exactly what it's supposed to do: "If the object is owned, when the entry is removed from the dictionary, the key and/or value is freed". You removed the value when you overwrote entry[1] - therefore the object referred to in 'testObject' is immediately deleted and your reference to 'testObject' is invalid.
Currently, each time I add a value I have to check first if it's already in the Dictionary.
Why is that? The behavior you described should only occur if you overwrite a previously used key with a reference to the same object.
Edit:
Perhaps there is something 'odd' after all - try this test code:
procedure testObjectList;
var ol:TObjectList;
o,o1:TObject;
begin
ol:=TObjectList.create;
ol.OwnsObjects:=true;//default behavior, not really necessary
try
o:=TObject.create;
ol.add(o);
ol[0]:=o;
showmessage(o.ClassName);//no av-although ol[0] is overwritten with o again, o is not deleted
o1:=TObject.create;
ol[0]:=o1;
showmessage(o.ClassName);//av - when o is overwritten with o1, o is deleted
finally
ol.free
end;
end;
This in spite of what it says in the (Delphi 7) help: "TObjectList controls the memory of its objects, freeing an object when its index is reassigned"
I think it is a bug.
I ran into it a week ago.
I use the TObjectDictionary for storing some real time telemetria datas, which are very often updated with new datas.
for example:
Type TTag = class
updatetime : TDateTime;
Value : string ;
end ;
TTagDictionary:= TObjectDictionary<string,TTag>.Create([doOwnsValues]);
procedure UpdateTags(key: string; newValue: String) ;
var
tag : TTag ;
begin
if TTagDictionary.TryGetValue(key,tag) then begin // update the stored tag
tag.Value = newValue ;
tag.updatetime := now ;
TTagDictionary.AddorSetValue(key,tag) ;
else begin
tag := TTag.Create ;
tag.updatetime := now ;
tag.Vluae := newValue ;
TTagDictionary.AddorSetValue(key,tag) ;
end ;
end ;
After several updates I ended up with some nasty access violations and with an dictionary full of freed objects.
It is a very poor designed container.
At update it need check if the new object is the same as the old only and then it must NOT free the object.