Chromium Code Reviews| Index: examples/indirect_service/indirect_service_demo.cc |
| diff --git a/examples/indirect_service/indirect_service_demo.cc b/examples/indirect_service/indirect_service_demo.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..a11d3e5adbedaf93c682201785aa44235eb052fa |
| --- /dev/null |
| +++ b/examples/indirect_service/indirect_service_demo.cc |
| @@ -0,0 +1,148 @@ |
| +// 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 <cstdlib> |
| + |
| +#include "base/bind.h" |
| +#include "base/memory/scoped_vector.h" |
| +#include "base/message_loop/message_loop.h" |
| +#include "base/threading/thread.h" |
| +#include "base/time/time.h" |
| +#include "examples/indirect_service/indirect_service_demo.mojom.h" |
| +#include "mojo/application/application_runner_chromium.h" |
| +#include "mojo/public/c/system/main.h" |
| +#include "mojo/public/cpp/application/application_delegate.h" |
| +#include "mojo/public/cpp/application/application_impl.h" |
| + |
| +namespace mojo { |
| +namespace examples { |
| + |
| +class DemoTask; |
| + |
| +typedef typename base::Callback<void(DemoTask*, const std::vector<int32_t>&)> |
| + DemoTaskFinishedCallback; |
| + |
| +// A thread that connects to the IndirectIntegerService, gets a connection |
| +// to its IntegerService, and then calls Increment() iteration_count times. |
| +// The results are saved and returned with the finished_callback. |
| +class DemoTask { |
| + public: |
| + DemoTask(ScopedMessagePipeHandle proxy_handle, |
| + const DemoTaskFinishedCallback& finished_callback, |
| + unsigned iteration_count) |
| + : proxy_handle_(proxy_handle.Pass()), |
| + thread_("DemoTask"), |
| + finished_callback_(finished_callback), |
| + iteration_count_(iteration_count) { |
| + thread_.Start(); |
|
qsr
2014/11/20 08:49:10
You might want to put a MessagePumpMojo on this th
hansmuller
2014/11/20 17:53:04
I've just tried that.
base::Thread::Options o
|
| + thread_.message_loop()->PostTask( |
| + FROM_HERE, base::Bind(&DemoTask::Run, base::Unretained(this))); |
|
yzshen1
2014/11/20 18:17:17
wrong indent.
hansmuller
2014/11/20 19:27:59
Done.
|
| + } |
| + |
| + void Run() { |
| + integer_service_.Bind(proxy_handle_.Pass()); |
| + base::Callback<void(int32_t)> callback = |
| + base::Bind(&DemoTask::SaveResultAndFinish, base::Unretained(this)); |
| + for(int unsigned i = 0; i < iteration_count_; i++) { |
| + integer_service_->Increment(callback); |
| + // To ensure that the DemoTask threads' execution overlaps, sleep. |
| + base::PlatformThread::Sleep( |
| + base::TimeDelta::FromMilliseconds(rand() % 10)); |
| + } |
| + } |
| + |
| + private: |
| + void SaveResultAndFinish(int32_t result) { |
| + results_.push_back(result); |
| + if (results_.size() == iteration_count_) |
| + finished_callback_.Run(this, results_); |
| + } |
| + |
| + ScopedMessagePipeHandle proxy_handle_; |
| + base::Thread thread_; |
| + IntegerServicePtr integer_service_; |
|
yzshen1
2014/11/20 18:17:18
This needs to be destroyed on |thread_|.
|
| + DemoTaskFinishedCallback finished_callback_; |
| + unsigned iteration_count_; |
| + std::vector<int32_t> results_; |
| +}; |
| + |
| +// Connect to the IntegerService and give its proxy to the |
| +// IndirectIntegerService. Start task_count_ DemoTask threads all of |
| +// which will use the IndirectIntegerService to get their own connection |
| +// to the (one) IntegerService. Each DemoTask will call the IntegerService's |
| +// Increment() method task_iteration_count times, collect the results in |
|
yzshen1
2014/11/20 18:17:17
task_iteration_count_
hansmuller
2014/11/20 19:27:59
Done.
|
| +// a vector and return them to FinishDemoTask. |
| +// |
| +// The IntegerService, whose value is initially 0, will be called a total of |
| +// N = |task_count_ * task_iteration_count_| times. Each DemoTask's results |
| +// are displayed in array of length N. Digits appear in positions that |
| +// correspond to the results obtained by the DemoTask thread. The results |
| +// show that the DemoTask threads are accessing the Integer in parallel. |
| +// The fact that only digit appears in each column provies that things |
|
Aaron Boodman
2014/11/20 07:21:58
This sentence doesn't parse. Missing the word 'one
hansmuller
2014/11/20 17:53:04
And "provies". Yikes.
hansmuller
2014/11/20 17:53:04
Yes, thanks for reading all of this.
|
| +// are working correctly. |
| + |
|
Aaron Boodman
2014/11/20 07:21:58
No empty line necessary.
hansmuller
2014/11/20 17:53:04
Done.
|
| +class IndirectServiceDemoAppDelegate : public ApplicationDelegate { |
| + public: |
| + virtual void Initialize(ApplicationImpl* app) override { |
| + IntegerServicePtr indirect_service_delegate; |
| + app->ConnectToService("mojo:indirect_integer_service", |
| + &indirect_integer_service_); |
| + app->ConnectToService("mojo:integer_service", &indirect_service_delegate); |
| + indirect_integer_service_->Set(indirect_service_delegate.Pass()); |
| + |
| + for (unsigned i = 0; i < task_count_; i++) { |
| + IntegerServicePtr integer_service; |
| + indirect_integer_service_->Get(GetProxy(&integer_service)); |
| + DemoTaskFinishedCallback finished_callback = base::Bind( |
| + &IndirectServiceDemoAppDelegate::FinishDemoTask, |
| + base::Unretained(this), |
| + base::Unretained(base::MessageLoop::current())); |
| + // We're passing the integer_service proxy to another thread, to |
| + // use its MessagePipe. |
| + tasks_.push_back(new DemoTask(integer_service.PassMessagePipe(), |
|
yzshen1
2014/11/20 18:17:17
Who owns these DemoTask instances?
|
| + finished_callback, |
| + task_iteration_count_)); |
| + } |
| + } |
| + |
| + private: |
| + const unsigned task_count_ = 10; |
|
yzshen1
2014/11/20 18:17:17
Maybe consider "static const" and name them kTaskC
hansmuller
2014/11/20 19:27:59
Done.
|
| + const unsigned task_iteration_count_ = 6; |
| + |
| + // This method is called on a DemoTask thread. It just calls DoFinishDemoTask |
| + // on the application's run loop. Doing so serializes the DoFinishDemoTask |
| + // calls. |
| + void FinishDemoTask(base::MessageLoop *run_loop, |
| + DemoTask* task, |
| + const std::vector<int32_t>& results) { |
| + run_loop->PostTask(FROM_HERE, base::Bind( |
| + &IndirectServiceDemoAppDelegate::DoFinishDemoTask, |
| + base::Unretained(this), |
| + base::Unretained(task), |
| + results)); |
| + } |
| + |
| + void DoFinishDemoTask(DemoTask* task, const std::vector<int32_t>& results) { |
| + std::string display(task_count_ * task_iteration_count_, ' '); |
| + for (unsigned i = 0; i < results.size(); i++) |
| + display[results[i]] = '0' + (results[i] % 10); |
| + printf("DemoTask Thread [%s]\n", display.c_str()); |
| + tasks_.erase(std::remove(tasks_.begin(), tasks_.end(), task), tasks_.end()); |
| + if (tasks_.empty()) |
| + ApplicationImpl::Terminate(); |
| + } |
| + |
| + IndirectIntegerServicePtr indirect_integer_service_; |
| + std::vector<DemoTask*> tasks_; |
| +}; |
| + |
| + |
| +} // namespace examples |
| +} // namespace mojo |
| + |
| +MojoResult MojoMain(MojoHandle shell_handle) { |
| + mojo::ApplicationRunnerChromium runner( |
| + new mojo::examples::IndirectServiceDemoAppDelegate); |
| + return runner.Run(shell_handle); |
| +} |