OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/public/cpp/application/run_application.h" | 5 #include "mojo/public/cpp/application/run_application.h" |
6 | 6 |
| 7 #include <assert.h> |
| 8 #include <pthread.h> |
| 9 |
7 #include "mojo/public/cpp/application/application_impl_base.h" | 10 #include "mojo/public/cpp/application/application_impl_base.h" |
| 11 #include "mojo/public/cpp/system/macros.h" |
8 #include "mojo/public/cpp/system/message_pipe.h" | 12 #include "mojo/public/cpp/system/message_pipe.h" |
9 #include "mojo/public/cpp/utility/run_loop.h" | 13 #include "mojo/public/cpp/utility/run_loop.h" |
10 #include "mojo/public/interfaces/application/application.mojom.h" | 14 #include "mojo/public/interfaces/application/application.mojom.h" |
11 | 15 |
12 namespace mojo { | 16 namespace mojo { |
13 | 17 |
14 void RunApplication(MojoHandle application_request_handle, | 18 namespace { |
15 ApplicationImplBase* application_impl) { | 19 |
16 // TODO(vtl): Possibly we should have an assertion that we're not running, but | 20 // We store a pointer to a |ResultHolder|, which just stores a |MojoResult|, in |
17 // that requires TLS. | 21 // TLS so that |TerminateApplication()| can provide the result that |
| 22 // |RunApplication()| will return. (The |ResultHolder| is just on |
| 23 // |RunApplication()|'s stack.) |
| 24 struct ResultHolder { |
| 25 #ifndef NDEBUG |
| 26 bool is_set = false; |
| 27 #endif |
| 28 MojoResult result = MOJO_RESULT_UNKNOWN; |
| 29 }; |
| 30 |
| 31 pthread_key_t g_current_result_holder_key; |
| 32 |
| 33 // Ensures that we have a TLS slot to store the current result in. |
| 34 void InitializeCurrentResultHolderIfNecessary() { |
| 35 static pthread_once_t current_result_holder_key_once = PTHREAD_ONCE_INIT; |
| 36 int error = pthread_once(¤t_result_holder_key_once, []() { |
| 37 int error = pthread_key_create(&g_current_result_holder_key, nullptr); |
| 38 MOJO_ALLOW_UNUSED_LOCAL(error); |
| 39 assert(!error); |
| 40 }); |
| 41 MOJO_ALLOW_UNUSED_LOCAL(error); |
| 42 assert(!error); |
| 43 } |
| 44 |
| 45 ResultHolder* GetCurrentResultHolder() { |
| 46 InitializeCurrentResultHolderIfNecessary(); |
| 47 return static_cast<ResultHolder*>( |
| 48 pthread_getspecific(g_current_result_holder_key)); |
| 49 } |
| 50 |
| 51 void SetCurrentResultHolder(ResultHolder* result_holder) { |
| 52 InitializeCurrentResultHolderIfNecessary(); |
| 53 |
| 54 int error = pthread_setspecific(g_current_result_holder_key, result_holder); |
| 55 MOJO_ALLOW_UNUSED_LOCAL(error); |
| 56 assert(!error); |
| 57 } |
| 58 |
| 59 } // namespace |
| 60 |
| 61 MojoResult RunApplication(MojoHandle application_request_handle, |
| 62 ApplicationImplBase* application_impl) { |
| 63 assert(!GetCurrentResultHolder()); |
| 64 |
| 65 ResultHolder result_holder; |
| 66 SetCurrentResultHolder(&result_holder); |
18 | 67 |
19 RunLoop loop; | 68 RunLoop loop; |
20 application_impl->Bind(InterfaceRequest<Application>( | 69 application_impl->Bind(InterfaceRequest<Application>( |
21 MakeScopedHandle(MessagePipeHandle(application_request_handle)))); | 70 MakeScopedHandle(MessagePipeHandle(application_request_handle)))); |
22 loop.Run(); | 71 loop.Run(); |
23 | 72 |
24 // TODO(vtl): Should we unbind stuff here? (Should there be "will start"/"did | 73 // TODO(vtl): Should we unbind stuff here? (Should there be "will start"/"did |
25 // stop" notifications to the |ApplicationImplBase|?) | 74 // stop" notifications to the |ApplicationImplBase|?) |
| 75 |
| 76 SetCurrentResultHolder(nullptr); |
| 77 |
| 78 // TODO(vtl): We'd like to enable the following assertion, but we do things |
| 79 // like |RunLoop::current()->Quit()| in various places. |
| 80 // assert(result_holder.is_set); |
| 81 |
| 82 return result_holder.result; |
26 } | 83 } |
27 | 84 |
28 void TerminateApplication() { | 85 void TerminateApplication(MojoResult result) { |
29 RunLoop::current()->Quit(); | 86 RunLoop::current()->Quit(); |
| 87 |
| 88 ResultHolder* result_holder = GetCurrentResultHolder(); |
| 89 assert(result_holder); |
| 90 assert(!result_holder->is_set); |
| 91 result_holder->result = result; |
| 92 #ifndef NDEBUG |
| 93 result_holder->is_set = true; |
| 94 #endif |
30 } | 95 } |
31 | 96 |
32 } // namespace mojo | 97 } // namespace mojo |
OLD | NEW |