Branch data Line data Source code
1 : : /* Copyright 2006,2007 Savarese Software Research Corporation
2 : : *
3 : : * Licensed under the Apache License, Version 2.0 (the "License");
4 : : * you may not use this file except in compliance with the License.
5 : : * You may obtain a copy of the License at
6 : : *
7 : : * http://www.savarese.com/software/ApacheLicense-2.0
8 : : *
9 : : * Unless required by applicable law or agreed to in writing, software
10 : : * distributed under the License is distributed on an "AS IS" BASIS,
11 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : : * See the License for the specific language governing permissions and
13 : : * limitations under the License.
14 : : */
15 : :
16 : : /**
17 : : * @file
18 : : * This header defines the ScatterMessage class.
19 : : */
20 : :
21 : : #ifndef __SSRC_SPREAD_SCATTER_MESSAGE_H
22 : : #define __SSRC_SPREAD_SCATTER_MESSAGE_H
23 : :
24 : : #include <ssrc/spread/Message.h>
25 : :
26 : : #include <utility>
27 : : #include <vector>
28 : :
29 : : __BEGIN_NS_SSRC_SPREAD
30 : :
31 : : /**
32 : : * ScatterMessage is a reusable container of multiple in-place data
33 : : * buffers. It can be populated with Message instances or straight
34 : : * data pointers. However, the auto-resizing feature of
35 : : * Mailbox::receive will be exercised only if the ScatterMessage
36 : : * contains at least one Message instance. You will want to use a
37 : : * ScatterMessage primarily when you want to avoid multiple buffer
38 : : * copies. For example, if you know the format of an incoming message
39 : : * you can add data pointers for each message part instead of parsing
40 : : * the message and copying the data. Also, instead of allocating a
41 : : * message buffer and copying multiple data items to it for a send,
42 : : * you can populate a ScatterMessage with pointers to the data items
43 : : * and avoid an extra copy.
44 : : *
45 : : * We do not document ScatterMessage protected members because they
46 : : * are intended only for internal library use.
47 : : */
48 : 23 : class ScatterMessage : public BaseMessage {
49 : : public:
50 : :
51 : : enum {
52 : : /**
53 : : * The maximum number of elements that can be added to a scatter
54 : : * message.
55 : : */
56 : : MaxScatterElements = MAX_CLIENT_SCATTER_ELEMENTS
57 : : };
58 : :
59 : : private:
60 : : friend class Mailbox;
61 : :
62 : : typedef std::pair<Message *, int> value_type;
63 : :
64 : : Spread::scatter _scatter;
65 : : std::vector<value_type> _messages;
66 : : unsigned int _size;
67 : :
68 : 11 : const Spread::scatter *scatter() const {
69 : 11 : return &_scatter;
70 : : }
71 : :
72 : 11 : Spread::scatter *scatter() {
73 : 11 : return &_scatter;
74 : : }
75 : :
76 : : void init_pre_receive();
77 : :
78 : : void init_post_receive(int bytes_received);
79 : :
80 : 1 : Message * message(const unsigned int index) {
81 : 1 : return _messages[index].first;
82 : : }
83 : :
84 : 1 : void resize_message(const unsigned int message_index,
85 : : const unsigned int size)
86 : : {
87 : 1 : value_type & v = _messages[message_index];
88 : 1 : Message *m = v.first;
89 : :
90 : 1 : _size-=m->size();
91 : 1 : m->resize(size);
92 : 1 : _size+=m->size();
93 : 1 : _scatter.elements[v.second].buf = &((*m)[0]);
94 : 1 : _scatter.elements[v.second].len = m->size();
95 : 1 : }
96 : :
97 : : protected:
98 : :
99 : : #ifdef LIBSSRCSPREAD_ENABLE_MEMBERSHIP_INFO
100 : :
101 : 0 : virtual int sp_get_membership_info(Spread::membership_info *info) const {
102 : 0 : return Spread::SP_scat_get_memb_info(&_scatter, service(), info);
103 : : }
104 : :
105 : 0 : virtual int sp_get_vs_set_members(const Spread::vs_set_info *vs_set,
106 : : Spread::group_type member_names[],
107 : : unsigned int member_names_count)
108 : : const
109 : : {
110 : : return
111 : 0 : Spread::SP_scat_get_vs_set_members(&_scatter, vs_set, member_names,
112 : 0 : member_names_count);
113 : : }
114 : :
115 : 0 : virtual int sp_get_vs_sets_info(Spread::vs_set_info *vs_sets,
116 : : unsigned int num_vs_sets,
117 : : unsigned int *index)
118 : : const
119 : : {
120 : : return
121 : 0 : Spread::SP_scat_get_vs_sets_info(&_scatter, vs_sets, num_vs_sets, index);
122 : : }
123 : :
124 : : #endif
125 : :
126 : : public:
127 : :
128 : : /**
129 : : * Creates a ScatterMessage with a size of zero and no message parts.
130 : : * See BaseMessage() for the default values of various properties,
131 : : * including service type.
132 : : */
133 : 23 : ScatterMessage() : _messages(), _size(0) {
134 : 23 : _scatter.num_elements = 0;
135 : 23 : }
136 : :
137 : : /**
138 : : * Returns the total size of the message (comprising all of its
139 : : * parts) in bytes.
140 : : * @returns The total size of the message in bytes.
141 : : */
142 : 1 : virtual unsigned int size() const {
143 : 1 : return _size;
144 : : }
145 : :
146 : : /**
147 : : * Clears the message for reuse, resetting both its size and number
148 : : * of message parts to zero.
149 : : */
150 : 17 : virtual void clear() {
151 : 17 : _scatter.num_elements = 0;
152 : 17 : _size = 0;
153 : 17 : _messages.clear();
154 : 17 : }
155 : :
156 : : /**
157 : : * Returns the number of parts that have been added to the message.
158 : : * @return The number of parts that have been added to the message.
159 : : */
160 : : unsigned int count_message_parts() const {
161 : : return _scatter.num_elements;
162 : : }
163 : :
164 : : /**
165 : : * Returns the number of Message instances that have been added to
166 : : * the message. This number will be different from that returned by
167 : : * count_message_parts() if any straight pointers have ben added.
168 : : *
169 : : * @return The number of Message instances that have been added to the
170 : : * message.
171 : : */
172 : 2 : unsigned int count_message_objects() const {
173 : 2 : return _messages.size();
174 : : }
175 : :
176 : : bool add(const void *data, const unsigned int size);
177 : :
178 : : /**
179 : : * Adds a Message as a message part. ScatterMessage will store a
180 : : * pointer to the original Message; therefore you should not alter
181 : : * the Message between the time it is added and when the send or
182 : : * receive is performed. Note that for receives, each Message added
183 : : * will be filled up to its capacity, not its size. The size will
184 : : * be ajdusted to reflect the amount of data written to the Message.
185 : : * The capacity will not be increased to accommodate more data
186 : : * except for the last Message added to the ScatterMessage. If you
187 : : * don't want this behavior, use add(const void *, const unsigned int)
188 : : * instead, with <code>&message[0]</code> as the data argument.
189 : : * When using fixed-length message parts, it is often useful to tack
190 : : * on a Message as the last message part to store any unexpected
191 : : * overflow.
192 : : *
193 : : * @param message The Message to add.
194 : : * @return true if the message part was added, false if no more parts
195 : : * can be added.
196 : : */
197 : 22 : bool add(const Message & message) {
198 [ + - ]: 22 : if(add(&message[0], message.size())) {
199 : : // We cheat and cast away constness!
200 : 44 : _messages.push_back(value_type(const_cast<Message*>(&message),
201 [ + - ]: 66 : _scatter.num_elements - 1));
202 : 22 : return true;
203 : : } else
204 : 0 : return false;
205 : : }
206 : : };
207 : :
208 : :
209 : : __END_NS_SSRC_SPREAD
210 : :
211 : : #endif
|