Search code examples
c++functionwinapiprivatequeueuserworkitem

Calling Win32 QueueUserWorkItem() with a private member function


I am attempting to call a private member function (should not be available as public or protected) as a worker item with the Win32 function QueueUserWorkItem(). I know I've done this before and it was easy, but now I can't find that snippet, nor can I make bind() voodoo work. So for the purposes of this question the class is:

class Arbitrary {

    public:
        Arbitrary() ;
        ~Arbitrary() ;

        bool    UsefulPublicFunction(unsigned uParameter) ;

    protected:

    private:
        void    PrivateWorkItem(void* pVoid) ;
} ;

And inside UsefulPublicFunction() we might see:

LPTHREAD_START_ROUTINE pThreadStartRoutine ;
ULONG uFlags = 0 ;
void* pContext = nullptr ;

if (QueueUserWorkItem(pThreadStartRoutine, pContext, uFlags)) {
    //blah blah blah
}

Where I seem to go off in the weeds is with the assignment to pThreadStartRoutine with something like:

pThreadStartRoutine = std::bind<&Arbitrary::PrivateWorkItem, this, std::placeholders::_1> ;

I recognize that the signature for PrivateWorkItem probably should change to:

private:
    DWORD   WINAPI  PrivateWorkItem(void* pVoid) ;

Even with that change, no joy. VS2015 really hates the way I'm using bind().

What should my assignment to pThreadStartRoutine look like?


Solution

  • This seems to work:

    #include <Windows.h>
    
    #include <stdio.h>
    
    #include <functional>
    
    using namespace std::placeholders;
    
    class Arbitrary {
    
        public:
    
            bool UsefulPublicFunction(int uParameter);
    
        protected:
    
        private:
            typedef std::function<void (void)> CallbackType;
            static DWORD WINAPI ProcessWorkItem(void* pVoid);
            void PrivateWorkItem1(int arg1, int arg2);
            void PrivateWorkItem2(char * arg1);
    };
    
    void Arbitrary::PrivateWorkItem1(int arg1, int arg2)
    {
        printf("Numbers are %u %u\n", arg1, arg2);
        return;
    }
    
    void Arbitrary::PrivateWorkItem2(char * arg1)
    {
        printf("String is %s\n", arg1);
        return;
    }
    
    DWORD WINAPI Arbitrary::ProcessWorkItem(void* pVoid)
    {
        CallbackType * callback = static_cast<CallbackType *>(pVoid);
        (*callback)();
        delete callback;
        return 0;
    }
    
    bool Arbitrary::UsefulPublicFunction(int param1)
    {
        QueueUserWorkItem(&ProcessWorkItem, new CallbackType(std::bind(&Arbitrary::PrivateWorkItem1, this, param1, 7)), 0);
    
        QueueUserWorkItem(&ProcessWorkItem, new CallbackType(std::bind(&Arbitrary::PrivateWorkItem2, this, (char *)"This is my string")), 0);
    
        Sleep(1000);
        return true;
    }
    
    int main(int argc, char ** argv)
    {
        Arbitrary x;
    
        x.UsefulPublicFunction(5);
    
        return 0;
    }