From: dnavas@oracle.uucp (David Navas)
Newsgroups: comp.sys.amiga.programmer
Subject: Re: IPC and shared memory
Date: 7 Jan 93 20:35:35 GMT
Organization: Oracle Corporation, Redwood Shores CA
X-Disclaimer: This message was written by an unauthenticated user
              at Oracle Corporation.  The opinions expressed are those
              of the user and not necessarily those of Oracle.

In article <1ifq0hINNak2@uwm.edu> bloc1469@ee.ee.uwm.edu (Gregory R Block) writes:
>Interesting.  So why not just have a server process which does the
>tracking of stuff, and use either spawned slaves, or use a separate
>binary for a slave and have the server send you a pointer to it?  That

Or, if each slave is just being used to handle some state, and it's the
server that's performing all the work, run the slaves in the server's
process context.  This depends a lot on what kind of code you already have
set up.

I've always tried to think of these types of problems in an "object-oriented"
manner (I put this in quotes to avoid needless finnagling about what
object-oriented does or does not mean).  If I'm understanding correctly,
each of these 'slaves' has its own I/O ports to the separate users, but
the game-code itself needs to reside in one separate place and communicate
with everybody else.

Assuming that things aren't quite so simple (the slaves might have
different I/O requirements, etc.), I would view each type of slave as a
subclass of the server.  Here, the 'state' of the server would be thought of as
the server class' 'class-variables', and the state of each  slave would be
kept in the process-instance of the slave (or perhaps in the slave's
class-variables, depending on your implementation).

Now why have I introduced this seemingly messy representation into a
discussion that has already produced several good answers?

Well, chew a minute on this:

Let's say that one of the methods you've defined in your server-class is
METH_GET_MAP -- which might get you a pointer to some kind of shared map.
Let's say that we define this method to run synchronously to the caller --
the slaves in this case.

The method itself might look like:
	APTR MethGetMap(METHOD_ARGS)
        {
	   PSem(MyGlobalMap, SSEM_LOCK);
           return MyGlobalMap;
        }

[Note: this code would reside in the server-process only, and I'm assuming
 the existance of a global variable "MyGlobalMap"]

Each slave, having appropriately sub-classed the server-class, could then
invoke the method on itself:
	map = DoShadowMethod(MySlaveObject, NULL, METH_GET_MAP, METHOD_END);

[Note: this code in the slave.]

Notice -- the method is invoked within the slave-process-context, so the
semaphore is requested/owned by the slave.  The code, however, exists within
the server, and hence has access to the server's variables.

Once you have the map pointer, you can diddle as much as you like with it,
and then call some kind of method to release the semaphore -- or, considering
this particular implementation, you can call "VSem(map);" directly.

What advantages over using an IPCMessage for this?
	1) The semaphore code can be hidden in the server, where knowledge
	   about access arguably belongs.
	2) You don't have to create two IPCPorts to handle the messages.
	3) You (may or may not) have the overhead of a task switch.
	4) You can change the way the code behaves (what process the method
	   is synchronous to) during the programming phase -- compare this
	   with rewriting event-loops.
	5) You don't have to write multiple-event-loops (or worse, your
	   own thread-code ala AmigaOS filesystem) to avoid dead-lock
	   situations.  Note that this doesn't elminate dead-locks, but
	   because of 4) above, your life will be easier.
	6) You keep code and data usage down.

>enables you to do LOTS of things by having the "master" know
>everything that's going on, and having the slave be that user's

That, however, is exactly what I wouldn't want to have happen.  Because then
you get in the business of one process keeping several process' state
updated, and as master-slave process integration increases, you start having
fun discussions about how to keep the master and the slave's idea of the
slave's state synchronized.

Obviously, with a simple example like semaphore sharing, this is not a problem,
but things can get more complicated, and hence more hairy.  That way lies
sleepless nights....  :)

>interface to the world.  One could write slaves that are nothing more
>than "windows to the world" for the users of the bbs.  More

Yes, slaves as subclasses -- specialized versions of the server program
that package both the users' code differences (if any) from the server,
and the users' separate states.

>importantly, one could write "AI slaves" as seen in muds, robots if
>you will, or perhaps highly intelligent monsters.  It all depends on
>how you're designing the game, but it does sound as if you could
>benefit from having a master process with either subprocesses (perhaps
>your bbs could call an AREXX script which launched a slave or
>something) or as separate slaves (the more complex but more powerful
>solution).

The other problem with this discussion is that there seems to be an inherent
assumption that different programs == different processes.  First of all,
AmigaOS does have the concept of a library -- you could stick your
semaphore someplace in the libraryBase.  Second of all, it's not unreasonable,
as shown above, that slave processes would have access (in whatever way)
to some other program's global variables.  That's one of the FEATURES of
AmigaOS ;)

>Who knows.  :)

Well, I won't claim omniscience, but I will claim experience.  All of my
Amiga programming has been this kind of master-slave programming we're
discussing here.  I don't think I've ever written a standalone, mono-process
program for the Amiga....  Hm....

Of course, I'm still young, so what do I know :) :) :)

David C. Navas						dnavas@oracle.com
Working for, but not speaking on behalf of, Oracle Corp.