[comp.sys.mac.programmer] HandleObject vs. 5+ meg of RAM and Virtual Memory

shite@unf7.UUCP (Stephen Hite) (07/06/90)

   If I have 5 or 8 meg of RAM and virtual memory (a.k.a System 7.0.2 :-))
is it really *worth* the limitations of using HandleObject?  Some of limitations
are (as taken from the MPW C++ Beta Manual):

   1. You can't "...declare global variables, local variables, arrays, members,
      or parameters of handle-based types (rather than pointers to them)."

   2. You can't use multiple inheritance (as discussed previously ad nauseum).

   3. "It is not possible to allocate an array of handle-based objects, for
      example, new MyObjects[10]."

   4. You cannot "...take a pointer to a field of an indirect class (i.e.,
      &x->y).  This restriction includes the implicit use of pointers by ref-
      erences, such as int& p = x->y."

There are a few more mentioned on pages 27 and 28 but I think I've included
the main ones.  I feel like I'm trying to build  a tree or forest of objects
and all the while I have to keep in mind that the ground below me is constantly
moving :-).   I can see it now..."Programmer's Guidelines to MPW C++" or 
"MPW C++...What Bjarne Stroustrup Didn't Tell You"...that'll be $35 pleeez. 

lippin@brahms.berkeley.edu (The Apathist) (07/07/90)

Recently shite@unf7.UUCP (Stephen Hite) wrote:
>   If I have 5 or 8 meg of RAM and virtual memory (a.k.a System 7.0.2 :-))
> is it really *worth* the limitations of using HandleObject?

In a word, no.  In four words, both yes and no.  And neither answer
depends on how much memory you have, virtual or not.

A popular misconception about C++ is that since its native objects are
"Pointer based" a call to NewPtr (or worse, malloc) is made for each
object.  The truth is that a native class works just like a struct --
if it's local, it goes on the stack; if global, it goes in global
space; if allocated with new, then it goes into the heap.

Most of my classes are C++ native ones.  They don't fragment the heap
at all -- mostly they're on the stack or in global space.  When they
are on the heap, I can put them in a handle, or even in part of a
larger structure that I put into the handle.  (As usual, I have to
keep an eye out for relocation -- it would be bad to have "this" slide
out from under a method.  But that's no worse than with any other
parameter.  Lock the handle, make a copy on the stack, or just don't
move memory, as appropriate.)

Of course, you do need HandleObjects and PascalObjects for dealing
with MacApp, and they're handy for classes you really want to store
that way.  Just don't think every object has to be one.

My recommendation is to ignore the different kinds of objects until
you've figured out how you want to store a thing.  Then choose the
kind of object that stores it where you want it.

A final note on virtual memory: handles are still important.  A
fragmented virtual memory leads to thrashing, while an unfragmented
one will map better into physical memory.  The combination of handles
and virtual memory will be a great strength of system 7.  On the other
hand, a weakness of the system 7 memory manager is fixed heap sizes.
This weakness is also less important if you keep a clean heap.

						--Tom Lippincott
						  lippin@math.berkeley.edu

	"It's a poor sort of memory that only works backwards."
						--Lewis Caroll

casseres@apple.com (David Casseres) (07/07/90)

In article <279@unf7.UUCP> shite@unf7.UUCP (Stephen Hite) writes:
>    If I have 5 or 8 meg of RAM and virtual memory (a.k.a System 7.0.2
> :-)) is it really *worth* the limitations of using HandleObject?
> Some of limitations are (as taken from the MPW C++ Beta Manual):

The reason for using HandleObject subclasses has little to do with the 
size of memory.  The virtue of handles is that they avoid *fragmenting* 
whatever memory space you use.  The virtue of HandleObjects, beyond that, 
is that they avoid the extreme tendency (on the Mac) of malloc to eat up 
memory.

>    1. You can't "...declare global variables, local variables, arrays
>       members, or parameters of handle-based types (rather than
>       pointers to them)."

This is not a problem.  All your handle objects have to be declared as 
typed pointers and allocated with new, rather than being declared directly 
as objects with automatic storage, that's all.

>    2. You can't use multiple inheritance (as discussed previously ad
>       nauseum).

And despite what its partisans say, you can do a helluva lot of good 
object-oriented programming without it.

>    3. "It is not possible to allocate an array of handle-based objects,
>       for example, new MyObjects[10]."

Again, not a real problem.  You have to write a loop to allocate each 
object, then stick its pointer into the array.  No big deal, and remember, 
no one is saying you have to use handle objects for everything.  Use them 
where they're useful.

>    4. You cannot "...take a pointer to a field of an indirect class
>       (i.e., &x->y).  This restriction includes the implicit use of
>       pointers by references, such as int& p = x->y."

Gackhhh.  Forgive my bigotry, but only a dyed-in-the-wool old-time C 
weenie, or a dyed-in-the-wool groping-for-the-future C** guru can even 
guess what that means you can't do!  Us ordinary mortals can probably 
still do a lot of good OOP without doing whatever that is... 

Handle objects are very nice and very useful, when used where they are 
appropriate, i.e. for objects that might otherwise cause heap fragging.  
The also avoid the evils of malloc, but if you want to avoid malloc 
without using handle objects, you can still create a PtrObject class as 
explained in the d e v e l o p  magazine article.

David Casseres
     Exclaimer:  Hey!

lsr@Apple.COM (Larry Rosenstein) (07/07/90)

In article <279@unf7.UUCP> shite@unf7.UUCP (Stephen Hite) writes:
>
>   If I have 5 or 8 meg of RAM and virtual memory (a.k.a System 7.0.2 :-))
>is it really *worth* the limitations of using HandleObject?  Some of limitations

A lot depends on your application.  Memory fragmentation occurs when you
have a lot of allocations & deallocations or varying sizes.  If you memory
allocation patterns are fairly regular, then fragmentation may not be a
problem.  

Even if you have 8Mb of RAM, you still have to think about the application
partition size under MultiFinder, since that's what limits the application's
available memory.  Even 8Mb is still a finite amount of memory, and it isn't
hard for an application to fill it all up.

>   1. You can't "...declare global variables, local variables, arrays, members,
>      or parameters of handle-based types (rather than pointers to them)."

This isn't really a limitation.  What that means is that all instances of a
HandleObject must be on the heap.

>   3. "It is not possible to allocate an array of handle-based objects, for
>      example, new MyObjects[10]."

Again, you can allocate an array that contain the handles, but not an array
that contains the objects themselves.

>   4. You cannot "...take a pointer to a field of an indirect class (i.e.,
>      &x->y).  This restriction includes the implicit use of pointers by ref-
>      erences, such as int& p = x->y."

When I tried this out, it appears that the compiler allows you to do this.
But, of course, you are dereferencing a handle, and the pointer isn't valid
if the heap is compacted.


C++ was designed in the UNIX environment where memory space isn't (as much
of) an issue.  The dispatching scheme, for example, is about as fast any
scheme can be, at the cost of larger virtual tables than Object Pascal, for
example.  (Multiple inheritance doubles the size of the virtual tables, by
the way.  That's why MPW C++ also includes the SingleObject class.)

The nice thing about MPW C++ is that you can mix native C++ objects with
HandleObjects or Pascal objects.  Other than the restrictions on the use of
the objects (which aren't very onerous), you use each kind of object in the
same way.  

In the case of HandleObjects, the basic restrictions are: (1) they must be
allocated on the heap, (2) the can't use multiple inheritance, (3) they're
implemented with handles which means you have to worry about heap
compactions.

-- 
		 Larry Rosenstein,  Object Specialist
 Apple Computer, Inc.  20525 Mariani Ave, MS 46-B  Cupertino, CA 95014
	    AppleLink:Rosenstein1    domain:lsr@Apple.COM
		UUCP:{sun,voder,nsc,decwrl}!apple!lsr

lsr@Apple.COM (Larry Rosenstein) (07/07/90)

In article <1990Jul6.190245.5781@agate.berkeley.edu> lippin@math.berkeley.edu writes:
>
>Of course, you do need HandleObjects and PascalObjects for dealing
>with MacApp, and they're handy for classes you really want to store
>that way.  Just don't think every object has to be one.

In general, most of the objects created by an application are
application-specific, which means you can use any kind of C++ object.  You
only have to use PascalObjects when you are interfacing with MacApp.

I agree with you about the use of stack-based objects.  Not only don't you
fragment the heap, but you also don't pay the memory allocation cost, and
you don't have to worry about freeing them.  

Lastly, it is important to remember that you can override operator new for a
certain class, and take over the allocation of the storage yourself.  You
can use this to place groups of objects in a handle, for example.  (See
develop issue #2.)


-- 
		 Larry Rosenstein,  Object Specialist
 Apple Computer, Inc.  20525 Mariani Ave, MS 46-B  Cupertino, CA 95014
	    AppleLink:Rosenstein1    domain:lsr@Apple.COM
		UUCP:{sun,voder,nsc,decwrl}!apple!lsr

sabbagh@acf5.NYU.EDU (sabbagh) (08/19/90)

In article <279@unf7.UUCP> shite@unf7.UUCP (Stephen Hite) writes:
>
>   If I have 5 or 8 meg of RAM and virtual memory (a.k.a System 7.0.2 :-))
>is it really *worth* the limitations of using HandleObject?  Some of limitations
>are (as taken from the MPW C++ Beta Manual):
>
>   1. You can't "...declare global variables, local variables, arrays, members,
>      or parameters of handle-based types (rather than pointers to them)."
>
>   2. You can't use multiple inheritance (as discussed previously ad nauseum).
>
>   3. "It is not possible to allocate an array of handle-based objects, for
>      example, new MyObjects[10]."
>
>   4. You cannot "...take a pointer to a field of an indirect class (i.e.,
>      &x->y).  This restriction includes the implicit use of pointers by ref-
>      erences, such as int& p = x->y."
>
>   [stuff deleted].

More thought would have revealed that these restrictions are quite reasonable.
What is a HandleObject?  It is an object that is intended to be allocated from
the Mac heap! These are referenced using handles, which allows the Memory 
manager to deal with fragmentation, etc.

Suppose you were writing code in C, Pascal, or any other language besides C++.  Can you allocate handle objects as global or local variables, arrays, members
or parameters of handle-based objects? NO, you can only manipulate pointers
to them!  Can you allocate an array of handle-based objects?  No, you would
need an array of handles to point to them (which you CAN do).

Basically, HandleObject alleviates you from dealing with 1) dereferencing
issues when dealing with the heap and 2) knowing which Toolbox calls move
memory.

So, my $0.02:

1) Use HandleObjects for things you would ordinarily allocate from the heap
in another language.  It will alleviate a number of programming issues
unique to the Macintosh.

2) Don't use HandleObjects for things you would want as variables, array
items, etc.  I wouldn't make a Point class a HandleObject.  Note that
you can still use the heap for these other object classes, but you have
to manage them yourself.


Hadil G. Sabbagh
E-mail:		sabbagh@csd27.nyu.edu
Voice:		(212) 998-3125
Snail:		Courant Institute of Math. Sci.
		251 Mercer St.
		New York,NY 10012

"'He was killed by the usual cabal: by himself, first of all; by the woman
  he knew; by the woman he did not know; by the man who granted his inmost
  wish; and by the inevitable fifth, who was keeper of his conscience and
  keeper of the stone.'"	-R. Davies, "Fifth Business"