-----Original Message-----
From: Laurence Harris [mailto:email@hidden]
Sent: Tuesday, June 12, 2007 9:27 PM
To: Yaron Tadmor
Cc: carbon-dev
Subject: Re: Creating a Handle from an existing memory
On Jun 12, 2007, at 4:43 AM, Yaron Tadmor wrote:
If you look at various packages supplying memory management, some
allow
you to pass your own memory and even your own deallocation method.
For
example, boost:share_ptr.
Boost is not part of the OS. I'm not aware of any part of the Mac OS
that can release your C++ objects for you if they were allocated with
new. Furthermore, let's suppose such an API exists. What is supposed
to happen in the last line of the following:
Char *myP = new char[100];
Handle myH = MemoryToHandle (myP, 100);
SetHandleSize( myH, 200 ); // <-- what happens here?
Or better yet:
CThing *myP = new CThing();
Handle myH = MemoryToHandle (myP, sizeof( CThing ) );
SetHandleSize( myH, 2 * sizeof( CThing ) ); // <-- what happens here?
Now you need to provide allocation and deallocation functions. Messy.
Very messy IMO.
If you want resizable memory and you're using C++, use a vector.
By default, when reference counting drops to
0, it calls c++ delete on the object. But you could very well pass a
deleter object which does something else.
So it's perfectly fine to assume such a MemoryToHandle function can
be
available,
Not really:
- If it were available it would be in MacMemory.h. Since there is no
such API in MacMemory.h and no such API is documented anywhere, it's
actually perfectly fine to assume such a function does *not*
exist. ;-) Furthermore, it should be obvious that they wouldn't have
added such functionality in Carbon (see below for why it's obvious to
me).
- The code you provided:
Handle myH = MemoryToHandle (myP, 100);
didn't have any provision for specifying how the memory should or
should not be released. The function you describe in your discussion
above is reasonable; the one to which I was responding was not.
- Resizing such a handle would be problematic. Handles are not just
allocated and released, they are also resizable. Would you have the
Memory Manager simply return an error if you tried to resize one of
these handles?
marking that handle as a "no delete" handle. Meaning that
when it's released, the memory is not to be deleted, and deletion
should
be handled by the user. Carbon has quite a few examples of such
things.
Yes, but there have been no new APIs introduced for creating handles
in Carbon (or for many years before that ;-), and if there were,
they'd be in MacMemory.h with all the other basic handle APIs.
They *could* have introduced such APIs (although they would involve
issues such as I describe above), but handles are very much a Mac
thing that exist to facilitate having blocks of memory that can move
to avoid memory fragmentation. Since this need has essentially
disappeared in Mac OS X and Apple encourages developers to use malloc
and new to allocate memory, I'm sure they saw little or no value in
enhancing the Memory Manager to do the kind of thing you describe.
Now that Mac OS X is based on Unix some of the old Mac-specific
technologies are pretty much only supported to provide legacy support
for applications using them.
For example, some CF creation APIs let you specify an deallocator.
You can specify kCFAllocatorMalloc, in which case CF will release the
memory for you, but you can't specify a deallocator for memory
allocated with NewPtr. I'm sure the old Memory Manager is considered
legacy technology by the people driving Mac OS X. It hasn't been
deprecated and may never be deprecated, but I'd be very surprised if
they ever do anything to enhance any of it.
And as a test, I tried using PtrToHand and PtrToXHand, passing my
c++
allocated memory instead of a real Ptr allocated by the system.
Guess
what.... It worked!!! Releasing the handle, did not try to delete
the
memory, as I would expect.
Of course it worked. Both of these APIs allocate a new block of
memory or resize the existing memory and copy the data to it. A
pointer allocated by new is a valid pointer and any valid address
will work with these APIs. You can even use the address of a stack
variable to copy its contents to a handle:
Rect r = { 0,0,100,100 };
Handle h;
err = PtrToHand( &r, &h, sizeof( Rect ) );
In all cases disposing of the handle will release the handle's
memory, but not the original, which the Memory Manager ignores once
it's been copied.
So, yes, I've been programming long enough to know such questions
are
certainly in place.
Matter of perspective. ;-) From my perspective, everything from the
lack of such an API in MacMemory to the various issues I mention
about make it unreasonable to expect the existence of such an API.
Now, all that said, the only value I could see in this it if you need
to pass something to an old API that expects a handle and you don't
want to copy data, but the right answer there is for Apple to provide
new APIs that accept pointers.
Larry