more cleanup
This commit is contained in:
parent
354e4b00a3
commit
5c17603a94
|
@ -13,6 +13,69 @@ using namespace winrt::Windows::UI::Composition;
|
|||
using namespace winrt::Windows::UI::Xaml::Hosting;
|
||||
using namespace winrt::Windows::Foundation::Numerics;
|
||||
|
||||
// We keep a weak ref to our ContentProcess singleton here.
|
||||
// Why?
|
||||
//
|
||||
// We need to always return the _same_ ContentProcess when someone comes to
|
||||
// instantiate this class. So we want to track the single instance we make. We
|
||||
// also want to track when the last outstanding reference to this object is
|
||||
// removed. If we're keeping a strong ref, then the ref count will always be > 1
|
||||
|
||||
winrt::weak_ref<winrt::Microsoft::Terminal::Control::ContentProcess> g_weak{ nullptr };
|
||||
wil::unique_event g_canExitThread;
|
||||
|
||||
struct ContentProcessFactory : implements<ContentProcessFactory, IClassFactory>
|
||||
{
|
||||
ContentProcessFactory(winrt::guid g) :
|
||||
_guid{ g } {};
|
||||
|
||||
HRESULT __stdcall CreateInstance(IUnknown* outer, GUID const& iid, void** result) noexcept final
|
||||
{
|
||||
*result = nullptr;
|
||||
if (outer)
|
||||
{
|
||||
return CLASS_E_NOAGGREGATION;
|
||||
}
|
||||
|
||||
if (!g_weak)
|
||||
{
|
||||
// Instantiate the ContentProcess here
|
||||
winrt::Microsoft::Terminal::Control::ContentProcess strong{};
|
||||
|
||||
// Now, create a weak ref to that ContentProcess object.
|
||||
winrt::weak_ref<winrt::Microsoft::Terminal::Control::ContentProcess> weak{ strong };
|
||||
|
||||
// Stash away that weak ref for future callers.
|
||||
g_weak = weak;
|
||||
return strong.as(iid, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto strong = g_weak.get();
|
||||
// !! LOAD BEARING !! If you set this event in the _first_ branch
|
||||
// here, when we first create the object, then there will be _no_
|
||||
// referernces to the ContentProcess object for a small slice. We'll
|
||||
// stash the ContentProcess in the weak_ptr, and return it, and at
|
||||
// that moment, there will be 0 outstanding references, it'll dtor,
|
||||
// and wei'll ExitProcess.
|
||||
//
|
||||
// Instead, set the event here, once there's already a reference
|
||||
// outside of just the weak one we keep. Experimentation showed this
|
||||
// waw always hit when creating the ContentProcess at least once.
|
||||
g_canExitThread.SetEvent();
|
||||
return strong.as(iid, result);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT __stdcall LockServer(BOOL) noexcept final
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
winrt::guid _guid;
|
||||
};
|
||||
|
||||
static bool checkIfContentProcess(winrt::guid& contentProcessGuid, HANDLE& eventHandle)
|
||||
{
|
||||
std::vector<std::wstring> args;
|
||||
|
@ -52,63 +115,13 @@ static bool checkIfContentProcess(winrt::guid& contentProcessGuid, HANDLE& event
|
|||
return false;
|
||||
}
|
||||
|
||||
winrt::weak_ref<winrt::Microsoft::Terminal::Control::ContentProcess> g_weak{ nullptr };
|
||||
wil::unique_event g_canExitThread;
|
||||
|
||||
struct HostClassFactory : implements<HostClassFactory, IClassFactory>
|
||||
{
|
||||
HostClassFactory(winrt::guid g) :
|
||||
_guid{ g } {};
|
||||
|
||||
HRESULT __stdcall CreateInstance(IUnknown* outer, GUID const& iid, void** result) noexcept final
|
||||
{
|
||||
*result = nullptr;
|
||||
if (outer)
|
||||
{
|
||||
return CLASS_E_NOAGGREGATION;
|
||||
}
|
||||
|
||||
if (!g_weak)
|
||||
{
|
||||
winrt::Microsoft::Terminal::Control::ContentProcess strong{};
|
||||
winrt::weak_ref<winrt::Microsoft::Terminal::Control::ContentProcess> weak{ strong };
|
||||
g_weak = weak;
|
||||
return strong.as(iid, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto strong = g_weak.get();
|
||||
// !! LOAD BEARING !! If you set this event in the _first_ branch
|
||||
// here, when we first create the object, then there will be _no_
|
||||
// referernces to the ContentProcess object for a small slice. We'll
|
||||
// stash the ContentProcess in the weak_ptr, and return it, and at
|
||||
// that moment, there will be 0 outstanding references, it'll dtor,
|
||||
// and wei'll ExitProcess.
|
||||
//
|
||||
// Instead, set the event here, once there's already a reference
|
||||
// outside of just the weak one we keep. Experimentation showed this
|
||||
// waw always hit when creating the ContentProcess at least once.
|
||||
g_canExitThread.SetEvent();
|
||||
return strong.as(iid, result);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT __stdcall LockServer(BOOL) noexcept final
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
winrt::guid _guid;
|
||||
};
|
||||
|
||||
static void doContentProcessThing(const winrt::guid& contentProcessGuid, const HANDLE& eventHandle)
|
||||
{
|
||||
// !! LOAD BEARING !! - important to be a MTA for these COM calls.
|
||||
winrt::init_apartment();
|
||||
DWORD registrationHostClass{};
|
||||
check_hresult(CoRegisterClassObject(contentProcessGuid,
|
||||
make<HostClassFactory>(contentProcessGuid).get(),
|
||||
make<ContentProcessFactory>(contentProcessGuid).get(),
|
||||
CLSCTX_LOCAL_SERVER,
|
||||
REGCLS_MULTIPLEUSE,
|
||||
®istrationHostClass));
|
||||
|
|
Loading…
Reference in a new issue