#swapping handles
6 messages in this thread
I would find it handy to be able to take two objects and swap their handles, so
that the handle of one pointed to the data of the other and vice versa. Like
this:
void HSwap(CObject *o1, CObject *o2)
{
Handle h1 = o1, h2 = o2;
Ptr p1 = *h1, p2 = *h2;
*h1 = p2;
*h2 = p1;
}
(with appropriate HLocking added). For one thing, this would make for an
elegant Do/Undo scheme, in which you could save an object before Doing anything
to it, then on Undo or Redo, just swap handles.
Is there any danger in this?
— Jim
I know that, under Symantec C++ with virtual methods, you're probably begging
for trouble doing this. More than likely you'll have trouble under THINK C,
also.
I'm not certain, but it's quite probable that the handle to an object points to
more than just the "data" (instance variables). There's probably also some
information to make virtual functions work correctly, and to make the member
function do its thing.
I would suggest using the standard TCL way of doing Undo, by using a task.
Joe
Jim,
I am not sure if you can dereference an object the way that you are trying to.
But if you were instead to something like the following:
void HSwap(CObject *o1, CObject *o2)
{
Handle h1 = (Handle) o1, h2 = (Handle) o2, temp;
long objSize;
temp = NewHandle(objSize = GetHandleSize(h1));
BlockMove(*h1, *temp, objSize);
BlockMove(*h2, *h1, objSize);
BlockMove(*temp, *h2, objSize);
DisposHandle(temp);
}
It should work correctly, AS LONG AS THE TWO OBJECTS ARE FROM THE SAME CLASS,
and they are both derived from __machdl or __pasObject (?… If they are handle
objects). There is vTable Information stored within each class, but it is
identical for every object of that class.
jud spencer
Jim–
I think the other replies to you message may be confused at least in talking
about virtual method tables and classes. Jud is probably right that you'll
have to copy the object contents.
At first glance, what you're proposing ought to work: simply swapping the
master pointers which are pointed to by the two handles. Unfortunately, I
don't think it can be done quite this simply because the block header (located
before the object's data block itself and maintained by the Memory Manager)
contains a copy of the handle (actually a "relative handle"). If you just
changed the master pointer as you propose, the handle in the block header would
be wrong.
I'm not sure how this copy of the handle in the block header is used–it is
certainly used by the RecoverHandle function, which converts a block pointer
back to a handle, but there are probably other reasons that this handle is
maintained.
Of course, you could update the handle in the block header also, but then you'd
be dependent on the structure of the block header (which may have changed with
System 7 and 32-bit mode).
Look at the Memory Manager chapter in Inside Mac Vol. I for details about the
block header. I think Vol. VI has more info about how these data structures
were changed for System 7; it probably contains strong words to the effect of,
"any programmer trying to manipulate Memory Manager internal structures will be
sent straight to MacHell."
Hope this helps.
–Ken
Ken:
>>>
Look at the Memory Manager chapter in Inside Mac Vol. I for details about the
block header. I think Vol. VI has more info about how these data structures
were changed for System 7
<<<
No. Inside Mac completely omits 32-bit Memory Mgr data structures. I'm sure
that was done deliberately to prevent programmers from depending on them. They
could conceivably change again.
Block headers in 32-bit mode have a very similar structure as in 24-bit mode,
but they are 12 bytes instead of 8.
Steve