OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "mojo/public/cpp/application/run_application.h" | |
6 | |
7 #include <assert.h> | |
8 #include <pthread.h> | |
9 | |
10 #include "mojo/public/cpp/application/application_impl_base.h" | |
11 #include "mojo/public/cpp/system/macros.h" | |
12 #include "mojo/public/cpp/system/message_pipe.h" | |
13 #include "mojo/public/cpp/utility/run_loop.h" | |
14 #include "mojo/public/interfaces/application/application.mojom.h" | |
15 | |
16 namespace mojo { | |
17 | |
18 namespace { | |
19 | |
20 // We store a pointer to a |ResultHolder|, which just stores a |MojoResult|, in | |
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 // TODO(vtl): The default result should probably be |MOJO_RESULT_UNKNOWN|, but | |
29 // |ApplicationRunner| always returned |MOJO_RESULT_OK|. | |
30 MojoResult result = MOJO_RESULT_OK; | |
31 }; | |
32 | |
33 pthread_key_t g_current_result_holder_key; | |
34 | |
35 // Ensures that we have a TLS slot to store the current result in. | |
36 void InitializeCurrentResultHolderIfNecessary() { | |
37 static pthread_once_t current_result_holder_key_once = PTHREAD_ONCE_INIT; | |
38 int error = pthread_once(¤t_result_holder_key_once, []() { | |
39 int error = pthread_key_create(&g_current_result_holder_key, nullptr); | |
40 MOJO_ALLOW_UNUSED_LOCAL(error); | |
41 assert(!error); | |
42 }); | |
43 MOJO_ALLOW_UNUSED_LOCAL(error); | |
44 assert(!error); | |
45 } | |
46 | |
47 ResultHolder* GetCurrentResultHolder() { | |
48 InitializeCurrentResultHolderIfNecessary(); | |
49 return static_cast<ResultHolder*>( | |
50 pthread_getspecific(g_current_result_holder_key)); | |
51 } | |
52 | |
53 void SetCurrentResultHolder(ResultHolder* result_holder) { | |
54 InitializeCurrentResultHolderIfNecessary(); | |
55 | |
56 int error = pthread_setspecific(g_current_result_holder_key, result_holder); | |
57 MOJO_ALLOW_UNUSED_LOCAL(error); | |
58 assert(!error); | |
59 } | |
60 | |
61 } // namespace | |
62 | |
63 MojoResult RunApplication(MojoHandle application_request_handle, | |
64 ApplicationImplBase* application_impl, | |
65 const RunApplicationOptions* options) { | |
66 assert(!options); // No options supported! | |
67 assert(!GetCurrentResultHolder()); | |
68 | |
69 ResultHolder result_holder; | |
70 SetCurrentResultHolder(&result_holder); | |
71 | |
72 RunLoop loop; | |
73 application_impl->Bind(InterfaceRequest<Application>( | |
74 MakeScopedHandle(MessagePipeHandle(application_request_handle)))); | |
75 loop.Run(); | |
76 | |
77 // TODO(vtl): Should we unbind stuff here? (Should there be "will start"/"did | |
78 // stop" notifications to the |ApplicationImplBase|?) | |
79 | |
80 SetCurrentResultHolder(nullptr); | |
81 | |
82 // TODO(vtl): We'd like to enable the following assertion, but we do things | |
83 // like |RunLoop::current()->Quit()| in various places. | |
84 // assert(result_holder.is_set); | |
85 | |
86 return result_holder.result; | |
87 } | |
88 | |
89 void TerminateApplication(MojoResult result) { | |
90 RunLoop::current()->Quit(); | |
91 | |
92 ResultHolder* result_holder = GetCurrentResultHolder(); | |
93 // TODO(vtl): We may execute code during |RunLoop|'s destruction (in | |
94 // particular, "handlers" are notified of destruction, and those handlers may | |
95 // call this). There's no |is_running()| method (unlike |base::MessageLoop|), | |
96 // so we detect this case by checking if there's a current result holder. Ugh. | |
97 if (!result_holder) | |
98 return; | |
99 assert(!result_holder->is_set); | |
100 result_holder->result = result; | |
101 #ifndef NDEBUG | |
102 result_holder->is_set = true; | |
103 #endif | |
104 } | |
105 | |
106 } // namespace mojo | |
OLD | NEW |