简体   繁体   中英

Combining STL(c++11) with WinAPI

Im trying to start a new thread using CreateThread and pass the pointee of a shared_pointer as an argument. If i was to use good old ATL, it would call Ccomptr's operator () and increase the ref count and eventually retrieve the pointer.

I'm trying to do the same using STL's shared_ptr, but I'm getting an error where conversion between std::shared_ptr to LPVOID doesn't exist.

        std::shared_ptr<X> m_pSettings = std::make_shared(new ....);
        if (nullptr == (m_hBackgroundThread = ::CreateThread(
            nullptr,                // default security attributes
            0,                      // use default stack size  
            ThreadProc,             // thread function name
            m_pSettings,            // argument to thread function 
            0,                      // use default creation flags 
            0)))
        {
            LOG_ERROR(L"Failed to create thread");
            return false;
        }

The correct answer, as you have already been told, is to use std::thread :

// Hey, look: No magic nullptrs and zeros nobody ever changes to non-defaults anyway!
std::thread t(ThreadProc, m_pSettings);

// Don't forget to
t.detach();
// if you let the std::thread object destruct without first joining it and making sure
// the thread finishes executing

Not only std::thread solves your problem, it has a multitude of other benefits such as allowing you to pass multiple parameters without fuss, it copies/moves/does-the-right-thing with the arguments you pass, etc. and it doesn't require you to resort to any supposedly clever but actually not hacks. If you use std::async instead of std::thread you can even get in the caller thread the exception that caused the thread function to unwind if there was one.

The alternative of passing CreateThread the address of your shared_ptr and then dereferencing it inside the ThreadProc might work, if you're extremely careful - at the very least you have to make sure the caller's shared_ptr doesn't go away until the ThreadProc is done with it - but that's just asking for bad things to happen.

Sure, if you had no alternatives that's what you do, but given std::thread and friends doing anything else is wrong and a waste of time.


Also, your comparison to ATL seems to be founded on a misunderstanding. The difference is not between ATL's smart pointers that are extra-clever and and are able in some magical way to keep the reference count even when giving you the raw pointer (though I am unaware of an CComPtr::operator() ) while C++ standard library smart pointers are lame and don't do that. The difference is between special object who manage keep their own reference count and manage their own lifetimes given that you declare when you use them (ie call AddRef ) and arbitrary resources.

A smart pointer for COM (be it CComPtr or _com_ptr_t or any half-baked lame class you fine online) is basically a wrapper around the COM object's innate capability to manage its own lifetime.

You could have just as much added AddRed , Release , etc. (with the associated semantics, obviously) to your class X and wrapped it in a COM smart pointer...

You could pass shared_ptr object by pointer like this: &m_pSettings

Then dereference it in your ThreadProc :

  std::shared_ptr<X> pSettings = *static_cast<std::shared_ptr<X>*>(lpParam);

Probably you need to copy your shared_ptr first before passing pointer to it into CreateTrhead so it'll be in scope while ThreadProc running.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM