[comp.sys.mac.programmer] Think C 4.0 questions

mithomas@bsu-cs.bsu.edu (Michael Thomas Niehaus) (02/01/90)

I have several questions that I hope someone out there can answer:

1.  If you declare an array in an object class definition, is it safe to
    use that array in a call to, say, an FSWrite routine?  I have created
    a 1K buffer and when it fills up I want to call FSWrite to write the
    whole chunk out.  Is this safe, or do I have to copy the whole array?
    (Or can I lock it down?)

2.  If you declare a superclass and then two or more subclasses, is it
    possible to create an object of one subclass and assign it to an object
    variable of the superclass?  I would like to have an array of objects of
    different types (but of similar structures).

3.  What does the debugger look like?  (My poor little 1MB SE has never seen
    it.)

Totally unrelated:

4.  How would you change the font that is used in a dialog's buttons to
    something other than Chicago?

5.  Does anyone have any source to convert BinHex->Mac files?  I am basically
    looking for a routine that will accept two file reference numbers and
    do the work, and hacking the xbin source currently looks like a headache.

-Michael

-- 
Michael Niehaus        UUCP: <backbones>!{iuvax,pur-ee}!bsu-cs!mithomas
Apple Student Rep      ARPA:  mithomas@bsu-cs.bsu.edu
Ball State University  AppleLink: ST0374 (from UUCP: st0374@applelink.apple.com)

ewing@boulder.Colorado.EDU (EWING DAVID JAMES) (02/02/90)

In article <10682@bsu-cs.bsu.edu> mithomas@bsu-cs.bsu.edu (Michael Thomas Niehaus) writes:
>I have several questions that I hope someone out there can answer:
>
>1.  If you declare an array in an object class definition, is it safe to
>    use that array in a call to, say, an FSWrite routine?  I have created
>    a 1K buffer and when it fills up I want to call FSWrite to write the
>    whole chunk out.  Is this safe, or do I have to copy the whole array?
>    (Or can I lock it down?)

I would declare a pointer in the class declaration and allocate it in your
initialization method and DisposPtr() it in your Dispose method.  This way
you won't have to worry about locking it down.  And, of course, the C syntax
for accessing the data will be the same as if it were an array.

>2.  If you declare a superclass and then two or more subclasses, is it
>    possible to create an object of one subclass and assign it to an object
>    variable of the superclass?  I would like to have an array of objects of
>    different types (but of similar structures).

Yes, most certainly.  This is the whole point of inheritance.  Look at the
CCluster class for an example.

>3.  What does the debugger look like?  (My poor little 1MB SE has never seen
>    it.)

The debugger is awesome!  Go buy some memory! :-)

>Totally unrelated:
>
>4.  How would you change the font that is used in a dialog's buttons to
>    something other than Chicago?

I simply use TextFont() and TextSize() routines imediatly after the window
is created to change the window's standard font.  Then create controls with
a procID or'd with useWFont (8).  See Inside Mac I-315 for details.

>5.  Does anyone have any source to convert BinHex->Mac files?  I am basically
>    looking for a routine that will accept two file reference numbers and
>    do the work, and hacking the xbin source currently looks like a headache.

I know its around somewhere.  You can try the info-mac archives via ftp at
sumex-aim.stanford.edu.

Dave Ewing
ewing@tramp.colorado.edu  (128.138.238.33)
..!hplabs!boulder!onecom!tyvax!iftech!dave (My Mac IIx running uupc & MacOS!)
AppleLink: D2408	  (D2408@applelink.apple.com)

dwb@archer.apple.com (David W. Berry) (02/02/90)

In article <10682@bsu-cs.bsu.edu> mithomas@bsu-cs.bsu.edu (Michael Thomas Niehaus) writes:
>I have several questions that I hope someone out there can answer:
>
>1.  If you declare an array in an object class definition, is it safe to
>    use that array in a call to, say, an FSWrite routine?  I have created
>    a 1K buffer and when it fills up I want to call FSWrite to write the
>    whole chunk out.  Is this safe, or do I have to copy the whole array?
>    (Or can I lock it down?)
	Remember there are two types of objects, handle based and pointer
based.  Pointer based objects will never move and therefore are always
safe to pass to FSWrite.
	Handle based objects are a little trickier, in theory it may be
safe.  It probably isn't though, especially if FSWrite isn't in the
currently executing segment.  Any routine (even those not marked "Can
move memory") called via glue can move memory due to a LoadSeg call.
The safest bet is something like:

	unsigned short state = HGetState((Handle) this);

	HLock((Handle) this);

	FSWrite(......)

	HSetState((Handle) this, state);

Of course, if these are all your objects, and your sure they are always
unlocked except for short explicit times, you can just use HLock and HUnlock,
but I'm a paranoid sort of guy...

>
>2.  If you declare a superclass and then two or more subclasses, is it
>    possible to create an object of one subclass and assign it to an object
>    variable of the superclass?  I would like to have an array of objects of
>    different types (but of similar structures).
	Yup, use a type cast:

		super = (CSuper*) new(CSubA*);

	See the collection type objects in TCL for more examples.

cosc10s4@jane.uh.edu (A JETSON News User) (02/02/90)

In article <10682@bsu-cs.bsu.edu>, mithomas@bsu-cs.bsu.edu (Michael Thomas Niehaus) writes:
> I have several questions that I hope someone out there can answer:
> 
> 1.  If you declare an array in an object class definition, is it safe to
>     use that array in a call to, say, an FSWrite routine?  I have created
>     a 1K buffer and when it fills up I want to call FSWrite to write the
>     whole chunk out.  Is this safe, or do I have to copy the whole array?
>     (Or can I lock it down?)

	As long as you are calling a routine, such as File Mgr calls, that
	don't move memory this is OK. If you are calling a routine, say
	EraseRect(), that can move memory, either HLock( this) temporarily
	or copy the instance variable to a local variable. 
> 2.  If you declare a superclass and then two or more subclasses, is it
>     possible to create an object of one subclass and assign it to an object
>     variable of the superclass?  I would like to have an array of objects of
>     different types (but of similar structures).

	Yes, you can do this.
> 3.  What does the debugger look like?  (My poor little 1MB SE has never seen
>     it.)
	It's very nice :-)

	Hopefully someone else can give a concise answer for your other
	two questions. 
--------------------------------
Dan Podwall
CS student, University of Houston
COSC10S4@jane.uh.edu
--------------------------------

cosc10s4@jane.uh.edu (A JETSON News User) (02/03/90)

In article <16455@boulder.Colorado.EDU>, ewing@boulder.Colorado.EDU (EWING DAVID JAMES) writes:
> In article <10682@bsu-cs.bsu.edu> mithomas@bsu-cs.bsu.edu (Michael Thomas Niehaus) writes:
>>I have several questions that I hope someone out there can answer:
>>
>>1.  If you declare an array in an object class definition, is it safe to
>>    use that array in a call to, say, an FSWrite routine?  I have created
>>    a 1K buffer and when it fills up I want to call FSWrite to write the
>>    whole chunk out.  Is this safe, or do I have to copy the whole array?
>>    (Or can I lock it down?)
> 
> I would declare a pointer in the class declaration and allocate it in your
> initialization method and DisposPtr() it in your Dispose method.  This way
> you won't have to worry about locking it down.  And, of course, the C syntax
> for accessing the data will be the same as if it were an array.

This is OK, but if you have a bunch of these objects it can lead to heap
fragmentation. Or if you make the items a handle, as in CCluster, you have less
fragmentation but more handles. One of the problems with implementing objects
as handles is that the Memory Manager gets bogged down when you have a lot of
handles. One way to help is simply to put the array directly into the object
handle, as Mike is doing. You can even make the array dynamic. Declaring
something like:

struct CMyCluster : CCollection
{
   /* inherits numItems instance variable */
   CObject* items[];

  /* declare some methods... */
}

and when inserting or deleting items just manage the size explicity via
SetHandleSize(), as CCluster does with its item Handle. 

I would only do this when efficiency is of utmost importance, since subclasses
of this class can no longer add instance variables.
--------------------------------
Dan Podwall
CS student, University of Houston
COSC10S4@jane.uh.edu
--------------------------------

olson@bootsie.UUCP (Eric Olson) (02/03/90)

In article <10682@bsu-cs.bsu.edu> mithomas@bsu-cs.bsu.edu (Michael Thomas Niehaus) writes:
>I have several questions that I hope someone out there can answer:
>
>1.  If you declare an array in an object class definition, is it safe to
>    use that array in a call to, say, an FSWrite routine?  I have created
>    a 1K buffer and when it fills up I want to call FSWrite to write the
>    whole chunk out.  Is this safe, or do I have to copy the whole array?
>    (Or can I lock it down?)

If you declared the array like so:

struct MyClass : Superclass {
	char	boofy[1024];
	}

then you'll want to lock the instance of the class any time you pass
this array to a routine that could move memory.  Lock the instance of
the object by doing a HLock(this).  Don't forget to unlock it!

A slightly better style might be to declare the buffer as a handle:

struct MyClass : Superclass {
	Handle	boofy;
	}

then in your initialization method for MyClass, do:

	boofy = NewHandle(1024L);

and when you want to access the buffer, do:

	HLock(boofy);
	RoutineThatMovesMem(*boofy);
	HUnlock(boofy);

You should also consider using HGetState and HSetState instead of
HUnlock, since it makes it possible for a subclass to lock the
handle and know that it won't be unlocked due to inherited method calls.

>2.  If you declare a superclass and then two or more subclasses, is it
>    possible to create an object of one subclass and assign it to an object
>    variable of the superclass?  I would like to have an array of objects of
>    different types (but of similar structures).

For example, if SpecialBoof is a subclass of BoofyClass, you can do:

	BoofyClass *	aBoof;
	SpecialBoof *	aSpecBoof;

	aBoof = aSpecBoof;

but not:

	aSpecBoof = aBoof;

This is because the struct for BoofyClass is just a subset of the
struct for SpecialBoof.  Note that objects always run their own
overridden versions of methods, even if they have been assigned
to a pointer of the superclass' type (e.g., coercing an object's
pointer does not change what methods it uses).

---
Please note!  olson@bootsie.uucp will not work!  Use an address below:

Eric K. Olson                 Internet:   olson@endor.harvard.edu
Lexington Software Design     Usenet:     harvard!endor!olson
72A Lowell St.                Applelink:  olson@endor.harvard.edu@dasnet#
Lexington, MA  02173          Compuserve: >INTERNET:olson@endor.harvard.edu
(617) 863-9624                Bitnet:     OLSON@HARVARD

ech@cbnewsk.ATT.COM (ned.horvath) (02/07/90)

From article <10682@bsu-cs.bsu.edu>, by mithomas@bsu-cs.bsu.edu (Michael Thomas Niehaus):
> I have several questions that I hope someone out there can answer:
> 
> 1.  If you declare an array in an object class definition, is it safe to
>     use that array in a call to, say, an FSWrite routine?  I have created
>     a 1K buffer and when it fills up I want to call FSWrite to write the
>     whole chunk out.  Is this safe, or do I have to copy the whole array?
>     (Or can I lock it down?)

Lock the object: FSWrite can move memory, and TC4 objects are relocatable.

> 2.  If you declare a superclass and then two or more subclasses, is it
>     possible to create an object of one subclass and assign it to an object
>     variable of the superclass?  I would like to have an array of objects of
>     different types (but of similar structures).

Yes, that's what polymorphism is all about.  The reverse is not, in general,
true (i.e. don't try to assign an object to one of it's subclasses).  You
CAN do this, but it's best to poll the object for it's type, to make sure
that the assignment is compatible (TC4 supports this).

> 3.  What does the debugger look like?  (My poor little 1MB SE has never seen
>     it.)

It's not perfect, but it's very very nice.   Go spend the $300 for the 4Mb,
you'll be glad you gave up the pizzas.

> 4.  How would you change the font that is used in a dialog's buttons to
>     something other than Chicago?

RTFM.  IM, Dialog Manager chapter, use SetDAFont to set the font for
subsequent dialogs.  Control Manager chapter (IM I-315): add 8 (useWFont)
to the control definition ID to use the windows font.  Caveat: I haven't
tried either this.

> 5.  Does anyone have any source to convert BinHex->Mac files?  I am basically
>     looking for a routine that will accept two file reference numbers and
>     do the work, and hacking the xbin source currently looks like a headache.

Nope.

=Ned Horvath=

tim@hoptoad.uucp (Tim Maroney) (02/08/90)

From article <10682@bsu-cs.bsu.edu>, by mithomas@bsu-cs.bsu.edu
(Michael Thomas Niehaus):
>> 1.  If you declare an array in an object class definition, is it safe to
>>     use that array in a call to, say, an FSWrite routine?  I have created
>>     a 1K buffer and when it fills up I want to call FSWrite to write the
>>     whole chunk out.  Is this safe, or do I have to copy the whole array?
>>     (Or can I lock it down?)

In article <1968@cbnewsk.ATT.COM> ech@cbnewsk.ATT.COM (ned.horvath) writes:
>Lock the object: FSWrite can move memory, and TC4 objects are relocatable.

Why do you say FSWrite can move memory?  It's not in the lists, so unless
it's in an unlocked segment, I don't see how (or why!) it would move memory.
-- 
Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com

"I've been called an evil genius by cities of assholes...  but I know who
 these people are!  And they're on my list!" -- Robert Crumb

CXT105@psuvm.psu.edu (Christopher Tate) (02/09/90)

In article <10111@hoptoad.uucp>, tim@hoptoad.uucp (Tim Maroney) says:

>Why do you say FSWrite can move memory?  It's not in the lists, so unless
>it's in an unlocked segment, I don't see how (or why!) it would move memory.
>--
>Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com
>
>"I've been called an evil genius by cities of assholes...  but I know who
> these people are!  And they're on my list!" -- Robert Crumb

According to Apple, the operating system has been patched from here to
hell and back again, and the lists are no longer valid.  A much safer
way to go is to assume that any trap routine can move memory, and set
things up to deal with this possibility.

Of course, this can be a real problem when you're trying to carefully
optimize things, or when you have to get down-and-dirty with the OS, but
it seems to me like a dandy way to ensure future compatibility....

-------
Christopher Tate                    |  "And as I watch the drops of rain
                                    |   Weave their weary paths and die,
cxt105@psuvm.psu.edu                |   I know that I am like the rain;
{...}!psuvax1!psuvm.bitnet!cxt105   |   There but for the grace of you go I."
cxt105@psuvm.bitnet                 |          -- Simon & Garfunkle

tim@hoptoad.uucp (Tim Maroney) (02/11/90)

In article <10111@hoptoad.uucp>, tim@hoptoad.uucp (Tim Maroney) says:
>>Why do you say FSWrite can move memory?  It's not in the lists, so unless
>>it's in an unlocked segment, I don't see how (or why!) it would move memory.

In article <90039.151841CXT105@PSUVM.BITNET> CXT105@psuvm.psu.edu
(Christopher Tate) writes:
>According to Apple, the operating system has been patched from here to
>hell and back again, and the lists are no longer valid.  A much safer
>way to go is to assume that any trap routine can move memory, and set
>things up to deal with this possibility.

FSWrite isn't even a trap, so it can't be patched.  It's a front-end to
the PBWrite trap.  I can assure you that the traps which have an argument
for asynchronous calling will always be callable at the interrupt level,
and therefore they will never move memory.

>Of course, this can be a real problem when you're trying to carefully
>optimize things, or when you have to get down-and-dirty with the OS, but
>it seems to me like a dandy way to ensure future compatibility....

It can also be a real problem in routine code writing.  I would hate to
think that I was supposed to start locking my handles before calling
BlockMove or TickCount or PBWrite (synchronously).  In real life,
that's not going to happen; there are many traps which clearly will
never move memory.
-- 
Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com

"Our newest idol, the Superman, celebrating the death of godhead, may be
 younger than the hills; but he is as old as the shepherds."
    - Shaw, "On Diabolonian Ethics"

oster@dewey.soe.berkeley.edu (David Phillip Oster) (02/12/90)

In article <10160@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes:
>I would hate to
>think that I was supposed to start locking my handles before calling
>BlockMove or TickCount or PBWrite (synchronously).  In real life,
>that's not going to happen; there are many traps which clearly will
>never move memory.

1.) Blockmove, since it is an O.S. trap requires glue to be callable by
most high level language compilers. If the glue is in a not currently
loaded segment, memory will move reading it in. (I know that you, Tim,
know about this, I am including it for completeness.)

2.) TickCount is one of the calls that is part of the Journaling system.
If Journaling is on, then TickCount will make a Control() call on the
journaling driver, which may do anything it wants, including i/o (such as
writing the journal log out to disk.)  (Many version sof Apple's
Imagewriter driver assume that TickCount() will not clobber A0. And it
won't, unless journaling is on.)

3.) PBWrite to the file manager may move memory, as I just discussed in an
immediately previous message.

Never? Well, hardly ever.

tim@hoptoad.uucp (Tim Maroney) (02/12/90)

In article <10160@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes:
>>I would hate to
>>think that I was supposed to start locking my handles before calling
>>BlockMove or TickCount or PBWrite (synchronously).  In real life,
>>that's not going to happen; there are many traps which clearly will
>>never move memory.

In article <34242@ucbvax.BERKELEY.EDU> oster@dewey.soe.berkeley.edu.UUCP
(David Phillip Oster) writes:
>1.) Blockmove, since it is an O.S. trap requires glue to be callable by
>most high level language compilers. If the glue is in a not currently
>loaded segment, memory will move reading it in. (I know that you, Tim,
>know about this, I am including it for completeness.)

Yeah, I also mentioned the segment issue during this discussion.  In my
opinion, the best solution is to keep all trap glue in a never-unloaded
segment, preferably segment 1.

>2.) TickCount is one of the calls that is part of the Journaling system.
>If Journaling is on, then TickCount will make a Control() call on the
>journaling driver, which may do anything it wants, including i/o (such as
>writing the journal log out to disk.)  (Many version sof Apple's
>Imagewriter driver assume that TickCount() will not clobber A0. And it
>won't, unless journaling is on.)

Interesting point.  This is in fact what IM says (I-261-2), but I just
disassembled the TickCount routine in my SE's RAM and it doesn't take
any side trips under any circumstances; there is simply no way for it
ever to call Control.  Journaling is activated by setting a flag in low
memory, so TickCount doesn't get patched when journaling recording mode
is turned on.  Perhaps this implementation of the routine is part of
the replacement of the old journaling system by MacroMaker.

In any case, the journaling behavior of TickCount has been documented
since IM I, but TickCount has never made it onto any list of traps that
can move or purge memory.  Therefore, any journaling driver that
allocates memory when it receives a (hypothetical) TickCount control
call is broken.  I reserve the right to be incompatible with
third-party trap patches and miscellaneous add-ons that blatantly
ignore the rules....

Journaling drivers *can* do i/o, but i/o doesn't move memory.

>3.) PBWrite to the file manager may move memory, as I just discussed in an
>immediately previous message.

Unfortunately, that discussion was incorrect.

Happens to the best of us.

Who is it who's started running that great signature line -- "Only a
mediocre man is always at his best"?
-- 
Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com

"Everything that gives us pleasure gives us pain to measure it by."
    -- The Residents, GOD IN THREE PERSONS

oster@dewey.soe.berkeley.edu (David Phillip Oster) (02/12/90)

tim@hoptoad.UUCP (Tim Maroney) replies to me:
_>>2.) TickCount is one of the calls that is part of the Journaling system.
_>>If Journaling is on, then TickCount will make a Control() call on the
_>>journaling driver, which may do anything it wants, including i/o (such as
_>>writing the journal log out to disk.)  (Many versions of Apple's
_>>Imagewriter driver assume that TickCount() will not clobber A0. And it
_>>won't, unless journaling is on.)
_>
_>Interesting point.  This is in fact what IM says (I-261-2), but I just
_>disassembled the TickCount routine in my SE's RAM and it doesn't take
_>any side trips under any circumstances; there is simply no way for it
_>ever to call Control.  Journaling is activated by setting a flag in low
_>memory, so TickCount doesn't get patched when journaling recording mode
_>is turned on.  Perhaps this implementation of the routine is part of
_>the replacement of the old journaling system by MacroMaker.

_>Journaling drivers *can* do i/o, but i/o doesn't move memory.
If you disassemble the MacPlus ROMs, you'll see the Control call that
TickCount makes if Journaling is turned on.


_>>3.) PBWrite to the file manager may move memory, as I just discussed in an
_>>immediately previous message.

_>Unfortunately, that discussion was incorrect.

I bow to your superior experience on this one.

lsr@Apple.COM (Larry Rosenstein) (02/13/90)

In article <10160@hoptoad.uucp> tim@hoptoad.uucp (Tim Maroney) writes:
> BlockMove or TickCount or PBWrite (synchronously).  In real life,

TickCount is listed as moving memory.

Larry Rosenstein, Apple Computer, Inc.
Object Specialist

Internet: lsr@Apple.com   UUCP: {nsc, sun}!apple!lsr
AppleLink: Rosenstein1

tim@hoptoad.uucp (Tim Maroney) (02/13/90)

In article <10160@hoptoad.uucp> tim@hoptoad.uucp (Tim Maroney) writes:
>> BlockMove or TickCount or PBWrite (synchronously).  In real life,

In article <6627@internal.Apple.COM> lsr@Apple.COM (Larry Rosenstein) writes:
>TickCount is listed as moving memory.

Good Lord, you're right.  I must have looked for it in the list five
times without seeing it.  I gotta spring for that brain upgrade one of
these days....
-- 
Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com

These are not my opinions, those of my ex-employers, my old schools, my
relatives, my friends, or really any rational person whatsoever.