The Jim Patchell Windows Programming Page
First Posted January 1, 2005
 Updated January  20, 2014

Contents:
Overlapped RS232
Simple Soft Synth
Mutex Class
Memory Heap Class
Message Queue Class
Sending Messages to Worker Thread


Overlapped RS232 Programming
January 1, 2005
    If you have ever tried to write a program that accessed the comm ports under Win32, you have probably been overwhelmed by the large number of convoluted functions you have to deal with in order to do this.  It is posible to open up the RS232 port on Non-overlapped mode, however, there are several problems with doing this, and if you have done it, you may have run into them.  By using the overlapped mode, the comm ports do work pretty much as you would expect, although, still not, in my opinion, perfectly.  Of course, there are probably still some features I don't know about that would even cure these problems.

    What you will find here is a zip file of a skeleton program that opens up an RS232 port and provides functions for reading and writing to the port.

    Now, one of the problems still with using the Overlapped mode is that you need to have a thread that reads the characters that come back into the PC.  In the code, you will find this in a function called WorkerThread.  Yeah, not exactly an original name, but what the heck.  This worker thread is pretty simple.  It reads the character in and prints it into a static text box in the main dialog.  Now in a real program you will most likely have some sort of parser, be it simple or complex, that will look for messages in the data coming back.  Once you have located your messages you can do several things.  You can act on them directly, or you can send a notification back to the main dialog box by using PostMessage and sending user defined messages, just like I did for the message that notifies the main dialog box that the thread has stopped.

    As of January 1, 2005, I have not actually tested this code, although, most of it has been used before (that is no garentee).  Still for the time being, it should give you a good idea of how to proceed.

    Source Code for Overlapped RS232

A Simple Soft Synth for MicroSquish Windows
March 9, 2005
    This is a very simple softsynth that I did for running under Microsoft Windows.  It should run with Windows98, Windows2000, Windows XP and Windows ME.  I have only tried it on Windows XP running on a 2GHz Pentium.  There is a chance a slower computer could sound strange.  So, what you will find here is the source code and an executable for a very simple program that compiles, hopefully, with Microsoft Visual C++ 6.0.  I cannot predict what it will do with other versions of the compiler.

    There is not a whole lot that I can think of to say about this program.  Basically, I open up an audio out channel and set up two buffers.  The buffers are then ping-ponged as they empty out.  There is a synth engine routine that is called that fills the buffers up with data when a buffer is ready.

    Oh, yes, there is a simple little sequencer that plays a couple of little tunes.

    The modules that I implemented are a VCO, Multimode VCF, VCA, and a simple envelope generator.

    Source Code for Soft Synth Program



Mutex Class
Source Code for Mutex



Memory Heap Class

Source Code for Heap

I only turned some C functions into a C++ class.  The functions originally came from the run time library for WinAVR.  You will find the original copyright notice in the cpp file.  I don't know if this was all nessesary or not, but it sure made my life a lot easier.   Thank you Joerg Wunsch.



Message Queue Class

Source Code for Queue Class



Sending Messages to a Worker Thread
January 20, 2014

The reality is if you need to send messages to a worker thread, use the GUI thread model for CWinThread.  Even if you are not going to be doing a GUI, you can still use it as such, and life will probably be a whole lot easier.  OH, you are a control freak!  Just like me.  OK, well, here is what I did.

I found a really useful article on the "Code Project" called Using Worker Threads By Joseph M. Newcomer, 5 Apr 2001.  It is located at :

http://www.codeproject.com/Articles/552/Using-Worker-Threads

Now at first I felt kind of guilty about plagiarizing   his code, but as it tuns out, it appears that it was taken right out of the source code for MFC itself.  But, I digress.

One of the things it said in the article is using CWinThread::ResumeThread is not a good thing.  I discovered that it was pretty impossible to get along without it.  The problem I had was that the worker thread would  start using things before they were initialized.  So, I ended up having to use ResumeThread, and so far, I have seen no ill effects from it.

OK, now for the code.  First, let us take a look at the header file for CMyThread.

#include "MSG.h"

enum {  MT_SHUTDOWN = 0, MT_RUNNING, MT_MESSAGE, MT_ERROR = 0xffffffe,MT_TIMEOUT };


/////////////////////////////////////////////////////////////////////////////
// CMyThread thread

class CMyThread : public CWinThread
{
    DECLARE_DYNCREATE(CMyThread)
protected:
    CMyThread(){};           // protected constructor used by dynamic creation

// Attributes
public:

// Operations
public:
    CMsgQueue * m_MSGQ;
    int m_NwaitObjs;
    HANDLE m_WaitObjects[16];
    DWORD m_WaitRetVals[16];
    void ClearWaitObjects();
    int SetWaitObject(HANDLE hObj,DWORD RetVal);
    void Continue();
    void Pause(void);
    DWORD Wait(void);
    void ShutDown();
    static CMyThread * BeginThread(AFX_THREADPROC pProc, void *pP,int MsgQDepth);

// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CMyThread)
    public:
    virtual BOOL InitInstance();
    virtual int ExitInstance();
    //}}AFX_VIRTUAL

// Implementation
protected:
    HANDLE m_PauseEvent;
    HANDLE m_ShutdownEvent;
    CMyThread(AFX_THREADPROC pProc, void *pP);
    virtual ~CMyThread();

    // Generated message map functions
    //{{AFX_MSG(CMyThread)
        // NOTE - the ClassWizard will add and remove member functions here.
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()
};

 
And here is the code for implementation.


Constructor
IMPLEMENT_DYNCREATE(CMyThread, CWinThread)

CMyThread::CMyThread(AFX_THREADPROC pProc, void *pP):CWinThread(pProc,pP)
{
     m_bAutoDelete = FALSE;
     m_ShutdownEvent = ::CreateEvent(NULL,   // security
                                   TRUE,   // manual-reset
                                   FALSE,  // not signaled
                                   NULL);  // anonymous

     m_PauseEvent = ::CreateEvent(NULL,      // security
                                TRUE,      // manual-reset
                                TRUE,      // signaled
                                NULL);     // anonymouse
    this->m_NwaitObjs = 0;
    memset(this->m_WaitObjects,0,sizeof(HANDLE) * 16);
    this->m_MSGQ = 0;
}

This is the constructor for the object.  Mostly we are creating a bunch of event objects.   m_ShutdownEvent is the event we trigger when we want the thread to shut down.  m_PauseEvent can be used to make the thread run continuously.  When m_PauseEvent is Set, the event will always run.  And finally we initialize the wait objects m_WaitObjects to zero.  This is an array of HANDLEs that are used to let our thread what it needs to do.  It will contain the two EVENTs  listed above as well as any others we decide to add.

 

Begin Thread
CMyThread * CMyThread::BeginThread(AFX_THREADPROC pProc, void *pP,int MsgQDepth)
{
    CMyThread * thread = new CMyThread(pProc, pP);
    if(!thread->CreateThread(CREATE_SUSPENDED,0 ))
 //   if(!thread->CreateThread())
    { /* failed ? */
       delete thread;
       thread = 0;
    } /* failed */
    else
    {
        //-----------------------------
        // setup default wait objects
        //-----------------------------
        thread->SetWaitObject(thread->m_ShutdownEvent,MT_SHUTDOWN);
        thread->SetWaitObject(thread->m_PauseEvent,MT_RUNNING);
        thread->m_MSGQ = new CMsgQueue(MsgQDepth);
        thread->SetWaitObject(thread->m_MSGQ->GetSem()->GetHandle(),MT_MESSAGE);
    }
    return thread;
}

OK, here is the crux of the whole thing.  When I first saw this static member function, I was a bit confused because I forgot that a static member function is more like a real C function that a C++ class.  Now, if you were to look at the source code for the MFC function AfxBeginThread you will see that a lot of this is just pulled right out of that code.  And the reason I looked at that code was because I could find no documentation on a lot of the functions used, such as the constructor CWinThread(proc,pP) and the create thread function with no parameters.   Evidently, they do exist, as the code works (at least with Visual Studio 6) , so one of these days I need to look in the MFC source code and find out what the deal is.

I just looked at the code for CWinThread, and sure enough, there are undocumented methodes in the class.  It would appear that Microsoft wanted to encourage the use of AfxBeginThread.

After the tread is created, we add a few event objects to the mess.   We add the events for shutting down the thread, pausing and finally, the semaphore from the Message Queue (see above) that we will use to send messages to the thread.  We are using a semaphore as it will keep track of how many times it has been signaled so we won't miss any of the messages.

Wait Function
DWORD CMyThread::Wait()
{
    DWORD result = ::WaitForMultipleObjects(m_NwaitObjs, m_WaitObjects, FALSE, INFINITE);

    switch(result)
    { /* result */
       case WAIT_TIMEOUT:
           result =  MT_TIMEOUT;
           break;
       default:
          if(result <= WAIT_OBJECT_0+16)
           {
               result = m_WaitRetVals[result - WAIT_OBJECT_0];
           }
           else
            result =  MT_ERROR;
           break;
    } /* result */
    return result;
 }

When any of the events in the m_WaitObjects table are triggered (signaled), this function will return an integer value that  represents the event.  I used a table to look up these values, since I had no idea what the value of WAIT_OBJECT_0 might be, or could be in the future.  So, I made sure that I would always get a value that I knew.  This function is a bit different than the one described in the article I mentioned above.

Anyway, what this program does  is it allows you to start up the worker thread, and then send a message to it.  The worker thread then sends a message back to theapplication view window where it is displayed.  I know that this is a useless progrom but it does demonstrate how the message passing is done.  The worker thread uses the standard CWnd::PostMessage message function to send messages back.

Source Code for the Project

The above was built with Visual Studio 6.0.


Home
Bye...