00001 #ifndef __INSTANTIO_INSLOT_H
00002 #define __INSTANTIO_INSLOT_H
00003
00004 #ifdef _MSC_VER
00005 # pragma once
00006 #endif
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "InstantIODef.h"
00027 #include "BasicInSlot.h"
00028 #include "OutSlot.h"
00029 #include "Data.h"
00030 #include "TypeName.h"
00031 #include "InterruptedException.h"
00032 #include <string>
00033 #include <vector>
00034 #include <typeinfo>
00035 #ifdef __sgi
00036 # include <assert.h>
00037 #else
00038 # include <cassert>
00039 #endif
00040
00041
00042 namespace InstantIO
00043 {
00044
00045
00046 template <class T> class OutSlot;
00047
00048
00146 template <class T> class InSlot: public BasicInSlot
00147 {
00148
00150 friend class OutSlot<T>;
00151
00152 public:
00153
00161 inline explicit InSlot(const std::string &description = std::string())
00162 : BasicInSlot(description), outSlots_(), currentValue_(), empty_(true)
00163 {}
00164
00168 virtual ~InSlot() {};
00169
00179 virtual const char *getTypeName() const
00180 { return TypeName<T>::getName(); };
00181
00187 virtual const std::type_info &getTypeID() const
00188 { return typeid(T); };
00189
00202 inline bool isConnected() const
00203 {
00204 lock();
00205 bool result = outSlots_.empty() == false;
00206 unlock();
00207 return result;
00208 }
00209
00218 virtual bool empty() const
00219 {
00220 lock();
00221 bool result = empty_;
00222 unlock();
00223 return result;
00224 };
00225
00237 virtual const Data<T> top()
00238
00239 {
00240 lock();
00241 if (interrupted_ == true)
00242 {
00243 interrupted_ = false;
00244 unlock();
00245 throw InterruptedException();
00246 }
00247 Data<T> value = currentValue_;
00248 unlock();
00249 return value;
00250 };
00251
00270 virtual const Data<T> pop()
00271
00272 {
00273 down();
00274 lock();
00275 if (interrupted_ == true)
00276 {
00277 interrupted_ = false;
00278 unlock();
00279 throw InterruptedException();
00280 }
00281 empty_ = true;
00282 Data<T> value = currentValue_;
00283 unlock();
00284 return value;
00285 };
00286
00297 virtual void push(const Data<T> &data)
00298 {
00299 lock();
00300 if (empty_ == true)
00301 {
00302 empty_ = false;
00303 up();
00304 }
00305 currentValue_ = data;
00306 unlock();
00307 newData();
00308 };
00309
00328 virtual void connect(BasicOutSlot *outSlot)
00329 {
00330 OutSlot<T> *os = dynamic_cast<OutSlot<T>*>(outSlot);
00331 if (os != 0)
00332 {
00333
00334
00335
00336 addOutSlot(os);
00337 os->addInSlot(this);
00338 }
00339 };
00340
00356 virtual void disconnect(BasicOutSlot *outSlot)
00357 {
00358 OutSlot<T> *os = dynamic_cast<OutSlot<T>*>(outSlot);
00359 if (os != 0)
00360 {
00361
00362
00363
00364 os->removeInSlot(this);
00365 removeOutSlot(os);
00366 }
00367 };
00368
00369 private:
00370
00372 typedef std::pair<OutSlot<T>*, unsigned long> RefCountedOutSlot;
00373
00375 typedef std::vector<RefCountedOutSlot> OutSlotVector;
00376
00382 void addOutSlot(OutSlot<T> *outSlot)
00383 {
00384 assert(outSlot != 0);
00385 bool empty = false;
00386
00387
00388
00389
00390
00391
00392 listenersLock();
00393 lock();
00394 typename OutSlotVector::iterator it = findOutSlot(outSlot);
00395 if (it == outSlots_.end())
00396 {
00397 empty = outSlots_.empty();
00398 outSlots_.push_back(RefCountedOutSlot(outSlot, 1));
00399 }
00400 else
00401 ++(it->second);
00402 unlock();
00403 if (empty == true)
00404 startInSlot();
00405 listenersUnlock();
00406 };
00407
00413 void removeOutSlot(OutSlot<T> *outSlot)
00414 {
00415 assert(outSlot != 0);
00416
00417
00418
00419
00420
00421
00422 listenersLock();
00423 lock();
00424 typename OutSlotVector::iterator it = findOutSlot(outSlot);
00425 if ((it != outSlots_.end()) && (--(it->second) == 0))
00426 outSlots_.erase(it);
00427 unlock();
00428 if (outSlots_.empty())
00429 stopInSlot();
00430 listenersUnlock();
00431 };
00432
00439 typename OutSlotVector::iterator findOutSlot(OutSlot<T> *outSlot)
00440 {
00441
00442 assert(outSlot != 0);
00443 typename OutSlotVector::iterator it;
00444 for (it = outSlots_.begin(); it != outSlots_.end(); ++it)
00445 if (it->first == outSlot)
00446 break;
00447 return it;
00448 };
00449
00451
00452 OutSlotVector outSlots_;
00453
00455
00456 Data<T> currentValue_;
00457
00459
00460 bool empty_;
00461
00463 InSlot(const InSlot<T> &);
00464
00466 const InSlot<T> &operator=(const InSlot<T> &);
00467 };
00468
00469
00470 }
00471
00472
00473 #endif //__INSTANTIO_INSLOT_H