FB II Compiler

PG PRO

Debugging

Memory

System

Mathematics

Resources

Disk I/O

Windows

Controls

Menus

Mouse

Keyboard

Text

Fonts

Drawing

Sound

Clipboard

Printing

Communication

ASM

Made with FB

RESOURCES

Check if a resource is in memory


If you check `purgeable' bit of the resource, it will be deleted automatically when there is few memory by resource manager.

So, you have to load it each time and check the handle is not null.
Almost case, the resource handle still exists on the memory, so it's very fast to reload it from the file. So, you'd better make it purgeable and never call ReleaseResource.

ie.

pictureH& = FN GETPICTURE( 128 )
LONG IF pictureH& <> _NIL
' We can load that resource
' If you obtain other memory block, make it sure to call NoPurge,
' to not to be removed it.
  FN HNOPURGE( pictureH& )
' do something with picture

' Make sure to resume it to purgeable
  FN HPURGE( pictureH& )
XELSE
' Fail with loading resource
END IF

Osamu


Whoa. ReleaseResource does _not_ retain a valid handle. It calls DISPOSHANDLE, which not only dumps the block but makes the handle invalid. In particular, it does _not_ cause the value of [resHndle&] to be zero. Any copies of the handle you have laying around are then meaningless, and you can't trust [resHndl&] to be a valid indicator of anything.

Sounds like you are confusing "releasing" with "purging." A resource is purged (automatically by the Memory Manager) if the resource is marked as "purgeable" and the Memory Manager needs that memory for something else. When _that_ happens, then yes, the resHndl& is still valid, and [resHndl&] will be zero. If a resource has been purged, you can call LOADRESOURCE to get it loaded back into memory, and the Memory Manager still uses the same (old) handle value to reference it.

On the other hand, if you've called ReleaseResource, then to get the resource back into memory you need to call GETRESOURCE (or one of its variants). This will load the resource and give you a _new_, different handle to it. The old handle (and any copies of it) are bogus.

Rick


Thanks guys for the suggestions. I think I found the answer...
IM states that when a resource file is opened, handles to each resource are generated in the resource map along with type and ID information. If the global variable _resLoad is set to _true (default), then function FN GETRESOURCE will load a resource into memory if it is not already there... of course this idea sprung the initial question.

I did find out the following using a small program to load a resource. Using
resHndl& = FN GETRESOURCE(resTyp&,resID%) function, I found that if the
a) value of resHndl& is _nil, then the resource was not found
b) value of resHndl& is a longint , then a handle exists
c) value of [resHndl&] is _nil, then the resource is not in memory
d) value of [resHndl&] is a longint, then the resource is in memory

That business of the master pointer not being cleared to zero after a call to RELEASERESOURCE was only temporary. It functioned perfectly after a few programming steps.
I believe that if [resHndl&] is _nil, then the resource is not in memory.

Bill


This last sentence is true, but its converse is not. That is:

"If [resHndl&] is _nil, then the resource is not in memory." <-- true.
"If the resource is not in memory, then [resHndle&] is _nil." <-- not always true.

If the resource is _purged_ (as opposed to released), then it goes away from memory and [resHndle&] will be _nil. If the resource is _released_ (by calling RELEASERESOURCE), then it goes away from memory and [resHndle&] will _not_ be set to _nil.

Sounds like you've got a "handle" (ha) on what's going on.

Rick


... correct, as you usually are, but, the test program below begs to differ

Example:
The following test program uses GETRESOURCE for _"vers" types that are present in the rsrc map. It doesn't open any files and uses the currently open FB and system resource forks and should be safe to use. The program calls GETRESOURCE three times, 1st time resource loading true, 2nd time loading false, and 3rd time loading true. Look specifically at the value of the resHndle&. The results are confusing when compared to your excellent explanations given that matches IM to a tee. eg, IM states that RELEASERESOURCE sets the master pointer to _nil.. not the case as you will see.

WINDOW OFF
DEFSTR LONG
'-------------------------- Constants/Globals
DIM cRes%,gVers%,gCnt%
DIM myResID%,myResCnt%
DIM myResTyp&
DIM myVers!
END GLOBALS
'----------------------------- Assignments
gCnt% = 0
gVers% = 0
GOTO "main"
'------------------------------ Functions
CLEAR LOCAL
  DIM succ%,resCnt%
  DIM resHndl&
LOCAL FN checkRsrc%(resTyp&,resID%,loadFlag%)
  INC(gCnt%)
  IF loadFlag% = 0 THEN CALL SETRESLOAD(_false)
  resHndl& = FN GETRESOURCE(resTyp&,resID%)
  CALL SETRESLOAD(_true)
  LONG IF resHndl& <> _nil
    PRINT "Pass No.";gCnt%;" Load resource =";loadFlag%
    PRINT: PRINT "FN GETRESOURCE called"
    PRINT "Handle to _";MKI$(resTyp&);" resource";
    PRINT TAB(30);"$";HEX$(resHndl&)
    LONG IF [resHndl&] <> 0
'-- resource is in memory
      succ% = _true
      PRINT "Pointer to _";MKI$(resTyp&);" resource";
      PRINT TAB(30);"$";HEX$([resHndl&])
      PRINT
      gVers% = VAL(HEX$({[resHndl&]}))
      CALL RELEASERESOURCE(resHndl&)
      PRINT "RELEASERESOURCE called"
      PRINT "Handle to _";MKI$(resTyp&);" to resource";
      PRINT TAB(30);"$";HEX$(resHndl&)
      PRINT "Pointer to _";MKI$(resTyp&);" resource";
      PRINT TAB(30);"$";HEX$([resHndl&])
      PRINT STRING$(60,"-")
    XELSE
'-- resource is not in memory
      PRINT "Resource _";MKI$(resTyp&);" not in memory";
      PRINT TAB(30);"$";HEX$([resHndl&])
      PRINT STRING$(60,"-")
      succ% = _false
    END IF
  XELSE
'-- resource not found
    PRINT "Resource _";MKI$(resTyp&);" not found"
    PRINT "ResError = ";FN RESERROR
    succ% = _false
  END IF
END FN = succ%

'-------------------------------- Main
"main"
WINDOW 1,"",(5,45)-(400,500)
TEXT _monaco,9

myResTyp& = _"vers"
myResID% = 1
myResCnt% = FN COUNTRESOURCES(myResTyp&)
LONG IF myResCnt% > 0
  gCnt% = 0
  cRes% = FN checkRsrc%(myResTyp&,myResID%,1)
  cRes% = FN checkRsrc%(myResTyp&,myResID%,0)
  cRes% = FN checkRsrc%(myResTyp&,myResID%,1)
END IF

LONG IF cRes%
  myVers! = (gVers%)/100.0
  PRINT "Version =";
  PRINT USING " ##.##";myVers!
END IF

DO
UNTIL FN BUTTON
END

Bill


When I ran the program, the results I got were consistent with what I said above.
After RELEASERESOURCE was called, the value of resHndle& remained the same, but that doesn't mean it's still a valid handle. The value of [resHndle&] in fact changed (to a different nonzero value) after RELEASERESOURCE was called.

<< Sounds like you are confusing "releasing" with "purging." A resource is purged (automatically by the Memory Manager) if the resource is marked as "purgeable" and the Memory Manager needs that memory for something else. When _that_ happens, then yes, the resHndl& is still valid, and [resHndl&] will be zero. If a resource has been purged, you can call LOADRESOURCE to get it loaded back into memory, and the Memory Manager still uses the same (old) handle value to reference it. >>
<< ... you're correct here too! But, the test program below begs to differ >>

I didn't see where the test program tested this. It doesn't purge a resource or call LOADRESOURCE. Are you talking about "loading" the resource when the SetResLoad flag is false?

<< On the other hand, if you've called ReleaseResource, then to get the resource back into memory you need to call GETRESOURCE (or one of its variants). This will load the resource and give you a _new_, different handle to it. The old handle (and any copies of it) are bogus.
... this you'll like, the same bloomin' handle is always returned >>

This is just coincidence. If you release something and then immediately load something, chances are you'll get the same handle value. Try this:
1. Get Resource "A". Note its handle value.
2. Release Resource "A".
3. Get Resource "B".
4. Get Resource "A" again. Note its handle value.

This time, resource "B" is likely to grab the old handle that "A" had in step 1, and you'll likely find that the handle in Step 4 is different from that in Step 1.

This is a good test program. Inside Mac says that RELEASERESOURCE "...sets the master pointer of the resource's handle in the resource map in memory to NIL." I think this is incorrect documentation--in the first place, the master pointer is not in the resource map. What's in the resource map is a copy of the handle--and that is the thing that gets set to NIL. I still have a copy of the _old_ edition of Inside Mac (which I'll probably never get rid of!) and it has a nice diagram (p. I-120) of this process which seems to show it correctly.

Rick