/* Dieses Programm läuft erst ab OS 2.0.
 * Aus Platzgründen mußte diese Überprüfung
 * entfallen. Auch die, ob das Programm »Second«
 * läuft. Es demonstriert lediglich die Verwendung
 * von öffentlichen Semaphoren.
 * Autor: Rainer Zeitler
 */
#include <exec/types.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <exec/semaphores.h>
#include <dos/dostags.h>

char *SemName="mysema"; /* So heißt die Semaphore */
struct SignalSemaphore *mysema;

/* Diese Variable ist geschützt */
ULONG SemaphoreTest=0;

struct MyMessage {
  struct Message msg;
  struct MsgPort *ReplyPort;
  ULONG *change;
} MsgSend, *MsgReceived;

struct TagItem memtags[] = { SYS_Output, 0,
  SYS_Input, 0, SYS_Asynch, TRUE, TAG_DONE };

BOOL AddPubSemaphore() {
  if( !FindSemaphore(SemName)) {
    mysema=AllocMem(sizeof(struct SignalSemaphore),
                    MEMF_CLEAR|MEMF_PUBLIC);
    if( mysema ) {
      mysema->ss_Link.ln_Pri=0;
      mysema->ss_Link.ln_Name=SemName;
      AddSemaphore( mysema ); return TRUE;
    } else return FALSE;
  } else return FALSE;
}

BOOL StartSecond() {
  BOOL ret=FALSE;
  if( !System("run >nil: <nil: second",&memtags[0]))
    ret=TRUE;
  return ret;
}

main() {
  struct MsgPort *SemPort =
                     CreatePort("Test-Semaphore",0);
  if( SemPort ) {
    if( AddPubSemaphore() ) {
      if( StartSecond() ) {
        WaitPort( SemPort );
        MsgReceived=GetMsg( SemPort );
        MsgSend.msg.mn_Length=
                           sizeof(struct MyMessage);
        MsgSend.msg.mn_Node.ln_Type=NT_MESSAGE;
        MsgSend.msg.mn_ReplyPort=NULL;
        MsgSend.change=&SemaphoreTest;
        PutMsg( MsgReceived->ReplyPort,&MsgSend );
        /* Signal von Second, Semaphore ist belegt*/
        WaitPort( SemPort );
        while( AttemptSemaphore(mysema) == 0 ) {
          printf("Semaphore belegt. Kein Zugriff ");
          printf("auf die Variable möglich\n");
          Delay(4); }
        printf("Neuer Wert: %d\n",SemaphoreTest);
      }
      Forbid();
      RemSemaphore(mysema);
      ObtainSemaphore(mysema);
      ReleaseSemaphore(mysema);
      FreeMem( mysema,
                    sizeof(struct SignalSemaphore));
      Permit();
    }
    DeletePort( SemPort );
  }
}
