00001 #ifndef IPC_OBJECT_H
00002 #define IPC_OBJECT_H
00003
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00016 #include <string>
00017 #include <sstream>
00018 #include <iostream>
00019
00020 #include <owl/time.h>
00021 #include <owl/semaphore.h>
00022
00023 #include <ipc/objectadapter.h>
00024 #include <ipc/partition.h>
00025 #include <ipc/servant.h>
00026
00038 template <class T>
00039 class IPCObjectBase : public virtual T,
00040 public virtual PortableServer::RefCountServantBase
00041 {
00042 public:
00043
00044 virtual ~IPCObjectBase ( ) {
00045 ERS_ASSERT_MSG( !active_,
00046 "the IPCObjectBase destructor is called, but the corresponding servant is still active\n" <<
00047 "to fix the problem you have to respect the following rules:\n" <<
00048 " 1. Always allocate your IPC based objects in the heap using the new operator\n" <<
00049 " 2. Always use the _destroy() method instead of the delete operator" )
00050 if ( sem_ ) {
00051 sem_ -> post();
00052 }
00053 }
00054
00063 void _destroy( bool wait_for_completion = false )
00064 {
00065 if ( active_ ) {
00066 adapter_.remove( this );
00067 active_ = false;
00068 }
00069
00070 if ( wait_for_completion ) {
00071 OWLSemaphore * semaphore = sem_;
00072 _remove_ref();
00073 semaphore -> wait();
00074 delete semaphore;
00075 }
00076 else {
00077 delete sem_;
00078 sem_ = 0;
00079 _remove_ref();
00080 }
00081 }
00082
00083 protected:
00084 IPCObjectBase ( bool threaded )
00085 : adapter_( this, threaded ),
00086 active_( false )
00087 { sem_ = new OWLSemaphore(); }
00088
00089 IPCObjectBase ( const IPCObjectBase * s )
00090 : adapter_( s->adapter_ ),
00091 active_( false )
00092 { sem_ = new OWLSemaphore(); }
00093
00094
00095 PortableServer::POA_ptr _default_POA() {
00096 activate();
00097 return adapter_;
00098 }
00099
00100 void activate() {
00101 if ( !active_ ) {
00102 adapter_.add( this, oid() );
00103 active_ = true;
00104 }
00105 }
00106
00107 virtual const std::string & oid() const = 0;
00108
00109 private:
00111
00113 IPCObjectBase ( const IPCObjectBase & );
00114 IPCObjectBase & operator=( const IPCObjectBase & );
00115
00116 IPCObjectAdapter adapter_;
00117 bool active_;
00118 OWLSemaphore * sem_;
00119 };
00120
00125 template <class T>
00126 class IPCObjectOperations : public IPCObjectBase<T>
00127 {
00128 std::string name_;
00129 const std::string & oid() const { return name_; }
00130
00131 protected:
00132 IPCObjectOperations( bool threaded )
00133 : IPCObjectBase<T>( threaded ) {
00134 std::ostringstream out;
00135 out << this;
00136 name_ = out.str();
00137 }
00138
00139 IPCObjectOperations( const IPCObjectOperations * op )
00140 : IPCObjectBase<T>( op ) {
00141 std::ostringstream out;
00142 out << this;
00143 name_ = out.str();
00144 }
00145 };
00146
00171 template <class T, class TP = ipc::multi_thread>
00172 class IPCObject : public IPCObjectOperations<T>
00173 {
00174 public:
00175
00176 virtual ~IPCObject ( ) { ; }
00177
00178 protected:
00179 IPCObject ( ) : IPCObjectOperations<T>( TP::threaded() )
00180 { ; }
00181
00182 private:
00184
00186 IPCObject ( const IPCObject & );
00187 IPCObject & operator=( const IPCObject & );
00188 };
00189
00190
00198 template <class T>
00199 class IPCObject<T,ipc::single_thread> : public IPCObjectOperations<T>
00200 {
00201 public:
00202
00203 virtual ~IPCObject ( ) { ; }
00204
00205 protected:
00206
00209 IPCObject ( )
00210 : IPCObjectOperations<T>( ipc::single_thread::threaded() )
00211 { ; }
00212
00219 IPCObject ( const IPCObject * object )
00220 : IPCObjectOperations<T>( object )
00221 { ; }
00222
00223 private:
00225
00227 IPCObject ( const IPCObject & );
00228 IPCObject & operator=( const IPCObject & );
00229 };
00230
00235 template <class T>
00236 class IPCNamedObjectOperations : public IPCObjectBase<T>,
00237 public virtual IPCServant
00238 {
00239 const std::string & oid() const { return name_; }
00240
00241 IPCPartition partition_;
00242 std::string name_;
00243
00244 protected:
00245 IPCNamedObjectOperations ( const IPCPartition & partition,
00246 const std::string & name,
00247 bool threaded )
00248 : IPCObjectBase<T>( threaded ),
00249 partition_( partition ),
00250 name_( name )
00251 { ; }
00252
00253 IPCNamedObjectOperations ( const IPCPartition & partition,
00254 const std::string & name,
00255 const IPCNamedObjectOperations * op )
00256 : IPCObjectBase<T>( op ),
00257 partition_( partition ),
00258 name_( name )
00259 { ; }
00260
00261 public:
00266 const std::string & name ( ) const { return name_; }
00267
00271 const IPCPartition & partition ( ) const { return partition_; }
00272
00278 void publish ( ) throw ( daq::ipc::InvalidPartition, daq::ipc::InvalidObjectName ) {
00279 ipc::servant_var ref = _this();
00280 partition().publish( name(), ipc::util::getTypeName( this ), ref );
00281 }
00282
00289 void withdraw ( ) throw ( daq::ipc::InvalidPartition, daq::ipc::ObjectNotFound, daq::ipc::InvalidObjectName ) {
00290 partition().withdraw( name(), ipc::util::getTypeName( this ) );
00291 }
00292 };
00293
00317 template <class T, class TP = ipc::multi_thread>
00318 class IPCNamedObject : public IPCNamedObjectOperations<T>
00319 {
00320 public:
00321
00322 virtual ~IPCNamedObject ( ) { ; }
00323 protected:
00324
00330 IPCNamedObject ( const std::string & name )
00331 : IPCNamedObjectOperations<T>( IPCPartition(), name, TP::threaded() )
00332 { ; }
00333
00340 IPCNamedObject ( const IPCPartition & partition,
00341 const std::string & name )
00342 : IPCNamedObjectOperations<T>( partition, name, TP::threaded() )
00343 { ; }
00344
00345 private:
00347
00349 IPCNamedObject ( const IPCNamedObject & );
00350 IPCNamedObject & operator= ( const IPCNamedObject & );
00351 };
00352
00360 template <class T>
00361 class IPCNamedObject<T,ipc::single_thread> : public IPCNamedObjectOperations<T>
00362 {
00363 public:
00364
00365 virtual ~IPCNamedObject ( ) { ; }
00366
00367 protected:
00368
00372 IPCNamedObject ( const std::string & name )
00373 : IPCNamedObjectOperations<T>( IPCPartition(), name, ipc::single_thread::threaded() )
00374 { ; }
00375
00380 IPCNamedObject ( const IPCPartition & partition,
00381 const std::string & name )
00382 : IPCNamedObjectOperations<T>( partition, name, ipc::single_thread::threaded() )
00383 { ; }
00384
00392 IPCNamedObject ( const std::string & name,
00393 const IPCNamedObject * object )
00394 : IPCNamedObjectOperations<T>( IPCPartition(), name, object )
00395 { ; }
00396
00404 IPCNamedObject ( const IPCPartition & partition,
00405 const std::string & name,
00406 const IPCNamedObject * object )
00407 : IPCNamedObjectOperations<T>( partition, name, object )
00408 { ; }
00409
00410 private:
00412
00414 IPCNamedObject ( const IPCNamedObject & );
00415 IPCNamedObject & operator= ( const IPCNamedObject & );
00416 };
00417
00418 #endif // IPC_OBJECT_H