[comp.sys.amiga.tech] Resources, Take 3

dillon@CORY.BERKELEY.EDU (Matt Dillon) (06/06/88)

	As you all know, My big project right now is the implementation
of resources (remote reference to Mac-like resources).  I've gone through
many schemes, some of which I've posted.

	Well, I've been stupid.  I've been going about it the wrong way
entirely ... that old saying about making things as simple as possible?
Well, it applies here in all respects.

	Originally, my idea was to have this incredibly complex system
whereby resources have a 'structure' which determines various things, like
memory type requirements and what needs to be relocated and what does not.
This requires a huge convoluted structure and lots of complex code to 
implement.

	The *right* way to do it is to essentially have a relatively 
simple storage format, and then make the entire system object oriented.
So here is my *new* idea on the subject:

(1)	Where are they?

	Resources can be in separate files, or part of an executable.  If
	part of an executable the resources are assumed to be immediately
	required by the executable and all loaded into memory.  It is 
	assumed the program will be requested almost all of them.

	If not part of an executable (i.e. in a separate file), only 
	specifically requested resources are loaded from that file.  i.e.
	resources are loaded on demand.

	Resources can be both in the executable and elsewhere.  For instance,
	there will be one or more 'system global' resource files which are
	available for use.

(2)	Features of the resource system.

	Resources can either be private to an application  (only that 
	application and multiple invocations of that application see the
	resource), or global (any process in the system can see the resource)

	Resources can either be shared or non-shared.  A shared resource 
	exists in RAM once ... multiple references refer to the same 
	physical memory.  memory for a resource which is not shared is
	allocated every time it is requested.

	A resource consists of:

	(1) A resource-name
	(2) A resource-type (which is also a name)
	(3) bulk data pertaining to the resource

---------------

	Now, I want to be able to do something like:

	GetResource("MyWindow", "Window");

	Where "MyWindow" is the resource name and "Window" is the resource
	type... i.e. an intuition window.  But I want this to work even if
	the resource on disk is actually:

		resource MyWindow is type NewWindow

	In otherwords, when I do the GetResource(), the system should notice
	that I want a Window but it can only find a NewWindow, and 
	automatically OpenWindow() the structure for me.  How does one
	accomplish this generically?  Remember that resources *ARE* general
	in that the resource-types are not necessarily just those in
	the Amiga include's ... people will want to make their own custom
	resources.

Solution:
	There exists a special resource, usually GLOBAL and SHARED with the
	following specifications:

	Name = "FromType.ToType"	(e.g. "NewWindow.Window")
	Type = "Code"
	Contents = Relocatable code that converts a resource of 'FromType'
		   to a resource of 'ToType'

	Such resources are usually system global resources.  Thus, if a 
	resource "NewWindow.Window" of type "Code" exists my request can
	be properly performed.

----------------------------------------------------------------------

	You've got to understand what I've discussed above before reading
on.  Now there are a couple of items that need to be addressed which I
have yet to work out fully:

(1)	What if I want to implement a system-default window?  The resource
	on disk will be something like: name="SysWindow" type="NewWindow",
	and programs will get the resource via 

	struct Window *win = GetResource("SysWindow","Window"),

	Thus returning an intuition Window.  BUT I WANT ANOTHER PROGRAM
	WHICH MAKES THE SAME REQUEST TO RETURN THE ALREADY OPENNED WINDOW!

	So I will need to develope an intuitive mechanism that allows such
	conversions to either be SHARED (don't re-open the window just return
	the already openned window) or NOT-SHARED.  The "SysWindow" resource
	is, of course, system global and shared, but this 'shared'ness is
	different ... it simply means the NewWindow structure itself is
	shared, not necessarily the resultant structure after you apply a
	conversion.

	Obviously, both flavors are wanted:  (1) Where the GetResource()
	call takes the NewWindow structure and opens a new window on
	every reference, and (2) Where the GetResource() call takes the
	NewWindow structure, but if the window has already been openned
	simply returns the window, keeping a reference count on usage.

(2)	References.  A shared resource will have a reference count.  Thus,
	after all users of the "SysWindow" resource are done using it,
	the window will go away... or will it?

(3)	Disk swapping and memory usage.  Do we want resources to be swapped
	to some auxillary storage if they remain unused for long periods of
	time?  Taking the above example, do we want that SysWindow to stay
	open until the system either begins to run out of memory or it
	remains unused for a long time?

	A better example might be a device driver or font ...

(4)	Other special resources and relocation.  I suggest the following:
	Lets say you have a resource of type "List".  When you 
	GetResource() it you don't just want a List pointer, but an
	initialized List pointer... you don't want to have to NewList() it.

	It makes sense (at least to me), to do this:

	The resource on disk will have a type "_List", not "List".  There 
	will then be a conversion resource whos name is:  "List._List".

	So when I GetResource("MyList", "List") it will find "_List" and
	then do the conversion to "List".

	NOTE AWESOME POWER!  No matter whether a resource needs to be 
	converted or fixed up or whatever, the program always requests
	the resource by it's PROPER TYPE.  The only time a program would
	ever GetResource("MyList", "_List") would be if it wants the raw
	data!

	NOTE AWESOME POWER2!  Lets say you want to have a buffer resource...
	say 4K (the reason it's a resource in the first place is because
	you want the user to be able to modify the size of the buffer).
	It makes no sense to have 4K of nothing in a file.  But wait!  how
	about make a custom resource called "_Buffer" which contains two
	longwords: a buffer size and a memory type.

	Then, when you request "MyBuffer", "Buffer", the conversion resource
	will take those measily 8 bytes, call AllocMem(), and return to you
	a pointer to the specified amount of memory!

	NOTE AWSOME POWER3!  Lets say you want to allow the user to EDIT
	one of your custom resources.  Easy!  Just have a resource of 
	type "Code" whos name is "<blah>.EDIT" which, when executed, edits
	the specified resource:

		Resource to Edit:	Name = <SomeName>, Type = <Type>

		Edit resource:	Name = <Type.EDIT>, Type = "Code"

		To edit, simply:	GetResource("<SomeName>", "EDIT");


						-Matt

blandy@lakshmi.cs.cornell.edu (Jim Blandy) (06/09/88)

In article <8806052331.AA28897@cory.Berkeley.EDU> dillon@CORY.BERKELEY.EDU (Matt Dillon) writes:
>
>	As you all know, My big project right now is the implementation
>of resources ...

>	The *right* way to do it is to essentially have a relatively 
>simple storage format, and then make the entire system object oriented.
>So here is my *new* idea on the subject:

	[ ... description of standard code resources which convert one type of
	  resource to another ... ]

That is a completely fantastic idea, Matt.  I'd steal your brain in a
second, if I could use it.

It's similar to the way 'make' can assume how to get a .o file from a
.c file without being specific to C or whatever.

>(1)	What if I want to implement a system-default window?  ...

	[ ... stuff on shared resources and things, looking a bit
	  like a solicitation of suggestions :-) ...]

>						-Matt


The way I see it, the conversion resources take a resource of one type
and make a new resource of the asked-for type.  So if this converter
makes a Window out of a shared NewWindow, the Window so created is
shared too; it's a genuine resource, just like anything else.

You're maintaining a "shared resources currently in memory" list, so
put this new Window resource on the list; the next person that asks
for it finds the already-opened window.

In the general case: if a shared wombat_description is turned into a
wombat by some conversion resource (called wombat_description.wombat),
then that new wombat is also a shared resource, to be added to the
"shared resources in memory" list; other programs calling
GetResource() for that same wombat will be given the same value the
first one did.

(PS - where can I get a copy of MDE, and the Fred Fish listings?)
Jim Blandy - blandy@crnlcs.bitnet
"insects were insects when man was just a burbling whatsit."  - archie