Orocos Real-Time Toolkit  2.9.0
ServiceRequester.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: The SourceWorks Tue Sep 7 00:55:18 CEST 2010 ServiceRequester.cpp
3 
4  ServiceRequester.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 "ServiceRequester.hpp"
40 #include "Service.hpp"
41 #include "internal/mystd.hpp"
42 #include "Logger.hpp"
43 #include "TaskContext.hpp"
44 #include <boost/bind.hpp>
45 
46 #include <utility>
47 
48 namespace RTT
49 {
50  using namespace boost;
51  using namespace detail;
52  using namespace std;
53 
54  ServiceRequester::ServiceRequester(const std::string& name, TaskContext* tc) :
55  mrname(name), mrowner(tc)
56  {
57  }
58 
60  {
61  }
62 
64  {
65  if (mmethods.find(isb.getName()) != mmethods.end())
66  {
67  log(Error) << "OperationCaller with name '" + isb.getName() + "' already present." << endlog();
68  return false;
69  }
70  mmethods.insert(make_pair(isb.getName(), &isb));
71  return true;
72  }
73 
74  std::vector<std::string> ServiceRequester::getOperationCallerNames() const
75  {
76  return keys(mmethods);
77  }
78 
79  std::vector<std::string> ServiceRequester::getRequesterNames() const
80  {
81  return keys(mrequests);
82  }
83 
85  {
86  OperationCallers::iterator it = mmethods.find(name);
87  if (it != mmethods.end())
88  return it->second;
89  return 0;
90  }
91 
93  {
94  for(OperationCallers::iterator it = mmethods.begin(); it != mmethods.end(); ++it)
95  it->second->setCaller( new_owner ? new_owner->engine() : 0);
96 
97  this->mrowner = new_owner;
98 
99  for(Requests::iterator it = mrequests.begin(); it != mrequests.end(); ++it)
100  it->second->setOwner( new_owner );
101  }
102 
104  try {
105  return shared_from_this();
106  } catch( boost::bad_weak_ptr& /*bw*/ ) {
107  log(Error) <<"When using boost < 1.40.0 : You are not allowed to call requires() on a ServiceRequester that does not yet belong to a TaskContext or another ServiceRequester." << endlog();
108  log(Error) <<"Try to avoid using requires() in this case: omit it or use the service requester directly." <<endlog();
109  log(Error) <<"OR: upgrade to boost 1.40.0, then this error will go away." <<endlog();
110  throw std::runtime_error("Illegal use of requires()");
111  }
112  }
113 
114  ServiceRequester::shared_ptr ServiceRequester::requires(const std::string& service_name) {
115  if (service_name == "this")
116  return requires();
117  Requests::iterator it = mrequests.find(service_name);
118  if (it != mrequests.end() )
119  return it->second;
120  shared_ptr sp = boost::make_shared<ServiceRequester>(service_name, mrowner);
121  if ( addServiceRequester(sp) )
122  return sp;
123  return shared_ptr();
124  }
125 
127  if ( mrequests.find( obj->getRequestName() ) != mrequests.end() ) {
128  log(Error) << "Could not add ServiceRequester " << obj->getRequestName() <<": name already in use." <<endlog();
129  return false;
130  }
131 
132  // only set the owner if one is present.
133  if ( mrowner ) {
134  obj->setOwner( mrowner );
135  }
136  mrequests[obj->getRequestName()] = obj;
137  return true;
138  }
139 
141  if (!sp) return false;
142  for (OperationCallers::iterator it = mmethods.begin(); it != mmethods.end(); ++it) {
143  if ( !it->second->ready() ) {
144  if (sp->hasOperation( it->first )) {
145  it->second->setImplementation( sp->getLocalOperation( it->first ), mrowner ? mrowner->engine() : 0 );
146  if ( it->second->ready() ) {
147  log(Debug) << "Successfully set up OperationCaller " << it->first <<endlog();
148  if (!mrowner)
149  log(Debug) << "OperationCaller "<< it->first << " has no caller set: using GlobalEngine."<<endlog();
150  }
151  }
152  if (sp->hasMember( it->first )) {
153  it->second->setImplementationPart( sp->getOperation( it->first ), mrowner ? mrowner->engine() : 0 );
154  if ( it->second->ready() ) {
155  log(Debug) << "Successfully set up OperationCaller " << it->first <<endlog();
156  if (!mrowner)
157  log(Debug) << "OperationCaller "<< it->first << " has no caller set: using GlobalEngine."<<endlog();
158  }
159  }
160  }
161  }
162  if (ready()) {
163  if (!mprovider)
164  mprovider = sp;
165  log(Info) << "Found complete interface of requested service '" << mrname <<"'"<< endlog();
166  return true;
167  }
168 
169  return false;
170  }
171 
173  {
174  for_each(mmethods.begin(), mmethods.end(),
175  boost::bind(&OperationCallerBaseInvoker::disconnect, boost::bind(&OperationCallers::value_type::second, _1) )
176  );
177  }
178 
180  {
181  for (OperationCallers::const_iterator it = mmethods.begin(); it != mmethods.end(); ++it)
182  if ( !it->second->ready() ) {
183  log(Debug) << "ServiceRequester: "<< it->first << " not set up." <<endlog();
184  return false;
185  }
186  return true;
187  }
188 
190  {
191  mmethods.clear();
192  mrequests.clear();
193  }
194 }
An invoker can be given an implementation and is identified by a name.
virtual const std::string & getName() const =0
Returns the name of this method instance.
RequesterNames getRequesterNames() const
OperationCallers mmethods
virtual bool ready() const
Returns true when all methods were resolved.
virtual void clear()
Remove all operation callers from this service requester.
void setOwner(TaskContext *new_owner)
Sets the owning TaskContext that is considered as the caller of requested operations.
STL namespace.
boost::shared_ptr< ServiceRequester > shared_ptr
virtual void disconnect()
Disconnects all methods from their implementation.
Requests mrequests
the services we implement.
base::OperationCallerBaseInvoker * getOperationCaller(const std::string &name)
boost::shared_ptr< Service > shared_ptr
Definition: Service.hpp:101
ServiceRequester(const std::string &name, TaskContext *owner=0)
Service::shared_ptr mprovider
OperationCallerNames getOperationCallerNames() const
ServiceRequester::shared_ptr requires()
std::vector< typename MapT::key_type > keys(const MapT &map)
Definition: mystd.hpp:151
virtual void disconnect()=0
Disconnects this caller from the operation it was connected to.
virtual bool connectTo(Service::shared_ptr sp)
Connects this service&#39;s methods to the operations provided by op.
bool addServiceRequester(shared_ptr obj)
Add a new ServiceRequester to this TaskContext.
The TaskContext is the C++ representation of an Orocos component.
Definition: TaskContext.hpp:93
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:52
const ExecutionEngine * engine() const
Get a const pointer to the ExecutionEngine of this Task.
Definition: TaskCore.hpp:306
bool addOperationCaller(base::OperationCallerBaseInvoker &mbi)