Chromium Code Reviews| OLD | NEW |
|---|---|
| (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/public/c/system/main.h" | |
| 15 #include "mojo/public/cpp/application/application_delegate.h" | |
| 16 #include "mojo/public/cpp/application/application_impl.h" | |
| 17 | |
| 18 namespace mojo { | |
| 19 namespace examples { | |
| 20 | |
| 21 class DemoTask; | |
| 22 | |
| 23 typedef typename base::Callback<void(DemoTask*, const std::vector<int32_t>&)> | |
| 24 DemoTaskFinishedCallback; | |
| 25 | |
| 26 // A thread that connects to the IndirectIntegerService, gets a connection | |
| 27 // to its IntegerService, and then calls Increment() iteration_count times. | |
| 28 // The results are saved and returned with the finished_callback. | |
| 29 class DemoTask { | |
| 30 public: | |
| 31 DemoTask(ScopedMessagePipeHandle proxy_handle, | |
| 32 const DemoTaskFinishedCallback& finished_callback, | |
| 33 unsigned iteration_count) | |
| 34 : proxy_handle_(proxy_handle.Pass()), | |
| 35 thread_("DemoTask"), | |
| 36 finished_callback_(finished_callback), | |
| 37 iteration_count_(iteration_count) { | |
| 38 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
| |
| 39 thread_.message_loop()->PostTask( | |
| 40 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.
| |
| 41 } | |
| 42 | |
| 43 void Run() { | |
| 44 integer_service_.Bind(proxy_handle_.Pass()); | |
| 45 base::Callback<void(int32_t)> callback = | |
| 46 base::Bind(&DemoTask::SaveResultAndFinish, base::Unretained(this)); | |
| 47 for(int unsigned i = 0; i < iteration_count_; i++) { | |
| 48 integer_service_->Increment(callback); | |
| 49 // To ensure that the DemoTask threads' execution overlaps, sleep. | |
| 50 base::PlatformThread::Sleep( | |
| 51 base::TimeDelta::FromMilliseconds(rand() % 10)); | |
| 52 } | |
| 53 } | |
| 54 | |
| 55 private: | |
| 56 void SaveResultAndFinish(int32_t result) { | |
| 57 results_.push_back(result); | |
| 58 if (results_.size() == iteration_count_) | |
| 59 finished_callback_.Run(this, results_); | |
| 60 } | |
| 61 | |
| 62 ScopedMessagePipeHandle proxy_handle_; | |
| 63 base::Thread thread_; | |
| 64 IntegerServicePtr integer_service_; | |
|
yzshen1
2014/11/20 18:17:18
This needs to be destroyed on |thread_|.
| |
| 65 DemoTaskFinishedCallback finished_callback_; | |
| 66 unsigned iteration_count_; | |
| 67 std::vector<int32_t> results_; | |
| 68 }; | |
| 69 | |
| 70 // Connect to the IntegerService and give its proxy to the | |
| 71 // IndirectIntegerService. Start task_count_ DemoTask threads all of | |
| 72 // which will use the IndirectIntegerService to get their own connection | |
| 73 // to the (one) IntegerService. Each DemoTask will call the IntegerService's | |
| 74 // 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.
| |
| 75 // a vector and return them to FinishDemoTask. | |
| 76 // | |
| 77 // The IntegerService, whose value is initially 0, will be called a total of | |
| 78 // N = |task_count_ * task_iteration_count_| times. Each DemoTask's results | |
| 79 // are displayed in array of length N. Digits appear in positions that | |
| 80 // correspond to the results obtained by the DemoTask thread. The results | |
| 81 // show that the DemoTask threads are accessing the Integer in parallel. | |
| 82 // 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.
| |
| 83 // are working correctly. | |
| 84 | |
|
Aaron Boodman
2014/11/20 07:21:58
No empty line necessary.
hansmuller
2014/11/20 17:53:04
Done.
| |
| 85 class IndirectServiceDemoAppDelegate : public ApplicationDelegate { | |
| 86 public: | |
| 87 virtual void Initialize(ApplicationImpl* app) override { | |
| 88 IntegerServicePtr indirect_service_delegate; | |
| 89 app->ConnectToService("mojo:indirect_integer_service", | |
| 90 &indirect_integer_service_); | |
| 91 app->ConnectToService("mojo:integer_service", &indirect_service_delegate); | |
| 92 indirect_integer_service_->Set(indirect_service_delegate.Pass()); | |
| 93 | |
| 94 for (unsigned i = 0; i < task_count_; i++) { | |
| 95 IntegerServicePtr integer_service; | |
| 96 indirect_integer_service_->Get(GetProxy(&integer_service)); | |
| 97 DemoTaskFinishedCallback finished_callback = base::Bind( | |
| 98 &IndirectServiceDemoAppDelegate::FinishDemoTask, | |
| 99 base::Unretained(this), | |
| 100 base::Unretained(base::MessageLoop::current())); | |
| 101 // We're passing the integer_service proxy to another thread, to | |
| 102 // use its MessagePipe. | |
| 103 tasks_.push_back(new DemoTask(integer_service.PassMessagePipe(), | |
|
yzshen1
2014/11/20 18:17:17
Who owns these DemoTask instances?
| |
| 104 finished_callback, | |
| 105 task_iteration_count_)); | |
| 106 } | |
| 107 } | |
| 108 | |
| 109 private: | |
| 110 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.
| |
| 111 const unsigned task_iteration_count_ = 6; | |
| 112 | |
| 113 // This method is called on a DemoTask thread. It just calls DoFinishDemoTask | |
| 114 // on the application's run loop. Doing so serializes the DoFinishDemoTask | |
| 115 // calls. | |
| 116 void FinishDemoTask(base::MessageLoop *run_loop, | |
| 117 DemoTask* task, | |
| 118 const std::vector<int32_t>& results) { | |
| 119 run_loop->PostTask(FROM_HERE, base::Bind( | |
| 120 &IndirectServiceDemoAppDelegate::DoFinishDemoTask, | |
| 121 base::Unretained(this), | |
| 122 base::Unretained(task), | |
| 123 results)); | |
| 124 } | |
| 125 | |
| 126 void DoFinishDemoTask(DemoTask* task, const std::vector<int32_t>& results) { | |
| 127 std::string display(task_count_ * task_iteration_count_, ' '); | |
| 128 for (unsigned i = 0; i < results.size(); i++) | |
| 129 display[results[i]] = '0' + (results[i] % 10); | |
| 130 printf("DemoTask Thread [%s]\n", display.c_str()); | |
| 131 tasks_.erase(std::remove(tasks_.begin(), tasks_.end(), task), tasks_.end()); | |
| 132 if (tasks_.empty()) | |
| 133 ApplicationImpl::Terminate(); | |
| 134 } | |
| 135 | |
| 136 IndirectIntegerServicePtr indirect_integer_service_; | |
| 137 std::vector<DemoTask*> tasks_; | |
| 138 }; | |
| 139 | |
| 140 | |
| 141 } // namespace examples | |
| 142 } // namespace mojo | |
| 143 | |
| 144 MojoResult MojoMain(MojoHandle shell_handle) { | |
| 145 mojo::ApplicationRunnerChromium runner( | |
| 146 new mojo::examples::IndirectServiceDemoAppDelegate); | |
| 147 return runner.Run(shell_handle); | |
| 148 } | |
| OLD | NEW |