Orocos Real-Time Toolkit  2.9.0
Service.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: The SourceWorks Tue Sep 7 00:55:18 CEST 2010 Service.cpp
3 
4  Service.cpp - description
5  -------------------
6  begin : Tue September 07 2010
7  copyright : (C) 2010 The SourceWorks
8  email : peter@thesourceworks.com
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU General Public *
13  * License as published by the Free Software Foundation; *
14  * version 2 of the License. *
15  * *
16  * As a special exception, you may use this file as part of a free *
17  * software library without restriction. Specifically, if other files *
18  * instantiate templates or use macros or inline functions from this *
19  * file, or you compile this file and link it with other files to *
20  * produce an executable, this file does not by itself cause the *
21  * resulting executable to be covered by the GNU General Public *
22  * License. This exception does not however invalidate any other *
23  * reasons why the executable file might be covered by the GNU General *
24  * Public License. *
25  * *
26  * This library is distributed in the hope that it will be useful, *
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
29  * Lesser General Public License for more details. *
30  * *
31  * You should have received a copy of the GNU General Public *
32  * License along with this library; if not, write to the Free Software *
33  * Foundation, Inc., 59 Temple Place, *
34  * Suite 330, Boston, MA 02111-1307 USA *
35  * *
36  ***************************************************************************/
37 
38 
39 #include "Service.hpp"
40 #include "TaskContext.hpp"
41 #include <algorithm>
42 #include "internal/mystd.hpp"
43 #include <algorithm>
44 
45 namespace RTT {
46  using namespace detail;
47  using namespace std;
48  using namespace boost;
49 
50  Service::shared_ptr Service::Create(const std::string& name, TaskContext* owner) {
51  shared_ptr ret(new Service(name,owner));
52  if (owner)
53  owner->provides()->addService( ret );
54  return ret;
55  }
56 
57  Service::Service(const std::string& name, TaskContext* owner)
58  : mname(name),
59  mowner(owner),
60  parent()
61  {
62  // Inform DataFlowInterface.
63  mservice = this;
64  }
65 
67  {
68  clear();
69  }
70 
71  vector<string> Service::getProviderNames() const {
72  return keys(services);
73  }
74 
76  if(this->getOwner())
77  return this->getOwner()->engine();
78  return NULL;
79  }
80 
82  if ( services.find( obj->getName() ) != services.end() ) {
83  log(Error) << "Could not add Service " << obj->getName() <<": name already in use." <<endlog();
84  return false;
85  }
86  // we pass and store a shared ptr in setParent, so we hack it like this:
87  shared_ptr me;
88  try {
89  me = shared_from_this();
90  } catch ( boost::bad_weak_ptr& bw ) {
91  me.reset(this); // take ownership
92  }
93  obj->setParent( me );
94 
95  // only set the owner if one is present.
96  if ( mowner ) {
97  obj->setOwner( mowner );
98  }
99  services[obj->getName()] = obj;
100  return true;
101  }
102 
103  void Service::removeService( string const& name) {
104  // carefully written to avoid destructor to call back on us when called from clear().
105  if ( services.count(name) ) {
106  shared_ptr sp = services.find(name)->second;
107  services.erase(name);
108  sp->setParent(Service::shared_ptr());
109  sp.reset(); // this possibly deletes.
110  }
111  }
112 
114  try {
115  return shared_from_this();
116  } catch( boost::bad_weak_ptr& /*bw*/ ) {
117  log(Error) <<"When using boost < 1.40.0 : You are not allowed to call provides() on a Service that does not yet belong to a TaskContext or another Service (for example in a constructor)." << endlog();
118  log(Error) <<"Try to avoid using provides() in this case: omit it or use the service directly." <<endlog();
119  throw std::runtime_error("Illegal use of provides()");
120  }
121  }
122 
123  Service::shared_ptr Service::provides(const std::string& service_name) {
124  shared_ptr sp = getService(service_name);
125  if (sp)
126  return sp;
127  sp = boost::make_shared<Service>(service_name, mowner);
128  if ( addService(sp) )
129  return sp;
130  return shared_ptr();
131  }
132 
133  Service::shared_ptr Service::getService(const std::string& service_name) {
134  if (service_name == "this")
135  return provides();
136  Services::iterator it = services.find(service_name);
137  if (it != services.end() )
138  return it->second;
139  return shared_ptr();
140  }
141 
143  {
144  Logger::In in("Service::getOperation");
145  if ( this->hasMember(name ) ) {
146  return this->getPart(name);
147  }
148  log(Warning) << "No such operation in service '"<< getName() <<"': "<< name <<endlog();
149  return 0;
150  }
151 
152  bool Service::resetOperation(std::string name, base::OperationBase* impl)
153  {
154  if (!hasOperation(name))
155  return false;
156  simpleoperations[name] = impl;
157  return true;
158  }
159 
160  bool Service::setOperationThread(std::string const& name, ExecutionThread et)
161  {
162  if ( !hasOperation(name) )
163  return false;
165  OperationCallerInterface::shared_ptr oci = dynamic_pointer_cast<OperationCallerInterface>(di);
166  if (oci) {
167  return oci->setThread( et, getOwner() ? getOwner()->engine() : 0 );
168  }
169  return false;
170  }
171 
172  bool Service::hasService(const std::string& service_name) {
173  if (service_name == "this")
174  return true;
175  return services.find(service_name) != services.end();
176  }
177 
179  {
180  Logger::In in("Service::addLocalOperation");
181  if ( op.getName().empty() ) {
182  log(Error) << "Failed to add Operation: '"<< op.getName() <<"' has no name." <<endlog();
183  return false;
184  }
185  // don't check ready() since the op may not have an owner yet:
186  if ( !op.getImplementation() ) {
187  log(Error) << "Failed to add Operation: '"<< op.getName() <<"' is not ready: not bound to a function." <<endlog();
188  return false;
189  }
190  if ( simpleoperations.count( op.getName() ) ) {
191  log(Warning) << "While adding Operation: '"<< op.getName() <<"': replacing previously added operation." <<endlog();
192  this->removeOperation(op.getName());
193  }
194  simpleoperations[op.getName()] = &op;
195  // finally set the (new) owner:
196  if (mowner) {
197  // also updates the Executor:
198  op.setOwner(mowner->engine());
199  }
200  return true;
201  }
202 
203  boost::shared_ptr<base::DisposableInterface> Service::getLocalOperation( std::string name ) {
204  if ( hasOperation(name) ) {
205  return simpleoperations.find(name)->second->getImplementation();
206  }
207  return boost::shared_ptr<base::DisposableInterface>();
208  }
209 
211  {
212  while ( !simpleoperations.empty() )
213  {
214  simpleoperations.erase(simpleoperations.begin() );
215  }
216 
217  for( OperationList::const_iterator it = ownedoperations.begin(); it != ownedoperations.end(); ++it )
218  {
219  delete *it;
220  }
221  ownedoperations.clear();
222 
225  while ( !services.empty() ) {
226  this->removeService( services.begin()->first );
227  }
228  }
229 
230  std::vector<std::string> Service::getOperationNames() const
231  {
232  return keys(simpleoperations);
233  //return getNames();
234  }
235 
236  bool Service::hasOperation(const std::string& name) const
237  {
238  return simpleoperations.count(name) == 1;
239  //return hasMember(name);
240  }
241 
242  void Service::removeOperation(const std::string& name)
243  {
244  if (!hasOperation(name))
245  return;
246  OperationList::iterator it = find(ownedoperations.begin(), ownedoperations.end(), simpleoperations.find(name)->second );
247  if (it != ownedoperations.end()) {
248  delete *it;
249  ownedoperations.erase(it);
250  }
251  simpleoperations.erase( name );
253  }
254  void Service::setOwner(TaskContext* new_owner) {
255  for( SimpleOperations::iterator it= simpleoperations.begin(); it != simpleoperations.end(); ++it)
256  it->second->setOwner( new_owner ? new_owner->engine() : 0);
257 
258  this->mowner = new_owner;
259 
260  for( Services::iterator it= services.begin(); it != services.end(); ++it)
261  it->second->setOwner( new_owner );
262  }
263 
265  parent = p;
266  }
267 
269  return internal::OperationCallerC( getPart(name), name, caller );
270  }
271 
272 }
const std::string & getName() const
Returns the name of this service instance.
Definition: Service.hpp:139
void setParent(shared_ptr new_parent)
Sets the parent service in case this service is a sub-service.
Definition: Service.cpp:264
TaskContext * getOwner() const
The owner is the top-level TaskContext owning this service (indirectly).
Definition: Service.hpp:185
This base class serves as a template-less handle for operation objects and also stores the name and d...
Service::shared_ptr provides()
Returns this Service, unless no shared_ptr yet exists.
Definition: Service.cpp:113
bool hasOperation(const std::string &name) const
Query for the existence of a Operation in this interface.
Definition: Service.cpp:236
static Service::shared_ptr Create(const std::string &name, TaskContext *owner=0)
Creates a Service with a name and an owner.
Definition: Service.cpp:50
Service::shared_ptr provides()
Returns this Service.
The interface class for operation callers.
boost::shared_ptr< base::DisposableInterface > getLocalOperation(std::string name)
Get a locally added operation from this interface.
Definition: Service.cpp:203
Service(const std::string &name, TaskContext *owner=0)
Creates a Service with a name and an owner.
Definition: Service.cpp:57
void clear()
Erases the whole repository.
bool setThread(ExecutionThread et, ExecutionEngine *executor)
Sets the Thread execution policy of this object.
virtual void removeService(std::string const &service_name)
Remove a previously added sub-service, potentially freeing it (and this) from memory.
Definition: Service.cpp:103
STL namespace.
Services services
the services we implement.
Definition: Service.hpp:563
bool hasMember(const std::string &name) const
Query if an operation is present.
virtual ProviderNames getProviderNames() const
Return a standard container which contains all the sub-service names of this Service.
Definition: Service.cpp:71
void removeOperation(const std::string &name)
Removes a previously added operation.
Definition: Service.cpp:242
bool resetOperation(std::string name, base::OperationBase *impl)
Reset the implementation of a operation.
Definition: Service.cpp:152
boost::shared_ptr< OperationCallerInterface > shared_ptr
Use this type for shared pointer storage of an OperationCallerInterface object.
An execution engine serialises (executes one after the other) the execution of all commands...
boost::shared_ptr< Service > shared_ptr
Definition: Service.hpp:101
OperationInterfacePart * getPart(const std::string &name)
Get a previously added part of this factory.
This class allows storage and retrieval of operations, ports, attributes and properties provided by a...
Definition: Service.hpp:93
Service * getService() const
Returns the service this interface belongs to.
SimpleOperations simpleoperations
Definition: Service.hpp:568
virtual ~Service()
Definition: Service.cpp:66
A template-less manager for OperationCaller calls.
virtual bool addService(shared_ptr obj)
Add a new sub-service to this Service.
Definition: Service.cpp:81
This class defines the interface for creating operation objects without using C++ templates...
bool hasService(const std::string &service_name)
Check if this service has the sub-service service_name.
Definition: Service.cpp:172
bool addLocalOperation(base::OperationBase &op)
Add an Operation object to the operation interface.
Definition: Service.cpp:178
TaskContext * mowner
Definition: Service.hpp:572
virtual DisposableInterface::shared_ptr getImplementation()=0
Returns the implementation object of this operation.
boost::shared_ptr< DisposableInterface > shared_ptr
Use this type for shared pointer storage of an DisposableInterface object.
std::vector< std::string > getOperationNames() const
Returns the names of all operations added to this interface.
Definition: Service.cpp:230
virtual RTT_API boost::shared_ptr< base::DisposableInterface > getLocalOperation() const
Returns any local operation associated with this operation.
void clear()
Remove and delete all added operations.
OperationList ownedoperations
Definition: Service.hpp:569
std::vector< typename MapT::key_type > keys(const MapT &map)
Definition: mystd.hpp:151
Notify the Logger in which &#39;module&#39; the message occured.
Definition: Logger.hpp:159
ExecutionEngine * getOwnerExecutionEngine() const
Return the execution engine of this service owner.
Definition: Service.cpp:75
The TaskContext is the C++ representation of an Orocos component.
Definition: TaskContext.hpp:93
void setOwner(ExecutionEngine *ee)
Updates the owning ExecutionEngine that might execute this operation.
OperationInterfacePart * getOperation(std::string name)
Get a previously added operation for use in a C++ OperationCaller object.
Definition: Service.cpp:142
Service * mservice
The parent Service.
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:52
bool setOperationThread(std::string const &name, ExecutionThread et)
Sets the thread of execution of a previously added operation.
Definition: Service.cpp:160
const std::string & getName()
Returns the name of this operation.
void setOwner(TaskContext *new_owner)
Sets the owning TaskContext that will execute the operations in this service.
Definition: Service.cpp:254
internal::OperationCallerC create(std::string name, ExecutionEngine *caller)
Create a OperationCallerC object, a template-less operation invocation object.
Definition: Service.cpp:268
void remove(const std::string &name)
Remove an added operation from the interface.
const ExecutionEngine * engine() const
Get a const pointer to the ExecutionEngine of this Task.
Definition: TaskCore.hpp:306
void clear()
Clear all added operations, properties and sub-services from this Service.
Definition: Service.cpp:210
ExecutionThread
Users can choose if an operation&#39;s function is executed in the component&#39;s thread (OwnThread) or in t...
shared_ptr parent
Definition: Service.hpp:573