00001 /* 00002 * lib/message/manager.cc 00003 * 00004 * Message handling "system" for errors, warnings and verbose messages. 00005 * Message manager implementation. 00006 * 00007 * Copyright (c) 2004 by Wolfgang Wieser ] wwieser (a) gmx <*> de [ 00008 * 00009 * This file may be distributed and/or modified under the terms of the 00010 * GNU General Public License version 2 as published by the Free Software 00011 * Foundation. (See COPYING.GPL for details.) 00012 * 00013 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00014 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00015 * 00016 */ 00017 00018 #include "manager.h" 00019 #include "handler.h" 00020 00021 00022 // Initializing static data: 00023 MessageManager *MessageManager::manager=NULL; 00024 00025 00026 void MessageManager::_PostMessage(const Message &m) 00027 { 00028 if(!this) return; 00029 00030 // If the message is not needed by any client, we can bail 00031 // out early. 00032 // Actually, we should not even be here in this case, but oh well... 00033 if(!_IsRequestedType(m.type())) return; 00034 00035 main_mutex.lock(); 00036 00037 // Deliver to all clients: 00038 for(MessageHandler *_hdl=hdl_list.first(); _hdl; ) 00039 { 00040 // If you don't know why these two lines are here, then leave 00041 // them untouched. (They ARE necessary!) 00042 MessageHandler *hdl=_hdl; 00043 _hdl=_hdl->next; 00044 00045 if(m.MatchesTypeMask(hdl->mtmask)) 00046 { hdl->HandleMessage(m); } 00047 } 00048 00049 // In case it is a fatal error, we need to exit. 00050 bool is_fatal=(m.type() & Message::MTFatal); 00051 bool must_exit = is_fatal && exit_on_fatal; 00052 00053 main_mutex.unlock(); 00054 00055 if(must_exit) 00056 { 00057 // It's time to say goodbye... 00058 exit(2); 00059 } 00060 } 00061 00062 00063 void MessageManager::_RecomputeMTMask() 00064 { 00065 // (NOT mutex-protected!) 00066 00067 // OR together again: 00068 int all_mask=0; 00069 for(MessageHandler *hdl=hdl_list.first(); hdl; hdl=hdl->next) 00070 { all_mask|=hdl->mtmask; } 00071 00072 // Update global type mask. 00073 type_mask.set(all_mask); 00074 } 00075 00076 00077 void MessageManager::_SelectMessageTypes(MessageHandler *hdl, 00078 Message::Type mask) 00079 { 00080 if(!this) return; 00081 00082 main_mutex.lock(); 00083 00084 // (Needs to be stored; bit removal problem :) 00085 hdl->mtmask=mask; 00086 00087 _RecomputeMTMask(); 00088 00089 main_mutex.unlock(); 00090 } 00091 00092 00093 void MessageManager::_RegisterHandler(MessageHandler *hdl) 00094 { 00095 if(!this || !hdl) return; 00096 00097 main_mutex.lock(); 00098 hdl->mtmask=Message::MTNone; 00099 hdl_list.append(hdl); 00100 main_mutex.unlock(); 00101 } 00102 00103 void MessageManager::_UnregisterHandler(MessageHandler *hdl) 00104 { 00105 if(!this || !hdl) return; 00106 00107 main_mutex.lock(); 00108 hdl_list.dequeue(hdl); 00109 _RecomputeMTMask(); 00110 main_mutex.unlock(); 00111 } 00112 00113 00114 void MessageManager::init() 00115 { 00116 // Initialize the manager. 00117 new MessageManager(); // <-- Constructor will set MessageManager::manager. 00118 } 00119 00120 00121 void MessageManager::cleanup() 00122 { 00123 if(manager) 00124 { delete manager; } 00125 // manager=NULL here by destructor of MessageManager. 00126 } 00127 00128 00129 MessageManager::MessageManager() : 00130 hdl_list(), 00131 main_mutex() 00132 { 00133 // This is needed as we use an atomic integer for mask storage. 00134 CritAssert(sizeof(int)>=sizeof(Message::Type)); // critical 00135 00136 type_mask=0; 00137 00138 exit_on_fatal=1; 00139 00140 Assert(!manager); 00141 manager=this; 00142 } 00143 00144 00145 MessageManager::~MessageManager() 00146 { 00147 Assert(manager==this); 00148 00149 // Simply ignore the managers in the list. We dequeue them 00150 // and leave them alone. 00152 main_mutex.lock(); 00153 while(!hdl_list.IsEmpty()) 00154 { _UnregisterHandler(hdl_list.first()); } 00155 main_mutex.unlock(); 00156 00157 manager=NULL; 00158 } 00159 00160