Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1082)

Unified Diff: mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc

Issue 258623005: First step at synchronizing client model changes with service. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc
diff --git a/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc b/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c441841116853f2e2d32af3cdf728634366d108f
--- /dev/null
+++ b/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc
@@ -0,0 +1,284 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.h"
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "mojo/public/cpp/bindings/allocation_scope.h"
+#include "mojo/public/cpp/shell/application.h"
+#include "mojo/public/interfaces/shell/shell.mojom.h"
+#include "mojo/services/public/cpp/view_manager/lib/view_manager_private.h"
+
+namespace mojo {
+namespace services {
+namespace view_manager {
+
+class ViewManagerTransaction {
+ public:
+ virtual ~ViewManagerTransaction() {}
+
+ virtual bool Equals(ViewManagerTransaction* other) {
sky 2014/04/28 23:04:19 const ViewManagerTransaction* or const ViewManager
+ return other->type_ == type_;
+ }
+
+ virtual void Commit() = 0;
+
+ bool committed() const { return committed_; }
+ int change_id() const { return change_id_; }
sky 2014/04/28 23:04:19 uint32_t
+
+ protected:
+ enum TransactionType {
+ TYPE_CREATE_VIEW_TREE_NODE,
+ TYPE_HIERARCHY
sky 2014/04/28 23:04:19 Add description for TYPE_HIERARCH as it isn't obvi
+ };
+
+ ViewManagerTransaction(TransactionType type,
+ ViewManagerSynchronizer* synchronizer)
+ : type_(type),
+ change_id_(synchronizer->GetNextChangeId()),
+ committed_(false),
+ synchronizer_(synchronizer) {
+ }
+
+ IViewManager* service() { return synchronizer_->service_.get(); }
+
+ uint32_t MakeTransportId(uint16_t id) {
+ return (synchronizer_->connection_id_ << 16) | id;
+ }
+
+ int type_;
sky 2014/04/28 23:04:19 TransactionType?
sky 2014/04/28 23:04:19 Style guide says no protected members.
+ int change_id_;
sky 2014/04/28 23:04:19 Can this be const? And uint32_t.
+ bool committed_;
+ ViewManagerSynchronizer* synchronizer_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ViewManagerTransaction);
+};
+
+class CreateViewTreeNodeTransaction
+ : public ViewManagerTransaction {
+ public:
+ CreateViewTreeNodeTransaction(int node_id,
+ ViewManagerSynchronizer* synchronizer)
+ : ViewManagerTransaction(TYPE_CREATE_VIEW_TREE_NODE, synchronizer),
+ node_id_(node_id) {}
+ virtual ~CreateViewTreeNodeTransaction() {}
+
+ private:
+ // Overridden from ViewManagerTransaction:
+ virtual bool Equals(ViewManagerTransaction* other) OVERRIDE {
+ return ViewManagerTransaction::Equals(other) &&
+ static_cast<CreateViewTreeNodeTransaction*>(other)->node_id_ ==
+ node_id_;
+ }
+ virtual void Commit() OVERRIDE {
+ DCHECK(!committed());
sky 2014/04/28 23:04:19 Maybe the DCHECK and boolean should be part of the
+ committed_ = true;
+ service()->CreateNode(
+ node_id_,
+ base::Bind(&CreateViewTreeNodeTransaction::OnActionCompleted,
+ base::Unretained(this)));
+ }
+
+ void OnActionCompleted(bool success) {
+ DCHECK(success);
+ // TODO(beng): Failure means we tried to create with an extant id for this
+ // connection. Figure out what to do.
+ }
+
+ int node_id_;
sky 2014/04/28 23:04:19 uint16_t I believe.
+
+ DISALLOW_COPY_AND_ASSIGN(CreateViewTreeNodeTransaction);
+};
+
+class HierarchyTransaction : public ViewManagerTransaction {
+ public:
+ enum HierarchyChangeType {
+ TYPE_ADD,
+ TYPE_REMOVE
+ };
+ HierarchyTransaction(HierarchyChangeType hierarchy_change_type,
+ int child_id,
+ int parent_id,
+ ViewManagerSynchronizer* synchronizer)
+ : ViewManagerTransaction(TYPE_HIERARCHY, synchronizer),
+ hierarchy_change_type_(hierarchy_change_type),
+ child_id_(child_id),
+ parent_id_(parent_id) {}
+ virtual ~HierarchyTransaction() {}
+
+ private:
+ // Overridden from ViewManagerTransaction:
+ virtual bool Equals(ViewManagerTransaction* other) OVERRIDE {
+ if (!ViewManagerTransaction::Equals(other))
+ return false;
+
+ HierarchyTransaction* hier_txn = static_cast<HierarchyTransaction*>(other);
+ return hier_txn->hierarchy_change_type_ == hierarchy_change_type_ &&
+ hier_txn->child_id_ == child_id_ &&
+ hier_txn->parent_id_ == parent_id_;
+ }
+ virtual void Commit() OVERRIDE {
+ DCHECK(!committed());
+ committed_ = true;
+ switch (hierarchy_change_type_) {
+ case TYPE_ADD:
sky 2014/04/28 23:04:19 nit: indentation is off for the switch statement.
+ service()->AddNode(MakeTransportId(parent_id_),
+ MakeTransportId(child_id_),
+ change_id_,
+ base::Bind(&HierarchyTransaction::OnActionCompleted,
+ base::Unretained(this)));
+ break;
+ case TYPE_REMOVE:
+ service()->RemoveNodeFromParent(
+ MakeTransportId(child_id_),
+ change_id_,
+ base::Bind(&HierarchyTransaction::OnActionCompleted,
+ base::Unretained(this)));
+ break;
+ default:
sky 2014/04/28 23:04:19 You should be able to remove this so that you get
+ NOTREACHED();
+ }
+ }
+
+ void OnActionCompleted(bool success) {
+ DCHECK(success);
+ // TODO(beng): Failure means either one of the nodes specified didn't exist,
+ // or we passed the same node id for both params. Roll back?
+ }
+
+ HierarchyChangeType hierarchy_change_type_;
sky 2014/04/28 23:04:19 const
+ int child_id_;
sky 2014/04/28 23:04:19 uint16_t for both of these.
+ int parent_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(HierarchyTransaction);
+};
+
+ViewManagerSynchronizer::ViewManagerSynchronizer(ViewManager* view_manager)
+ : view_manager_(view_manager),
+ connected_(false),
+ connection_id_(0),
+ next_change_id_(0),
sky 2014/04/28 23:04:19 order doesn't match header.
+ next_id_(0) {
+ InterfacePipe<services::view_manager::IViewManager, AnyInterface>
+ view_manager_pipe;
+ AllocationScope scope;
+ ViewManagerPrivate(view_manager_).application()->shell()->Connect(
+ "mojo:mojo_view_manager", view_manager_pipe.handle_to_peer.Pass());
+ service_.reset(view_manager_pipe.handle_to_self.Pass(), this);
+}
+
+ViewManagerSynchronizer::~ViewManagerSynchronizer() {
+}
+
+int ViewManagerSynchronizer::CreateViewTreeNode() {
+ int id = next_id_++;
+ pending_transactions_.push_back(new CreateViewTreeNodeTransaction(id, this));
+ ScheduleSync();
+ return id;
+}
+
+void ViewManagerSynchronizer::AddChild(int child_id, int parent_id) {
+ pending_transactions_.push_back(
+ new HierarchyTransaction(HierarchyTransaction::TYPE_ADD,
+ child_id,
+ parent_id,
+ this));
+ ScheduleSync();
+}
+
+void ViewManagerSynchronizer::RemoveChild(int child_id, int parent_id) {
+ pending_transactions_.push_back(
+ new HierarchyTransaction(HierarchyTransaction::TYPE_REMOVE,
+ child_id,
+ parent_id,
+ this));
+ ScheduleSync();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ViewManagerSynchronizer, IViewManagerClient implementation:
+
+void ViewManagerSynchronizer::OnConnectionEstablished(uint16 connection_id) {
+ connected_ = true;
+ connection_id_ = connection_id;
+ ScheduleSync();
+}
+
+void ViewManagerSynchronizer::OnNodeHierarchyChanged(uint32 node,
+ uint32 new_parent,
+ uint32 old_parent,
+ int32 change_id) {
+ // The service will still notify us about changes made from this connection,
+ // but we use our transaction queue as a record of what those changes were.
+ // We use this ack as an opportunity to remove these entries from our queue.
+ // Non-zero change_id is the service's way of telling us the change originated
+ // from this connection.
+ if (RemovedFromPendingQueue(change_id))
sky 2014/04/28 23:04:19 One problematic area is if a transaction generates
Ben Goodger (Google) 2014/04/29 00:00:54 Hrm and probably for nested hiers.
+ return;
+
+ if (change_id == 0) {
+ // TODO(beng): Apply changes from another client.
+ }
+
+ // TODO(beng): possible that changes from this client are never ack'ed? e.g.
+ // node creates are treated as txns & there is no ack.
+}
+
+void ViewManagerSynchronizer::OnNodeViewReplaced(uint32_t node,
+ uint32_t new_view_id,
+ uint32_t old_view_id,
+ int32_t change_id) {
+ // ..
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ViewManagerSynchronizer, private:
+
+void ViewManagerSynchronizer::ScheduleSync() {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&ViewManagerSynchronizer::DoSync, base::Unretained(this)));
+}
+
+void ViewManagerSynchronizer::DoSync() {
+ // The service connection may not be set up yet. OnConnectionEstablished()
+ // will schedule another sync when it is.
+ if (!connected_)
+ return;
+
+ Transactions::const_iterator it = pending_transactions_.begin();
+ for (; it != pending_transactions_.end(); ++it) {
+ if (!(*it)->committed())
+ (*it)->Commit();
+ }
+}
+
+int ViewManagerSynchronizer::GetNextChangeId() {
+ // TODO(beng): update once change id becomes uint.
+ // TODO(beng): deal with change id collisions? Important in the "never ack'ed
+ // change" case mentioned in OnNodeHierarchyChanged().
+ // "0" is a special value passed to other connected clients, so we can't use
+ // it.
+ next_change_id_ = std::max(1, ++next_change_id_);
+ return next_change_id_;
+}
+
+bool ViewManagerSynchronizer::RemovedFromPendingQueue(int change_id) {
+ if (change_id != 0) {
+ Transactions::iterator it = pending_transactions_.begin();
sky 2014/04/28 23:04:19 I think you should only have to check the first tr
Ben Goodger (Google) 2014/04/29 00:00:54 Not quite. I currently have transactions for node
+ for (; it != pending_transactions_.end(); ++it) {
+ if ((*it)->change_id() == change_id) {
+ pending_transactions_.erase(it);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+} // namespace view_manager
+} // namespace services
+} // namespace mojo

Powered by Google App Engine
This is Rietveld 408576698