Go to the documentation of this file.00001 #include <canopen_master/master.h>
00002 #include <boost/interprocess/allocators/allocator.hpp>
00003 #include <boost/interprocess/containers/list.hpp>
00004
00005 namespace can{
00006 std::size_t hash_value(can::Header const& h){ return (unsigned int)(h);}
00007 }
00008
00009 using namespace canopen;
00010
00011 void IPCSyncMaster::run() {
00012 boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock = sync_obj_->waiter.get_lock();
00013 boost::posix_time::ptime abs_time = boost::get_system_time();
00014
00015 can::Frame frame(sync_obj_->properties.header_, sync_obj_->properties.overflow_ ? 1 : 0);
00016 while(true){
00017 abs_time += boost::posix_time::milliseconds(sync_obj_->properties.period_ms_);
00018 if(abs_time >= boost::get_system_time()){
00019 if(!sync_obj_->waiter.sync(abs_time)) LOG("Slave timeout");
00020
00021 if(sync_obj_->nextSync(frame.data[0])){
00022 interface_->send(frame);
00023 }
00024
00025 boost::this_thread::sleep(abs_time);
00026 }
00027
00028 }
00029 }
00030
00031
00032 void IPCSyncLayer::handleInit(LayerStatus &status) {
00033 boost::mutex::scoped_lock lock(mutex_);
00034 if(!nodes_.empty()){
00035 status.warn("Nodes list was not empty");
00036 nodes_.clear();
00037 }
00038 sync_master_->start(status);
00039 }
00040
00041
00042
00043 boost::shared_ptr<SyncLayer> LocalMaster::getSync(const SyncProperties &p){
00044 boost::mutex::scoped_lock lock(mutex_);
00045 boost::unordered_map<can::Header, boost::shared_ptr<LocalIPCSyncMaster> >::iterator it = syncmasters_.find(p.header_);
00046 if(it == syncmasters_.end()){
00047 std::pair<boost::unordered_map<can::Header, boost::shared_ptr<LocalIPCSyncMaster> >::iterator, bool>
00048 res = syncmasters_.insert(std::make_pair(p.header_, boost::make_shared<LocalIPCSyncMaster>(p,interface_)));
00049 it = res.first;
00050 }else if(!it->second->matches(p)) return boost::shared_ptr<SyncLayer>();
00051 return boost::make_shared<IPCSyncLayer>(p, interface_, it->second);
00052 }
00053
00054 boost::shared_ptr<SyncLayer> SharedMaster::getSync(const SyncProperties &p){
00055 boost::mutex::scoped_lock lock(mutex_);
00056 boost::unordered_map<can::Header, boost::shared_ptr<SharedIPCSyncMaster> >::iterator it = syncmasters_.find(p.header_);
00057 if(it == syncmasters_.end()){
00058 std::pair<boost::unordered_map<can::Header, boost::shared_ptr<SharedIPCSyncMaster> >::iterator, bool>
00059 res = syncmasters_.insert(std::make_pair(p.header_, boost::make_shared<SharedIPCSyncMaster>(boost::ref(managed_shm_), p,interface_)));
00060 it = res.first;
00061 }else if(!it->second->matches(p)) return boost::shared_ptr<SyncLayer>();
00062 return boost::make_shared<IPCSyncLayer>(p, interface_, it->second);
00063 }
00064 IPCSyncMaster::SyncObject * SharedIPCSyncMaster::getSyncObject(LayerStatus &status){
00065 typedef boost::interprocess::allocator<SyncObject, boost::interprocess::managed_shared_memory::segment_manager> SyncAllocator;
00066 typedef boost::interprocess::list<SyncObject, SyncAllocator> SyncList;
00067
00068 boost::interprocess::interprocess_mutex *list_mutex = managed_shm_.find_or_construct<boost::interprocess::interprocess_mutex>("SyncListMutex")();
00069
00070 if(!list_mutex){
00071 status.error("Could not find/construct SyncListMutex");
00072 return 0;
00073 }
00074
00075 SyncList *synclist = managed_shm_.find_or_construct<SyncList>("SyncList")(managed_shm_.get_allocator<SyncAllocator>());
00076
00077 if(!synclist){
00078 status.error("Could not find/construct SyncList");
00079 return 0;
00080 }
00081
00082
00083 SyncObject * sync_obj = 0;
00084
00085 boost::posix_time::ptime abs_time = boost::get_system_time() + boost::posix_time::seconds(1);
00086
00087 boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(*list_mutex, abs_time);
00088 if(!lock){
00089 status.error("Could not lock master mutex");
00090 return 0;
00091 }
00092
00093 for(SyncList::iterator it = synclist->begin(); it != synclist->end(); ++it){
00094 if( it->properties.header_ == properties_.header_){
00095
00096 if(it->properties.overflow_ != properties_.overflow_ || it->properties.period_ms_ != properties_.period_ms_){
00097 status.error("sync properties mismatch");
00098 return 0;
00099 }
00100
00101 sync_obj = &(*it);
00102 break;
00103 }
00104 }
00105 if(!sync_obj) {
00106 synclist->emplace_back(properties_);
00107 sync_obj = &synclist->back();
00108 }
00109 return sync_obj;
00110 }