How to use Command::reset()

Hie,
I try to use the reset on commmands. I thought I could reuse a command which would not be finished.
You can see on the following exactly what I tried (on C++ code):

//In the component calling the command :
cmdMyCommand = ...->getCommand("cmdMyCommand");
cmdMyCommand(2);
cmdMyCommand.reset();
cmdMyCommand(3);

//In the component executing the command
bool cmdDoMyCommand(int a)
{
log(Info) << "my value is : " << a << endlog();
}

//what I see on my logs:
my value is 3
my value is 3

=> I thought I would get only once "my value is 3", but I have twice. How do you think I could do better?
Thanks for your help.
Guillaume

How to use Command::reset()

On Monday 26 January 2009 12:27:18 gde [..] ... wrote:
> Hie,
> I try to use the reset on commmands. I thought I could reuse a command
> which would not be finished. You can see on the following exactly what I
> tried (on C++ code):
>
>
> //In the component calling the command :
> cmdMyCommand = ...->getCommand("cmdMyCommand");
> cmdMyCommand(2);
> cmdMyCommand.reset();
> cmdMyCommand(3);

Say that after cmdMyCommand(2), another command ('Cx()' ) is called. Would you
expect cmdMyCommand(3) to be run A. instead of cmdMyCommand(2) or B. after
'Cx()' ?

To orocos-dev:
Sander proposed to check the state of the command when it's pulled from the
queue. A reset() would then leave it in the queue, but with such a state that
it would be discarded when dequeued. In addition, if a command ends up twice
in the queue, the first one is executed and the second one is discarded (again
by checking state).

The net result of this minimal change is that the first command in queue is
executed with the data of the first and the second command is discarded, hence
my question.

diff --git a/src/LocalCommand.hpp b/src/LocalCommand.hpp
index b4e3edf..750843b 100644
--- a/src/LocalCommand.hpp
+++ b/src/LocalCommand.hpp
@@ -226,6 +226,9 @@ namespace RTT
             }
 
             virtual bool execute() {
+                // do not allow to execute twice or if not queued.
+                if (!this->maccept || this->mexec)
+                    return false;
                 this->mvalid = this->exec();
                 this->mexec = true;
                 return this->mvalid;

Peter

How to use Command::reset()

On Monday 26 January 2009 12:27:18 gde [..] ... wrote:
> Hie,
> I try to use the reset on commmands. I thought I could reuse a command
> which would not be finished. You can see on the following exactly what I
> tried (on C++ code):
>
>
> //In the component calling the command :
> cmdMyCommand = ...->getCommand("cmdMyCommand");
> cmdMyCommand(2);
> cmdMyCommand.reset();
> cmdMyCommand(3);

Say that after cmdMyCommand(2), another command ('Cx()' ) is called. Would you
expect cmdMyCommand(3) to be run A. instead of cmdMyCommand(2) or B. after
'Cx()' ?

To orocos-dev:
Sander proposed to check the state of the command when it's pulled from the
queue. A reset() would then leave it in the queue, but with such a state that
it would be discarded when dequeued. In addition, if a command ends up twice
in the queue, the first one is executed and the second one is discarded (again
by checking state).

The net result of this minimal change is that the first command in queue is
executed with the data of the first and the second command is discarded, hence
my question.

diff --git a/src/LocalCommand.hpp b/src/LocalCommand.hpp
index b4e3edf..750843b 100644
--- a/src/LocalCommand.hpp
+++ b/src/LocalCommand.hpp
@@ -226,6 +226,9 @@ namespace RTT
             }
 
             virtual bool execute() {
+                // do not allow to execute twice or if not queued.
+                if (!this->maccept || this->mexec)
+                    return false;
                 this->mvalid = this->exec();
                 this->mexec = true;
                 return this->mvalid;

Peter

How to use Command::reset()

Le jeudi 29 janvier 2009 à 10:37 +0100, Peter Soetens a écrit :
> On Monday 26 January 2009 12:27:18 gde [..] ... wrote:
> > Hie,
> > I try to use the reset on commmands. I thought I could reuse a command
> > which would not be finished. You can see on the following exactly what I
> > tried (on C++ code):
> >
> >
> > //In the component calling the command :
> > cmdMyCommand = ...->getCommand("cmdMyCommand");
> > cmdMyCommand(2);
> > cmdMyCommand.reset();
> > cmdMyCommand(3);
>
> Say that after cmdMyCommand(2), another command ('Cx()' ) is called. Would you
> expect cmdMyCommand(3) to be run A. instead of cmdMyCommand(2) or B. after
> 'Cx()' ?
>

I think B could do what I expect.
In fact, when I call reset(), I expect that the cmdMyCommand(2) is
canceled, so is never executed. I don't want to replace cmdMyCommand(2)
by cmdMyCommand(3), but I would like to remove cmdMyCommand(2).
Guillaume

> To orocos-dev:
> Sander proposed to check the state of the command when it's pulled from the
> queue. A reset() would then leave it in the queue, but with such a state that
> it would be discarded when dequeued. In addition, if a command ends up twice
> in the queue, the first one is executed and the second one is discarded (again
> by checking state).
>
> The net result of this minimal change is that the first command in queue is
> executed with the data of the first and the second command is discarded, hence
> my question.
>
>

> diff --git a/src/LocalCommand.hpp b/src/LocalCommand.hpp
> index b4e3edf..750843b 100644
> --- a/src/LocalCommand.hpp
> +++ b/src/LocalCommand.hpp
> @@ -226,6 +226,9 @@ namespace RTT
>              }
> 
>              virtual bool execute() {
> +                // do not allow to execute twice or if not queued.
> +                if (!this->maccept || this->mexec)
> +                    return false;
>                  this->mvalid = this->exec();
>                  this->mexec = true;
>                  return this->mvalid;
> 

>
> Peter

How to use Command::reset()

Le jeudi 29 janvier 2009 à 10:37 +0100, Peter Soetens a écrit :
> On Monday 26 January 2009 12:27:18 gde [..] ... wrote:
> > Hie,
> > I try to use the reset on commmands. I thought I could reuse a command
> > which would not be finished. You can see on the following exactly what I
> > tried (on C++ code):
> >
> >
> > //In the component calling the command :
> > cmdMyCommand = ...->getCommand("cmdMyCommand");
> > cmdMyCommand(2);
> > cmdMyCommand.reset();
> > cmdMyCommand(3);
>
> Say that after cmdMyCommand(2), another command ('Cx()' ) is called. Would you
> expect cmdMyCommand(3) to be run A. instead of cmdMyCommand(2) or B. after
> 'Cx()' ?
>

I think B could do what I expect.
In fact, when I call reset(), I expect that the cmdMyCommand(2) is
canceled, so is never executed. I don't want to replace cmdMyCommand(2)
by cmdMyCommand(3), but I would like to remove cmdMyCommand(2).
Guillaume

> To orocos-dev:
> Sander proposed to check the state of the command when it's pulled from the
> queue. A reset() would then leave it in the queue, but with such a state that
> it would be discarded when dequeued. In addition, if a command ends up twice
> in the queue, the first one is executed and the second one is discarded (again
> by checking state).
>
> The net result of this minimal change is that the first command in queue is
> executed with the data of the first and the second command is discarded, hence
> my question.
>
>

> diff --git a/src/LocalCommand.hpp b/src/LocalCommand.hpp
> index b4e3edf..750843b 100644
> --- a/src/LocalCommand.hpp
> +++ b/src/LocalCommand.hpp
> @@ -226,6 +226,9 @@ namespace RTT
>              }
> 
>              virtual bool execute() {
> +                // do not allow to execute twice or if not queued.
> +                if (!this->maccept || this->mexec)
> +                    return false;
>                  this->mvalid = this->exec();
>                  this->mexec = true;
>                  return this->mvalid;
> 

>
> Peter

Ruben Smits's picture

How to use Command::reset()

On Thursday 29 January 2009 10:37:03 Peter Soetens wrote:
> On Monday 26 January 2009 12:27:18 gde [..] ... wrote:
> > Hie,
> > I try to use the reset on commmands. I thought I could reuse a command
> > which would not be finished. You can see on the following exactly what I
> > tried (on C++ code):
> >
> >
> > //In the component calling the command :
> > cmdMyCommand = ...->getCommand("cmdMyCommand");
> > cmdMyCommand(2);
> > cmdMyCommand.reset();
> > cmdMyCommand(3);
>
> Say that after cmdMyCommand(2), another command ('Cx()' ) is called. Would
> you expect cmdMyCommand(3) to be run A. instead of cmdMyCommand(2) or B.
> after 'Cx()' ?
>
> To orocos-dev:
> Sander proposed to check the state of the command when it's pulled from the
> queue. A reset() would then leave it in the queue, but with such a state
> that it would be discarded when dequeued. In addition, if a command ends up
> twice in the queue, the first one is executed and the second one is
> discarded (again by checking state).

This does not look like desired behaviour to me :s, since the execution of the
commands would depend on the scheduling of the activities of the caller and
the callee. If the first command is dequeued by the callee before the caller
queues the second command the execution is different than in the case were the
caller is not interrupted by the callee in between the two calls of the
caller.

Ruben

>
> The net result of this minimal change is that the first command in queue is
> executed with the data of the first and the second command is discarded,
> hence my question.

>

> diff --git a/src/LocalCommand.hpp b/src/LocalCommand.hpp
> index b4e3edf..750843b 100644
> --- a/src/LocalCommand.hpp
> +++ b/src/LocalCommand.hpp
> @@ -226,6 +226,9 @@ namespace RTT
>              }
>
>              virtual bool execute() {
> +                // do not allow to execute twice or if not queued.
> +                if (!this->maccept || this->mexec)
> +                    return false;
>                  this->mvalid = this->exec();
>                  this->mexec = true;
>                  return this->mvalid;
> 

>
> Peter
> --
> Peter Soetens -- FMTC -- <http://www.fmtc.be>

Disclaimer: http://www.kuleuven.be/cwis/email_disclaimer.htm

Ruben Smits's picture

How to use Command::reset()

On Thursday 29 January 2009 10:37:03 Peter Soetens wrote:
> On Monday 26 January 2009 12:27:18 gde [..] ... wrote:
> > Hie,
> > I try to use the reset on commmands. I thought I could reuse a command
> > which would not be finished. You can see on the following exactly what I
> > tried (on C++ code):
> >
> >
> > //In the component calling the command :
> > cmdMyCommand = ...->getCommand("cmdMyCommand");
> > cmdMyCommand(2);
> > cmdMyCommand.reset();
> > cmdMyCommand(3);
>
> Say that after cmdMyCommand(2), another command ('Cx()' ) is called. Would
> you expect cmdMyCommand(3) to be run A. instead of cmdMyCommand(2) or B.
> after 'Cx()' ?
>
> To orocos-dev:
> Sander proposed to check the state of the command when it's pulled from the
> queue. A reset() would then leave it in the queue, but with such a state
> that it would be discarded when dequeued. In addition, if a command ends up
> twice in the queue, the first one is executed and the second one is
> discarded (again by checking state).

This does not look like desired behaviour to me :s, since the execution of the
commands would depend on the scheduling of the activities of the caller and
the callee. If the first command is dequeued by the callee before the caller
queues the second command the execution is different than in the case were the
caller is not interrupted by the callee in between the two calls of the
caller.

Ruben

>
> The net result of this minimal change is that the first command in queue is
> executed with the data of the first and the second command is discarded,
> hence my question.

>

> diff --git a/src/LocalCommand.hpp b/src/LocalCommand.hpp
> index b4e3edf..750843b 100644
> --- a/src/LocalCommand.hpp
> +++ b/src/LocalCommand.hpp
> @@ -226,6 +226,9 @@ namespace RTT
>              }
>
>              virtual bool execute() {
> +                // do not allow to execute twice or if not queued.
> +                if (!this->maccept || this->mexec)
> +                    return false;
>                  this->mvalid = this->exec();
>                  this->mexec = true;
>                  return this->mvalid;
> 

>
> Peter
> --
> Peter Soetens -- FMTC -- <http://www.fmtc.be>

Disclaimer: http://www.kuleuven.be/cwis/email_disclaimer.htm

How to use Command::reset()

On Thursday 29 January 2009 10:50:34 Ruben Smits wrote:
> On Thursday 29 January 2009 10:37:03 Peter Soetens wrote:
> > On Monday 26 January 2009 12:27:18 gde [..] ... wrote:
> > > Hie,
> > > I try to use the reset on commmands. I thought I could reuse a command
> > > which would not be finished. You can see on the following exactly what
> > > I tried (on C++ code):
> > >
> > >
> > > //In the component calling the command :
> > > cmdMyCommand = ...->getCommand("cmdMyCommand");
> > > cmdMyCommand(2);
> > > cmdMyCommand.reset();
> > > cmdMyCommand(3);
> >
> > Say that after cmdMyCommand(2), another command ('Cx()' ) is called.
> > Would you expect cmdMyCommand(3) to be run A. instead of cmdMyCommand(2)
> > or B. after 'Cx()' ?
> >
> > To orocos-dev:
> > Sander proposed to check the state of the command when it's pulled from
> > the queue. A reset() would then leave it in the queue, but with such a
> > state that it would be discarded when dequeued. In addition, if a command
> > ends up twice in the queue, the first one is executed and the second one
> > is discarded (again by checking state).
>
> This does not look like desired behaviour to me :s, since the execution of
> the commands would depend on the scheduling of the activities of the caller
> and the callee. If the first command is dequeued by the callee before the
> caller queues the second command the execution is different than in the
> case were the caller is not interrupted by the callee in between the two
> calls of the caller.

A Command::reset() will always depend on the execution order of the callee.
The above scenario clearly only applies to SlaveActivity's or a twisted
priority ordering. The question is also if, after Command::reset(), the
command object may be destroyed or not. Currently, you can't, which is a
stability problem. From a safety view, I would remove it from the queue when
reset().

The real (fundamental) problem we're having is that the command object is
reused, which causes ambiguities. In 'pure' event/message based systems, the
object is sent and forgotten and can no longer be canceled or removed. It can
only be overridden by sending a new, second object to the same target that
overrides the first.

An rt-malloc implementation could allow to lift this restriction, both for
events(which suffer the same) and commands.

Peter

How to use Command::reset()

On Monday 26 January 2009 12:27:18 gde [..] ... wrote:
> Hie,
> I try to use the reset on commmands. I thought I could reuse a command
> which would not be finished. You can see on the following exactly what I
> tried (on C++ code):
>
>
> //In the component calling the command :
> cmdMyCommand = ...->getCommand("cmdMyCommand");
> cmdMyCommand(2);
> cmdMyCommand.reset();
> cmdMyCommand(3);
>
> //In the component executing the command
> bool cmdDoMyCommand(int a)
> {
> log(Info)

This mail got cut-off on the mailing list... for some reason. Next time, try to
post on the website as a MediaWiki and use  ... to guard your
code. It looks nicer too ! Anyway, it continues like this...

Quote:

<< "my value is : " << a << endlog();
}

//what I see on my logs:
my value is 3
my value is 3

=> I thought I would get only once "my value is 3", but I have twice. How do
you think I could do better?

A command doesn't remove itself from a command queue when it is reset(). When
you execute it a second time, it is pushed again in the queue. I don't know
yet how easy it is to extend reset() such that it effectively removes the
command from the queue. We would need to extend AtomicQueue.hpp and the
CommandProcessor interface such that queued commands can be removed (as long
as they are in the queue...).

I won't have time until thursday to take a look at this, but it should be
possible to fix without much effort.

Peter