xref: /haiku/src/apps/cortex/support/MultiInvoker.cpp (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
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