1 /* 2 * Copyright 2005, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 */ 8 9 10 #include "MessageLooper.h" 11 12 #include <Autolock.h> 13 #include <stdio.h> 14 #include <string.h> 15 16 17 MessageLooper::MessageLooper(const char* name) 18 : BLocker(name), 19 fQuitting(false) 20 { 21 } 22 23 24 MessageLooper::~MessageLooper() 25 { 26 } 27 28 29 bool 30 MessageLooper::Run() 31 { 32 BAutolock locker(this); 33 34 fQuitting = false; 35 36 char name[B_OS_NAME_LENGTH]; 37 _GetLooperName(name, sizeof(name)); 38 39 // Spawn our message-monitoring thread 40 fThread = spawn_thread(_message_thread, name, B_NORMAL_PRIORITY, this); 41 if (fThread < B_OK) { 42 fQuitting = true; 43 return false; 44 } 45 46 if (resume_thread(fThread) != B_OK) { 47 fQuitting = true; 48 kill_thread(fThread); 49 fThread = -1; 50 return false; 51 } 52 53 return true; 54 } 55 56 57 void 58 MessageLooper::Quit() 59 { 60 fQuitting = true; 61 _PrepareQuit(); 62 63 if (fThread < B_OK) { 64 // thread has not been started yet 65 delete this; 66 return; 67 } 68 69 if (fThread == find_thread(NULL)) { 70 // called from our message looper 71 delete this; 72 exit_thread(0); 73 } else { 74 // called from a different thread 75 PostMessage(kMsgQuitLooper); 76 } 77 } 78 79 80 /*! 81 \brief Send a message to the looper without any attachments 82 \param code ID code of the message to post 83 */ 84 void 85 MessageLooper::PostMessage(int32 code) 86 { 87 BPrivate::LinkSender link(MessagePort()); 88 link.StartMessage(code); 89 link.Flush(); 90 } 91 92 93 void 94 MessageLooper::_PrepareQuit() 95 { 96 // to be implemented by subclasses 97 } 98 99 100 void 101 MessageLooper::_GetLooperName(char* name, size_t length) 102 { 103 strcpy(name, "unnamed looper"); 104 } 105 106 107 void 108 MessageLooper::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) 109 { 110 } 111 112 113 void 114 MessageLooper::_MessageLooper() 115 { 116 BPrivate::LinkReceiver& receiver = fLink.Receiver(); 117 118 while (true) { 119 int32 code; 120 status_t status = receiver.GetNextMessage(code); 121 if (status < B_OK) { 122 // that shouldn't happen, it's our port 123 printf("Someone deleted our message port!\n"); 124 break; 125 } 126 127 Lock(); 128 129 if (code == kMsgQuitLooper) { 130 Quit(); 131 } else 132 _DispatchMessage(code, receiver); 133 134 Unlock(); 135 } 136 } 137 138 139 /*! 140 \brief Message-dispatching loop starter 141 */ 142 /*static*/ 143 int32 144 MessageLooper::_message_thread(void* _looper) 145 { 146 MessageLooper* looper = (MessageLooper*)_looper; 147 148 looper->_MessageLooper(); 149 return 0; 150 } 151 152