Orocos Real-Time Toolkit  2.8.3
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 
101  try {
102  return shared_from_this();
103  } catch( boost::bad_weak_ptr& /*bw*/ ) {
104  log(Error) <<"When using boost < 1.40.0 : You are not allowed to call provides() on a ServiceRequester that does not yet belong to a TaskContext or another ServiceRequester." << endlog();
105  log(Error) <<"Try to avoid using requires() in this case: omit it or use the service requester directly." <<endlog();
106  log(Error) <<"OR: upgrade to boost 1.40.0, then this error will go away." <<endlog();
107  throw std::runtime_error("Illegal use of requires()");
108  }
109  }
110 
111  ServiceRequester::shared_ptr ServiceRequester::requires(const std::string& service_name) {
112  if (service_name == "this")
113  return requires();
114  shared_ptr sp = mrequests[service_name];
115  if (sp)
116  return sp;
117  sp = boost::make_shared<ServiceRequester>(service_name, mrowner);
118  mrequests[service_name] = sp;
119  return sp;
120  }
121 
123  if ( mrequests.find( obj->getRequestName() ) != mrequests.end() ) {
124  log(Error) << "Could not add ServiceRequester " << obj->getRequestName() <<": name already in use." <<endlog();
125  return false;
126  }
127 
128  // only set the owner if one is present.
129  if ( mrowner ) {
130  obj->setOwner( mrowner );
131  }
132  mrequests[obj->getRequestName()] = obj;
133  return true;
134  }
135 
137  if (!sp) return false;
138  for (OperationCallers::iterator it = mmethods.begin(); it != mmethods.end(); ++it) {
139  if ( !it->second->ready() ) {
140  if (sp->hasOperation( it->first )) {
141  it->second->setImplementation( sp->getLocalOperation( it->first ), mrowner ? mrowner->engine() : 0 );
142  if ( it->second->ready() ) {
143  log(Debug) << "Successfully set up OperationCaller " << it->first <<endlog();
144  if (!mrowner)
145  log(Debug) << "OperationCaller "<< it->first << " has no caller set: using GlobalEngine."<<endlog();
146  }
147  }
148  if (sp->hasMember( it->first )) {
149  it->second->setImplementationPart( sp->getOperation( it->first ), mrowner ? mrowner->engine() : 0 );
150  if ( it->second->ready() ) {
151  log(Debug) << "Successfully set up OperationCaller " << it->first <<endlog();
152  if (!mrowner)
153  log(Debug) << "OperationCaller "<< it->first << " has no caller set: using GlobalEngine."<<endlog();
154  }
155  }
156  }
157  }
158  if (ready()) {
159  if (!mprovider)
160  mprovider = sp;
161  log(Info) << "Found complete interface of requested service '" << mrname <<"'"<< endlog();
162  return true;
163  }
164 
165  return false;
166  }
167 
169  {
170  for_each(mmethods.begin(), mmethods.end(),
171  boost::bind(&OperationCallerBaseInvoker::disconnect, boost::bind(&OperationCallers::value_type::second, _1) )
172  );
173  }
174 
176  {
177  for (OperationCallers::const_iterator it = mmethods.begin(); it != mmethods.end(); ++it)
178  if ( !it->second->ready() ) {
179  log(Debug) << "ServiceRequester: "<< it->first << " not set up." <<endlog();
180  return false;
181  }
182  return true;
183  }
184 
186  {
187  mmethods.clear();
188  mrequests.clear();
189  }
190 }
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:51
const ExecutionEngine * engine() const
Get a const pointer to the ExecutionEngine of this Task.
Definition: TaskCore.hpp:327
bool addOperationCaller(base::OperationCallerBaseInvoker &mbi)