00001
00002 #ifndef INCLUDED_SharedObject_h
00003 #define INCLUDED_SharedObject_h
00004
00005 #include "RCRegion.h"
00006 #include <stdexcept>
00007
00008
00009
00010 class SharedObjectBase {
00011 public:
00012 void* data() const { return rcr->Base(); }
00013 RCRegion * getRegion() const { return rcr; }
00014
00015 virtual ~SharedObjectBase() {}
00016
00017 #ifndef PLATFORM_APERIOS
00018
00019 static unsigned int getNextKey() { return serialNumber+1; }
00020 #endif
00021
00022 protected:
00023
00024 SharedObjectBase() : rcr(NULL) {}
00025
00026 SharedObjectBase(const SharedObjectBase& sob) : rcr(sob.rcr) {
00027 rcr->AddReference();
00028 }
00029
00030 SharedObjectBase& operator=(const SharedObjectBase& sob) {
00031 if(rcr==sob.rcr)
00032 return *this;
00033 removeRef();
00034 rcr=sob.rcr;
00035 rcr->AddReference();
00036 }
00037
00038
00039 virtual void removeRef()=0;
00040
00041 RCRegion * rcr;
00042
00043 #ifndef PLATFORM_APERIOS
00044 static unsigned int serialNumber;
00045 #endif
00046 };
00047
00048
00049
00050
00051 template<class MC>
00052 class SharedObject : public SharedObjectBase {
00053 public:
00054
00055
00056
00057
00058 SharedObject() : SharedObjectBase() {
00059 rcr=createRCRegion();
00060 new (rcr->Base()) MC;
00061 }
00062
00063 template<class T1> explicit SharedObject(const T1& t1) : SharedObjectBase() {
00064 rcr=createRCRegion();
00065 new (rcr->Base()) MC(t1);
00066 }
00067
00068 template<class T1, class T2> SharedObject(const T1& t1, const T2& t2) : SharedObjectBase(){
00069 rcr=createRCRegion();
00070 new (rcr->Base()) MC(t1,t2);
00071 }
00072
00073 template<class T1, class T2, class T3> SharedObject(const T1& t1, const T2& t2, const T3& t3) : SharedObjectBase(){
00074 rcr=createRCRegion();
00075 new (rcr->Base()) MC(t1,t2,t3);
00076 }
00077
00078 template<class T1, class T2, class T3, class T4> SharedObject(const T1& t1, const T2& t2, const T3& t3, const T4& t4) : SharedObjectBase(){
00079 rcr=createRCRegion();
00080 new (rcr->Base()) MC(t1,t2,t3,t4);
00081 }
00082
00083 template<class T1, class T2, class T3, class T4, class T5> SharedObject(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) : SharedObjectBase(){
00084 rcr=createRCRegion();
00085 new (rcr->Base()) MC(t1,t2,t3,t4,t5);
00086 }
00087
00088
00089
00090
00091
00092
00093 explicit SharedObject(RCRegion * r) : SharedObjectBase() {
00094 rcr=r;
00095 if(rcr->Size()!=sizeof(MC)) {
00096 #ifdef PLATFORM_APERIOS
00097 std::cerr << "ERROR: SharedObject(RCRegion* r) region size ("<<rcr->Size()<<") does not match size of SharedObject type ("<<sizeof(MC)<<")" << std::endl;
00098 #else
00099 std::cerr << "ERROR: SharedObject(RCRegion* r) region "<<rcr->ID().key<<" size ("<<rcr->Size()<<") does not match size of SharedObject type ("<<sizeof(MC)<<")" << std::endl;
00100 #endif
00101 throw std::invalid_argument("SharedObject(RCRegion* r): region size does not match sizeof(type)");
00102 }
00103 }
00104
00105
00106
00107 virtual ~SharedObject() { removeRef(); }
00108
00109 MC* operator->() const { return dataCasted(); }
00110 MC& operator*() const { return *dataCasted(); }
00111 MC& operator[](int i) const { return dataCasted()[i]; }
00112
00113 protected:
00114 MC* dataCasted() const { return static_cast<MC*>(data()); }
00115
00116
00117 virtual void removeRef() {
00118 if(rcr) {
00119
00120 if(rcr->NumberOfReference()>0) {
00121 if(rcr->NumberOfReference()==1)
00122 dataCasted()->~MC();
00123 rcr->RemoveReference();
00124 } else
00125 std::cerr << "WARNING: SharedObjectBase destructed without reference" << std::endl;
00126 rcr=NULL;
00127 }
00128 }
00129
00130
00131 static RCRegion * createRCRegion() {
00132 #ifdef PLATFORM_APERIOS
00133 RCRegion * r = new RCRegion(calcsize());
00134 #else
00135 char name[RCRegion::MAX_NAME_LEN];
00136 unsigned int suffixlen=snprintf(name,RCRegion::MAX_NAME_LEN,".%d.%d",ProcessID::getID(),++serialNumber);
00137 if(suffixlen>RCRegion::MAX_NAME_LEN)
00138 suffixlen=RCRegion::MAX_NAME_LEN;
00139 snprintf(name,RCRegion::MAX_NAME_LEN,"Sh.%.*s.%d.%d",RCRegion::MAX_NAME_LEN-suffixlen-3,typeid(MC).name(),ProcessID::getID(),++serialNumber);
00140 name[RCRegion::MAX_NAME_LEN-1]='\0';
00141 RCRegion * r = new RCRegion(name,calcsize());
00142 #endif
00143
00144
00145
00146
00147
00148 return r;
00149 }
00150
00151
00152
00153
00154
00155 static unsigned int calcsize() {
00156 #ifndef PLATFORM_APERIOS
00157 return sizeof(MC);
00158 #else
00159 size_t size = sizeof(MC);
00160 sError error;
00161 size_t page_size;
00162 error = GetPageSize(&page_size);
00163 if (error != sSUCCESS) {
00164 cout << "error: " << error << " getting page size in SharedMem" << endl;
00165 page_size = 4096;
00166 }
00167
00168 int new_size,num_pages;
00169 num_pages = (size+page_size-1)/page_size;
00170 new_size = num_pages*page_size;
00171
00172
00173
00174
00175
00176
00177 return new_size;
00178 #endif
00179 }
00180 };
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 #endif //INCLUDED_SharedObject_h