/** * Copyright - See the COPYRIGHT that is included with this distribution. * pvAccessCPP is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. */ #include #include #include #include #include #if !defined(_WIN32) #include #define USE_SIGNAL #endif #include #include #include #include #include #include #include namespace pvd = epics::pvData; namespace pva = epics::pvAccess; namespace { typedef epicsGuard Guard; epicsEvent done; bool debug; #ifdef USE_SIGNAL void alldone(int num) { (void)num; done.signal(); } #endif pvd::Structure::const_shared_pointer spamtype(pvd::getFieldCreate()->createFieldBuilder() ->setId("epics:nt/NTScalar:1.0") ->add("value", pvd::pvInt) ->createStructure()); struct SpamProvider; struct SpamChannel; struct SpamSource : public pva::MonitorFIFO::Source { epicsMutex mutex; epicsUInt32 counter; const pvd::PVStructurePtr cur; const pvd::PVIntPtr val; pvd::BitSet changed; SpamSource() :counter(0) ,cur(pvd::getPVDataCreate()->createPVStructure(spamtype)) ,val(cur->getSubFieldT("value")) { changed.set(val->getFieldOffset()); // our value always changes } virtual ~SpamSource() {} virtual void freeHighMark(pva::MonitorFIFO *mon, size_t numEmpty) OVERRIDE FINAL { Guard G(mutex); for(;numEmpty; numEmpty--) { val->put(counter); if(!mon->tryPost(*cur, changed) && numEmpty!=1) { std::cerr<<"spam tryPost() inconsistent "< { const std::tr1::shared_ptr provider; const std::string name; const pva::ChannelRequester::weak_pointer requester; SpamChannel(const std::tr1::shared_ptr& provider, const std::string& name, const pva::ChannelRequester::shared_pointer& requester) :provider(provider) ,name(name) ,requester(requester) {} virtual ~SpamChannel() {} virtual std::string getChannelName() OVERRIDE FINAL {return name;} virtual std::string getRemoteAddress() OVERRIDE FINAL {return "";} virtual ConnectionState getConnectionState() OVERRIDE FINAL {return CONNECTED;} virtual pva::ChannelRequester::shared_pointer getChannelRequester() OVERRIDE FINAL { return pva::ChannelRequester::shared_pointer(requester); } virtual void destroy() OVERRIDE FINAL {} virtual std::tr1::shared_ptr getProvider() OVERRIDE FINAL {return provider;} virtual pva::AccessRights getAccessRights(pvd::PVField::shared_pointer const & pvField) OVERRIDE FINAL { return pva::readWrite; } virtual void getField(pva::GetFieldRequester::shared_pointer const & requester,std::string const & subField) OVERRIDE FINAL { requester->getDone(pvd::Status::Ok, spamtype); } virtual pva::Monitor::shared_pointer createMonitor(const pva::MonitorRequester::shared_pointer &requester, const pvd::PVStructure::shared_pointer &pvRequest) OVERRIDE FINAL { std::tr1::shared_ptr us(new SpamSource); std::tr1::shared_ptr ret(new pva::MonitorFIFO(requester, pvRequest, us)); // ret holds strong ref. to us ret->open(spamtype); ret->notify(); return ret; } }; struct SpamProvider : public pva::ChannelProvider, public pva::ChannelFind, public std::tr1::enable_shared_from_this { const std::string channelName; SpamProvider(const std::string& name) :channelName(name) {} virtual ~SpamProvider() {} virtual std::string getProviderName() OVERRIDE FINAL {return "SpamProvider";} virtual void destroy() OVERRIDE FINAL {} virtual pva::ChannelFind::shared_pointer channelFind(std::string const & name, pva::ChannelFindRequester::shared_pointer const & requester) OVERRIDE FINAL { std::cerr<<"XXX '"<=this->channelName.size() && strncmp(name.c_str(), this->channelName.c_str(), this->channelName.size())==0) { ret = shared_from_this(); } std::cout<<__FUNCTION__<<" "<channelFindResult(pvd::Status::Ok, ret, !!ret); return ret; } virtual std::tr1::shared_ptr getChannelProvider() OVERRIDE FINAL { return shared_from_this(); } virtual void cancel() OVERRIDE FINAL {} virtual pva::Channel::shared_pointer createChannel(std::string const & name, pva::ChannelRequester::shared_pointer const & requester, short priority, std::string const & address) OVERRIDE FINAL { std::tr1::shared_ptr ret; if(name.size()>=this->channelName.size() && strncmp(name.c_str(), this->channelName.c_str(), this->channelName.size())==0) { ret.reset(new SpamChannel(shared_from_this(), channelName, requester)); } std::cout<<__FUNCTION__<<" "<channelCreated(ret ? pvd::Status::Ok : pvd::Status::error(""), ret); return ret; } }; } // namespace int main(int argc, char *argv[]) { try { for(int i=1; i provider(new SpamProvider("spam")); pva::ServerContext::shared_pointer server(pva::ServerContext::create(pva::ServerContext::Config() .provider(provider) .config(pva::ConfigurationBuilder() .push_env() .build()))); std::cout<<"Server use_count="<printInfo(); std::cout<<"Waiting\n"; done.wait(); std::cout<<"Done\n"; std::cout<<"Server use_count="<