
This example illustrates how to use different types of subscriptions in GizmoDistribution clients. A subscriber client start by subscribing for sessions and a publisher client perform actions. When a new session is created, the subscriber will join and subscribe for new events and objects. When a new object is added, the subscriber will subscribe for new attributes. When new attributes are added, the subscriber will subscribe for value updates, etc.
The source code can also be found in the examples directory of the GizmoDistribution installation.
.
00001 //***************************************************************************** 00002 // File : subscriptions.cpp 00003 // Module : subscriptions 00004 // Description : subscriptions (example application) 00005 // Author : Anders Sandblad 00006 // Product : GizmoDistribution 00007 // 00008 // Copyright © 2004- Saab Training Systems AB, Sweden 00009 // 00010 // NOTE: GizmoDistribution is a toolkit used for implementing distributed 00011 // objects and events in C++ 00012 // 00013 // 00014 // Revision History... 00015 // 00016 // Who Date Description 00017 // 00018 // XAA 040419 Created file 00019 // 00020 //***************************************************************************** 00021 00022 // Includes 00023 #include <stdio.h> 00024 #include "gzBaseLibrary.h" 00025 #include "gzDistLibrary.h" 00026 00027 // Session name 00028 static const gzString A_SESSION = "A"; 00029 static const gzString B_SESSION = "B"; 00030 static const gzString C_SESSION = "C"; 00031 00032 00033 //----------------------------- Publisher ------------------------------- 00034 00035 // A client that publish events, objects and attribute updates 00036 class Publisher : public gzDistClientInterface 00037 { 00038 public: 00039 00040 explicit Publisher(const gzString& sessionName); 00041 00042 virtual ~Publisher(); 00043 00044 00045 private: 00046 00047 // thread ticker callback 00048 00049 gzVoid onClientTick(); 00050 00051 00052 // notification callbacks 00053 00054 gzVoid onNewObject(gzDistObject* object, gzDistSession* session); 00055 00056 gzVoid onRemoveObject(gzDistObject* object, gzDistSession* session); 00057 00058 gzVoid onSystemShutdown(); 00059 00060 00061 private: 00062 00063 // members 00064 00065 gzULong m_tickCount; 00066 00067 gzBool m_add; 00068 00069 gzString m_sessionName; 00070 00071 gzDistSessionPtr m_session; 00072 00073 gzRefList<gzDistObject> m_objects; 00074 00075 }; 00076 00077 00078 Publisher::Publisher(const gzString& sessionName) 00079 : gzDistClientInterface(sessionName + gzString("_publisher")), 00080 m_tickCount(0), 00081 m_add(FALSE), 00082 m_sessionName(sessionName) 00083 { 00084 // initialize client 00085 initialize(2); 00086 00087 // create session 00088 m_session = getSession(sessionName, TRUE); 00089 joinSession(m_session); 00090 subscribeObjects(gzDistObject::getClassType(), m_session); 00091 00092 } 00093 00094 00095 Publisher::~Publisher() 00096 { 00097 // uninitialize client 00098 uninitialize(); 00099 } 00100 00101 00102 gzVoid Publisher::onClientTick() 00103 { 00104 if (!m_session) 00105 { 00106 return; 00107 } 00108 00109 if (m_tickCount%5 == 0) 00110 { 00111 // add / remove objects 00112 00113 if (m_add) 00114 { 00115 // first add 4 objects... 00116 00117 if (m_objects.entries() < 5) 00118 { 00119 gzDistObjectPtr object = new gzDistObject(m_sessionName + gzString(m_objects.entries())); 00120 object->setAttributeValue(gzString(m_tickCount%5), gzString(m_tickCount)); 00121 addObject(object, m_session); 00122 } 00123 else 00124 { 00125 m_add = FALSE; 00126 } 00127 } 00128 else 00129 { 00130 // and then remove them 00131 00132 if (m_objects.entries()) 00133 { 00134 gzDistObjectPtr object = m_objects.first(); 00135 removeObject(object); 00136 } 00137 else 00138 { 00139 m_add = TRUE; 00140 } 00141 } 00142 } 00143 else 00144 { 00145 // add / update attributes of the current objects 00146 00147 gzListIterator<gzDistObject> iter(m_objects); 00148 00149 gzDistObject* object; 00150 00151 while (object = iter()) 00152 { 00153 updateObject(gzString(m_tickCount%5), gzString(m_tickCount), object); 00154 } 00155 } 00156 00157 00158 // send an event 00159 gzDistEventPtr event = new gzDistEvent; 00160 sendEvent(event, m_session); 00161 00162 00163 // increment tick counter 00164 ++m_tickCount; 00165 00166 } 00167 00168 00169 gzVoid Publisher::onNewObject(gzDistObject* object, gzDistSession* session) 00170 { 00171 m_objects.insert(object); 00172 } 00173 00174 00175 gzVoid Publisher::onRemoveObject(gzDistObject* object, gzDistSession* session) 00176 { 00177 m_objects.remove(object); 00178 } 00179 00180 00181 gzVoid Publisher::onSystemShutdown() 00182 { 00183 // GizmoDistribution is shutting down 00184 // free all references to enable the library to be unloaded properly 00185 // it is recommended to always implement this callback 00186 m_session = NULL; 00187 m_objects.clear(); 00188 } 00189 00190 00191 //------------------------------- Subscriber ---------------------------------- 00192 00193 // A client that subscribe for events, objects and attributes 00194 class Subscriber : public gzDistClientInterface 00195 { 00196 public: 00197 00198 Subscriber(const gzString& sessionName); 00199 00200 virtual ~Subscriber(); 00201 00202 00203 private: 00204 00205 // notification callbacks 00206 00207 gzVoid onNewSession(gzDistSession* session); 00208 00209 gzVoid onRemoveSession(gzDistSession* session); 00210 00211 gzVoid onEvent(gzDistEvent* event); 00212 00213 gzVoid onNewObject(gzDistObject* object, gzDistSession* session); 00214 00215 gzVoid onRemoveObject(gzDistObject* object, gzDistSession* session); 00216 00217 gzVoid onNewAttributes(const gzDistNotificationSet& attributes, gzDistObject* object, gzDistSession* session); 00218 00219 gzVoid onRemoveAttributes(const gzDistNotificationSet& attributes, gzDistObject* object, gzDistSession* session); 00220 00221 gzVoid onUpdateAttributes(const gzDistNotificationSet& attributes, gzDistObject* object, gzDistSession* session); 00222 00223 gzVoid onSystemShutdown(); 00224 00225 00226 private: 00227 00228 // members 00229 00230 gzString m_sessionName; 00231 00232 gzDistSessionPtr m_session; 00233 00234 }; 00235 00236 00237 Subscriber::Subscriber(const gzString& sessionName) 00238 : gzDistClientInterface(sessionName + gzString("_subscriber")), 00239 m_sessionName(sessionName) 00240 { 00241 // initialize client 00242 initialize(); 00243 00244 // subscribe for sessions 00245 // notifications will be received in onNewSession() and onRemoveSession() 00246 // callbacks when sessions are created or removed from this process 00247 subscribeSessions(); 00248 00249 } 00250 00251 00252 Subscriber::~Subscriber() 00253 { 00254 // uninitialize client 00255 uninitialize(); 00256 } 00257 00258 00259 gzVoid Subscriber::onNewSession(gzDistSession* session) 00260 { 00261 GZMESSAGE(GZ_MESSAGE_NOTICE, "New session '%s'", (const char*)session->getName()); 00262 00263 00264 if (session->getName() == m_sessionName) 00265 { 00266 // join the new session 00267 joinSession(session); 00268 00269 // subscribe for objects on the session 00270 // notifications will be received in onNewObject() and onRemoveObject() 00271 // callbacks when objects are created or removed from this session 00272 subscribeObjects(gzDistObject::getClassType(), session); 00273 00274 // subscribe for events on the session 00275 // notifications will be received in the onEvent() callback 00276 // when events are sent on this session 00277 subscribeEvents(gzDistEvent::getClassType(), session); 00278 00279 m_session = session; 00280 00281 } 00282 } 00283 00284 00285 gzVoid Subscriber::onRemoveSession(gzDistSession* session) 00286 { 00287 // a session was removed from this process 00288 // this will happen when a session no longer has 00289 // any local clients joined to it 00290 00291 GZMESSAGE(GZ_MESSAGE_NOTICE, "Removed session '%s'", (const char*)session->getName()); 00292 } 00293 00294 00295 gzVoid Subscriber::onEvent(gzDistEvent* event) 00296 { 00297 // an event was received 00298 00299 GZMESSAGE(GZ_MESSAGE_NOTICE, "Event received on sessions '%s'", 00300 (const char*)event->getSession()->getName()); 00301 } 00302 00303 00304 gzVoid Subscriber::onNewObject(gzDistObject* object, gzDistSession* session) 00305 { 00306 // an object has been added 00307 00308 GZMESSAGE(GZ_MESSAGE_NOTICE, "New object '%s' on session '%s'", 00309 (const char*)object->getName(), (const char*)object->getSession()->getName()); 00310 00311 // subscribe for attributes on the new object 00312 // notifications will be received in the onNewAttributes() and onRemoveAttributes() 00313 // callbacks when attributes are created or removed from this object 00314 subscribeAttributes(object); 00315 } 00316 00317 00318 gzVoid Subscriber::onRemoveObject(gzDistObject* object, gzDistSession* session) 00319 { 00320 // an object was removed 00321 // all subscriptions associated with the object are automatically removed 00322 00323 GZMESSAGE(GZ_MESSAGE_NOTICE, "Removed object '%s' from session '%s'", 00324 (const char*)object->getName(), (const char*)session->getName()); 00325 } 00326 00327 00328 gzVoid Subscriber::onNewAttributes(const gzDistNotificationSet& attributes, gzDistObject* object, gzDistSession* session) 00329 { 00330 // attributes were added to an object 00331 00332 GZMESSAGE(GZ_MESSAGE_NOTICE, "%u new attributes on object '%s' on session '%s'", 00333 attributes.entries(), (const char*)object->getName(), (const char*)object->getSession()->getName()); 00334 00335 00336 gzDistNotificationSetIterator iter(attributes); 00337 00338 gzDistNotificationData* data; 00339 00340 while (data = iter()) 00341 { 00342 // subscribe for updates of the attribute value 00343 // notifications will be received in the onUpdateAttributes() callback 00344 subscribeAttributeValue(data->getAttributeName(), object); 00345 } 00346 00347 } 00348 00349 00350 gzVoid Subscriber::onRemoveAttributes(const gzDistNotificationSet& attributes, gzDistObject* object, gzDistSession* session) 00351 { 00352 // attributes were removed form an object 00353 00354 GZMESSAGE(GZ_MESSAGE_NOTICE, "%u removed attributes from object '%s' on session '%s'", 00355 attributes.entries(), (const char*)object->getName(), (const char*)object->getSession()->getName()); 00356 } 00357 00358 00359 gzVoid Subscriber::onUpdateAttributes(const gzDistNotificationSet& attributes, gzDistObject* object, gzDistSession* session) 00360 { 00361 // attribute values were updated 00362 00363 GZMESSAGE(GZ_MESSAGE_NOTICE, "%u attributes updated on object '%s' on session '%s'", 00364 attributes.entries(), (const char*)object->getName(), (const char*)object->getSession()->getName()); 00365 } 00366 00367 00368 gzVoid Subscriber::onSystemShutdown() 00369 { 00370 // GizmoDistribution is shutting down 00371 // free all references to enable the library to be unloaded properly 00372 // it is recommended to always implement this callback 00373 m_session = NULL; 00374 } 00375 00376 00377 //--------------------------------- main -------------------------------------- 00378 00379 // Application entry point 00380 int main(int argc, char* argv[]) 00381 { 00382 // setup default message receiver 00383 gzMessage::setMessageLevel(GZ_MESSAGE_NOTICE); 00384 00385 // create manager and start 00386 gzDistManagerPtr manager = gzDistManager::getManager(TRUE); 00387 manager->start(); 00388 00389 GZMESSAGE(GZ_MESSAGE_NOTICE, "Hit return to quit!\n"); 00390 00391 // create publisher and subscriber 00392 Subscriber* subscriberA = new Subscriber(A_SESSION); 00393 gzSleep(GZ_SLEEP_SECOND); 00394 Publisher* publisherA = new Publisher(A_SESSION); 00395 00396 00397 // wait for return 00398 getchar(); 00399 00400 00401 // delete publisher and subscriber 00402 delete publisherA; 00403 gzSleep(GZ_SLEEP_SECOND); 00404 delete subscriberA; 00405 00406 00407 // shut down and release manager 00408 manager->shutDown(); 00409 manager = NULL; 00410 00411 gzSleep(GZ_SLEEP_SECOND); 00412 00413 return 0; 00414 00415 } 00416