home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / sys / amiga / programm / 17995 < prev    next >
Encoding:
Text File  |  1992-12-31  |  6.5 KB  |  184 lines

  1. Path: sparky!uunet!zaphod.mps.ohio-state.edu!pacific.mps.ohio-state.edu!linac!att!mcdchg!chinet!miroc!caw
  2. From: caw@miroc.Chi.IL.US (Christopher A. Wichura)
  3. Newsgroups: comp.sys.amiga.programmer
  4. Subject: Re: IPC and shared memory
  5. Distribution: world
  6. Message-ID: <caw.0wk9@miroc.Chi.IL.US>
  7. References:  <Jean-Guy_Speton.056u@tvbbs.wimsey.bc.ca>
  8. X-NewsSoftware: GRn-beta 1.16g (28.12.92) by Michael B. Smith & Mike Schwartz
  9. MIME-Version: 1.0
  10. Content-Type: text/plain; charset=iso-8859-1
  11. Content-Transfer-Encoding: 8bit
  12. Date: 31 Dec 92 09:02:22 CST
  13. Lines: 169
  14.  
  15. In article <Jean-Guy_Speton.056u@tvbbs.wimsey.bc.ca> Jean-Guy_Speton@tvbbs.wimsey.bc.ca (Jean-Guy Speton) writes:
  16. > I am looking for information on inter-process communications (IPC) and
  17.  
  18. IPC is real easy.  The Amiga has had message passing functions since day one.
  19.  
  20. > shared memory functions.  Do the Amiga libraries have any functions along
  21.  
  22. Shared memory is a little trickier.  The best way to go about this (that I've
  23. come up with) is to allocate a chunk of memory and protect it with a
  24. semaphore.  Subsequent instances of the program would not allocate but rather
  25. simply find the semaphore and use that as the chunk base.  When you free the
  26. semaphore, if you are the last instance then you free the memory chunk.
  27.  
  28. Here's some code I wrote to do this a little while back:
  29.  
  30. /* structure for handling our public semaphores. */
  31. struct MyPublicSema {
  32.     struct SignalSemaphore mps_Sema;
  33.     UBYTE *mps_SemaData;
  34.     ULONG mps_UseCount;
  35.     UBYTE mps_SemaName[4];
  36. };
  37.  
  38.  /*
  39.   * this routine sets up a public semaphore.  If it already exists we just
  40.   * bump its use count up by one.  Otherwise we have to allocate a new one.
  41.   * semaDataSize is a number of bytes to allocate with the semaphore that can
  42.   * be shared by those locking the semaphore.  Let's us have "global" data
  43.   * between seperate processes.  These routines don't care what is put in
  44.   * this data space.  It will be cleared to 0s when first allocated, though.
  45.   */
  46.  
  47. struct MyPublicSema *InitMyPublicSemaphore(STRPTR semaName, ULONG semaDataSize)
  48. {
  49.     struct MyPublicSema *theSema;
  50.     ULONG semaNameLen;
  51.  
  52.     if (!semaName)
  53.         return (struct MyPublicSema *) NULL;
  54.  
  55.     /*
  56.      * we want the semaphore's name to be a longword in length, at least
  57.      * in space allocated for it
  58.      */
  59.     semaNameLen = ((strlen(semaName) + 3) / 4) * 4;
  60.  
  61.     Forbid();
  62.     if (theSema = (struct MyPublicSema *) FindSemaphore(semaName))
  63.         theSema->mps_UseCount++;    /* only safe way to diddle
  64.                          * with this is under
  65.                          * Forbid()... sigh */
  66.     else {
  67.  
  68.         /*
  69.          * we didn't find the semaphore around already so we have to
  70.          * allocate and initialize it
  71.          */
  72.         if (!(theSema = AllocVec(sizeof(struct MyPublicSema) + semaNameLen + semaDataSize, MEMF_CLEAR | MEMF_PUBLIC))) {
  73.             Permit();
  74.             return (struct MyPublicSema *) NULL;
  75.         }
  76.  
  77.         strcpy(theSema->mps_SemaName, semaName);
  78.         theSema->mps_Sema.ss_Link.ln_Name = theSema->mps_SemaName;
  79.         if (semaDataSize)
  80.             theSema->mps_SemaData = &theSema->mps_SemaName[semaNameLen];
  81.         theSema->mps_UseCount = 1;
  82.  
  83.         AddSemaphore(&theSema->mps_Sema);
  84.     }
  85.  
  86.     Permit();
  87.  
  88.     return theSema;
  89. }
  90.  
  91.  /*
  92.   * this dealocates what we got from InitMyPublicSemaphore().  If there are
  93.   * others still using it then just down the use count.  Otherwise remove the
  94.   * semaphore from the public lists and down the use count.
  95.   */
  96.  
  97. void FreeMyPublicSemaphore(struct MyPublicSema * mySema)
  98. {
  99.     if (mySema) {
  100.         ObtainSemaphore(&mySema->mps_Sema);
  101.         Forbid();
  102.         ReleaseSemaphore(&mySema->mps_Sema);
  103.         if (!--mySema->mps_UseCount) {
  104.             RemSemaphore(&mySema->mps_Sema);
  105.             FreeVec(mySema);
  106.         }
  107.         Permit();
  108.     }
  109. }
  110.  
  111. To use this, early on in your program you would call InitMyPublicSemaphore()
  112. with the name you want to refer to your shared memory chunk as.  It returns
  113. null if it failed to init.
  114.  
  115. Anytime you want to access shared memory you would go something like:
  116.  
  117.     ObtainSemaphore(handle->mps_Sema);
  118.     /* twiddle with the memory by referencing mps_SemaData */
  119.     ReleaseSemaphore(handle->mps_Sema);
  120.  
  121. Note that semaphores are very quick when there is noone else currently
  122. holding the lock.  Of course, good multitasking ethics dictate that you
  123. ObtainSemaphore() for as little time as possible.
  124.  
  125. By using Semaphore()s, you protect your public memory from being stomped on
  126. by multiple instances at the same time.  By not using Forbid(), you don't
  127. cause the rest of the system to suffer.
  128.  
  129. Note that I only needed this memory to be initialized to all zeros for my
  130. program.  If you need something in it initialized to something other than
  131. that, the only safe way to do this is to modify the routines to take a
  132. pointer to a chunk of memory you have already allocated and filled in.  This
  133. eliminates the possibility of you creating the semaphore and then a second
  134. instance started right after it coming along and using the data before you
  135. have had a chance to initialize the data area.  Doing this, however, requires
  136. that you always allocate a chunk of memory (and you must use the exec
  137. allocators to be safe when the process that created the public memory
  138. terminates before the last process that is using it terminates), even when
  139. you probably won't need it (only the first instance would).  If
  140. InitMyPublicSempahore() returns a handle to you, you'd have to check to see
  141. if the mps_SemaData in the handle is the same as the chunk you allocated and
  142. if it isn't you'd free the chunk you allocated.  Not good if you have a large
  143. public chunk.
  144.  
  145. A better alternative would probably be to have InitMyPublicSemaphore() do an
  146. ObtainSemaphore() after the } and before the Permit().  This way a second
  147. instance couldn't use the sempahore until after you had initialized the data
  148. section.  This requires that you always call ReleaseSemaphore() sometime
  149. shortly after calling InitMyPublicSemaphore(). Actually, this isn't too bad
  150. since you could do something like:
  151.  
  152.     /* assume struct MyShared is defined somewhere to give easy access
  153.        to the elements you need in the public data section */
  154.  
  155.     handle = InitMyPublicSemaphore("name", sizeof(struct MyShared));
  156.     if (!handle)
  157.         panic();
  158.  
  159.     pubmem = (struct MyShared *) handle->mps_SemaData;
  160.  
  161.     if (!pubmem->Initialized) {
  162.         /* initialized the data section */
  163.         pubmem->Initialized = TRUE;
  164.     }
  165.  
  166.     ReleaseSemaphore(handle->mps_Sema);
  167.  
  168. Then anytime you wanted to use data in the public section it would be easy to
  169. go:
  170.  
  171.     ObtainSemaphore(handle->mps_Sema);
  172.     pubmem->Foo = BAR;
  173.     ReleaseSemaphore(handle->mps_Sema);
  174.  
  175. Hope this helps.
  176.  
  177. -=> CAW
  178.  
  179. --
  180.  
  181. Christopher A. Wichura                Multitasking.  Just DO it.
  182. caw@miroc.chi.il.us  (my amiga)                          ...the Amiga way...
  183. u12401@uicvm.uic.edu (school account)
  184.