Storing a reference to an object ...
BlitzMax Forums/BlitzMax Programming/Storing a reference to an object ...
| ||
I have a conceptual problem, and I can't figure out the most effective way to do it. I have two objects of the exact same type, but I want one to be the "parent" of the other, so that when I manipulate one object I can then call back and perform functions on the parent as well. In short, when I create the "child", I want the "parent" to become inactive (through a flag setting). When the child has finished doing what it is going to do, I want it to reactivate (through the same flag) the parent. I thought of creating parent/child lists, but iterating through lists to find a single object seemed inefficient. I also considered using pointers, but I'm not comfortable enough with how Blitz handles memory to be sure of the form. This is the kind of thing I wanted to do: '----------------------------------------------------------- '***********************Widget Type ************************ '----------------------------------------------------------- Type Widget Field Name$ = Null Field Uses =0 Field pos_x,pos_y Field Is_child = False Field Parent:Widget Ptr = Null Field Is_Active = True Global WidgetList:TList '*************************Create**************************** Function CreateWidget:Widget(temp_name$,x,y,num_uses) temp_widget:widget = New widget temp_widget.name = temp_name temp_widget.pos_x = x temp_widget.pos_y = y temp_widget.uses = num_uses If WidgetList=Null Then WidgetList = CreateList() WidgetList.AddLast(temp_widget) Return temp.widget End Function '***********************Make Widget a child of another ************** Method MakeChild (in:widget Ptr) Is_child = True parent = in End Method '********************** Where the Widget does stuff, and where it turns off the parent!!!!! Method DoStuff() Var Parent.MakeInactive() 'This is where I try to make the parent object inactive but ' it doesn't work. I need to know either how to make the ' pointer able to refernce the method of the object or a ' better way to do this! ...... Do other stuff .... 'All the rest of the programming. Var Parent.MakeActive() ' Same issue... End Method ' ********************* Sets Flag to active ************************ Method MakeActive () Is_active = True End Method '***********************Sets flag to inactive ******************** Method MakeInactive() Is_active = False End Method End Type '---------------------------------------------------------------- '******************** Starts the main program ******************* '---------------------------------------------------------------- Global thing1:widget = Widget.CreateWidget ("First",1,1,0) Global thing2:widget = Widget.CreateWidget ("Second",1,1,0) thing2.MakeChild(Varptr thing1) thing2.DoStuff() '<----------------- The parent should be inactive While this is happening Any suggestions are welcome. I'd really rather avoid pointers altogether, but I can't think of any other way that doesn't involve looking through a "ParentList" or ChildList" etc... |
| ||
Why are you using pointers here in the first place? |
| ||
Well, I couldn't create a widget field in a widget type to store the widget, etc... (good old recursive declarations). This shouldn't work: Type widget Field Parent:widget new widget So I tried to find another way to store the location to the parent. Perhaps it would work without the "new widget", but I ended up going with a "ParentList:TList", because I realized one case where I might have to have more than one parent. I'm still curious if there is another (more efficient) way to store a parent, though. Besides, I could use some practice/experimentation with pointers and pointer references to variables, anyway... |
| ||
Uh, you can have recursive handles. You just have to clean um up manually. |
| ||
an example of storing a parent on the child and cleaning up after yourself:Strict Framework BRL.Blitz Import BRL.LinkedList Type widget Field name:String Field parent:widget=Null Field children:TList=Null Function createWidget:widget(name:String,parent:widget=Null) Local retval:widget=New widget retval.name=name retval.parent=parent Return retval EndFunction Method addchild:widget(name:String) ' init the list If children=Null Then children=New TList Local retval:widget=widget.createWidget(name,Self) children.AddLast(retval) Return retval EndMethod Method clearChildren() If children<>Null Local child:widget ' make sure we clear our childrens children For child=EachIn children child.clearChildren() Next ' clear out the list children.Clear() EndIf EndMethod ' delete will never fire unless all other references are gone first Method Delete() DebugLog("destroying: "+name) parent=Null EndMethod EndType DebugLog("mem: "+MemAlloced()) ' create the top level Local testwidget:widget=widget.createWidget("top_level") ' create some first level children testwidget.addchild(testwidget.name+": child1_1") testwidget.addchild(testwidget.name+": child2_1") testwidget.addchild(testwidget.name+": child3_1") ' create some second level children Local child:widget For child=EachIn testwidget.children child.addchild(child.name+": child1_2") child.addchild(child.name+": child2_2") child.addchild(child.name+": child3_2") Next child=Null DebugLog("13 total nodes we should see cleaned up at the End") DebugLog("mem: "+MemAlloced()) ' this is the big key... in order for something to be set to Null to work it ' must have no remaining references. this is a problem if a child still has ' a reference to the parent so you must get rid of the children first and those ' children must be sure to clean themselves up. testwidget.clearchildren() testwidget=Null FlushMem DebugLog("mem: "+MemAlloced()) should yield something like: mem: 1902 13 total nodes we should see cleaned up at the End mem: 3513 destroying: top_level: child3_1: child3_2 destroying: top_level: child3_1: child2_2 destroying: top_level: child3_1: child1_2 destroying: top_level: child2_1: child3_2 destroying: top_level: child2_1: child2_2 destroying: top_level: child2_1: child1_2 destroying: top_level: child1_1: child3_2 destroying: top_level: child1_1: child2_2 destroying: top_level: child1_1: child1_2 destroying: top_level: child3_1 destroying: top_level: child2_1 destroying: top_level: child1_1 destroying: top_level mem: 1902 Process complete |
| ||
That's pretty much the way I ended up doing it, except I didn't store the parent in a reference at all, just created a list for them. Also, instead of storing children (as I won't be using the code that way.. though I did build in a search routine to sort through the list for any child that has a parent's name... just in case, but slower), I only stored the parent of the object. Didn't have a list.clear() on the destruction routine, though, so that will be added. My main curiousity was the difference in memory footprint across the different methods, as I may end up with lots of "widgets." But I guess if all that is being stored is a pointer to the object (whether is a object reference, a variable pointer, or an entry in a list), then it doesn't make much difference. Thanks for the input, folks! |