library functions which use callbacks

I am using several libraries whose functions need a callback function in
its arguments. For example, there is a function getGpsData() which needs
a callback. The callback will be called whenever data as available from
the GPS device.

What would be a good way to use this in an Orocos environment? Should I
use an aperiodic task, define a private function like process_gps_data()
and call the getGpsData(..., process_gps_data) in the updateHook()?
getGpsData() doesn't block.. so how/when exactly will process_gps_data()
be executed? The library will try to execute it as soon as there is some
data available from the GPS device, but orocos might be executing a
different TC at that time (this shouldn't even be possible on a
uniprocessor system). So when exactly will that function be executed?

Is there a better way to use a library function which needs a callback
to be registered?

On Wednesday 15 September 2010 14:04:31 Sagar Behere wrote:
> Hello,
>
> I'm a bit confused about how scheduling works in orocos.
>
> I am using several libraries whose functions need a callback function in
> its arguments. For example, there is a function getGpsData() which needs
> a callback. The callback will be called whenever data as available from
> the GPS device.
>
> What would be a good way to use this in an Orocos environment? Should I
> use an aperiodic task, define a private function like process_gps_data()
> and call the getGpsData(..., process_gps_data) in the updateHook()?

What we do in these cases is to create such a private function and let the
private function trigger() the TaskContext that is using this data such that
it's updateHook() function is executed, and a new call to getGpsData can be
scheduled (assuming that you need to do this each time you want new data).

Your library will determine that moment, so you must assume that
process_gps_data may not modify data shared with other threads, or the
TaskContext's updateHook()

> The library will try to execute it as soon as there is some
> data available from the GPS device, but orocos might be executing a
> different TC at that time (this shouldn't even be possible on a
> uniprocessor system).

It is possible, since the scheduler may interrupt your threads at any time to
execute another thread.

> So when exactly will that function be executed?
>
> Is there a better way to use a library function which needs a callback
> to be registered?

You're pretty close to what you need. Take this snippet as an inspiration:

Then the problem becomes that since process_gps_data() is static, it
doesn't have a "this" pointer, and so it cannot access any other class
member (for example, it cannot extract information from GPSData *data
and set values of Component's WriteDataPorts.

So what should be done? One thing I can think of is to take advantage of
the fact that a static method of a class can access other static data
members of that class (which can be accessed by other non-static methods
in that class). So it should be possible to use an RTT::OS::Mutex
protected copy operation in process_gps_data() to copy GPSData *data
into a static GPSData current_data; kind of member. But then, once this
is copied, this->trigger() still needs to be called to process the
current_data and we run into the same problem i.e. "this" pointer does
not exist in a static member function :(

Am I missing something here? Or it seems there is no way to get the
callback to interact with the other class members.

[ There are some hacks on the internet which would have worked if the
callback allowed passing a pointer to user data, which is not the case
here ]

Another option is to pull some dirty hacks after making the class singleton.

Oh yeah, I had seen that coming, but I was hoping your lib had a
STL-ish API that accepted function objects too :-]

We once had this problem with a CAN driver, exactly the same
situation. What we did was to create
a 'static' lookup table in the component class and let each instance
of the component register itself
in that std::map/vector/list... Then a static callback is registered
with the getGpsData function, which
has access to this lookup table and calls an object function for each
instance with a pointer to the new data.

Like this:

&#10;class GPSComponent : public TaskContext {&#10;public:&#10; GPSComponent(...) ... {&#10; instances.push_back(this);&#10; }&#10; static vector&lt;GPSComponent*&gt; instances;&#10; static process_gps_data(GPSData * gd) {&#10; for(vector&lt;GPSComponent::iterator it =instances.begin(); it !=&#10;instances.end; ++it)&#10; (*it)-&gt;newGPSData(gd);&#10; }&#10; void newGPSData(GPSData* gd) {&#10; // copy gd to local instance data&#10; // maybe only the last component in &#039;instances&#039; sends a new trigger&#10; // it depends...&#10; }&#10;};&#10;&lt;code&gt;&#10;You could also codify a singleton, or assign gps devices to different&#10;instances etc&#10;(we had one component for each CAN channel for example).&#10;It&#039;s mostly a C++ problem, due to the fact that Orocos components&#10;might run in the&#10;same process, which excludes a singleton solution in case of multiple&#10;gps devices&#10;(only makes sense in redundancy setups...).&#10;&#10;I don&#039;t think there&#039;s another solution than something similar as the above.&#10;&#10;Peter&#10;-- &#10;Orocos-Users mailing list&#10;Orocos-Users [..] ...&#10;http://lists.mech.kuleuven.be/mailman/listinfo/orocos-users

On 09/20/2010 10:34 PM, Sagar Behere wrote:
> Hi Peter,
>
> There is a problem with the suggested approach.
>
> On 09/15/2010 03:29 PM, Peter Soetens wrote:
>
>> You're pretty close to what you need. Take this snippet as an
>> inspiration:
>>
>> &#10;&gt;&gt; #include&lt;boost/bind.hpp&gt;&#10;&gt;&gt; using namespace boost;&#10;&gt;&gt;&#10;&gt;&gt; class Component : public TaskContext {&#10;&gt;&gt; void process_gps_data( GPSData* data ) {&#10;&gt;&gt; // make a copy of &#039;data&#039;, ...&#10;&gt;&gt; // finally, wake up component:&#10;&gt;&gt; this-&gt;trigger();&#10;&gt;&gt; }&#10;&gt;&gt; void updateHook() {&#10;&gt;&gt; // process data received from process_gps_data&#10;&gt;&gt; // ...&#10;&gt;&gt; // finally, trigger a new read: (see boost::bind for syntax examples)&#10;&gt;&gt; getGpsData(..., bind(&amp;Component::process_gps_data, this, _1) );&#10;&gt;&gt; }&#10;&gt;&gt; };&#10;&gt;&gt;
>
> boost::bind(&Component::process_gps_data, this, _1) does not produce a
> raw function pointer of the type void (*process_gps_data) (GPSData *)
> that getGpsData() needs. [ The signature of getGpsData is:
> int getGpsData (void (*process_gps_data) (GPSData *)); ]
>
> Therefore, the member function Component::process_gps_data() can't be
> used as a callback, unless it is declared static.
> http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.2
>
> Then the problem becomes that since process_gps_data() is static, it
> doesn't have a "this" pointer, and so it cannot access any other class
> member (for example, it cannot extract information from GPSData *data
> and set values of Component's WriteDataPorts.
>
> So what should be done? One thing I can think of is to take advantage of
> the fact that a static method of a class can access other static data
> members of that class (which can be accessed by other non-static methods
> in that class). So it should be possible to use an RTT::OS::Mutex
> protected copy operation in process_gps_data() to copy GPSData *data
> into a static GPSData current_data; kind of member. But then, once this
> is copied, this->trigger() still needs to be called to process the
> current_data and we run into the same problem i.e. "this" pointer does
> not exist in a static member function :(
>
> Am I missing something here? Or it seems there is no way to get the
> callback to interact with the other class members.
>
> [ There are some hacks on the internet which would have worked if the
> callback allowed passing a pointer to user data, which is not the case
> here ]
>
> Another option is to pull some dirty hacks after making the class
> singleton.
>
> What do you think?
>
> /Sagar
>
>> Your final code would be a nice example for on the Wiki.
>>
>> Peter
>

On Mon, Sep 20, 2010 at 10:53 PM, Sagar Behere <sagar [dot] behere [..] ...> wrote:
> Hi again,
>
> The following approach compiled. [Can't test it yet, since I'm coding from
> home and the embedded development kit is back in the office]. But I'd like
> your comments anyway :)

This is similar to what I proposed, but with the 'static' part in
plain C, and which
only works for one instance of the component (may be perfectly fine for you).

If this works for you, go for it :-)

Peter

>
> ----in file gps.cpp----
>
> #include "gps.hpp"
>
> using namespace RTT;
>
> gps *temp_gps_pointer = NULL;
>
> gps::gps(std::string name, std::string propertyfilename):
> TaskContext(name)
> {
> temp_gps_pointer = this;
> }
>
> void gpsDataCallback (gpsData *data)
> {
> //do stuff with data using temp_gps_pointer to get into gps
> //TaskContext
> temp_gps_pointer->getActivity()->trigger();
> }
>
> void gps::updateHook(void)
> {
> // process data received from process_gps_data
> // ...
> getGpsData(gpsDataCallback);
> }
>
> ---end of gps.cpp contents---
>
> Regards,
> Sagar
>
> On 09/20/2010 10:34 PM, Sagar Behere wrote:
>>
>> Hi Peter,
>>
>> There is a problem with the suggested approach.
>>
>> On 09/15/2010 03:29 PM, Peter Soetens wrote:
>>
>>> You're pretty close to what you need. Take this snippet as an
>>> inspiration:
>>>
>>> &#10;&gt;&gt;&gt; #include&lt;boost/bind.hpp&gt;&#10;&gt;&gt;&gt; using namespace boost;&#10;&gt;&gt;&gt;&#10;&gt;&gt;&gt; class Component : public TaskContext {&#10;&gt;&gt;&gt; void process_gps_data( GPSData* data ) {&#10;&gt;&gt;&gt; // make a copy of &#039;data&#039;, ...&#10;&gt;&gt;&gt; // finally, wake up component:&#10;&gt;&gt;&gt; this-&gt;trigger();&#10;&gt;&gt;&gt; }&#10;&gt;&gt;&gt; void updateHook() {&#10;&gt;&gt;&gt; // process data received from process_gps_data&#10;&gt;&gt;&gt; // ...&#10;&gt;&gt;&gt; // finally, trigger a new read: (see boost::bind for syntax examples)&#10;&gt;&gt;&gt; getGpsData(..., bind(&amp;Component::process_gps_data, this, _1) );&#10;&gt;&gt;&gt; }&#10;&gt;&gt;&gt; };&#10;&gt;&gt;&gt;
>>
>> boost::bind(&Component::process_gps_data, this, _1) does not produce a
>> raw function pointer of the type void (*process_gps_data) (GPSData *)
>> that getGpsData() needs. [ The signature of getGpsData is:
>> int getGpsData (void (*process_gps_data) (GPSData *)); ]
>>
>> Therefore, the member function Component::process_gps_data() can't be
>> used as a callback, unless it is declared static.
>> http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.2
>>
>> Then the problem becomes that since process_gps_data() is static, it
>> doesn't have a "this" pointer, and so it cannot access any other class
>> member (for example, it cannot extract information from GPSData *data
>> and set values of Component's WriteDataPorts.
>>
>> So what should be done? One thing I can think of is to take advantage of
>> the fact that a static method of a class can access other static data
>> members of that class (which can be accessed by other non-static methods
>> in that class). So it should be possible to use an RTT::OS::Mutex
>> protected copy operation in process_gps_data() to copy GPSData *data
>> into a static GPSData current_data; kind of member. But then, once this
>> is copied, this->trigger() still needs to be called to process the
>> current_data and we run into the same problem i.e. "this" pointer does
>> not exist in a static member function :(
>>
>> Am I missing something here? Or it seems there is no way to get the
>> callback to interact with the other class members.
>>
>> [ There are some hacks on the internet which would have worked if the
>> callback allowed passing a pointer to user data, which is not the case
>> here ]
>>
>> Another option is to pull some dirty hacks after making the class
>> singleton.
>>
>> What do you think?
>>
>> /Sagar
>>
>>> Your final code would be a nice example for on the Wiki.
>>>
>>> Peter
>>
>
>
--
Orocos-Users mailing listOrocos-Users [..] ...http://lists.mech.kuleuven.be/mailman/listinfo/orocos-users

>> getGpsData() doesn't block.. so how/when exactly will process_gps_data()
>> be executed?
>
> Your library will determine that moment, so you must assume that
> process_gps_data may not modify data shared with other threads, or the
> TaskContext's updateHook()
>
>> The library will try to execute it as soon as there is some
>> data available from the GPS device, but orocos might be executing a
>> different TC at that time (this shouldn't even be possible on a
>> uniprocessor system).
>
> It is possible, since the scheduler may interrupt your threads at any time to
> execute another thread.

Assume the functions & callback of this library are defined and executed
in TC A. updateHook() of TC A calls the getGpsData() function, thus
registering the callback. getGpsData() is non-blocking() and returns
immediately and TC A finishes executing. Then TC B starts execution and
the GPS device receives data. What happens? Is TC B stopped and
callback() in TC A executed? Does TC B continue executing and the
callback function executed whenever TC A gets its chance to execute? Are
there any rules to specify what should happen?

>> So when exactly will that function be executed?
>>
>> Is there a better way to use a library function which needs a callback
>> to be registered?
>
> You're pretty close to what you need. Take this snippet as an inspiration:
>
> &#10;&gt; #include&lt;boost/bind.hpp&gt;&#10;&gt; using namespace boost;&#10;&gt;&#10;&gt; class Component : public TaskContext {&#10;&gt; void process_gps_data( GPSData* data ) {&#10;&gt; // make a copy of &#039;data&#039;, ...&#10;&gt; // finally, wake up component:&#10;&gt; this-&gt;trigger();&#10;&gt; }&#10;&gt; void updateHook() {&#10;&gt; // process data received from process_gps_data&#10;&#10;[really basic question :( ] So the copy of the data that &#10;process_gps_data() makes is used by the TC&#039;s updateHook(). But above, &#10;you said that process_gps_data() may not modify data shared with the &#10;TC&#039;s updateHook(). I didn&#039;t understand why you said that, since this &#10;code makes sense.&#10;&#10;&gt; // ...&#10;&gt; // finally, trigger a new read: (see boost::bind for syntax examples)&#10;&gt; getGpsData(..., bind(&amp;Component::process_gps_data, this, _1) );&#10;&#10;Right! And I guess I don&#039;t have to call this function here if I tell the &#10;library &quot;Call the callback() everytime you get data&quot; ( which is also &#10;possible. )&#10;&#10;&gt; Your final code would be a nice example for on the Wiki.&#10;&#10;Sure! I will do so once it is ready.&#10;&#10;&gt; Peter&#10;Sagar

On Thursday 16 September 2010 11:02:52 Sagar Behere wrote:
> Hi,
>
> Thanks, this makes sense. I need two more clarifications.
>
> >> getGpsData() doesn't block.. so how/when exactly will process_gps_data()
> >> be executed?
> >
> > Your library will determine that moment, so you must assume that
> > process_gps_data may not modify data shared with other threads, or the
> > TaskContext's updateHook()
> >
> >> The library will try to execute it as soon as there is some
> >> data available from the GPS device, but orocos might be executing a
> >> different TC at that time (this shouldn't even be possible on a
> >> uniprocessor system).
> >
> > It is possible, since the scheduler may interrupt your threads at any
> > time to execute another thread.
>
> Assume the functions & callback of this library are defined and executed
> in TC A. updateHook() of TC A calls the getGpsData() function, thus
> registering the callback. getGpsData() is non-blocking() and returns
> immediately and TC A finishes executing. Then TC B starts execution and
> the GPS device receives data. What happens? Is TC B stopped and
> callback() in TC A executed? Does TC B continue executing and the
> callback function executed whenever TC A gets its chance to execute? Are
> there any rules to specify what should happen?

All thread scheduling is done by the Linux/Windows/Mac-OS-X/... schedulers.
There is one thread for each component (the default setting), and as such the
mapping thread <-> updateHook() is 1:1. So for your specific case:
1. GPS data is received
2. B's thread is preempted (stopped temporarily) by the callback
3. A is trigger() 'ed by the callback
4.a If A's thread has a higher priority, A's updateHook will run, when it
finishes, B's updateHook will continue OR
4.b If B's thread has a higher priority, B's updateHook will continue first and
when it's done, A's updateHook will be executed.

>
> >> So when exactly will that function be executed?
> >>
> >> Is there a better way to use a library function which needs a callback
> >> to be registered?
> >
> > You're pretty close to what you need. Take this snippet as an
> > inspiration:
> >
> > &#10;&gt; &gt; #include&lt;boost/bind.hpp&gt;&#10;&gt; &gt; using namespace boost;&#10;&gt; &gt;&#10;&gt; &gt; class Component : public TaskContext {&#10;&gt; &gt; void process_gps_data( GPSData* data ) {&#10;&gt; &gt; // make a copy of &#039;data&#039;, ...&#10;&gt; &gt; // finally, wake up component:&#10;&gt; &gt; this-&gt;trigger();&#10;&gt; &gt; }&#10;&gt; &gt; void updateHook() {&#10;&gt; &gt; // process data received from process_gps_data&#10;&gt; &#10;&gt; [really basic question :( ] So the copy of the data that&#10;&gt; process_gps_data() makes is used by the TC&#039;s updateHook(). But above,&#10;&gt; you said that process_gps_data() may not modify data shared with the&#10;&gt; TC&#039;s updateHook(). I didn&#039;t understand why you said that, since this&#10;&gt; code makes sense.&#10;&#10;I meant, we copy the data to a safe place, like a DataObject&lt;GPDData&gt;, OR, we &#10;put a MutexLock around it (RTT::os namespace), ie typical critical section &#10;protection. &#10;&#10;Normally, Orocos users don&#039;t need to care that much about critical sections, &#10;because the copying is done between components, but when you&#039;re using an &#10;external library which calls you back, you almost always need a mutex or some &#10;safe-copy container like DataObject.&#10;&#10;&gt; &#10;&gt; &gt; // ...&#10;&gt; &gt; // finally, trigger a new read: (see boost::bind for syntax&#10;&gt; &gt; examples) getGpsData(..., bind(&amp;Component::process_gps_data, this, _1) );&#10;&gt; &#10;&gt; Right! And I guess I don&#039;t have to call this function here if I tell the&#10;&gt; library &quot;Call the callback() everytime you get data&quot; ( which is also&#10;&gt; possible. )&#10;&#10;Exactly.&#10;&#10;Peter