Skip to content

Commit

Permalink
a picture says 1000 words, a gif says 60000 words per second
Browse files Browse the repository at this point in the history
  • Loading branch information
zadjii-msft committed Nov 5, 2020
1 parent 1eb883c commit fb442f1
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 62 deletions.
20 changes: 10 additions & 10 deletions src/tools/MonarchPeasantSample/AppState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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<MonarchPeasantSample::implementation::Monarch> monarchImpl;
monarchImpl.copy_from(winrt::get_self<MonarchPeasantSample::implementation::Monarch>(_monarch));
monarchImpl.copy_from(winrt::get_self<MonarchPeasantSample::implementation::Monarch>(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
Expand All @@ -72,7 +72,7 @@ winrt::MonarchPeasantSample::Monarch AppState::instantiateAMonarch()
MonarchPeasantSample::IPeasant AppState::_createOurPeasant()
{
auto peasant = winrt::make_self<MonarchPeasantSample::implementation::Peasant>();
auto ourID = _monarch.AddPeasant(*peasant);
auto ourID = monarch.AddPeasant(*peasant);
printf("The monarch assigned us the ID %llu\n", ourID);

if (areWeTheKing())
Expand All @@ -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
Expand All @@ -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
Expand Down
45 changes: 6 additions & 39 deletions src/tools/MonarchPeasantSample/AppState.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<winrt::hstring> args;

private:
Expand All @@ -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
4 changes: 2 additions & 2 deletions src/tools/MonarchPeasantSample/MonarchMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<winrt::MonarchPeasantSample::implementation::Monarch> monarchImpl;
monarchImpl.copy_from(winrt::get_self<winrt::MonarchPeasantSample::implementation::Monarch>(state._monarch));
monarchImpl.copy_from(winrt::get_self<winrt::MonarchPeasantSample::implementation::Monarch>(state.monarch));

while (!exitRequested)
{
const auto ch = _getch();
if (ch == 'l')
{
printPeasants(state._monarch);
printPeasants(state.monarch);
}
else if (ch == 'q')
{
Expand Down
4 changes: 2 additions & 2 deletions src/tools/MonarchPeasantSample/PeasantMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ bool peasantReadInput(AppState& state)
{
printf("This window was activated\n");
winrt::com_ptr<winrt::MonarchPeasantSample::implementation::Peasant> peasantImpl;
peasantImpl.copy_from(winrt::get_self<winrt::MonarchPeasantSample::implementation::Peasant>(state._peasant));
peasantImpl.copy_from(winrt::get_self<winrt::MonarchPeasantSample::implementation::Peasant>(state.peasant));
if (peasantImpl)
{
peasantImpl->raiseActivatedEvent();
Expand All @@ -61,7 +61,7 @@ bool peasantReadInput(AppState& state)

bool peasantAppLoop(AppState& state)
{
wil::unique_handle hMonarch{ OpenProcess(PROCESS_ALL_ACCESS, FALSE, static_cast<DWORD>(state._monarch.GetPID())) };
wil::unique_handle hMonarch{ OpenProcess(PROCESS_ALL_ACCESS, FALSE, static_cast<DWORD>(state.monarch.GetPID())) };
// printf("handle for the monarch process is %d\n", hMonarch.get());

HANDLE handlesToWaitOn[2]{ hMonarch.get(), state.hInput };
Expand Down
18 changes: 12 additions & 6 deletions src/tools/MonarchPeasantSample/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
11 changes: 8 additions & 3 deletions src/tools/MonarchPeasantSample/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<MonarchPeasantSample::implementation::Monarch> g_weak{ nullptr };

struct MonarchFactory : implements<MonarchFactory, IClassFactory>
Expand All @@ -34,13 +37,15 @@ struct MonarchFactory : implements<MonarchFactory, IClassFactory>

if (!g_weak)
{
// Create a new Monarch instance
auto strong = make_self<MonarchPeasantSample::implementation::Monarch>();

g_weak = (*strong).get_weak();
return strong.as(iid, result);
}
else
{
// We already instantiated one Monarch, let's just return that one!
auto strong = g_weak.get();
return strong.as(iid, result);
}
Expand Down Expand Up @@ -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);
}
}

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

1 comment on commit fb442f1

@github-actions

This comment was marked as resolved.

Please sign in to comment.