Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BatchingUIManager for UWP #2481

Merged
merged 42 commits into from
May 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
5cacd5c
Merge pull request #1 from Microsoft/master
randy-flynn Mar 25, 2019
0ee032e
Merge pull request #8 from Microsoft/rnwcpp-preview
randy-flynn Apr 4, 2019
854f3c7
Reduce and rationalize some header file includes related to ShadowNod…
randy-flynn Apr 4, 2019
40927ed
Merge pull request #9 from Microsoft/rnwcpp-preview
randy-flynn Apr 5, 2019
ca6d7d6
Merge pull request #10 from Microsoft/rnwcpp-preview
randy-flynn Apr 8, 2019
4ad2e3e
Checkpoint.
randy-flynn Apr 16, 2019
6249abf
Merge pull request #11 from Microsoft/rnwcpp-preview
randy-flynn Apr 16, 2019
95e5f1d
Remove debugging code. Update view sample to drive three scenarios.
randy-flynn Apr 20, 2019
5ed22e4
Merge pull request #12 from Microsoft/rnwcpp-preview
randy-flynn Apr 20, 2019
3e63116
Merge branch 'rnwcpp-preview' of https://github.com/randy-flynn/react…
randy-flynn Apr 20, 2019
b31735a
Merge pull request #13 from Microsoft/rnwcpp-preview
randy-flynn Apr 22, 2019
762d72a
Merge branch 'rnwcpp-preview' of https://github.com/randy-flynn/react…
randy-flynn Apr 22, 2019
dd60cb3
merge upstream
randy-flynn Apr 24, 2019
04f686e
Merge branch 'rnwcpp-preview' of https://github.com/randy-flynn/react…
randy-flynn Apr 24, 2019
95da46f
Merge pull request #17 from randy-flynn/ViewElements
randy-flynn Apr 24, 2019
1610567
Remove TODO NOW comment.
randy-flynn Apr 24, 2019
4be0ecf
Merge pull request #18 from randy-flynn/ViewElements
randy-flynn Apr 24, 2019
ab002f9
Merge branch 'master' into rnwcpp-preview
randy-flynn Apr 24, 2019
1e7fcf8
Merge branch 'master' into rnwcpp-preview
randy-flynn Apr 24, 2019
7c5cb09
Merge branch 'master' into rnwcpp-preview
randy-flynn Apr 24, 2019
8a3442a
Merge pull request #19 from Microsoft/master
randy-flynn Apr 24, 2019
8fcd5be
Merge branch 'master' into rnwcpp-preview
randy-flynn Apr 25, 2019
fa5dca7
Merge branch 'master' into rnwcpp-preview
randy-flynn Apr 25, 2019
9d530fb
Merge pull request #20 from Microsoft/master
randy-flynn Apr 25, 2019
bb53182
Merge pull request #21 from randy-flynn/rnwcpp-preview
randy-flynn Apr 25, 2019
0565e45
Merge pull request #22 from Microsoft/master
randy-flynn Apr 25, 2019
e1780cf
Merge pull request #23 from Microsoft/master
randy-flynn Apr 26, 2019
7f11966
Merge pull request #24 from microsoft/master
randy-flynn May 13, 2019
37751ce
Merge pull request #25 from microsoft/master
randy-flynn May 13, 2019
4b718b3
Working version of BatchingUIManager. Right now it takes over for the…
randy-flynn May 13, 2019
2edd70c
Separate Batching components into own file. Temporarily include diagn…
randy-flynn May 15, 2019
d9d4f15
Put tracking behind ifdefs. Fix whitespace so no change in UIManagerM…
randy-flynn May 15, 2019
6688dee
Merge pull request #27 from microsoft/master
randy-flynn May 15, 2019
72633e5
Merge branch 'master' into BatchUI
randy-flynn May 15, 2019
945c3ad
Merge pull request #28 from randy-flynn/BatchUI
randy-flynn May 15, 2019
119b1aa
Merge pull request #29 from microsoft/master
randy-flynn May 16, 2019
2d47a7a
Use smaller queue size and empty it when full.
randy-flynn May 24, 2019
e5d4b9b
Merge pull request #30 from microsoft/master
randy-flynn May 24, 2019
7253c04
Merge branch 'master' into BatchUI
randy-flynn May 24, 2019
5f8315f
Merge pull request #31 from randy-flynn/BatchUI
randy-flynn May 24, 2019
ef07f63
Port JSI changes from UIManager to BatchingUIManager.
randy-flynn May 24, 2019
9a27142
Merge pull request #32 from randy-flynn/BatchUI
randy-flynn May 24, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions vnext/ReactUWP/Base/UwpReactInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
#include <Modules/LocationObserverModule.h>
#include <Modules/NativeUIManager.h>
#include <Modules/NetworkingModule.h>
#include <Modules/UIManagerModule.h>
#include <Modules/BatchingUIManagerModule.h>
#include <Modules/WebSocketModuleUwp.h>
#include <ReactWindowsCore/IUIManager.h>
#include <Threading/UIMessageQueueThread.h>
Expand Down Expand Up @@ -108,7 +108,7 @@ REACTWINDOWS_API_(std::shared_ptr<facebook::react::IUIManager>) CreateUIManager(
viewManagers.push_back(std::make_unique<polyester::IconViewManager>(instance));

// Create UIManager, passing in ViewManagers
return createIUIManager(std::move(viewManagers), new NativeUIManager());
return createBatchingUIManager(std::move(viewManagers), new NativeUIManager());
}

UwpReactInstance::UwpReactInstance(
Expand All @@ -133,7 +133,7 @@ std::vector<facebook::react::NativeModuleDescription> GetModules(

modules.emplace_back(
"UIManager",
[uiManager = std::move(uiManager)]() { return facebook::react::createUIManagerModule(uiManager); },
[uiManager = std::move(uiManager)]() { return facebook::react::createBatchingUIManagerModule(uiManager); },
messageQueue);
randy-flynn marked this conversation as resolved.
Show resolved Hide resolved

modules.emplace_back(
Expand Down
9 changes: 9 additions & 0 deletions vnext/ReactUWP/Threading/UIMessageQueueThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ void UIMessageQueueThread::runOnQueue(std::function<void()>&& func)
m_uiDispatcher.RunAsync(
winrt::Windows::UI::Core::CoreDispatcherPriority::Normal,
[func = std::move(func)]() {

//#define TRACK_UI_CALLS
#ifdef TRACK_UI_CALLS
char buffer[1024];
static uint32_t cCalls = 0;
_snprintf_s(buffer, _countof(buffer), _TRUNCATE, "UIMessageQueueThread Calls: %u\r\n", ++cCalls);
OutputDebugStringA(buffer);
#endif

func();
});
}
Expand Down
3 changes: 3 additions & 0 deletions vnext/ReactWindowsCore/IUIManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,7 @@ class IUIManager
std::shared_ptr<IUIManager> createIUIManager(std::vector<std::unique_ptr<IViewManager>>&& viewManagers, INativeUIManager* nativeManager);
std::unique_ptr<facebook::xplat::module::CxxModule> createUIManagerModule(std::shared_ptr<IUIManager> uimanager);

std::shared_ptr<IUIManager> createBatchingUIManager(std::vector<std::unique_ptr<IViewManager>>&& viewManagers, INativeUIManager* nativeManager);
std::unique_ptr<facebook::xplat::module::CxxModule> createBatchingUIManagerModule(std::shared_ptr<IUIManager> uimanager);

}}
277 changes: 277 additions & 0 deletions vnext/ReactWindowsCore/Modules/BatchingUIManagerModule.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include "BatchingUIManagerModule.h"

#include <algorithm>
#include <cxxreact/JsArgumentHelpers.h>
#include <folly/json.h>

using namespace folly;
using namespace facebook::xplat;
using namespace std;

namespace facebook {
namespace react {

BatchingUIManager::BatchingUIManager(std::vector<std::unique_ptr<IViewManager>>&& viewManagers, INativeUIManager* nativeManager)
: UIManager(std::move(viewManagers), nativeManager)
{
m_queue = std::make_unique<folly::ProducerConsumerQueue<std::function<void()>>>(2048);
}

#define TRACK_QUEUE
#ifdef TRACK_QUEUE
static uint32_t cBatches = 0;
static uint32_t cCalls = 0;
#endif

void BatchingUIManager::processQueue()
{
#ifdef TRACK_QUEUE
uint32_t cTheseCalls = 0;
#endif

std::function<void()> func;
while (m_queue->read(func)) {
func();

#ifdef TRACK_QUEUE
++cTheseCalls;
#endif
}

#ifdef TRACK_QUEUE
cCalls += cTheseCalls;
char buffer[1024];
_snprintf_s(buffer, _countof(buffer), _TRUNCATE, "BatchingUIManager Batches: %u Calls: %u (%u new)\r\n", ++cBatches, cCalls, cTheseCalls);
OutputDebugStringA(buffer);
#endif
}

void BatchingUIManager::dispatchFunction(std::function<void()> func)
{
// If the queue is full then dispatch all items in the queue first
if (this->m_queue->isFull())
{
#ifdef TRACK_QUEUE
OutputDebugStringA("BatchingUIManager: Processing Full Queue ...");
#endif

processQueue();
}

m_queue->write(func);
}

void BatchingUIManager::onBatchComplete()
{
processQueue();
UIManager::onBatchComplete();
}

void BatchingUIManager::removeRootView(folly::dynamic&& args)
{
auto manager = std::static_pointer_cast<UIManager>(shared_from_this());
dispatchFunction([manager, args]()
{
manager->removeRootView(jsArgAsInt(args, 0));
});
}

void BatchingUIManager::configureNextLayoutAnimation(folly::dynamic&& args, facebook::xplat::module::CxxModule::Callback success, facebook::xplat::module::CxxModule::Callback error)
{
auto manager = shared_from_this();
dispatchFunction([manager, args, success, error]()
{
auto config = jsArgAsDynamic(args, 3);
manager->configureNextLayoutAnimation(std::move(config), success, error);
});
}

void BatchingUIManager::createView(folly::dynamic&& args)
{
auto manager = shared_from_this();
dispatchFunction([manager, args]()
{
auto arg3 = jsArgAsDynamic(args, 3);
static_cast<IUIManager*>(manager.get())->createView(jsArgAsInt(args, 0), jsArgAsString(args, 1), jsArgAsInt(args, 2), std::move(arg3));
});
}

void BatchingUIManager::setChildren(folly::dynamic&& args)
{
auto manager = shared_from_this();
dispatchFunction([manager, args]()
{
auto arg1 = jsArgAsArray(args, 1);
static_cast<IUIManager*>(manager.get())->setChildren(jsArgAsInt(args, 0), std::move(arg1));
});
}

void BatchingUIManager::updateView(folly::dynamic&& args)
{
auto manager = shared_from_this();
dispatchFunction([manager, args]()
{
auto arg2 = jsArgAsDynamic(args, 2);
static_cast<IUIManager*>(manager.get())->updateView(jsArgAsInt(args, 0), jsArgAsString(args, 1), std::move(arg2));
});
}

void BatchingUIManager::removeSubviewsFromContainerWithID(folly::dynamic&& args)
{
auto manager = shared_from_this();
dispatchFunction([manager, args]()
{
static_cast<IUIManager*>(manager.get())->removeSubviewsFromContainerWithID(jsArgAsInt(args, 0));
});
}

void BatchingUIManager::manageChildren(folly::dynamic&& args)
{
auto manager = shared_from_this();
dispatchFunction([manager, args]()
{
auto arg1 = jsArgAsDynamic(args, 1);
auto arg2 = jsArgAsDynamic(args, 2);
auto arg3 = jsArgAsDynamic(args, 3);
auto arg4 = jsArgAsDynamic(args, 4);
auto arg5 = jsArgAsDynamic(args, 5);
static_cast<IUIManager*>(manager.get())->manageChildren(jsArgAsInt(args, 0), arg1, arg2, arg3, arg4, arg5);
});
}

void BatchingUIManager::dispatchViewManagerCommand(folly::dynamic&& args)
{
auto manager = shared_from_this();
dispatchFunction([manager, args]()
{
auto arg2 = jsArgAsDynamic(args, 2);
static_cast<IUIManager*>(manager.get())->dispatchViewManagerCommand(jsArgAsInt(args, 0), jsArgAsInt(args, 1), std::move(arg2));
});
}

void BatchingUIManager::replaceExistingNonRootView(folly::dynamic&& args)
{
auto manager = shared_from_this();
dispatchFunction([manager, args]()
{
static_cast<IUIManager*>(manager.get())->replaceExistingNonRootView(jsArgAsInt(args, 0), jsArgAsInt(args, 1));
});
}

void BatchingUIManager::measure(folly::dynamic&& args, facebook::xplat::module::CxxModule::Callback cb)
{
auto manager = shared_from_this();
dispatchFunction([manager, args, cb]()
{
static_cast<IUIManager*>(manager.get())->measure(jsArgAsInt(args, 0), cb);
});
}


BatchingUIManagerModule::BatchingUIManagerModule(std::shared_ptr<IUIManager>&& manager)
: m_manager(std::move(manager))
{
}

std::string BatchingUIManagerModule::getName()
{
return "UIManager";
}

std::map<std::string, folly::dynamic> BatchingUIManagerModule::getConstants()
{
std::map<std::string, folly::dynamic> constants {};

m_manager->populateViewManagerConstants(constants);

return constants;
}

std::vector<facebook::xplat::module::CxxModule::Method> BatchingUIManagerModule::getMethods()
{
auto manager = std::static_pointer_cast<BatchingUIManager>(m_manager);
return
{
Method("getConstantsForViewManager", [manager](dynamic argsJson) -> dynamic
{
dynamic args;
if (argsJson.isString())
{
args = folly::parseJson(argsJson.asString());
}
else
{
// In JSI mode this is an array
assert(argsJson.isArray());
args = argsJson;
}
return manager->getConstantsForViewManager(jsArgAsString(args, 0));
}, SyncTag),
Method("removeRootView", [manager](dynamic args)
{
manager->removeRootView(std::move(args));
}),
Method("createView", [manager](dynamic args)
{
manager->createView(std::move(args));
}),
Method("configureNextLayoutAnimation", [manager](dynamic args, Callback cbSuccess, Callback cbError)
{
manager->configureNextLayoutAnimation(std::move(args), cbSuccess, cbError);
}, AsyncTag),
Method("setChildren", [manager](dynamic args)
{
manager->setChildren(std::move(args));
}),
Method("updateView", [manager](dynamic args)
{
manager->updateView(std::move(args));
}),
Method("removeSubviewsFromContainerWithID", [manager](dynamic args)
{
manager->removeSubviewsFromContainerWithID(std::move(args));
}),
Method("manageChildren", [manager](dynamic args)
{
manager->manageChildren(std::move(args));
}),
Method("replaceExistingNonRootView", [manager](dynamic args)
{
manager->replaceExistingNonRootView(std::move(args));
}),
Method("dispatchViewManagerCommand", [manager](dynamic args)
{
manager->dispatchViewManagerCommand(std::move(args));
}),
Method("measure", [manager](dynamic args, facebook::xplat::module::CxxModule::Callback cb)
{
manager->measure(std::move(args), cb);
}),
Method("setJSResponder", [](dynamic args)
{
// TODO: Implement?
//manager->setJSResponder(std::move(args));
}),
Method("clearJSResponder", []()
{
// TODO: Implement?
//manager->clearJSResponder();
}),
};
}

shared_ptr<IUIManager> createBatchingUIManager(std::vector<std::unique_ptr<IViewManager>>&& viewManagers, INativeUIManager* nativeManager)
{
return std::make_shared<BatchingUIManager>(std::move(viewManagers), nativeManager);
}

std::unique_ptr<facebook::xplat::module::CxxModule> createBatchingUIManagerModule(std::shared_ptr<IUIManager> uimanager)
{
return std::make_unique<BatchingUIManagerModule>(std::move(uimanager));
}

}
} // namespace facebook::react
65 changes: 65 additions & 0 deletions vnext/ReactWindowsCore/Modules/BatchingUIManagerModule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#pragma once

#include "UIManagerModule.h"

#include <folly/ProducerConsumerQueue.h>

#include <ViewManager.h>
#include <IUIManager.h>
#include <INativeUIManager.h>

#include <memory>
#include <vector>

namespace facebook { namespace react {

struct IReactRootView;
struct ShadowNode;

class BatchingUIManager
: public UIManager
, public ::std::enable_shared_from_this<BatchingUIManager>
{
public:
BatchingUIManager(std::vector<std::unique_ptr<IViewManager>>&& viewManagers, INativeUIManager* nativeManager);
virtual ~BatchingUIManager() noexcept {}

void removeRootView(folly::dynamic&& args);
void createView(folly::dynamic&& args);
void setChildren(folly::dynamic&& args);
void updateView(folly::dynamic&& args);
void removeSubviewsFromContainerWithID(folly::dynamic&& args);
void manageChildren(folly::dynamic&& args);
void dispatchViewManagerCommand(folly::dynamic&& args);
void replaceExistingNonRootView(folly::dynamic&& args);
void measure(folly::dynamic&& args, facebook::xplat::module::CxxModule::Callback cb);
void configureNextLayoutAnimation(folly::dynamic&& args, facebook::xplat::module::CxxModule::Callback success, facebook::xplat::module::CxxModule::Callback error);

void onBatchComplete() override;

private:
void dispatchFunction(std::function<void()> func);
void processQueue();

private:
std::shared_ptr<folly::ProducerConsumerQueue<std::function<void()>>> m_queue;
};

class BatchingUIManagerModule : public facebook::xplat::module::CxxModule
{
public:
BatchingUIManagerModule(std::shared_ptr<IUIManager>&& manager);

// CxxModule
std::string getName() override;
std::map<std::string, folly::dynamic> getConstants() override;
std::vector<Method> getMethods() override;

private:
std::shared_ptr<IUIManager> m_manager;
};

} }
Loading