xref: /haiku/src/apps/cortex/support/MultiInvoker.cpp (revision 3cb015b1ee509d69c643506e8ff573808c86dcfc)
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 
82 	return err;
83 }
84 
85 status_t MultiInvoker::AddTarget(BMessenger* msgr)
86 {
87 	if (msgr) {
88 		m_messengers.AddItem(msgr);
89 		return B_OK;
90 	} else {
91 		return B_BAD_VALUE;
92 	}
93 }
94 
95 void MultiInvoker::RemoveTarget(const BHandler* h)
96 {
97 	int32 i = IndexOfTarget(h);
98 	if (i >= 0)
99 		RemoveTarget(i);
100 }
101 
102 void MultiInvoker::RemoveTarget(int32 index)
103 {
104 	BMessenger* msgr = static_cast<BMessenger*>
105 		(m_messengers.RemoveItem(index));
106 	delete msgr;
107 }
108 
109 int32 MultiInvoker::IndexOfTarget(const BHandler* h) const
110 {
111 	int32 len = CountTargets();
112 	for (int32 i=0; i<len; i++) {
113 		BMessenger* msgr = MessengerAt(i);
114 		if (msgr && msgr->Target(0) == h) {
115 			return i;
116 		}
117 	}
118 	return -1;
119 }
120 
121 int32 MultiInvoker::CountTargets() const
122 {
123 	return m_messengers.CountItems();
124 }
125 
126 BHandler* MultiInvoker::TargetAt(int32 index, BLooper** looper) const
127 {
128 	BMessenger* msgr = MessengerAt(index);
129 	if (msgr) {
130 		return msgr->Target(looper);
131 	} else {
132 		if (looper) *looper = 0;
133 		return 0;
134 	}
135 }
136 
137 BMessenger* MultiInvoker::MessengerAt(int32 index) const
138 {
139 	return static_cast<BMessenger*>
140 		(m_messengers.ItemAt(index));
141 }
142 
143 bool MultiInvoker::IsTargetLocal(int32 index) const
144 {
145 	BMessenger* msgr = MessengerAt(index);
146 	return (msgr) ? msgr->IsTargetLocal() : false;
147 }
148 
149 void MultiInvoker::SetTimeout(bigtime_t timeout)
150 {
151 	m_timeout = timeout;
152 }
153 
154 bigtime_t MultiInvoker::Timeout() const
155 {
156 	return m_timeout;
157 }
158 
159 void MultiInvoker::SetHandlerForReply(BHandler* h)
160 {
161 	m_replyHandler = h;
162 }
163 
164 BHandler* MultiInvoker::HandlerForReply() const
165 {
166 	return m_replyHandler;
167 }
168 
169 status_t MultiInvoker::Invoke(BMessage* msg)
170 {
171 	BMessage* sendMsg = (msg) ? msg : m_message;
172 	if (! sendMsg)
173 		return B_BAD_VALUE;
174 
175 	status_t err, finalResult=B_OK;
176 	BMessage replyMsg;
177 	int32 len = CountTargets();
178 	for (int32 i=0; i<len; i++) {
179 		BMessenger* msgr = MessengerAt(i);
180 		if (msgr) {
181 			err = msgr->SendMessage(sendMsg,
182 				HandlerForReply(), m_timeout);
183 			if (err != B_OK) finalResult = err;
184 		}
185 	}
186 	return finalResult;
187 }
188