| 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 |