Make UEFI boot-platform build again
[haiku.git] / src / servers / app / MessageLooper.cpp
blob56ce033668544ed7cfbcda22a69972b04ac472e4
1 /*
2 * Copyright 2005-2016, Haiku.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Axel Dörfler, axeld@pinc-software.de
7 */
10 #include "MessageLooper.h"
12 #include <stdio.h>
13 #include <string.h>
15 #include <Autolock.h>
18 MessageLooper::MessageLooper(const char* name)
20 BLocker(name),
21 fThread(-1),
22 fQuitting(false),
23 fDeathSemaphore(-1)
28 MessageLooper::~MessageLooper()
33 status_t
34 MessageLooper::Run()
36 BAutolock locker(this);
38 fQuitting = false;
40 char name[B_OS_NAME_LENGTH];
41 _GetLooperName(name, sizeof(name));
43 // Spawn our message-monitoring thread
44 fThread = spawn_thread(_message_thread, name, B_DISPLAY_PRIORITY, this);
45 if (fThread < B_OK) {
46 fQuitting = true;
47 return fThread;
50 if (resume_thread(fThread) != B_OK) {
51 fQuitting = true;
52 kill_thread(fThread);
53 fThread = -1;
54 return B_BAD_THREAD_ID;
57 return B_OK;
61 void
62 MessageLooper::Quit()
64 fQuitting = true;
65 _PrepareQuit();
67 if (fThread < B_OK) {
68 // thread has not been started yet
69 delete this;
70 return;
73 if (fThread == find_thread(NULL)) {
74 // called from our message looper
75 delete this;
76 exit_thread(0);
77 } else {
78 // called from a different thread
79 PostMessage(kMsgQuitLooper);
84 /*!
85 \brief Send a message to the looper without any attachments
86 \param code ID code of the message to post
88 status_t
89 MessageLooper::PostMessage(int32 code, bigtime_t timeout)
91 BPrivate::LinkSender link(MessagePort());
92 link.StartMessage(code);
93 return link.Flush(timeout);
97 /*static*/
98 status_t
99 MessageLooper::WaitForQuit(sem_id semaphore, bigtime_t timeout)
101 status_t status;
102 do {
103 status = acquire_sem_etc(semaphore, 1, B_RELATIVE_TIMEOUT, timeout);
104 } while (status == B_INTERRUPTED);
106 if (status == B_TIMED_OUT)
107 return status;
109 return B_OK;
113 void
114 MessageLooper::_PrepareQuit()
116 // to be implemented by subclasses
120 void
121 MessageLooper::_GetLooperName(char* name, size_t length)
123 sem_id semaphore = Sem();
124 sem_info info;
125 if (get_sem_info(semaphore, &info) == B_OK)
126 strlcpy(name, info.name, length);
127 else
128 strlcpy(name, "unnamed looper", length);
132 void
133 MessageLooper::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
138 void
139 MessageLooper::_MessageLooper()
141 BPrivate::LinkReceiver& receiver = fLink.Receiver();
143 while (true) {
144 int32 code;
145 status_t status = receiver.GetNextMessage(code);
146 if (status < B_OK) {
147 // that shouldn't happen, it's our port
148 char name[256];
149 _GetLooperName(name, 256);
150 printf("MessageLooper \"%s\": Someone deleted our message port %"
151 B_PRId32 ", %s!\n", name, receiver.Port(), strerror(status));
152 break;
155 Lock();
157 if (code == kMsgQuitLooper)
158 Quit();
159 else
160 _DispatchMessage(code, receiver);
162 Unlock();
168 \brief Message-dispatching loop starter
170 /*static*/
171 int32
172 MessageLooper::_message_thread(void* _looper)
174 MessageLooper* looper = (MessageLooper*)_looper;
176 looper->_MessageLooper();
177 return 0;