[net.micro.amiga] Question on Intuition Screens and Windows

dillon@PAVEPAWS.BERKELEY.EDU (Matt Dillon) (05/31/86)

	I have a program which spawns other processes (via CreatProc).  My
question is simply:  
	
	If the master process creates an intuition screen, can the 
subprocesses create windows in this new screen?  It seems to work, sorta
(the Amiga crashes when I try to close everything up)... I would like to
know whether it's illegal to do in Intution (and if it isn't, I know the
problem lies somewhere in my code)

					Thanks,

					-Matt

jimm@amiga.UUCP (Jim Mackraz) (06/02/86)

In article <8605311838.AA02246@pavepaws> dillon@PAVEPAWS.BERKELEY.EDU (Matt Dillon) writes:
>
>	I have a program which spawns other processes (via CreatProc).  My
>question is simply:  
>	
>	If the master process creates an intuition screen, can the 
>subprocesses create windows in this new screen?  It seems to work, sorta
>(the Amiga crashes when I try to close everything up)... I would like to
>know whether it's illegal to do in Intution (and if it isn't, I know the
>problem lies somewhere in my code)
>
>					Thanks,
>
>					-Matt

What you said sounds OK as it stands, but the dangers lie in different
tasks closing up.  Opening a typical window leads to the creation of 
a Port (IDCMP) with the associated allocation of a signal.  Closing
the window typically deallocates that signal, and should be done by the same
task that created it.

Another route is to handle all of the port stuff yourself (create windows
with IDCMP initially NULL, and so on as described earlier and in the
developer's newsletter).

I don't think there is anything else.  The tasks which calls BeginRefresh
should be the same which calls EndRefresh().

If you can get a minimal program to display the problem, I would like
to see it.  Thanks.
				jimm

higgin@cbmvax.cbm.UUCP (Paul Higginbottom) (06/02/86)

In article <8605311838.AA02246@pavepaws> dillon@PAVEPAWS.BERKELEY.EDU (Matt Dillon) writes:
>	I have a program which spawns other processes (via CreatProc).  My
>question is simply:  
>	
>	If the master process creates an intuition screen, can the 
>subprocesses create windows in this new screen?  It seems to work, sorta
>(the Amiga crashes when I try to close everything up)... I would like to
>know whether it's illegal to do in Intution (and if it isn't, I know the
>problem lies somewhere in my code)
>
>					Thanks,
>
>					-Matt

<chomp...>
Intuition doesn't know anything about the processes controlling screens and
windows (I don't believe) so it should be perfectly legal for processes to
use the same screen, each put windows on it, etc.  I am doing this without
any problem.

	Regards, Paul Higginbottom

Disclaimer: I do not work for Commodore, and my opinions are at least my own.

rj@amiga.UUCP (Robert J. Mical) (06/04/86)

Hello, folks.  I'm back online!  So, what's going on, eh?
Anyone care to hear about the Sidecar and my adventures in Germany?

RJ Mical >:-{)*

But first, I flex my fingers and ... here's some notes on multiple tasks
using a common screen, and a tutorial about tasks exchanging data using
messages.


In article <8605311838.AA02246@pavepaws> dillon@PAVEPAWS.BERKELEY.EDU (Matt Dillon) writes:
>
>	I have a program which spawns other processes (via CreatProc).  My
>question is simply:  
>	
>	If the master process creates an intuition screen, can the 
>subprocesses create windows in this new screen?  It seems to work, sorta
>(the Amiga crashes when I try to close everything up)... I would like to
>know whether it's illegal to do in Intution (and if it isn't, I know the
>problem lies somewhere in my code)
>
>					Thanks,
>
>					-Matt


Any task can use a screen once the screen is opened.  The only trick is
to coordinate the usage of the screen among the tasks that will use it.

I describe two solutions to the problem.  They are in the sections below,
named "Multiple tasks in one program can share a screen" and "Tasks from
any program can share a screen."


=== Multiple tasks in one program can share a screen ======================

If you've created several tasks in one program, those tasks should be
able to access a global variable that has the address of the screen.  Call
it something like ScreenAddress.  Remember to initialize the variable to 
something appropriate like NULL, and to have your tasks check the value in 
the variable before they use it, just in case it's still NULL.

Once the screen is opened, you can use the Screen variable UserData to stand
for the number of users of the screen.  I believe you will be able to count 
on this variable being initialized to zero by Intuition when you call 
OpenScreen().  If you don't want to count on that or if Jim Macraz won't say 
that this is so, then go ahead and initialize UserData to zero just to be sure.

The screen should be opened before tasks are created that will use the 
screen.  Save the value returned by OpenScreen() in the variable 
ScreenAddress.

If some task knows the address of the variable that contains the 
address of the Screen structure, and the task wants to use the screen, it 
should take these steps:

	- Forbid()

	- If the Screen pointer variable is still NULL, you're
	  in trouble, probably the system is out of memory.  You
	  should either abort or retry testing the Screen variable.

	- If the Screen pointer is not NULL, increment the UserData variable 
	  in the Screen structure.  Now you have marked that you share
	  control of the screen.

	- Permit()

To release control of the screen, take these steps:

	- Forbid()

	- Test if the Screen pointer is NULL, and fail if it is.

	- Decrement the UserData variable in the SCreen structure.

	- If UserData is zero, call CloseScreen() and set ScreenAddress 
	  to NULL.

	- Permit()


=== Tasks from any program can share a screen =============================

There is a way of doing this that doesn't require a globally-accessible
variable.  Instead, tasks communicate with one another using messages
to share the Screen address.  It's a bit complicated, but it stands as
an example of multiple unassociated tasks sharing the same piece of data.
This is an abbreviated example, so please bear with me.

	- Define a message structure that includes a Message structure at
	  the front, and at least one pointer to a Screen.  Left as
	  a short exercise for the reader.

	- Have one task be responsible for opening and owning the screen.
	  That task:

		- Opens the screen.

		- Initializes a variable ScreenUsers to zero.

		- Creates a port with a unique name, something like:
	  	  #define SCREEN_PORT_NAME "ScreenPort.ProjectX.V1.1"
		  OpenPort(SCREEN_PORT_NAME...);

		- Wait()s at the port for messages of the class USE_SCREEN and
		  FREE_SCREEN.  With USE_SCREEN messages, the variable
		  ScreenUsers is incremented and the address of the screen 
		  is returned in the message structure.  With FREE_SCREEN 
		  messages, ScreenUsers is decremented.  After all pending
		  messages have been processed, test if ScreenUsers is equal
		  to zero.  If not zero, go Wait() for more messages.

		- If ScreenUsers is zero, close and exit:

			- Forbid()

			- Drain the message port, replying to all outstanding
			  messages with a Screen address of NULL.

			- RemPort() the message port out of the system.

			- CloseScreen()

			- Permit()

			- Go away

	- Now any other task can gain access to the screen with these steps:

		- Create a message port where you at least receive a reply
		  to the message you're about to send.  You can use
		  this port for other messages, too.
		  
		- If FindPort(SCREEN_PORT_NAME) == NULL, it doesn't
		  exist yet which means that the screen creation task
		  is broken or non-existent, so you should either 1) abandon 
		  hope or 2) put up a system requester or something, and
		  then try again.

		- If the port exists, send it a USE_SCREEN message.

		- Wait for a reply.

		- If the Screen pointer in the reply message is equal
		  to NULL, something's gone wrong at the other end.  You can
		  either 1) abandon ship or 2) restart this *whole* process.

		- Else, now you're free to use the Screen pointer for 
		  whatever you would like.  Just don't break it.

		- When you're done with the Screen, here's what you do
		  to release it:

			- Forbid()

			- If FindPort(SCREEN_PORT_NAME) == NULL, this time
			  you're in trouble because the screen task has
			  mysteriously disappeared while you're still 
			  using the screen.  Don't use the Screen variable
			  for anything else, maybe put up a requester 
			  telling the user what went wrong.  Exit.

			- If you found the screen port, send a message of
			  class FREE_SCREEN to the port.

			- Permit()



See you later.    

The Amiga lives.  Keep the faith.   RJ Mical >:-{)*  1986