I know I can make a static property for the object, test it for valid-object on GET, and instantiate an instance when needed, however the problem with a static property is that it means the created object will always have a reference, making it - in essence - static as well.
Is there a way to accomplish what I'm after, or do I need to NEW the "user" object before I use it in each program's instance?
I know I can make a static property for the object, test it for valid-
object on GET, and instantiate an instance when needed, however the
problem with a static property is that it means the created object
will always have a reference, making it - in essence - static as well.
>
Not really.
Delete object Context:GetInstance.
Will kill the associated object instance. Next time you do the GET, a new one will be created.
Not necessarily agreeing with the use of statics, just saying that the property is static, not what it contains.
-- peter
There have been several publications on doing singletons without statics.
you want it to "be unchanged over the course of the session." , but
you don't want it static ? Confusing.
you can always do
delete object MyStaticProperty
if you want to remove the object from the session
pjudge wrote:
Not necessarily agreeing with the use of statics, just saying that the property is static, not what it contains.
True - however a given non-static object will not be destructed until all references to it go away. If the "parent" reference is static, it, by definition, will never go away, ergo the object itself will not be destructed.
I think...
but the object stays for the length of the session ....
also, be very careful about classes that have use abl handles (like
a query or persistent procedure). These will not be Garbage
collected automatically.
jmls wrote:
you want it to "be unchanged over the course of the session." , but you don't want it static ? Confusing.
you can always do
delete object MyStaticProperty
if you want to remove the object from the session
1) The "don't be static" constraint refers to the site this code will be run on, as using static "class members" have resulted in other issues.
2) Hmmm.... in which case maybe I could just walk SESSION:FIRST-OBJECT / :NEXT-SIBLING and delete the objects in order to clean out all the objects between runs of the 4GL editor....
1) we have a "static" class that comprises simply of properties to
singleton classes
2) won't work. They do not appear in the
session:first-object/next-object chain. But they are still there. And
I wasn't talking about editor runs. We had a system run out of sockets
because the persistent procedure wasn't being deleted, so the class
didn't get removed from memory and the socket released ...
Trying to come up with a specific simple test case .
Come to think about it, both cases where this happened involved
sockets ... perhaps that's the problem, not the handles ...
So, here's a structure I'm thinking'll work as I want- as Julian mentioned, have a manager with static properties that point to instances that are used as singletons, and are non-static:
CLASS SessionManager:
DEFINE STATIC VARIABLE oUser AS SessionUser NO-UNDO.
DEFINE STATIC VARIABLE oSystem AS SessionSystem NO-UNDO.
DEFINE STATIC PUBLIC PROPERTY GetUser AS SessionUser
GET():
CheckUser().
RETURN(oUser).
END GET.
PRIVATE SET.
DEFINE STATIC PUBLIC PROPERTY GetSystem AS SessionSystem
GET():
CheckSystem().
RETURN(oSystem).
END GET.
PRIVATE SET.
METHOD PRIVATE STATIC VOID CheckSystem():
IF NOT VALID-OBJECT(oSystem) THEN
oSystem = NEW SessionSystem().
END METHOD.
METHOD PRIVATE STATIC VOID CheckUser():
IF NOT VALID-OBJECT(oUser) THEN
oUser = NEW SessionUser().
END METHOD.
END CLASS.
----------
Now, my test program shows that the resulting objects show up on the FIRST-OBJECt / NEXT-OBJECT chain, so they can be deleted and regenerated on successive runs, so one only has a "single" manager with static properties in order to implement the singleton property.
Test program to demonstrate follows.
NOTE: "SessionUser" and "SessionSystem" are both empty classes. (the class file only has CLASS ... END CLASS).
------------
DEFINE VARIABLE oSMgr AS SessionManager NO-UNDO.
DEFINE VARIABLE oSUser AS SessionUser NO-UNDO.
DEFINE VARIABLE oSSys AS SessionSystem NO-UNDO.
DEFINE VARIABLE oObj AS Progress.Lang.Object NO-UNDO.
DEFINE VARIABLE oNextObj AS Progress.Lang.Object NO-UNDO.
DEFINE VARIABLE is-v1 AS LOGICAL NO-UNDO.
DEFINE VARIABLE is-v2 AS LOGICAL NO-UNDO.
oSUser = SessionManager:GetUser.
oSSys = SessionManager:GetSystem.
oObj = SESSION:FIRST-OBJECT.
REPEAT WHILE VALID-OBJECT(oObj):
oNextObj = oObj:NEXT-SIBLING.
DISPLAY
oObj:tostring() FORMAT "X(30)"
oObj:equals(oSUser)
oObj:equals(oSSys)
VALID-OBJECT(oObj) @ is-v1
WITH DOWN.
DELETE OBJECT oObj.
DISPLAY
VALID-OBJECT(oObj) @ is-v2
WITH DOWN.
DOWN.
oObj = oNextObj.
END.
jmls wrote:
1) we have a "static" class that comprises simply of properties to singleton classes
Ok - I modeled my test program after that.
2) won't work. They do not appear in the session:first-object/next-object chain. But they are still there. And I wasn't talking about editor runs. We had a system run out of sockets because the persistent procedure wasn't being deleted, so the class didn't get removed from memory and the socket released ...
As the test program shows, the object instances do appear in the FIRST/NEXT object chain.
Come to think about it, both cases where this happened involved sockets ... perhaps that's the problem, not the handles ...
I'm thinking if you didn't properly handle the socket shutdown / deletion in the destructor, they _may_ have hung around and caused your out-of-sockets problem.
1). I saw - but I think that this is easier on the eye :
def static property SessionFoo as class library.SessionFoo no-undo
get():
if not valid-object(SessionFoo) then SessionFoo = new
library.sessionFoo().
return SessionFoo.
end get. private set .
2) No, it was something to do with the auto GC. I put a message in the
destructor which never appeared. If I manually deleted the object,
things worked just fine
jmls wrote:
2) No, it was something to do with the auto GC. I put a message in the destructor which never appeared. If I manually deleted the object, things worked just fine
Objects will not be GC'd if there are any references to them - are you sure all the references to the object were gone?
jmls wrote:
1). I saw - but I think that this is easier on the eye :
def static property SessionFoo as class library.SessionFoo no-undo
get():
if not valid-object(SessionFoo) then SessionFoo = new
library.sessionFoo().
return SessionFoo.
end get. private set .
That's another possibility.
The reason for my structure is to seperate the instantiation logic from the GETter logic. This allows for other portions of the code to call the instantiating method w/out having to reference the property, and if the object's instantiation isn't a straightforward NEW, it keeps the associated mess away from the property GETter.
The structure you're using certainly benefits from not needing to code a method per property though.