/*++

Copyright (c) Microsoft Corporation. All rights reserved.

Module Name:

    mspthrd.h

Abstract:

    Definitions for MSP thread management classes.

--*/

#ifndef __MSPTHRD_H
#define __MSPTHRD_H

//
// Commands that the worker worker thread can handle.
//

typedef enum
{
    WORK_ITEM,          // process a work item
    STOP,               // kill the worker thread.

} COMMAND;

typedef struct
{
    COMMAND                cmd;
    LPTHREAD_START_ROUTINE pfn;
    PVOID                  pContext;
    HANDLE                 hEvent;

} COMMAND_NODE;

typedef struct
{
    LIST_ENTRY  link;
    COMMAND_NODE node;

} COMMAND_QUEUE_ITEM;

typedef struct _NOTIF_LIST
{
    CMSPAddress      *addr;
    _NOTIF_LIST      *next;
} NOTIF_LIST, *PNOTIF_LIST;

class CMSPThread
{
public:
    CMSPThread()
    {
        InitializeListHead(&m_CommandQueue);

        m_hCommandEvent = NULL;
        m_hThread       = NULL;

        m_NotifList     = NULL;

        m_iStartCount = 0;
    }

    ~CMSPThread() { };

    HRESULT Start();
    HRESULT Stop();

    // Shutdown is used to clean up the thread unconditionally. This can be
    // used as an alternative to matched Start() / Stop() calls.

    HRESULT Shutdown();

    HRESULT ThreadProc();

    static LRESULT CALLBACK NotifWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

    HRESULT RegisterPnpNotification(CMSPAddress *pCMSPAddress);
    HRESULT UnregisterPnpNotification(CMSPAddress *pCMSPAddress);

    HRESULT QueueWorkItem(
        LPTHREAD_START_ROUTINE Function,
        PVOID Context,
        BOOL  fSynchronous
        );

private:
    BOOL SignalThreadProc() { return SetEvent(m_hCommandEvent); }

private:

    CMSPCritSection         m_CountLock;     // Protects start count
    CMSPCritSection         m_QueueLock;     // Protects command queue
    int                     m_iStartCount;   // number of times we've been
                                             // started minus number of times
                                             // we've been stopped. If == 0
                                             // then we actually stop thread.
    LIST_ENTRY              m_CommandQueue;  // Queue of commands for thread
                                             // to process.
    HANDLE                  m_hCommandEvent; // Signaled to tell us to do
                                             // something.

    HANDLE                  m_hThread;       // The thread handle. We need to
                                             // save it so that we can wait
                                             // for it when stopping the
                                             // thread.

    HDEVNOTIFY              m_hDevNotifyVideo;  // Handles of device notification registration
    HDEVNOTIFY              m_hDevNotifyAudio;  // for video and audio devices.

    HWND                    m_hWndNotif;     // Window handle for notification window

    PNOTIF_LIST             m_NotifList;     // List of notification functions to call
                                             // on a PNP event
    CMSPCritSection         m_NotifLock;     // Notification list critical section
};

extern CMSPThread g_Thread;

#endif // __MSPTHRD_H

// eof
