///////////////////////////////////////////////////////////////////////////////
//
// Module: msgq.c
//
// Abstract: Inter-thread message queue mechanism.
// Since Windows 95 limits an app to only 15 mailslots,
// this queue mechanism is used in place of the built-in
// Mailslot service of Windows 95 and Windows NT.
//
// Author: Mark Hornick
//
// Revisions:
// $History: MSGQ.C $
//
// ***************** Version 3 *****************
<- Note modification history inserted by version control
// User: Markh Date: 1/10/97 Time: 3:17p
// Updated in $/QuickTeach/msgqueue
// add msg queue length limit for MOC
//
// ***************** Version 2 *****************
<-
// User: Markh Date: 2/02/96 Time: 2:56p
// Updated in $/QuickTeach/msgqueue
// added conditionally compiled debug code
//
// ***************** Version 1 ***************** <-
// User: Markh Date: 10/17/95 Time: 1:56p
// Created in $/quickteach/msgqueue/msgqueue
//
// Copyright 1995 ABB Flexible Automation, Inc.
//
// Notes:
// A queue is implemented as a linked list of message structures;
// each queue is coupled to an Event object used for read
// timeout notifications.
//
// A queue is structured as a FIFO. Writing to the queue appends
// msgs to the end of the FIFO, while reading msgs pulls them
// off the front of the FIFO. Msgs pile up indefinitely if
// they are not read and a maximum number of msgs is not specified
// via a call to SetMsgQueueMaxMsgs(). If a maximum is specified,
// then calls to WriteMsgQueue() block until a msg is pulled off
// the queue by ReadMsgQueue() or until a timeout specified via a
// call to SetMsgQueueWriteTimeout() expires.
//
// This class presents an API that basically parallels
// that of the Win32 Mailslot service: Create, Connect, Read,
// Write, and Set functions are provided. No queue
// deletion or flush API is provided at this time.
//
// The diagram below illustrates the relationships between
// the various elements comprising the queue mechanism.
//
// +---------------+
// | queue |
// | handle |
// |(LPQUEUEHEADER)|
// +---------------+
// |
// \/
// +-------------+ +--------------+ +-----+ +-----+
// | queue | | message | | msg | | msg |
// | #1 |-->| #1 |-->| #2 |-->| #n1 |-->NULL
// |(QUEUEHEADER)| |(MESSAGEQUEUE)| | | | |
// +-------------+ +--------------+ +-----+ +-----+
// |
// \/
// +-------------+ +--------------+ +-----+ +-----+
// | queue | | message | | msg | | msg |
// | #2 |-->| #1 |-->| #2 |-->| #n1 |-->NULL
// |(QUEUEHEADER)| |(MESSAGEQUEUE)| | | | |
// +-------------+ +--------------+ +-----+ +-----+
// |
// \/
// +-------------+ +--------------+ +-----+ +-----+
// | queue | | message | | msg | | msg |
// | #3 |-->| #1 |-->| #2 |-->| #n1 |-->NULL
// |(QUEUEHEADER)| |(MESSAGEQUEUE)| | | | |
// +-------------+ +--------------+ +-----+ +-----+
// |
// \/
// NULL
//
///////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include "msgq.h"
static CRITICAL_SECTION gCS; //
private critical section object for
// queue management
static BOOL gbCSInit = FALSE;
// initialization flag for Critical Section
static LPQUEUEHEADER gpQMaster = NULL; //
private ptr to first QUEUEHEADER
...
Note: This code comes from a product I worked on some time ago. It was an implementation of the ABB robot controller software for Windows (first for NT 3.5 beta). The software for the production robot controller targeted the VxWorks real-time operating system. The Windows NT version served as the "engine" for a simulation of the controller within various ABB desktop software products. The robot controller software consisted (at that time) of around 500k LOC (then grew to >3M). The Windows versions of the software implemented the controller as 1 process using multiple threads (23-30, depending upon configuration). The threads sent and received messages via an interthread communications system called the IPC bus. The class shown here was used by each thread to post and get messages to and from the bus. As you can see from the comments, the IPC bus was built originally upon the mailslot mechanism of the Windows Win32 API; however, while NT (and now W2K and XP) support an unlimited number of mailslots, 95 (and 98) were "dumbed down" considerably. This class circumvented that limitation within 95, and ultimately obviated the use of the Win32 mailslot mechanism.
The history log of revisions was created automatically by using Microsoft's Visual SourceSafe product for revision control.
Note also the use of the static keyword for the variable declarations. Since the code was written in C, not C++, this technique was used to make the variables private to this source module. In some cases, functions (they weren't referred to as methods in C) were also marked static - also to prevent public access.
Trivia: We had a hard time convincing management to use NT, since the system requirements were, at the time, imposing. I had one of the few PCs in the entire company that had the requisite Intel '386 processor, 16MB RAM, and CD-ROM (single-speed; it cost around $500). Note: I had one installation of NT that ran on a 4MB PC. Most people thought we were way off in choosing NT over OS/2.