1 /* 2 * Copyright 1999, Be Incorporated. 3 * Copyright (c) 1999-2000, Eric Moon. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions, and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions, and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 28 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 33 //////////////////////////////////////////////////////////// 34 // MultiInvoker.cpp 35 // ---------------- 36 // Implements the MultiInvoker class. 37 // 38 39 #include <Messenger.h> 40 #include "MultiInvoker.h" 41 42 MultiInvoker::MultiInvoker() 43 { 44 m_message = 0; 45 m_timeout = B_INFINITE_TIMEOUT; 46 m_replyHandler = 0; 47 } 48 49 MultiInvoker::MultiInvoker(const MultiInvoker& src) 50 { 51 Clone(src); 52 } 53 54 MultiInvoker::~MultiInvoker() 55 { 56 Clear(); 57 } 58 59 MultiInvoker& MultiInvoker::operator=(const MultiInvoker& src) 60 { 61 if (this != &src) { 62 Clear(); 63 Clone(src); 64 } 65 return *this; 66 } 67 68 void MultiInvoker::Clear() 69 { 70 delete m_message; 71 int32 i=CountTargets(); 72 while (--i >=0) { 73 RemoveTarget(i); 74 } 75 } 76 77 void MultiInvoker::Clone(const MultiInvoker& src) 78 { 79 m_message = new BMessage(*src.Message()); 80 int32 len=src.CountTargets(); 81 for (int32 i=0; i<len; i++) { 82 AddTarget(src.TargetAt(i)); 83 } 84 m_timeout = src.Timeout(); 85 m_replyHandler = src.HandlerForReply(); 86 } 87 88 void MultiInvoker::SetMessage(BMessage* message) 89 { 90 delete m_message; 91 m_message = message; 92 } 93 94 BMessage* MultiInvoker::Message() const 95 { 96 return m_message; 97 } 98 99 uint32 MultiInvoker::Command() const 100 { 101 return (m_message) ? m_message->what : 0; 102 } 103 104 status_t MultiInvoker::AddTarget(const BHandler* h, const BLooper* loop) 105 { 106 status_t err; 107 BMessenger* msgr = new BMessenger(h, loop, &err); 108 if (err == B_OK) 109 m_messengers.AddItem(msgr); 110 else 111 delete msgr; 112 return err; 113 } 114 115 status_t MultiInvoker::AddTarget(BMessenger* msgr) 116 { 117 if (msgr) { 118 m_messengers.AddItem(msgr); 119 return B_OK; 120 } else { 121 return B_BAD_VALUE; 122 } 123 } 124 125 void MultiInvoker::RemoveTarget(const BHandler* h) 126 { 127 int32 i = IndexOfTarget(h); 128 if (i >= 0) 129 RemoveTarget(i); 130 } 131 132 void MultiInvoker::RemoveTarget(int32 index) 133 { 134 BMessenger* msgr = static_cast<BMessenger*> 135 (m_messengers.RemoveItem(index)); 136 delete msgr; 137 } 138 139 int32 MultiInvoker::IndexOfTarget(const BHandler* h) const 140 { 141 int32 len = CountTargets(); 142 for (int32 i=0; i<len; i++) { 143 BMessenger* msgr = MessengerAt(i); 144 if (msgr && msgr->Target(0) == h) { 145 return i; 146 } 147 } 148 return -1; 149 } 150 151 int32 MultiInvoker::CountTargets() const 152 { 153 return m_messengers.CountItems(); 154 } 155 156 BHandler* MultiInvoker::TargetAt(int32 index, BLooper** looper) const 157 { 158 BMessenger* msgr = MessengerAt(index); 159 if (msgr) { 160 return msgr->Target(looper); 161 } else { 162 if (looper) *looper = 0; 163 return 0; 164 } 165 } 166 167 BMessenger* MultiInvoker::MessengerAt(int32 index) const 168 { 169 return static_cast<BMessenger*> 170 (m_messengers.ItemAt(index)); 171 } 172 173 bool MultiInvoker::IsTargetLocal(int32 index) const 174 { 175 BMessenger* msgr = MessengerAt(index); 176 return (msgr) ? msgr->IsTargetLocal() : false; 177 } 178 179 void MultiInvoker::SetTimeout(bigtime_t timeout) 180 { 181 m_timeout = timeout; 182 } 183 184 bigtime_t MultiInvoker::Timeout() const 185 { 186 return m_timeout; 187 } 188 189 void MultiInvoker::SetHandlerForReply(BHandler* h) 190 { 191 m_replyHandler = h; 192 } 193 194 BHandler* MultiInvoker::HandlerForReply() const 195 { 196 return m_replyHandler; 197 } 198 199 status_t MultiInvoker::Invoke(BMessage* msg) 200 { 201 BMessage* sendMsg = (msg) ? msg : m_message; 202 if (! sendMsg) 203 return B_BAD_VALUE; 204 205 status_t err, finalResult=B_OK; 206 BMessage replyMsg; 207 int32 len = CountTargets(); 208 for (int32 i=0; i<len; i++) { 209 BMessenger* msgr = MessengerAt(i); 210 if (msgr) { 211 err = msgr->SendMessage(sendMsg, 212 HandlerForReply(), m_timeout); 213 if (err != B_OK) finalResult = err; 214 } 215 } 216 return finalResult; 217 } 218