home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!zaphod.mps.ohio-state.edu!pacific.mps.ohio-state.edu!linac!att!mcdchg!chinet!miroc!caw
- From: caw@miroc.Chi.IL.US (Christopher A. Wichura)
- Newsgroups: comp.sys.amiga.programmer
- Subject: Re: IPC and shared memory
- Distribution: world
- Message-ID: <caw.0wk9@miroc.Chi.IL.US>
- References: <Jean-Guy_Speton.056u@tvbbs.wimsey.bc.ca>
- X-NewsSoftware: GRn-beta 1.16g (28.12.92) by Michael B. Smith & Mike Schwartz
- MIME-Version: 1.0
- Content-Type: text/plain; charset=iso-8859-1
- Content-Transfer-Encoding: 8bit
- Date: 31 Dec 92 09:02:22 CST
- Lines: 169
-
- In article <Jean-Guy_Speton.056u@tvbbs.wimsey.bc.ca> Jean-Guy_Speton@tvbbs.wimsey.bc.ca (Jean-Guy Speton) writes:
- > I am looking for information on inter-process communications (IPC) and
-
- IPC is real easy. The Amiga has had message passing functions since day one.
-
- > shared memory functions. Do the Amiga libraries have any functions along
-
- Shared memory is a little trickier. The best way to go about this (that I've
- come up with) is to allocate a chunk of memory and protect it with a
- semaphore. Subsequent instances of the program would not allocate but rather
- simply find the semaphore and use that as the chunk base. When you free the
- semaphore, if you are the last instance then you free the memory chunk.
-
- Here's some code I wrote to do this a little while back:
-
- /* structure for handling our public semaphores. */
- struct MyPublicSema {
- struct SignalSemaphore mps_Sema;
- UBYTE *mps_SemaData;
- ULONG mps_UseCount;
- UBYTE mps_SemaName[4];
- };
-
- /*
- * this routine sets up a public semaphore. If it already exists we just
- * bump its use count up by one. Otherwise we have to allocate a new one.
- * semaDataSize is a number of bytes to allocate with the semaphore that can
- * be shared by those locking the semaphore. Let's us have "global" data
- * between seperate processes. These routines don't care what is put in
- * this data space. It will be cleared to 0s when first allocated, though.
- */
-
- struct MyPublicSema *InitMyPublicSemaphore(STRPTR semaName, ULONG semaDataSize)
- {
- struct MyPublicSema *theSema;
- ULONG semaNameLen;
-
- if (!semaName)
- return (struct MyPublicSema *) NULL;
-
- /*
- * we want the semaphore's name to be a longword in length, at least
- * in space allocated for it
- */
- semaNameLen = ((strlen(semaName) + 3) / 4) * 4;
-
- Forbid();
- if (theSema = (struct MyPublicSema *) FindSemaphore(semaName))
- theSema->mps_UseCount++; /* only safe way to diddle
- * with this is under
- * Forbid()... sigh */
- else {
-
- /*
- * we didn't find the semaphore around already so we have to
- * allocate and initialize it
- */
- if (!(theSema = AllocVec(sizeof(struct MyPublicSema) + semaNameLen + semaDataSize, MEMF_CLEAR | MEMF_PUBLIC))) {
- Permit();
- return (struct MyPublicSema *) NULL;
- }
-
- strcpy(theSema->mps_SemaName, semaName);
- theSema->mps_Sema.ss_Link.ln_Name = theSema->mps_SemaName;
- if (semaDataSize)
- theSema->mps_SemaData = &theSema->mps_SemaName[semaNameLen];
- theSema->mps_UseCount = 1;
-
- AddSemaphore(&theSema->mps_Sema);
- }
-
- Permit();
-
- return theSema;
- }
-
- /*
- * this dealocates what we got from InitMyPublicSemaphore(). If there are
- * others still using it then just down the use count. Otherwise remove the
- * semaphore from the public lists and down the use count.
- */
-
- void FreeMyPublicSemaphore(struct MyPublicSema * mySema)
- {
- if (mySema) {
- ObtainSemaphore(&mySema->mps_Sema);
- Forbid();
- ReleaseSemaphore(&mySema->mps_Sema);
- if (!--mySema->mps_UseCount) {
- RemSemaphore(&mySema->mps_Sema);
- FreeVec(mySema);
- }
- Permit();
- }
- }
-
- To use this, early on in your program you would call InitMyPublicSemaphore()
- with the name you want to refer to your shared memory chunk as. It returns
- null if it failed to init.
-
- Anytime you want to access shared memory you would go something like:
-
- ObtainSemaphore(handle->mps_Sema);
- /* twiddle with the memory by referencing mps_SemaData */
- ReleaseSemaphore(handle->mps_Sema);
-
- Note that semaphores are very quick when there is noone else currently
- holding the lock. Of course, good multitasking ethics dictate that you
- ObtainSemaphore() for as little time as possible.
-
- By using Semaphore()s, you protect your public memory from being stomped on
- by multiple instances at the same time. By not using Forbid(), you don't
- cause the rest of the system to suffer.
-
- Note that I only needed this memory to be initialized to all zeros for my
- program. If you need something in it initialized to something other than
- that, the only safe way to do this is to modify the routines to take a
- pointer to a chunk of memory you have already allocated and filled in. This
- eliminates the possibility of you creating the semaphore and then a second
- instance started right after it coming along and using the data before you
- have had a chance to initialize the data area. Doing this, however, requires
- that you always allocate a chunk of memory (and you must use the exec
- allocators to be safe when the process that created the public memory
- terminates before the last process that is using it terminates), even when
- you probably won't need it (only the first instance would). If
- InitMyPublicSempahore() returns a handle to you, you'd have to check to see
- if the mps_SemaData in the handle is the same as the chunk you allocated and
- if it isn't you'd free the chunk you allocated. Not good if you have a large
- public chunk.
-
- A better alternative would probably be to have InitMyPublicSemaphore() do an
- ObtainSemaphore() after the } and before the Permit(). This way a second
- instance couldn't use the sempahore until after you had initialized the data
- section. This requires that you always call ReleaseSemaphore() sometime
- shortly after calling InitMyPublicSemaphore(). Actually, this isn't too bad
- since you could do something like:
-
- /* assume struct MyShared is defined somewhere to give easy access
- to the elements you need in the public data section */
-
- handle = InitMyPublicSemaphore("name", sizeof(struct MyShared));
- if (!handle)
- panic();
-
- pubmem = (struct MyShared *) handle->mps_SemaData;
-
- if (!pubmem->Initialized) {
- /* initialized the data section */
- pubmem->Initialized = TRUE;
- }
-
- ReleaseSemaphore(handle->mps_Sema);
-
- Then anytime you wanted to use data in the public section it would be easy to
- go:
-
- ObtainSemaphore(handle->mps_Sema);
- pubmem->Foo = BAR;
- ReleaseSemaphore(handle->mps_Sema);
-
- Hope this helps.
-
- -=> CAW
-
- --
-
- Christopher A. Wichura Multitasking. Just DO it.
- caw@miroc.chi.il.us (my amiga) ...the Amiga way...
- u12401@uicvm.uic.edu (school account)
-