xref: /haiku/src/apps/cortex/support/MultiInvoker.cpp (revision 508f54795f39c3e7552d87c95aae9dd8ec6f505b)
1 ////////////////////////////////////////////////////////////
2 // MultiInvoker.cpp
3 // ----------------
4 // Implements the MultiInvoker class.
5 //
6 // Copyright 1999, Be Incorporated.   All Rights Reserved.
7 // This file may be used under the terms of the Be Sample
8 // Code License.
9 
10 #include <Messenger.h>
11 #include "MultiInvoker.h"
12 
13 MultiInvoker::MultiInvoker()
14 {
15 	m_message = 0;
16 	m_timeout = B_INFINITE_TIMEOUT;
17 	m_replyHandler = 0;
18 }
19 
20 MultiInvoker::MultiInvoker(const MultiInvoker& src)
21 {
22 	Clone(src);
23 }
24 
25 MultiInvoker::~MultiInvoker()
26 {
27 	Clear();
28 }
29 
30 MultiInvoker& MultiInvoker::operator=(const MultiInvoker& src)
31 {
32 	if (this != &src) {
33 		Clear();
34 		Clone(src);
35 	}
36 	return *this;
37 }
38 
39 void MultiInvoker::Clear()
40 {
41 	delete m_message;
42 	int32 i=CountTargets();
43 	while (--i >=0) {
44 		RemoveTarget(i);
45 	}
46 }
47 
48 void MultiInvoker::Clone(const MultiInvoker& src)
49 {
50 	m_message = new BMessage(*src.Message());
51 	int32 len=src.CountTargets();
52 	for (int32 i=0; i<len; i++) {
53 		AddTarget(src.TargetAt(i));
54 	}
55 	m_timeout = src.Timeout();
56 	m_replyHandler = src.HandlerForReply();
57 }
58 
59 void MultiInvoker::SetMessage(BMessage* message)
60 {
61 	delete m_message;
62 	m_message = message;
63 }
64 
65 BMessage* MultiInvoker::Message() const
66 {
67 	return m_message;
68 }
69 
70 uint32 MultiInvoker::Command() const
71 {
72 	return (m_message) ? m_message->what : 0;
73 }
74 
75 status_t MultiInvoker::AddTarget(const BHandler* h, const BLooper* loop)
76 {
77 	status_t err;
78 	BMessenger* msgr = new BMessenger(h, loop, &err);
79 	if (err == B_OK)
80 		m_messengers.AddItem(msgr);
81 	else
82 		delete msgr;
83 	return err;
84 }
85 
86 status_t MultiInvoker::AddTarget(BMessenger* msgr)
87 {
88 	if (msgr) {
89 		m_messengers.AddItem(msgr);
90 		return B_OK;
91 	} else {
92 		return B_BAD_VALUE;
93 	}
94 }
95 
96 void MultiInvoker::RemoveTarget(const BHandler* h)
97 {
98 	int32 i = IndexOfTarget(h);
99 	if (i >= 0)
100 		RemoveTarget(i);
101 }
102 
103 void MultiInvoker::RemoveTarget(int32 index)
104 {
105 	BMessenger* msgr = static_cast<BMessenger*>
106 		(m_messengers.RemoveItem(index));
107 	delete msgr;
108 }
109 
110 int32 MultiInvoker::IndexOfTarget(const BHandler* h) const
111 {
112 	int32 len = CountTargets();
113 	for (int32 i=0; i<len; i++) {
114 		BMessenger* msgr = MessengerAt(i);
115 		if (msgr && msgr->Target(0) == h) {
116 			return i;
117 		}
118 	}
119 	return -1;
120 }
121 
122 int32 MultiInvoker::CountTargets() const
123 {
124 	return m_messengers.CountItems();
125 }
126 
127 BHandler* MultiInvoker::TargetAt(int32 index, BLooper** looper) const
128 {
129 	BMessenger* msgr = MessengerAt(index);
130 	if (msgr) {
131 		return msgr->Target(looper);
132 	} else {
133 		if (looper) *looper = 0;
134 		return 0;
135 	}
136 }
137 
138 BMessenger* MultiInvoker::MessengerAt(int32 index) const
139 {
140 	return static_cast<BMessenger*>
141 		(m_messengers.ItemAt(index));
142 }
143 
144 bool MultiInvoker::IsTargetLocal(int32 index) const
145 {
146 	BMessenger* msgr = MessengerAt(index);
147 	return (msgr) ? msgr->IsTargetLocal() : false;
148 }
149 
150 void MultiInvoker::SetTimeout(bigtime_t timeout)
151 {
152 	m_timeout = timeout;
153 }
154 
155 bigtime_t MultiInvoker::Timeout() const
156 {
157 	return m_timeout;
158 }
159 
160 void MultiInvoker::SetHandlerForReply(BHandler* h)
161 {
162 	m_replyHandler = h;
163 }
164 
165 BHandler* MultiInvoker::HandlerForReply() const
166 {
167 	return m_replyHandler;
168 }
169 
170 status_t MultiInvoker::Invoke(BMessage* msg)
171 {
172 	BMessage* sendMsg = (msg) ? msg : m_message;
173 	if (! sendMsg)
174 		return B_BAD_VALUE;
175 
176 	status_t err, finalResult=B_OK;
177 	BMessage replyMsg;
178 	int32 len = CountTargets();
179 	for (int32 i=0; i<len; i++) {
180 		BMessenger* msgr = MessengerAt(i);
181 		if (msgr) {
182 			err = msgr->SendMessage(sendMsg,
183 				HandlerForReply(), m_timeout);
184 			if (err != B_OK) finalResult = err;
185 		}
186 	}
187 	return finalResult;
188 }
189