I am working on a C module that has a method like so:
int do_something(string s, array|void extras)
If they passed the method an array, then I would like to fill it in with some extra data for them. How do I do this, and make sure that it doesn't mess up the reference so they can actually access the data I put in the array for them?
Thanks Adam
On Mon, 3 Jul 2006 23:30:01 +0000 (UTC) "Martin Nilsson (Opera Mini - AFK!) @ Pike (-) developers forum" 10353@lyskom.lysator.liu.se wrote:
If you resize an array you will lose the reference.
How come? I mean, I see that realloc_array creates a whole new array, but why does it do that? Couldn't it just realloc the array of svalues and adjust size and malloced_size?
Adam
On Mon, 3 Jul 2006 21:08:22 -0400 Adam Montague amontague@siriushosting.com wrote:
If you resize an array you will lose the reference.
How come? I mean, I see that realloc_array creates a whole new array, but why does it do that? Couldn't it just realloc the array of svalues and adjust size and malloced_size?
Adam
To clarify, I don't mean "can we change how realloc_array works". I am just wondering if its safe for me to make my own array resizing function just for this. If I lock the array with its mutex, then realloc() the item array, and adjust the size and malloced_size, then unlock the mutex am I safe? What is the real_item[1] for?
And while I am at it, how come pike doesn't have explicit pass by reference? Are there objections to adding it?
Thanks Adam
You can easily pass by reference explicit by putting things in for instance an array or object.
(No, it wasn't the direct answer on your question. ;))
This is simply how the semantics of arrays are defined in Pike. An array has an invariant size, just as a string has invariant contents. []= modifies an array destructively, but other array operations (such as +) create new arrays instead. As an optimization, the array can be resized in place _if no other references exist_, but semantically there is always a new array created.
Example:
array z = ({ 17, 42 });
foo(z);
void foo(array x){ x[0]++; // z[0] becomes 18 x += ({ 3 }); // `+ generates a new array ({ 18, 42, 3 }) and // a reference to this array is stored in x x[1]++; // x[1] becomes 43, but z is still ({ 18, 42 }) }
As for the _reason_ why arrays have these semantics, I expect it's because of this: When an array grows, it might be necessary to allocate new memory for it. Since references are pointers to the data, reallocating an array which has references would mean having to find all those references and update them, which would take a lot of time.
couldn't the time problem be solved by in direct references? (ie, all pike level references point to one reference location. and this reference location then points to the real memory. if the memory location changes then only the reference location needs to be updated.
ok, lookups would be a bit slower because one extra lookup is required, but other than that, i don't see any problem.
am i missing something?
note that i am not arguing to change things, i am just trying to understand, and maybe suggesting that the reason for breaking rerefences is elsewhere. (like other problems that may occur when the size of an array changes underneath you)
greetings, martin.
Yes, as a general rule (coined by David Wheeler), all problems in computer science can be solved by another level of indirection. But that usually will create another problem. Pike chooses not to, and, while a potential gotcha should you not be aware of it, it is a tradeoff worth making.
pike-devel@lists.lysator.liu.se