Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / TAO / examples / Advanced / ch_8_and_10 / icp.cpp
blobc0223f2b86c8f4e9bff1272cd413401acde3728e
1 //=============================================================================
2 /**
3 * @file icp.cpp
5 * @author Source code used in TAO has been modified and adapted from the codeprovided in the book
6 * @author "Advanced CORBA Programming with C++" by MichiHenning and Steve Vinoski. Copyright 1999. Addison-Wesley
7 * @author Reading
8 * @author MA.Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
9 */
10 //=============================================================================
15 #include <string>
16 #include <map>
17 #include <algorithm>
18 //#include <stdlib.h>
19 #include "icp.h"
21 using namespace std;
23 //----------------------------------------------------------------
25 enum DeviceType { thermometer, thermostat };
27 struct DeviceState { // State for a device
28 DeviceType type;
29 const char * model;
30 string location;
31 short nominal_temp; // For thermostats only
33 typedef std::map<unsigned long, DeviceState> StateMap;
35 //----------------------------------------------------------------
37 const size_t MAXSTR = 32; // Max len of string including NUL
39 const long MIN_TEMP = 40; // 40 F == 4.44 C
40 const long MAX_TEMP = 90; // 90 F == 32.22 C
41 const long DFLT_TEMP = 68; // 68 F == 20.00 C
43 static StateMap dstate; // Map of known devices
45 //----------------------------------------------------------------
47 // ICP_online() simulates adding a new device to the network by
48 // adding it to the dstate map.
50 // For this simple simulation, devices with odd asset numbers
51 // are thermometers and devices with even asset numbers
52 // are thermostats.
54 // Thermostats get an initial nominal temperature of DFLT_TEMP.
55 // The location string is intentionally left blank because it
56 // must be programmed by the controller after putting the device
57 // on-line (as should be the nominal temperature).
59 // If a device with the specified ID is already on-line, the
60 // return value is -1. A zero return value indicates success.
62 extern "C"
63 int
64 ICP_online(unsigned long id)
66 // Look for id in state map.
67 StateMap::iterator pos = dstate.find(id);
68 if (pos != dstate.end())
69 return -1; // Already exists
71 // Fill in state.
72 DeviceState ds;
73 ds.type = (id % 2) ? thermometer : thermostat;
74 ds.model = (ds.type == thermometer)
75 ? "Sens-A-Temp" : "Select-A-Temp";
76 ds.nominal_temp = DFLT_TEMP;
78 // Insert new device into map
79 dstate[id] = ds;
81 return 0;
84 //----------------------------------------------------------------
86 // ICP_offline() simulates removing a device from the network by
87 // removing it from the dstate map. If the device isn't known, the
88 // return value is -1. A zero return value indicates success.
90 extern "C"
91 int
92 ICP_offline(unsigned long id)
94 // Look for id in state map
95 StateMap::iterator pos = dstate.find(id);
96 if (pos == dstate.end())
97 return -1; // No such device
98 dstate.erase(id);
99 return 0;
102 //----------------------------------------------------------------
104 // vary_temp() simulates the variation in actual temperature
105 // around a thermostat. The function randomly varies the
106 // temperature as a percentage of calls as follows:
108 // 3 degrees too cold: 5%
109 // 3 degrees too hot: 5%
110 // 2 degrees too cold: 10%
111 // 2 degrees too hot: 10%
112 // 1 degree too cold: 15%
113 // 1 degree too hot: 15%
114 // exact temperature: 40%
116 static
117 long
118 vary_temp(long temp)
120 long r = ACE_OS::rand() % 50;
121 long delta;
122 if (r < 5)
123 delta = 3;
124 else if (r < 15)
125 delta = 2;
126 else if (r < 30)
127 delta = 1;
128 else
129 delta = 0;
130 if (ACE_OS::rand() % 2)
131 delta = -delta;
132 return temp + delta;
135 //----------------------------------------------------------------
137 // Function object. Locates a thermostat that is in the same room
138 // as the device at position pos.
140 class ThermostatInSameRoom {
141 public:
142 ThermostatInSameRoom(
143 const StateMap::iterator & pos
144 ) : m_pos(pos) {}
145 bool operator()(
146 pair<const unsigned long, DeviceState> & p) const
148 return(
149 p.second.type == thermostat
150 && p.second.location
151 == m_pos->second.location
154 private:
155 const StateMap::iterator & m_pos;
158 //----------------------------------------------------------------
160 // actual_temp() is a helper function to determine the actual
161 // temperature returned by a particular thermometer or thermostat.
162 // The pos argument indicates the device.
164 // The function locates all thermostats that are in the same room
165 // as the device denoted by pos and computes the average of all
166 // the thermostats' nominal temperatures. (If no thermostats are
167 // in the same room as the device, the function assumes that the
168 // average of the nominal temperatures is DFLT_TEMP.)
170 // The returned temperature varies from the average as
171 // determined by vary_temp().
173 static
174 long
175 actual_temp(const StateMap::iterator & pos)
177 long sum = 0;
178 long count = 0;
179 StateMap::iterator where = std::find_if(
180 dstate.begin(), dstate.end(),
181 ThermostatInSameRoom(pos)
183 while (where != dstate.end()) {
184 count++;
185 sum += where->second.nominal_temp;
186 where = std::find_if(
187 ++where, dstate.end(),
188 ThermostatInSameRoom(pos)
191 return vary_temp(count == 0 ? DFLT_TEMP : sum / count);
194 //---------------------------------------------------------------
196 // ICP_get() returns an attribute value of the device with the
197 // given id. The attribute is named by the attr parameter. The
198 // value is copied into the buffer pointed to by the value
199 // pointer. The len parameter is the size of the passed buffer,
200 // so ICP_get can avoid overrunning the buffer.
202 // By default, thermometers report a temperature that varies
203 // somewhat around DFLT_TEMP. However, if there is another
204 // thermostat in the same room as the thermometer, the
205 // thermometer reports a temperature that varies around that
206 // thermostat's temperature. For several thermostats that are in
207 // the same room, the thermometer reports a temperature that
208 // varies around the average nominal temperature of all the
209 // thermostats.
211 // Attempts to read from a non-existent device or to read a
212 // non-existent attribute return -1. A return value of zero
213 // indicates success. If the supplied buffer is too short to hold
214 // a value, ICP_get() silently truncates the value and
215 // returns success.
217 extern "C"
219 ICP_get(
220 unsigned long id,
221 const char * attr,
222 void * value,
223 size_t len)
225 // Look for id in state map
226 StateMap::iterator pos = dstate.find(id);
227 if (pos == dstate.end())
228 return -1; // No such device
230 // Depending on the attribute, return the
231 // corresponding piece of state.
232 if (ACE_OS::strcmp(attr, "model") == 0) {
233 ACE_OS::strncpy((char *)value, pos->second.model, len);
234 } else if (ACE_OS::strcmp(attr, "location") == 0) {
235 ACE_OS::strncpy((char *)value, pos->second.location.c_str(), len);
236 } else if (ACE_OS::strcmp(attr, "nominal_temp") == 0) {
237 if (pos->second.type != thermostat)
238 return -1; // Must be thermostat
239 ACE_OS::memcpy(
240 value, &pos->second.nominal_temp,
241 ace_min(len, sizeof(pos->second.nominal_temp))
243 } else if (ACE_OS::strcmp(attr, "temperature") == 0) {
244 long temp = actual_temp(pos);
245 ACE_OS::memcpy(value, &temp, ace_min(len, sizeof(temp)));
246 } else if (ACE_OS::strcmp(attr, "MIN_TEMP") == 0) {
247 ACE_OS::memcpy(value, &MIN_TEMP, ace_min(len, sizeof(MIN_TEMP)));
248 } else if (ACE_OS::strcmp(attr, "MAX_TEMP") == 0) {
249 ACE_OS::memcpy(value, &MAX_TEMP, ace_min(len, sizeof(MAX_TEMP)));
250 } else {
251 return -1; // No such attribute
253 return 0; // OK
256 //----------------------------------------------------------------
258 // ICP_set() sets the attribute specified by attr to the
259 // value specified by value for the device with ID id. Attempts to
260 // write a string longer than MAXSTR bytes (including the
261 // terminating NUL) result in silent truncation of the string.
262 // Attempts to access a non-existent device or attribute
263 // return -1. Attempts to set a nominal temperature outside the
264 // legal range also return -1. A zero return value
265 // indicates success.
267 extern "C"
269 ICP_set(unsigned long id, const char * attr, const void * value)
271 // Look for id in state map
272 StateMap::iterator pos = dstate.find(id);
273 if (pos == dstate.end())
274 return -1; // No such device
276 // Change either location or nominal temp, depending on attr.
277 if (ACE_OS::strcmp(attr, "location") == 0) {
278 pos->second.location.assign(
279 (const char *)value, MAXSTR - 1
281 } else if (ACE_OS::strcmp(attr, "nominal_temp") == 0) {
282 if (pos->second.type != thermostat)
283 return -1; // Must be thermostat
284 short temp;
285 ACE_OS::memcpy(&temp, value, sizeof(temp));
286 if (temp < MIN_TEMP || temp > MAX_TEMP)
287 return -1;
288 pos->second.nominal_temp = temp;
289 } else {
290 return -1; // No such attribute
292 return 0; // OK