Entraides et échanges autour de la technologie Scol - Informations and exchanges on the Scol technology
Vous pouvez changer la langue de l'interface une fois inscrit - You can change the language once registered
You are not logged in.
in the code below (I assume) that the vm allocates memory locations for all the variables contained in a Cylinder object whenever one is created....at what point (before the user shuts down the console) does the vm free the memory allocated for the instances of Cylinders?
in the example below, is the memory taken up by the two Cylinders that are created then freed once main() function is finished executing?
struct Cylinder =[
Fradius : F,
Fheight : F,
funreturnheightasintergerasstring: fun[Cylinder] S,
funreturnarea : fun [Cylinder] F,
funreturnvolume: fun[Cylinder] F
]mkCylinder;;
fun returnheight(dcylinder)=
let ftoi dcylinder.Fheight -> height in
itoa height;;
fun return_area_function(dyclinder)=
let dyclinder.Fradius *. PIf-> result in
result;;
fun return_volune_function(dyclinder)=
let return_area_function dyclinder-> area in
area *. dyclinder.Fheight;;
fun initcylinder(radius, height, returnheightfunction, returnareafunction, returnvolumefunction)=
_fooS "initializing cylinder";
mkCylinder [radius height returnheightfunction returnareafunction returnvolumefunction];;
fun copy_this_cylinder(dcylinder)=
initcylinder dcylinder.Fradius dcylinder.Fheight dcylinder.funreturnheightasintergerasstring dcylinder.funreturnarea dcylinder.funreturnvolume;;
fun main()=
_showconsole;
let initcylinder 102.0 19.087 @returnheight @return_area_function @return_volune_function -> dcylinder in
(
_fooS strcatn "the height of the cylinder as a float converted to an interger converted to a string is " :: (returnheight dcylinder) :: nil;
_fooS strcatn "the area taken up by the cylinder is ":: (ftoa (return_area_function dcylinder)):: " square meters."::nil;
_fooS strcatn "the volume taken up by the cylinder is " ::(ftoa (return_volune_function dcylinder)):: " cubic meters"::nil;
let copy_this_cylinder dcylinder-> new_cylinder in
(
_fooS "creating new cylinder and changing radius from 102.0 to 10.5 with copy_this_cylinder (dcylinder) function";
set new_cylinder.Fradius= 10.5;
_fooS strcat "the radius of the copied cylinder is" ftoa new_cylinder.Fradius;
);
);
0;;
Last edited by hebdemnobad (24-Nov-2015 03:00:08)
Offline
Hello
Right, mkCylinder is the constructor to allocate in memory and create in the current Scol environment a Cylinder object.
The object can be freeed when two events :
- when the VM exits (or the owner channel is closed);
- when the object is no longer needed. In this case, the Scol garbage collection (GC) should find, destroy and deallocate the such objects.
In your example, dcylinder should be freeed after the end of the next instruction. Indeed, dcylinder is created in a local variable.
Same thing for new_cylinder.
The locale variables are not reachable when the next instruction ends. This is sure. But the objects can be still in memory until the GC destroys it.
Offline
I see. In the example above, two cylinders are created, one with initcylinder and the other with copy_this_cylinder. Is there a way I could use scol code at the end of the main function to deallocaye memory before main terminates and the cylinders become unreachable?
I've seen many functions in the 3d API to destroy objects but was wondering what to do with other objects, like basic scol types or structs.
Last edited by hebdemnobad (24-Nov-2015 14:25:13)
Offline
You can not do that explicitely !
Scol manages itself the memory.
In some APIs, functions destroys some objects explicitely. These objects call externaly (= third party library, = not directly managed by Scol) a memory function. But even in this case, they should be automatically destroyed when the VM exits, their owner channel are closed or if they are a local object.
If you would do these inoperable objects, you can set them to nil.
set dcylinder = nil;
Something like unset doesn't exist in Scol.
Another way, if this is a critical problem, is to create a new channel from the current channel, to load in it a package with all structure (struct) code and to close it when you no longer need. With your code, you may write that :
In a cylinder package (cylinder.pkg) :
I just change your main function name to "mainCylinder" and i remove the _showconsole function.
struct Cylinder =[
Fradius : F,
Fheight : F,
funreturnheightasintergerasstring: fun[Cylinder] S,
funreturnarea : fun [Cylinder] F,
funreturnvolume: fun[Cylinder] F
]mkCylinder;;
fun returnheight(dcylinder)=
let ftoi dcylinder.Fheight -> height in
itoa height;;
fun return_area_function(dyclinder)=
let dyclinder.Fradius *. PIf-> result in
result;;
fun return_volune_function(dyclinder)=
let return_area_function dyclinder-> area in
area *. dyclinder.Fheight;;
fun initcylinder(radius, height, returnheightfunction, returnareafunction, returnvolumefunction)=
_fooS "initializing cylinder";
mkCylinder [radius height returnheightfunction returnareafunction returnvolumefunction];;
fun copy_this_cylinder(dcylinder)=
initcylinder dcylinder.Fradius dcylinder.Fheight dcylinder.funreturnheightasintergerasstring dcylinder.funreturnarea dcylinder.funreturnvolume;;
fun mainCylinder ()=
let initcylinder 102.0 19.087 @returnheight @return_area_function @return_volune_function -> dcylinder in
(
_fooS strcatn "the height of the cylinder as a float converted to an interger converted to a string is " :: (returnheight dcylinder) :: nil;
_fooS strcatn "the area taken up by the cylinder is ":: (ftoa (return_area_function dcylinder)):: " square meters."::nil;
_fooS strcatn "the volume taken up by the cylinder is " ::(ftoa (return_volune_function dcylinder)):: " cubic meters"::nil;
let copy_this_cylinder dcylinder-> new_cylinder in
(
_fooS "creating new cylinder and changing radius from 102.0 to 10.5 with copy_this_cylinder (dcylinder) function";
set new_cylinder.Fradius= 10.5;
_fooS strcat "the radius of the copied cylinder is" ftoa new_cylinder.Fradius;
);
);
0;;
In a main package :
proto mainCylinder = fun [] I;;
// Return the new channel created
fun callCylinder ()=
let _openchannel nil "_load \"tests/cylinder.pkg\"" _envchannel _channel -> newChnannel in
(
mainCylinder;
newChnannel
);;
fun closeCylinder (channel)=
_killchannel channel;
0;;
fun main()=
_showconsole;
closeCylinder callCylinder;
0;;
mainCylinder must be prototyped : this function is still unknown when the main package is loaded by the VM.
Note : if you want call this function only, you can call it directly when the new channel is created. In this case, your callCylinder function should only be :
fun callCylinder ()=
_openchannel nil "_load \"tests/cylinder.pkg\"\nmainCylinder" _envchannel _channel;;
In the main function (or anywhere you want), you call the function which creates the new channel (here : callCylinder) and, later (when you want), you close this channel (here : closeCylinder).
Offline
thanks Iri!
so what exactly does the code:
set dcylinder = nil;
do in terms of freeing memory.
what I'm thinking of is how scol would handle a game or simulation where you have, say, thousands of animals swimming around the viewer (most would not be rendered by the so3 engine, but scol would keep track of them since once they come close to the viewer, they will become visible), where each animal holds variables like strings (names), hit-points (integers) and transforms ([scale][location][rotation][speed][transform coefficient])[FFF][FFF][FFFF][F][F] tuples, where they are eating each other and mating, therefore destroying and creating new animals, increasing and decreasing hitpoints.
or the simulation of a planet containing thousands of scene nodes (buildings or perhaps life forms) which must be dynamically created and destroyed.
Last edited by hebdemnobad (24-Nov-2015 15:30:36)
Offline
so what exactly does the code:
set dcylinder = nil;
do in terms of freeing memory.
Look this code :
struct MyStructure = [
myInteger : I,
myString : S
] mkMyStructure;;
typeof myS = MyStructure;;
fun createGlobalStructure (iValue, szValue)=
set myS = mkMyStructure [iValue szValue];
0;;
fun createLocalStructure (iValue, szValue)=
mkMyStructure [iValue szValue];;
fun testGlobalStructure ()=
_fooS "Global ... !";
_fooId myS.myInteger;
_fooS myS.myString;
0;;
fun testLocalStructure (localStructure)=
_fooS "Local ... !";
_fooId localStructure.myInteger;
_fooS localStructure.myString;
0;;
fun main ()=
_showconsole;
_fooS "Test one :";
testGlobalStructure;
testLocalStructure nil;
_fooS "Test two :";
createGlobalStructure 5 "The life is beautiful !";
testGlobalStructure;
testLocalStructure createLocalStructure 15 "Shinning";
_fooS "Test three :";
set myS = nil;
testGlobalStructure;
let createLocalStructure 15 "Shinning" -> local in
(
set local = nil;
testLocalStructure local
);
_fooS "Test four :";
createGlobalStructure 19 "One Flew Over the Cuckoo's Nest";
testGlobalStructure;
0;;
It displays in the log/console :
Test one :
Global ... !
NIL
NIL
Local ... !
NIL
NIL
Test two :
Global ... !
5
The life is beautiful !
Local ... !
15
Shinning
Test three :
Global ... !
NIL
NIL
Local ... !
NIL
NIL
Test four :
Global ... !
19
One Flew Over the Cuckoo's Nest
In the test 1, no struct variable is created, so all fields are nil.
In the test 2, global and local variables are created, all fields are set.
In the test 3, global and local variables are been created, then they set to nil. All fields are nil too.
In the test 4, global variable is set again. Their fields are not nil, the global variable is never freeed while the VM is not exited (or the owner channel exists).
Offline
what I'm thinking of is how scol would handle a game or simulation where you have, say, thousands of animals swimming around the viewer (most would not be rendered by the so3 engine, but scol would keep track of them since once they come close to the viewer, they will become visible), where each animal holds variables like strings (names), hit-points (integers) and transforms ([scale][location][rotation][speed][transform coefficient])[FFF][FFF][FFFF][F][F] tuples, where they are eating each other and mating, therefore destroying and creating new animals, increasing and decreasing hitpoints.
or the simulation of a planet containing thousands of scene nodes (buildings or perhaps life forms) which must be dynamically created and destroyed.
ooh ... several way to proceed ....
I think there is a client part and a server part. You can seperate datas in the client or in the server. The server stores the datas but it doesn't play. The client doesn't need all datas to play. You can also use lists to add / remove / modify the datas. in the server, you can work in memory or from data files. And more, i don't very cogitate.
Offline
I see, so what happens to the memory allocated by
let createLocalStructure 15 "Shinning" -> local in
when
(
set local = nil;
);
in other words, are the memory addresses allocated by "local" now free to be assigned to other variables, such as other MyStructures?
Last edited by hebdemnobad (24-Nov-2015 16:50:30)
Offline
I made a mistake in my previous example. I create again a new structure content in calling the mkMyStructure constructor. So, the result is false !
In the new code below, i set (not create) the fileds of the global and the local variable after set the variables to nil (test 3 and 4).
struct MyStructure = [
myInteger : I,
myString : S
] mkMyStructure;;
typeof myS = MyStructure;;
fun createGlobalStructure (iValue, szValue)=
set myS = mkMyStructure [iValue szValue];
0;;
fun createLocalStructure (iValue, szValue)=
mkMyStructure [iValue szValue];;
fun setGlobalStructure (iValue, szValue)=
set myS.myInteger = iValue;
set myS.myString = szValue;
0;;
fun setLocalStructure (s, iValue, szValue)=
set s.myInteger = iValue;
set s.myString = szValue;
0;;
fun testGlobalStructure ()=
_fooS "Global ... !";
_fooId myS.myInteger;
_fooS myS.myString;
0;;
fun testLocalStructure (localStructure)=
_fooS "Local ... !";
_fooId localStructure.myInteger;
_fooS localStructure.myString;
0;;
fun main ()=
_showconsole;
_fooS "Test one :";
testGlobalStructure;
testLocalStructure nil;
_fooS "Test two :";
createGlobalStructure 5 "The life is beautiful !";
testGlobalStructure;
testLocalStructure createLocalStructure 15 "Shinning";
_fooS "Test three :";
set myS = nil;
testGlobalStructure;
let createLocalStructure 15 "Shinning" -> local in
(
set local = nil;
testLocalStructure local;
setLocalStructure local 25 "Wolf";
testLocalStructure local;
);
_fooS "Test four :";
setGlobalStructure 19 "One Flew Over the Cuckoo's Nest";
testGlobalStructure;
0;;
The console prints :
Test one :
Global ... !
NIL
NIL
Local ... !
NIL
NIL
Test two :
Global ... !
5
The life is beautiful !
Local ... !
15
Shinning
Test three :
Global ... !
NIL
NIL
Local ... !
NIL
NIL
Local ... !
NIL
NIL
Test four :
Global ... !
NIL
NIL
So, after set myS = nil; or set local = nil; the variables are known but they are inoperable. To use them, you must call mkMyStructure again.
Is the variable memory freeed ? Not totally, its address is kept in the Scol heap as you declare a variable with typeof.
typeof myS = MyStructure;; myS is currently "empty" (nil). Like in C, an address is reserved. You are able to set the fields later.
A local variable is freeed when the next instruction ends.
Offline
in other words, are the memory addresses allocated by "local" now free to be assigned to other variables, such as other MyStructures?
Its memory address is not freeed ! It is empty and you must (re)create the content by the constructor.
Offline
If you want be safer, check the variable before to set a field.
By example :
fun createGlobalStructure (iValue, szValue)=
set myS = mkMyStructure [iValue szValue];
0;;
fun setGlobalStructure (iValue, szValue)=
if myS == nil then // this is safer !
createGlobalStructure iValue szValue
else
(
set myS.myInteger = iValue;
set myS.myString = szValue;
0
);;
Offline
I see, perhaps then if I create a global list like
typeof Cylinderlist= [[I Cylinder] r1];;
and
typeof Deleted_Cylinderlist= [I r1];;
I can add a new cylinder to the global list, and when a particular indexed cylinder and all its fields are set to NIL,its index is created in the Deleted_Cylinderlist.
When time comes to create a new cylinder, the vm could assign a new Cylinder to an index in the Deleted_Cylinderlist, and fill an 'empty' cylinder in the Cylinderlist with new values.
That way if hundreds of cylinders are being created and destroyed a second, and you have something like a hard limit to the number of cylinders (like, say 10,000), an empty Cylinder can be retrieved from the list and assigned new values, so the vm could search through the list of empty indexes in the Deleted_Cylinderlist, pick one index, and put new values in an empty Cylinder in the [[I Cylinder] r1] list.
Or something along those lines.
Offline
Yes.
Or you could define a limit of the size list.
By example :
- Can I a new Cylinder create ?
-> if the Cylinder list size is < max then ok, you can create it.
-> if the Cylinder list size is >= max then ko, you can not create it.
- I want delete a Cylinder :
-> If the Cylinder is in the Cylinder list, ok, it is deleted and it is removed from the list.
-> If the Cylinder is not in the Cylinder list, ko, there is a bug somewhere (or the Cylinder has not been created previously) !
Thus, with this method, you manage one list only. However, this list is not sorted. The sorting is important or not ?
Offline
I don't think in this case sorting is an issue because if I have a list of tuples such as [[I objecttype]r1] there are plenty of ways to find an object that has been emptied of values.
Thanks for answering these relatively abstract questions. They are applicable to any app/game/simulation where the vm is continually creating and destroying objects prior to vm shutdown. Another section for the O'Reilly book.
Offline
I don't think in this case sorting is an issue because if I have a list of tuples such as [[I objecttype]r1] there are plenty of ways to find an object that has been emptied of values.
You may search the first Cylinder object to nil.
typeof lCylinder = [[I Cylinder] r1];;
...
fun searchNilCylinder2 (list)=
if list == nil then
nil
else
let hd list -> [index cyl] in
if cyl == nil then
index // or hd list or what you want / need !
else
searchNilCylinder2 tl list;;
fun searchNilCylinder ()=
searchNilCylinder2 lCylinder;;
Note : you may include the index in the Cylinder structure ?
Another section for the O'Reilly book.
Yes
Offline
wip, i still have to manage the removal of specific cylinders from the cylinderlist with a timer, and i think i have to pass the index between a (some) function(s). todo..the objects have lifespans, and once the amount of cylinders reaches a specific number, the vm will have to wait for them to 'die' (be emptied of content) before they can be refilled with new values (two floats, radius and height)
typeof Cylinderlist = [[I Cylinder]r1];;
typeof Deleted_Cylinder_list =[I r1];;
//variable to keep track of total created cylinders
var Cylinder_counter = 0;;
//variable to keep track of empties cylinders
var Emptied_Cylinders =0;;
struct Cylinder =[
Fradius : F,
Fheight : F,
funreturnheightasintergerasstring: fun[Cylinder] S,
funreturnarea : fun [Cylinder] F,
funreturnvolume: fun[Cylinder] F
]mkCylinder;;
fun returnheight(dcylinder)=
let ftoi dcylinder.Fheight -> height in
itoa height;;
fun killcylinder (dcylinder)=
_fooS "stub for now, this function will kill cylinder,using the deletecylinder function with an index in the [[I Cylinder]r1] Cylinder list with a timer";;
fun return_area_function(dyclinder)=
let dyclinder.Fradius *. PIf-> result in
result;;
fun return_volune_function(dyclinder)=
let return_area_function dyclinder-> area in
area *. dyclinder.Fheight;;
fun initcylinder(radius, height, returnheightfunction, returnareafunction, returnvolumefunction)=
_fooS "initializing cylinder";
mkCylinder [radius height returnheightfunction returnareafunction returnvolumefunction];;
//deletes the first cylinder in the cylinder list
fun deletecylinder(cylinderlistindex)=
if ((sizelist Cylinderlist) == 0) then
(
_fooS "there are no cylinders to delete! none have been placed in the Cylinderlist yet!";
0;
)
else
(
let hd Cylinderlist -> [index dcylinder] in
(
//this does not remove the cylinder from the cylinder list, since it will still be in memory although unreachable, and we want to be as efficient as possible
//this function sets all the cylinder values to nil, and then places the index of the cylinder in the Deleted_Cylinder_list, so the vm can use the index
//this cylinder searches through the cylinder list to find a cylinder that still exists, and empties it of all values, I will use cylinderlistindex later
set dcylinder.Fradius=nil;
set dcylinder.Fheight=nil;
set dcylinder.funreturnheightasintergerasstring=nil;
set dcylinder.funreturnarea=nil;
set dcylinder.funreturnvolume=nil;
set dcylinder=nil;
set Deleted_Cylinder_list = index::Deleted_Cylinder_list;
_fooS strcatn (itoa (sizelist Deleted_Cylinder_list)):: " cylinders have been deleted, or, rather, set to nil in Cylinderlist." ::nil;
);
0;
);
0;;
//this function makes a new cylinder, given it's float radius and float height
fun makenewcylinder(fradius, fheight)=
if ((sizelist Deleted_Cylinder_list) == 0) then
(
//no cylinders have been deleted yet! place the new cylinder at the beginning of the list
_fooS "No cylinders have been deleted yet";
_fooS strcat (itoa sizelist Deleted_Cylinder_list) " are the amount of objects in the Deleted Cylinder list!";
let initcylinder fradius fheight @returnheight @return_area_function @return_volune_function -> lcylinder in
let Cylinderlist -> lcylinderlist in
let Cylinder_counter -> lcylindercounter in
(
set Cylinderlist = [lcylindercounter lcylinder]::Cylinderlist;
set Cylinder_counter = Cylinder_counter+1;
_fooS strcatn "there are: " :: (itoa (sizelist Cylinderlist)):: " cylinders in the Cylinderlist"::nil;
_fooS "this cylinder will live for 500 milliseconds, then the vm will kill it";
killcylinder lcylinder;
0;
);
)
else
//get an index from the deleted cylinder list
(
let sizelist Deleted_Cylinder_list ->lcounter in
(
while lcounter >0 do
(
if ((hd Deleted_Cylinder_list) != nil) then
(
let hd Deleted_Cylinder_list -> lDeleted_Cylinder_listindex in
(
//do switch statement here! use index from head of Deleted_Cylinder_list and get Cylinder from the [I Cylinder] tuple in Cylinderlist
//and put new values into that cylinder. that way you are using already allocated memory for a cylinder set to 'nil' for all its values
//fetch a nil Cylinder from the lDeleted_Cylinder_listindex and put the radius and height values in it
let switch Cylinderlist lDeleted_Cylinder_listindex -> dcylinder in
(
set dcylinder = initcylinder fradius fheight @returnheight @return_area_function @return_volune_function;
_fooS "filled an empty cylinder with new values!";
killcylinder dcylinder;
);
set lcounter = lcounter-1;
0;
)
)
else
(
set lcounter = lcounter-1;
0;
);
)
);
0;
);
0;;
fun main()=
_showconsole;
_fooS "the code up to now has compiled OK!";
deletecylinder nil;
makenewcylinder 1.0 12.0;
makenewcylinder 411.0 102.0;
deletecylinder nil;
makenewcylinder 411.0 102.0;;
Last edited by hebdemnobad (25-Nov-2015 20:26:12)
Offline
I've not really understand what you want here. Your code is not clear (perhaps old code is remained ...).
Your objective :
- Add some cylinders.
- Each cylinder lives a while. So, it dies after a moment.
- Sometimes, a cylinder can be dead before the end of its live.
Is it right ?
Very quickly, here is my idea :
struct Cylinder =[
iId : I, // cylinder identifier
Fradius : F,
Fheight : F,
funreturnheightasintergerasstring: fun[Cylinder] S,
funreturnarea : fun [Cylinder] F,
funreturnvolume: fun[Cylinder] F,
tClock : Timer // the cylinder life time
] mkCylinder;;
typeof lCylinder = [Cylinder r1];; // all living cylinders
var periodTimer = 1000;; // 1000 ms, the life time
var id = 0;;
/* --------- */
// Miscelleanous
// Note : A function already exists for that in the standard library
fun removeItemInList (list, item)=
if list == nil then
nil
else
if item == hd list then
tl list
else
(hd list) :: removeItemInList tl list item;;
/* --------- */
// initialize a Cylinder structure
fun initCylinder ()=
mkCylinder [++id nil nil nil nil nil nil];;
/* --------- */
// setters
fun setCylinderRadius (sCylinder, fRadius)=
set sCylinder.Fradius = fRadius;
sCylinder;;
fun setCylinderHeight (sCylinder, fHeight)=
set sCylinder.Fheight = fHeight;
sCylinder;;
/* --------- */
fun deleteCylinder (sCylinder)=
if sCylinder == nil then
(
_fooS "The cylinder was nil !";
1
)
else
(
_deltimer sCylinder.tClock;
set lCylinder = removeItemInList lCylinder sCylinder;
_fooS sprintf "The cylinder '%d' is destroying. It will remain %d cylinder(s)." [sCylinder.iId sizelist lCylinder];
set sCylinder = nil;
0
);;
/* --------- */
fun cbCylinderTimer (timer, sCylinder)=
_fooS sprintf "The cylinder %d dies ..." [sCylinder.iId];
deleteCylinder sCylinder;;
fun makeCylinderTimer (sCylinder)=
set sCylinder.tClock = _rfltimer _starttimer _channel periodTimer @cbCylinderTimer sCylinder;
sCylinder;;
/* --------- */
fun addCylinder (fRadius, fHeight)=
let initCylinder -> sCylinder in
(
setCylinderRadius sCylinder fRadius;
setCylinderHeight sCylinder fHeight;
makeCylinderTimer sCylinder;
set lCylinder = sCylinder :: lCylinder;
_fooS sprintf "The new cylinder '%d' is added. The total is currently of %d" [sCylinder.iId sizelist lCylinder];
sCylinder
);;
/* --------- */
fun main ()=
_showconsole;
_fooS " Application starts now !";
let mktab 5 nil -> array in // for my convenience only !
(
deleteCylinder array.0;
set array. 0 = addCylinder 1.0 12.0;
set array. 1 = addCylinder 4.0 32.0;
set array. 2 = addCylinder 7.0 16.0;
deleteCylinder array. 0;
set array. 3 = addCylinder 1.0 12.0;
deleteCylinder array. 2;
);
0;;
The console prints :
Application starts now !
The cylinder was nil !
The new cylinder '1' is added. The total is currently of 1
The new cylinder '2' is added. The total is currently of 2
The new cylinder '3' is added. The total is currently of 3
The cylinder '1' is destroying. It will remain 2 cylinder(s).
The new cylinder '4' is added. The total is currently of 3
The cylinder '3' is destroying. It will remain 2 cylinder(s).
The cylinder 2 dies ...
The cylinder '2' is destroying. It will remain 1 cylinder(s).
The cylinder 4 dies ...
The cylinder '4' is destroying. It will remain 0 cylinder(s).
Offline
thx iri, my goal is dynamically creating and destroying objects in a global list while minimizing the amount of memory taken up by them. so if the list is full, no more objects can be created, the objects are periodically 'dying' which means emptying the of value, and when time comes to create a new object, if there is an object with empty values in the list (or array, perhaps an table as you made it is a better solution), then that object is filled with new values
I coded with a list, because, for a time, memory allocation is less than if creating a table it automatically has the maximum numbers of elements. I'm just figuring out (for the sake of it) how to create and destroy lots of objects while being the most efficient with memory, so that local objects are not left on the heap and taking up memory where they can just be emptied of values and refilled with new ones
The problem I'm trying to think through is: if you create a local object and remove it from a list, then it's occupying memory until the garbage collector steps in. So if I cannot manually deallocate the memory set aside for an object, it's better to empty the values from an object and insert new values into it
I hope that makes things clear (and that will be determined by how clear the ideas are to me, which I'm not quite sure of here)
Thanks as always Iri
I will study your code iri it's much simpler than my spaghetti
Offline
Aha...are there drawbacks to using it?
Offline
gc take time so you should use it really only when you need it.
sometimes it's worst than better so do not abuse
I agree. Danger.
Else, it is not hidden
http://redmine.scolring.org/projects/sc … emory.html
Offline
gc take time so you should use it really only when you need it.
sometimes it's worst than better so do not abuse
I see, so at what point does the vm free the memory taken up by the cylinder after the removal of a cylinder from the global list lCylinder in the line below? Answer at your leisure.
(hd list) :: removeItemInList tl list item;
Offline
I don't remerber precisely.
(hd list) :: removeItemInList tl list item;
This line removes nothing. Instead of that, it adds (so, it keeps) the current item.
In fact, once the function finishes, the returned list is the truncated list.
Thus, it is after the line below that a GC could free the deleted item.
set lCylinder = removeItemInList lCylinder sCylinder;
I'm clear ?
Offline
Scol manages itself the memory. The developer should not manage himself the memory.
_freememory is dangerous because :
- it disturbs the internal working;
- it depends on the heap state at this moment;
- it depends on the how / when the processor performs this (see scheduling for more informations about that).
Mainly if you call frequently _freememory !
Finally, there is a risk to corrupt the memory and then to induce a crash.
Offline