Go to the documentation of this file.00001 #ifndef __SHM_OBJECT_HPP__
00002 #define __SHM_OBJECT_HPP__
00003
00004 #include <boost/interprocess/managed_shared_memory.hpp>
00005 #include <boost/atomic/atomic.hpp>
00006
00007 namespace shm_transport
00008 {
00009
00010
00011 typedef boost::atomic< uint32_t > atomic_uint32_t;
00012 typedef boost::interprocess::managed_shared_memory mng_shm;
00013 typedef boost::shared_ptr< boost::interprocess::managed_shared_memory > mng_shm_ptr;
00014 typedef boost::interprocess::interprocess_mutex ipc_mutex;
00015
00016 class MsgListHead
00017 {
00018 public:
00019 MsgListHead() : next(0), prev(0) { }
00020 ~MsgListHead() { }
00021
00022 void addLast(MsgListHead * lc, const mng_shm_ptr & pshm) {
00023 long hc = pshm->get_handle_from_address(lc);
00024 long hn = pshm->get_handle_from_address(this), hp = this->prev;
00025 MsgListHead * ln = this, * lp = (MsgListHead *)pshm->get_address_from_handle(hp);
00026 lc->next = hn;
00027 lc->prev = hp;
00028 lp->next = hc;
00029 ln->prev = hc;
00030 }
00031
00032 void remove(MsgListHead * lc, const mng_shm_ptr & pshm) {
00033 long hc = pshm->get_handle_from_address(lc);
00034 long hn = lc->next, hp = lc->prev;
00035 MsgListHead * ln = (MsgListHead *)pshm->get_address_from_handle(hn);
00036 MsgListHead * lp = (MsgListHead *)pshm->get_address_from_handle(hp);
00037 lp->next = hn;
00038 ln->prev = hp;
00039 }
00040
00041 void releaseFirst(const mng_shm_ptr & pshm) {
00042 long hc = next;
00043 MsgListHead * lc = (MsgListHead *)pshm->get_address_from_handle(hc);
00044 if (lc == this)
00045 return;
00046 long hn = lc->next, hp = lc->prev;
00047 MsgListHead * ln = (MsgListHead *)pshm->get_address_from_handle(hn), * lp = this;
00048 lp->next = hn;
00049 ln->prev = hp;
00050 pshm->deallocate(lc);
00051 }
00052
00053 long getFirstHandle() {
00054 return next;
00055 }
00056
00057 public:
00058 long next;
00059 long prev;
00060 };
00061
00062 class ShmObject
00063 {
00064 public:
00065 ShmObject(mng_shm * pshm, std::string name)
00066 : pshm_(pshm), name_(name) {
00067 pref_ = pshm_->find_or_construct< atomic_uint32_t >("ref")(0);
00068 plck_ = pshm_->find_or_construct< ipc_mutex >("lck")();
00069 pmsg_ = pshm_->find_or_construct< MsgListHead >("lst")();
00070
00071 pref_->fetch_add(1, boost::memory_order_relaxed);
00072 if (pmsg_->next == 0) {
00073 long handle = pshm_->get_handle_from_address(pmsg_);
00074 pmsg_->next = handle;
00075 pmsg_->prev = handle;
00076 }
00077 }
00078
00079 ~ShmObject() {
00080 if (pref_->fetch_sub(1, boost::memory_order_relaxed) == 1) {
00081 boost::interprocess::shared_memory_object::remove(name_.c_str());
00082
00083 }
00084 }
00085
00086 public:
00087
00088 mng_shm_ptr pshm_;
00089
00090 std::string name_;
00091
00092 atomic_uint32_t * pref_;
00093
00094 ipc_mutex * plck_;
00095
00096 MsgListHead * pmsg_;
00097 };
00098 typedef boost::shared_ptr< ShmObject > ShmObjectPtr;
00099
00100
00101 class ShmMessage
00102 {
00103 public:
00104
00105 void construct(const ShmObjectPtr & so) {
00106
00107 so->pmsg_->addLast(&lst, so->pshm_);
00108
00109 ref = 0;
00110 }
00111
00112
00113
00114 void take() {
00115 ref.fetch_add(1, boost::memory_order_relaxed);
00116 }
00117
00118 void release() {
00119
00120
00121 ref.fetch_sub(1, boost::memory_order_relaxed);
00122 }
00123
00124 public:
00125 MsgListHead lst;
00126 atomic_uint32_t ref;
00127 uint32_t len;
00128 uint8_t data[0];
00129 };
00130
00131 }
00132
00133 #endif // __SHM_PUBLISHER_HPP__
00134