diff --git a/src/tools/MonarchPeasantSample/AppState.cpp b/src/tools/MonarchPeasantSample/AppState.cpp index dc9dcffd8dd..b70c1a37935 100644 --- a/src/tools/MonarchPeasantSample/AppState.cpp +++ b/src/tools/MonarchPeasantSample/AppState.cpp @@ -30,7 +30,7 @@ void AppState::initializeState() bool AppState::areWeTheKing(const bool logPIDs) { - auto kingPID = _monarch.GetPID(); + auto kingPID = monarch.GetPID(); auto ourPID = GetCurrentProcessId(); if (logPIDs) { @@ -46,15 +46,15 @@ bool AppState::areWeTheKing(const bool logPIDs) return (ourPID == kingPID); } -void AppState::remindKingWhoTheyAre(const winrt::MonarchPeasantSample::IPeasant& peasant) +void AppState::remindKingWhoTheyAre(const winrt::MonarchPeasantSample::IPeasant& iPeasant) { winrt::com_ptr monarchImpl; - monarchImpl.copy_from(winrt::get_self(_monarch)); + monarchImpl.copy_from(winrt::get_self(monarch)); if (monarchImpl) { - auto ourID = peasant.GetID(); + auto ourID = iPeasant.GetID(); monarchImpl->SetSelfID(ourID); - monarchImpl->AddPeasant(peasant); + monarchImpl->AddPeasant(iPeasant); printf("The king is peasant #%lld\n", ourID); } else @@ -72,7 +72,7 @@ winrt::MonarchPeasantSample::Monarch AppState::instantiateAMonarch() MonarchPeasantSample::IPeasant AppState::_createOurPeasant() { auto peasant = winrt::make_self(); - auto ourID = _monarch.AddPeasant(*peasant); + auto ourID = monarch.AddPeasant(*peasant); printf("The monarch assigned us the ID %llu\n", ourID); if (areWeTheKing()) @@ -85,7 +85,7 @@ MonarchPeasantSample::IPeasant AppState::_createOurPeasant() void AppState::createMonarch() { - _monarch = AppState::instantiateAMonarch(); + monarch = AppState::instantiateAMonarch(); } // return true to exit early, false if we should continue into the main loop @@ -96,12 +96,12 @@ bool AppState::processCommandline() // launched with them! // // Otherwise, the King will tell us if we should make a new window - const bool createNewWindow = isKing || _monarch.ProposeCommandline({ args }, { L"placeholder CWD" }); + const bool createNewWindow = isKing || monarch.ProposeCommandline({ args }, { L"placeholder CWD" }); if (createNewWindow) { - _peasant = _createOurPeasant(); - _peasant.ExecuteCommandline({ args }, { L"placeholder CWD" }); + peasant = _createOurPeasant(); + peasant.ExecuteCommandline({ args }, { L"placeholder CWD" }); return false; } else diff --git a/src/tools/MonarchPeasantSample/AppState.h b/src/tools/MonarchPeasantSample/AppState.h index a6648aa29af..872293d8962 100644 --- a/src/tools/MonarchPeasantSample/AppState.h +++ b/src/tools/MonarchPeasantSample/AppState.h @@ -10,18 +10,16 @@ class AppState bool areWeTheKing(const bool logPIDs = false); void initializeState(); - HANDLE hInput = nullptr; - HANDLE hOutput = nullptr; - - winrt::MonarchPeasantSample::IPeasant _peasant{ nullptr }; - winrt::MonarchPeasantSample::Monarch _monarch{ nullptr }; - static winrt::MonarchPeasantSample::Monarch instantiateAMonarch(); void createMonarch(); bool processCommandline(); void remindKingWhoTheyAre(const winrt::MonarchPeasantSample::IPeasant& peasant); + HANDLE hInput{ INVALID_HANDLE_VALUE }; + HANDLE hOutput{ INVALID_HANDLE_VALUE }; + winrt::MonarchPeasantSample::IPeasant peasant{ nullptr }; + winrt::MonarchPeasantSample::Monarch monarch{ nullptr }; std::vector args; private: @@ -31,36 +29,5 @@ class AppState winrt::MonarchPeasantSample::IPeasant _createOurPeasant(); }; -bool monarchAppLoop(AppState& state); -bool peasantAppLoop(AppState& state); - -/* - -Useful test script: - -pushd %OPENCON%\bin\x64\Debug\MonarchPeasantSample -wt -d . cmd /k MonarchPeasantSample.exe ; sp -d . cmd /k MonarchPeasantSample.exe ; sp -d . cmd /k MonarchPeasantSample.exe ; sp -d . -popd - - -BIG OLE TODO LIST: - -* [x] The peasants need to be able to process commandlines passed to them by - other peasants -* [x] press a key in a peasant window to "activate" it -* [x] Add a key to toggle the monarch through ["never", "lastActive", "always"] - glomming behaviors -* [ ] Actually store a stack for the MRU peasant, not just the single MRU one -* [ ] The Monarch needs to wait on peasants, to remove them from the map when - they're dead -* [ ] Actually implement the "list peasants" thing -* [ ] After an election, the entire MRU window state is lost, because it was - only stored in the current monarch. -* [ ] Test: - - Create a monarch(#1) & peasant(#2) - - activate the peasant(#2) - - exit the peasant(#2) - - try running MonarchPeasantSample.exe -s 0 (or -s 2) - - THIS WILL FAIL, but it _should_ just run the commandline in the monarch - (in the case of `-s 0`) or in a new window (in the `-s 1` case) -*/ +bool monarchAppLoop(AppState& state); // Defined in MonarchMain.cpp +bool peasantAppLoop(AppState& state); // Defined in PeasantMain.cpp diff --git a/src/tools/MonarchPeasantSample/MonarchMain.cpp b/src/tools/MonarchPeasantSample/MonarchMain.cpp index af4d5ecab6e..ee16d14a632 100644 --- a/src/tools/MonarchPeasantSample/MonarchMain.cpp +++ b/src/tools/MonarchPeasantSample/MonarchMain.cpp @@ -16,14 +16,14 @@ bool monarchAppLoop(AppState& state) printf("Press `l` to list peasants, 'm' to change modes `q` to quit\n"); winrt::com_ptr monarchImpl; - monarchImpl.copy_from(winrt::get_self(state._monarch)); + monarchImpl.copy_from(winrt::get_self(state.monarch)); while (!exitRequested) { const auto ch = _getch(); if (ch == 'l') { - printPeasants(state._monarch); + printPeasants(state.monarch); } else if (ch == 'q') { diff --git a/src/tools/MonarchPeasantSample/PeasantMain.cpp b/src/tools/MonarchPeasantSample/PeasantMain.cpp index 9e8559a9e3c..0d1eafa73ce 100644 --- a/src/tools/MonarchPeasantSample/PeasantMain.cpp +++ b/src/tools/MonarchPeasantSample/PeasantMain.cpp @@ -34,7 +34,7 @@ bool peasantReadInput(AppState& state) { printf("This window was activated\n"); winrt::com_ptr peasantImpl; - peasantImpl.copy_from(winrt::get_self(state._peasant)); + peasantImpl.copy_from(winrt::get_self(state.peasant)); if (peasantImpl) { peasantImpl->raiseActivatedEvent(); @@ -61,7 +61,7 @@ bool peasantReadInput(AppState& state) bool peasantAppLoop(AppState& state) { - wil::unique_handle hMonarch{ OpenProcess(PROCESS_ALL_ACCESS, FALSE, static_cast(state._monarch.GetPID())) }; + wil::unique_handle hMonarch{ OpenProcess(PROCESS_ALL_ACCESS, FALSE, static_cast(state.monarch.GetPID())) }; // printf("handle for the monarch process is %d\n", hMonarch.get()); HANDLE handlesToWaitOn[2]{ hMonarch.get(), state.hInput }; diff --git a/src/tools/MonarchPeasantSample/README.md b/src/tools/MonarchPeasantSample/README.md index 0a348c9a3cf..4762ae7feb9 100644 --- a/src/tools/MonarchPeasantSample/README.md +++ b/src/tools/MonarchPeasantSample/README.md @@ -13,7 +13,6 @@ like: For an example of this sample running, see the below GIF: -[TODO]: # TODO ----------------------------------------------------------------- ![Gif of the MonarchPeasantSample](monarch-peasant-sample-000.gif) This sample operates largely by printing to the console, to help the reader @@ -47,11 +46,18 @@ The code is vaguely seperated into the following files, with the following purposes. As this code isn't production-ready code, the layering isn't particularily well organized nor enforced. -* `Monarch.idl/.h/.cpp`: -* `Peasant.idl/.h/.cpp`: -* `MonarchMain.cpp`: -* `PeasantMain.cpp`: -* `AppState.h/.cpp`: +* `Monarch.idl/.h/.cpp`: Code for the WinRT Monarch object, responsible for + coordinating the Peasants +* `Peasant.idl/.h/.cpp`: Code for the WinRT Peasant object, which represents any + individual application instance. +* `AppState.h/.cpp`: This file contains some common state that's used throughout + the application, in order to help encapsulate it all in one place. +* `MonarchMain.cpp`: This file contains the main loop for the monarch process. + It needs to be able to process console input, and additionally wait on the + peasants, to know when they've died. +* `PeasantMain.cpp`: This file contains the main loop for the peasant process. + It needs to be able to wait on both console input, and on the Monarch process, + to be able to determine who the next monarch should be. ## Remaining TODOs diff --git a/src/tools/MonarchPeasantSample/main.cpp b/src/tools/MonarchPeasantSample/main.cpp index 8eec60b5519..586d0db8611 100644 --- a/src/tools/MonarchPeasantSample/main.cpp +++ b/src/tools/MonarchPeasantSample/main.cpp @@ -17,6 +17,9 @@ using namespace ::Microsoft::Console; // Future callers who try to instantiate a Monarch will get the one that's // already been made. // +// I'm sure there's a better awy to do this with WRL, but I'm not familiar +// enough with WRL to know for sure. + winrt::weak_ref g_weak{ nullptr }; struct MonarchFactory : implements @@ -34,6 +37,7 @@ struct MonarchFactory : implements if (!g_weak) { + // Create a new Monarch instance auto strong = make_self(); g_weak = (*strong).get_weak(); @@ -41,6 +45,7 @@ struct MonarchFactory : implements } else { + // We already instantiated one Monarch, let's just return that one! auto strong = g_weak.get(); return strong.as(iid, result); } @@ -77,19 +82,19 @@ DWORD registerAsMonarch() // that we exist. void electNewMonarch(AppState& state) { - state._monarch = AppState::instantiateAMonarch(); + state.monarch = AppState::instantiateAMonarch(); bool isMonarch = state.areWeTheKing(true); printf("LONG LIVE THE %sKING\x1b[m\n", isMonarch ? "\x1b[33m" : ""); if (isMonarch) { - state.remindKingWhoTheyAre(state._peasant); + state.remindKingWhoTheyAre(state.peasant); } else { // Add us to the new monarch - state._monarch.AddPeasant(state._peasant); + state.monarch.AddPeasant(state.peasant); } } diff --git a/src/tools/MonarchPeasantSample/monarch-peasant-sample-000.gif b/src/tools/MonarchPeasantSample/monarch-peasant-sample-000.gif new file mode 100644 index 00000000000..77d4a9afa71 Binary files /dev/null and b/src/tools/MonarchPeasantSample/monarch-peasant-sample-000.gif differ