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

Side by Side Diff: examples/indirect_service/indirect_service_demo.cc

Issue 733563002: Mojo Example that demos the difference between providing and requesting an interface (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Manage IntegerServicePtr and DemoTask lifetimes. Fixed RunLoop::RemoveFirstInvalidHandle() Created 6 years, 1 month 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <cstdlib>
6
7 #include "base/bind.h"
8 #include "base/memory/scoped_vector.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/threading/thread.h"
11 #include "base/time/time.h"
12 #include "examples/indirect_service/indirect_service_demo.mojom.h"
13 #include "mojo/application/application_runner_chromium.h"
14 #include "mojo/common/message_pump_mojo.h"
15 #include "mojo/public/c/system/main.h"
16 #include "mojo/public/cpp/application/application_delegate.h"
17 #include "mojo/public/cpp/application/application_impl.h"
18
19 namespace mojo {
20 namespace examples {
21
22 class DemoTask;
23
24 typedef typename base::Callback<void(DemoTask*, const std::vector<int32_t>&)>
25 DemoTaskFinishedCallback;
26
27 // A thread that connects to the IndirectIntegerService, gets a connection
28 // to its IntegerService, and then calls Increment() iteration_count times.
29 // The results are saved and returned with the finished_callback.
30 class DemoTask {
31 public:
32 DemoTask(ScopedMessagePipeHandle proxy_handle,
33 const DemoTaskFinishedCallback& finished_callback,
34 unsigned iteration_count)
35 : proxy_handle_(proxy_handle.Pass()),
36 thread_("DemoTask"),
37 finished_callback_(finished_callback),
38 iteration_count_(iteration_count) {
39
yzshen1 2014/11/20 22:01:44 unnecessary empty line.
40 base::Thread::Options options;
41 options.message_loop_type = base::MessageLoop::TYPE_CUSTOM;
42 options.message_pump_factory = base::Bind(&common::MessagePumpMojo::Create);
43 CHECK(thread_.StartWithOptions(options));
44
45 thread_.message_loop()->PostTask(
46 FROM_HERE, base::Bind(&DemoTask::Run, base::Unretained(this)));
47 }
48
49 void Run() {
50 integer_service_.Bind(proxy_handle_.Pass());
51 base::Callback<void(int32_t)> callback =
52 base::Bind(&DemoTask::SaveResultAndFinish, base::Unretained(this));
53 for(int unsigned i = 0; i < iteration_count_; i++) {
54 integer_service_->Increment(callback);
55 // To ensure that the DemoTask threads' execution overlaps, sleep.
56 if (i < iteration_count_ - 1)
57 base::PlatformThread::Sleep(
58 base::TimeDelta::FromMilliseconds(rand() % 10));
59 }
60 }
61
62 private:
63 void SaveResultAndFinish(int32_t result) {
64 results_.push_back(result);
65 if (results_.size() == iteration_count_) {
66 finished_callback_.Run(this, results_);
67 integer_service_.reset(); // Must be done on thread_.
yzshen1 2014/11/20 22:01:44 It seems better to do the reset before running the
hansmuller 2014/11/20 22:35:38 Good point.
68 }
69 }
70
71 ScopedMessagePipeHandle proxy_handle_;
72 base::Thread thread_;
73 IntegerServicePtr integer_service_;
74 DemoTaskFinishedCallback finished_callback_;
75 unsigned iteration_count_;
76 std::vector<int32_t> results_;
77 };
78
79 // Connect to the IntegerService and give its proxy to the
80 // IndirectIntegerService. Start kTaskCount DemoTask threads all of
81 // which will use the IndirectIntegerService to get their own connection
82 // to the (one) IntegerService. Each DemoTask will call the IntegerService's
83 // Increment() method kTaskIterationCount times, collect the results in
84 // a vector and return them to FinishDemoTask.
85 //
86 // The IntegerService, whose value is initially 0, will be called a total of
87 // N = |kTaskCount * kTaskIterationCount| times. Each DemoTask's results
88 // are displayed in array of length N. Digits appear in positions that
89 // correspond to the results obtained by the DemoTask thread. The results
90 // show that the DemoTask threads are accessing the Integer in parallel.
91 // The fact that only one digit appears in each column shows that things
92 // are working correctly.
93 class IndirectServiceDemoAppDelegate : public ApplicationDelegate {
94 public:
95 virtual void Initialize(ApplicationImpl* app) override {
yzshen1 2014/11/20 22:01:44 nit: no need to have virtual
hansmuller 2014/11/20 22:35:38 Sorry, I missed that one.
96 IntegerServicePtr indirect_service_delegate;
97 app->ConnectToService("mojo:indirect_integer_service",
98 &indirect_integer_service_);
99 app->ConnectToService("mojo:integer_service", &indirect_service_delegate);
100 indirect_integer_service_->Set(indirect_service_delegate.Pass());
101
102 for (unsigned i = 0; i < kTaskCount; i++) {
103 IntegerServicePtr integer_service;
104 indirect_integer_service_->Get(GetProxy(&integer_service));
105 DemoTaskFinishedCallback finished_callback = base::Bind(
106 &IndirectServiceDemoAppDelegate::FinishDemoTask,
107 base::Unretained(this),
108 base::Unretained(base::MessageLoop::current()));
109 // We're passing the integer_service_ proxy to another thread, so
110 // use its MessagePipe.
111 scoped_ptr<DemoTask> task(new DemoTask(integer_service.PassMessagePipe(),
112 finished_callback,
113 kTaskIterationCount));
114 tasks_.push_back(task.Pass());
115 }
116 }
117
118 private:
119 static const unsigned kTaskCount = 10;
120 static const unsigned kTaskIterationCount = 6;
121
122 // This method is called on a DemoTask thread. It just calls DoFinishDemoTask
123 // on the application's run loop. Doing so serializes the DoFinishDemoTask
124 // calls.
125 void FinishDemoTask(base::MessageLoop *run_loop,
126 DemoTask* task,
127 const std::vector<int32_t>& results) {
128 run_loop->PostTask(FROM_HERE, base::Bind(
129 &IndirectServiceDemoAppDelegate::DoFinishDemoTask,
130 base::Unretained(this),
131 base::Unretained(task),
132 results));
133 }
134
135 void DoFinishDemoTask(DemoTask* task, const std::vector<int32_t>& results) {
136 std::string display(kTaskCount * kTaskIterationCount, ' ');
137 for (unsigned i = 0; i < results.size(); i++)
138 display[results[i]] = '0' + (results[i] % 10);
139 printf("DemoTask Thread [%s]\n", display.c_str());
140 tasks_.erase(std::remove(tasks_.begin(), tasks_.end(), task), tasks_.end());
141 if (tasks_.empty())
142 ApplicationImpl::Terminate();
143 }
144
145 IndirectIntegerServicePtr indirect_integer_service_;
146 std::vector<scoped_ptr<DemoTask>> tasks_;
yzshen1 2014/11/20 22:01:44 This is a library feature of C++11 (move-only obje
hansmuller 2014/11/20 22:35:38 OK.
147 };
148
149
150 } // namespace examples
151 } // namespace mojo
152
153 MojoResult MojoMain(MojoHandle shell_handle) {
154 mojo::ApplicationRunnerChromium runner(
155 new mojo::examples::IndirectServiceDemoAppDelegate);
156 return runner.Run(shell_handle);
157 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698