| 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..446df01294a38e456a6b59baeb602aa740fb5fb9
|
| --- /dev/null
|
| +++ b/examples/indirect_service/indirect_service_demo.cc
|
| @@ -0,0 +1,156 @@
|
| +// 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/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/common/message_pump_mojo.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) {
|
| +
|
| + base::Thread::Options options;
|
| + options.message_loop_type = base::MessageLoop::TYPE_CUSTOM;
|
| + options.message_pump_factory = base::Bind(&common::MessagePumpMojo::Create);
|
| + CHECK(thread_.StartWithOptions(options));
|
| +
|
| + thread_.message_loop()->PostTask(
|
| + FROM_HERE, base::Bind(&DemoTask::Run, base::Unretained(this)));
|
| + }
|
| +
|
| + 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.
|
| + if (i < iteration_count_ - 1)
|
| + base::PlatformThread::Sleep(
|
| + base::TimeDelta::FromMilliseconds(rand() % 10));
|
| + }
|
| + }
|
| +
|
| + private:
|
| + void SaveResultAndFinish(int32_t result) {
|
| + results_.push_back(result);
|
| + if (results_.size() == iteration_count_) {
|
| + integer_service_.reset(); // Must be done on thread_.
|
| + finished_callback_.Run(this, results_);
|
| + }
|
| + }
|
| +
|
| + ScopedMessagePipeHandle proxy_handle_;
|
| + base::Thread thread_;
|
| + IntegerServicePtr integer_service_;
|
| + DemoTaskFinishedCallback finished_callback_;
|
| + unsigned iteration_count_;
|
| + std::vector<int32_t> results_;
|
| +};
|
| +
|
| +// Connect to the IntegerService and give its proxy to the
|
| +// IndirectIntegerService. Start kTaskCount 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 kTaskIterationCount times, collect the results in
|
| +// a vector and return them to FinishDemoTask.
|
| +//
|
| +// The IntegerService, whose value is initially 0, will be called a total of
|
| +// N = |kTaskCount * kTaskIterationCount| 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 one digit appears in each column shows that things
|
| +// are working correctly.
|
| +class IndirectServiceDemoAppDelegate : public ApplicationDelegate {
|
| + public:
|
| + 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 < kTaskCount; 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, so
|
| + // use its MessagePipe.
|
| + tasks_.push_back(new DemoTask(integer_service.PassMessagePipe(),
|
| + finished_callback,
|
| + kTaskIterationCount));
|
| + }
|
| + }
|
| +
|
| + private:
|
| + static const unsigned kTaskCount = 10;
|
| + static const unsigned kTaskIterationCount = 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(kTaskCount * kTaskIterationCount, ' ');
|
| + 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());
|
| + delete task; // Stop the DemoTask's thread etc.
|
| + 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);
|
| +}
|
|
|