home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pmos2002.zip / SRC / MAILBOXE.MOD < prev    next >
Text File  |  1996-09-30  |  6KB  |  190 lines

  1. IMPLEMENTATION MODULE Mailboxes;
  2.  
  3.         (********************************************************)
  4.         (*                                                      *)
  5.         (*      Mailboxes for intertask communication           *)
  6.         (*                                                      *)
  7.         (*  Programmer:         P. Moylan                       *)
  8.         (*  Last edited:        30 September 1996               *)
  9.         (*  Status:             Working                         *)
  10.         (*                                                      *)
  11.         (********************************************************)
  12.  
  13. FROM SYSTEM IMPORT
  14.     (* type *)  BYTE, ADDRESS,
  15.     (* proc *)  ADR;
  16.  
  17. FROM Semaphores IMPORT
  18.     (* type *)  Semaphore,
  19.     (* proc *)  CreateSemaphore, Wait, Signal;
  20.  
  21. FROM Timer IMPORT
  22.     (* proc *)  TimedWait;
  23.  
  24. FROM TaskControl IMPORT
  25.     (* type *)  Lock,
  26.     (* proc *)  CreateLock, Obtain, Release;
  27.  
  28. FROM Storage IMPORT
  29.     (* proc *)  ALLOCATE, DEALLOCATE;
  30.  
  31. FROM LowLevel IMPORT
  32.     (* proc *)  Copy;
  33.  
  34. (************************************************************************)
  35.  
  36. CONST GuardConst = 3579;
  37.  
  38. TYPE
  39.     MessagePtr = POINTER TO Message;
  40.  
  41.     Message = RECORD
  42.                   next: MessagePtr;
  43.                   size: CARDINAL;
  44.                   content: ARRAY [0..0] OF BYTE;
  45.               END (*RECORD*);
  46.  
  47.     Mailbox = POINTER TO
  48.                     RECORD
  49.                         guard: CARDINAL;
  50.                         limit: CARDINAL;
  51.                         mutex: Lock;
  52.                         count: Semaphore;
  53.                         head, tail: MessagePtr;
  54.                     END (*RECORD*);
  55.  
  56. (************************************************************************)
  57.  
  58. PROCEDURE CreateMailbox (LengthLimit: CARDINAL): Mailbox;
  59.  
  60.     (* Creates a new mailbox.  LengthLimit is the maximum number of     *)
  61.     (* characters in a single message.  (A limit is needed so that a    *)
  62.     (* task reading the mailbox knows how much space to allocate.)      *)
  63.  
  64.     VAR result: Mailbox;
  65.  
  66.     BEGIN
  67.         NEW (result);
  68.         WITH result^ DO
  69.             guard := GuardConst;
  70.             limit := LengthLimit;
  71.             CreateLock (mutex);
  72.             CreateSemaphore (count, 0);
  73.             head := NIL;  tail := NIL;
  74.         END (*WITH*);
  75.         RETURN result;
  76.     END CreateMailbox;
  77.  
  78. (************************************************************************)
  79.  
  80. PROCEDURE SendMessage (MB: Mailbox;  messageptr: ADDRESS;
  81.                                         length: CARDINAL): BOOLEAN;
  82.  
  83.     (* Copies a string, specified by its address and length, into the   *)
  84.     (* specified mailbox.  Returns TRUE if successful, and FALSE if the *)
  85.     (* message is too long or the mailbox does not exist.               *)
  86.  
  87.     VAR pnew: MessagePtr;
  88.  
  89.     BEGIN
  90.  
  91.         (* Check for invalid mailbox. *)
  92.  
  93.         IF (MB = NIL) OR (MB^.guard <> GuardConst)
  94.                         OR (length > MB^.limit) THEN
  95.             RETURN FALSE;
  96.         END (*IF*);
  97.  
  98.         (* Create a new queue element containing the message. *)
  99.  
  100.         NEW (pnew);
  101.         ALLOCATE (pnew, SIZE(Message) + length - 1);
  102.         WITH pnew^ DO
  103.             next := NIL;  size := length;
  104.             IF length > 0 THEN
  105.                 Copy (messageptr, ADR(content), length);
  106.             END (*IF*);
  107.         END (*WITH*);
  108.  
  109.         (* Insert the new entry into the mailbox queue. *)
  110.  
  111.         WITH MB^ DO
  112.             Obtain (mutex);
  113.             IF head = NIL THEN
  114.                 head := pnew;
  115.             ELSE
  116.                 tail^.next := pnew;
  117.             END (*IF*);
  118.             tail := pnew;
  119.             Release (mutex);
  120.             Signal (count);
  121.         END (*WITH*);
  122.         RETURN TRUE;
  123.  
  124.     END SendMessage;
  125.  
  126. (************************************************************************)
  127.  
  128. PROCEDURE ReceiveMessage (MB: Mailbox;  VAR (*OUT*) message: ARRAY OF CHAR;
  129.                                         TimeLimit: CARDINAL): CARDINAL;
  130.  
  131.     (* Returns the next message (after waiting if necessary) from       *)
  132.     (* mailbox MB.  TimeLimit is a timeout value in milliseconds.       *)
  133.     (* (Specify TimeLimit=0 for infinite patience.)  The function       *)
  134.     (* return value is the message length; this is zero if no message   *)
  135.     (* was obtained, either because of a faulty mailbox or because of   *)
  136.     (* timeout.  Note: it is also possible to have a genuine message of *)
  137.     (* zero length.                                                     *)
  138.  
  139.     VAR length: CARDINAL;  TimedOut: BOOLEAN;
  140.         second: MessagePtr;
  141.  
  142.     BEGIN
  143.  
  144.         (* Check for invalid mailbox.   *)
  145.  
  146.         IF (MB = NIL) OR (MB^.guard <> GuardConst) THEN
  147.             RETURN 0;
  148.         END (*IF*);
  149.  
  150.         WITH MB^ DO
  151.  
  152.             (* Wait no longer than TimeLimit for a message to arrive. *)
  153.  
  154.             IF TimeLimit = 0 THEN
  155.                 Wait (count);
  156.             ELSE
  157.                 TimedWait (count, TimeLimit, TimedOut);
  158.                 IF TimedOut THEN RETURN 0 END(*IF*);
  159.             END (*IF*);
  160.  
  161.             (* If we reach here, at least one message is available. *)
  162.  
  163.             Obtain (mutex);
  164.  
  165.             (* Copy the message. *)
  166.  
  167.             WITH head^ DO
  168.                 second := next;  length := size;
  169.                 IF length > 0 THEN
  170.                     Copy (ADR(content), ADR(message), length);
  171.                 END (*IF*);
  172.             END (*WITH*);
  173.             DEALLOCATE (head, SIZE(Message) + length - 1);
  174.  
  175.             (* Update the queue. *)
  176.  
  177.             head := second;
  178.             IF head = NIL THEN
  179.                 tail := NIL;
  180.             END (*IF*);
  181.             Release (mutex);
  182.         END (*WITH*);
  183.         RETURN length;
  184.     END ReceiveMessage;
  185.  
  186. (************************************************************************)
  187.  
  188. END Mailboxes.
  189.  
  190.