state function library

P

Petroz

Is the following legal:

1/ Calling placement new for a different type that is guaranteed to
have the same member data.
2/ Calling placement new multiple times on the same memory.


example:

struct StateFuctorBase
{
virtual void execute() { throw; }
void *Data;
}

struct StateFunctorA : public StateFuctorBase
{
void execute() { std::cout << "StateFunctorA executed"; }
}

struct StateFunctorB : public StateFuctorBase
{
void execute() { std::cout << "StateFunctorB executed"; }
}


main()
{
StateFunctorBase base;

new (&base) StateFunctorA();
base.execute();

new (&base) StateFunctorB();
base.execute();
}
 
J

James Kanze

Is the following legal:
1/ Calling placement new for a different type that is guaranteed to
have the same member data.

Formally, no. Practically, it doesn't always work either, even
if there is enough memory. (In practice, it's likely to work
when optimization is turned off, and fail when it is turned on.)
2/ Calling placement new multiple times on the same memory.

Formally, only if the class has a trivial
destructor---otherwise, you have to call the destructor before
calling new the second time. Practically, it depends a lot on
what the non-trivial destructor does.
struct StateFuctorBase
{
virtual void execute() { throw; }
void *Data;
}
struct StateFunctorA : public StateFuctorBase
{
void execute() { std::cout << "StateFunctorA executed"; }
}
struct StateFunctorB : public StateFuctorBase
{
void execute() { std::cout << "StateFunctorB executed"; }
}

Formally, there's no guarantee even that StateFunctorB and
StateFunctorA have the same size. Practically, they will have.
Until someone modifies one of them.
main()
{
StateFunctorBase base;
new (&base) StateFunctorA();
base.execute()

new (&base) StateFunctorB();
base.execute();
}

Practically, this simple example may work, although it's
formally undefined behavior. More likely, it will fail---the
compiler has a right to assume that base doesn't change type,
and most compilers, knowing the type of base, will not bother
generating code to go through the virtual function mechanism,
but will call StateFunctorBase::execute directly.

I'm not sure what you're trying to do here, but even if it did
work in some cases, it looks like a good solution to make code
unreadable and unmaintainable.
 
P

Petroz

Thanks for the prompt and informative reply James.
I'm not sure what you're trying to do here, but even if it did
work in some cases, it looks like a good solution to make code
unreadable and unmaintainable.

I was planning on wrapping all that ugliness in macros so it's not
quite so unreadable and unmaintainable.

What I'm trying to do is create a simple way of declaring a function
that has different behavior depending on the objects state. So the
user-code can declare a function 'doStuff()' and then specialize that
function for various states doStuff<Idle>(), doStuff<Fleeing>(), etc.
The goal is to eliminate switch statements all over the code check
what the object's current state is.


The class inherits a generic 'StateObject' which handles updating the
fuctors when setState is called.

class MyClass : StateObject
{
DECLARE_STATE_FUNCTION( update, (int deltaTime) );
};

FUNCTION_STATE( MyClass, Idle, update, (int deltaTime) )
{
//put code here.
}

[ I'm not completely happy with this interface and I'm open to
suggestions ]

The problem I've encountered is there is no easy way to pass the
function arguments [in this case '(int deltaTime)'] inside the macro
because the contain the types and the names. i.e. I can't call a
function like this:
update_impl<Idle>(int deltaTime);

it should be just:
update_impl<Idle>(deltaTime);

For this reason I want the 'MyClass.update' to call the actual
function (in this case a functor's operator() ), the only way i can
think to do this is to have a single functor instance which changes
type. Am I going about this entirely the wrong way, is there a design
pattern for this already?

-Pete
 
Ö

Öö Tiib

Thanks for the prompt and informative reply James.
I'm not sure what you're trying to do here, but even if it did
work in some cases, it looks like a good solution to make code
unreadable and unmaintainable.

I was planning on wrapping all that ugliness in macros so it's not
quite so unreadable and unmaintainable.

What I'm trying to do is create a simple way of declaring a function
that has different behavior depending on the objects state. So the
user-code can declare a function 'doStuff()' and then specialize that
function for various states doStuff<Idle>(), doStuff<Fleeing>(), etc.
The goal is to eliminate switch statements all over the code check
what the object's current state is.

The class inherits a generic 'StateObject' which handles updating the
fuctors when setState is called.

class MyClass : StateObject
{
    DECLARE_STATE_FUNCTION( update, (int deltaTime) );

};

FUNCTION_STATE( MyClass, Idle, update, (int deltaTime) )
{
   //put code here.

}

[  I'm not completely happy with this interface and I'm open to
suggestions ]

The problem I've encountered is there is no easy way to pass the
function arguments [in this case '(int deltaTime)'] inside the macro
because the contain the types and the names. i.e. I can't call a
function like this:
  update_impl<Idle>(int deltaTime);

it should be just:
  update_impl<Idle>(deltaTime);

For this reason I want the 'MyClass.update' to call the actual
function (in this case a functor's operator() ), the only way i can
think to do this is to have a single functor instance which changes
type. Am I going about this entirely the wrong way, is there a design
pattern for this already?

-Pete

Why not to map each possible value of your state to a member function
of the object that has the state? When state value changes then member
function at what it points also changes by the mapping. This sounds at
least doable without breaking all the bones of C++ language also it
might be more obvious what you try to do there.
 
J

Jeff Flinn

Petroz said:
Thanks for the prompt and informative reply James.
I'm not sure what you're trying to do here, but even if it did
work in some cases, it looks like a good solution to make code
unreadable and unmaintainable.

I was planning on wrapping all that ugliness in macros so it's not
quite so unreadable and unmaintainable.

What I'm trying to do is create a simple way of declaring a function
that has different behavior depending on the objects state. So the
....

The problem I've encountered is there is no easy way to pass the
function arguments [in this case '(int deltaTime)'] inside the macro
because the contain the types and the names. i.e. I can't call a
function like this:
update_impl<Idle>(int deltaTime);

it should be just:
update_impl<Idle>(deltaTime);

For this reason I want the 'MyClass.update' to call the actual
function (in this case a functor's operator() ), the only way i can

....

Have you looked at state chart and state transition table
implementations from boost, either the existing statechart library, or
the recently accepted MSM library, or the state transition table example
in the "C++ Template Metaprogramming" book? They completely address the
issues involved in finite state machines.

Jeff
 
J

James Kanze

Thanks for the prompt and informative reply James.
I was planning on wrapping all that ugliness in macros so it's
not quite so unreadable and unmaintainable.
What I'm trying to do is create a simple way of declaring a
function that has different behavior depending on the objects
state. So the user-code can declare a function 'doStuff()' and
then specialize that function for various states
doStuff<Idle>(), doStuff<Fleeing>(), etc. The goal is to
eliminate switch statements all over the code check what the
object's current state is.
The class inherits a generic 'StateObject' which handles
updating the fuctors when setState is called.
class MyClass : StateObject
{
DECLARE_STATE_FUNCTION( update, (int deltaTime) );
};
FUNCTION_STATE( MyClass, Idle, update, (int deltaTime) )
{
//put code here.
}

What's wrong with using the strategy pattern here? That's the
usual solution, and doesn't involve any awkward, under the hood
manipulation of the type of an existing object.
 
P

Petroz

Thanks for all the feedback everyone.

There is no reason why I wouldn't call the destructor if that's the
only problem with my implementation. Since it is a trivial destructor
I omitted it. The main problem I see is what Mr Kanze pointed out,
that compiler optimizations might break it. Would declaring the
instance as 'volatile' and calling the destructor for every new be
sufficient to solve the problem?

Looking at the strategy pattern, it seems to be the same thing I'm
doing except overriding the entire interface instead of per function.
This is definitely in the spirit of what I'm trying to achieve.

Looking at the example code on wikipedia (http://en.wikipedia.org/wiki/
Strategy_pattern), the main difference is the layer of delegation
where the context's exectute() calls the strategy's execute()
function. This requires passing through all the arguments which is
additional maintenance overhead, and difficult to achieve in a macro.
Regardless of whether it's per function or the entire interface, this
delegation layer is what I'm trying to avoid with the placement new.

@Jeff
No i haven't looked at either of those, I will do so now.

-Pete
 
B

Brian

Formally, no.  Practically, it doesn't always work either, even
if there is enough memory.  (In practice, it's likely to work
when optimization is turned off, and fail when it is turned on.)


Formally, only if the class has a trivial
destructor---otherwise, you have to call the destructor before
calling new the second time.  Practically, it depends a lot on
what the non-trivial destructor does.


Would it be better to say trivial destruction rather than
a trivial destructor, since the class could be derived
from a class with a non-trivial destructor?

Currently I'm not calling any destructor when I use
placement new:

template <typename B>
void
Receive(B* buf, File& abt1)
{
new (&abt1) File(buf);
}

I guess it would be safer to make that:

template <typename B>
void
Receive(B* buf, File& abt1)
{
abt1.~File();
new (&abt1) File(buf);
}


Brian Wood
http://webEbenezer.net
(651) 251-9384
 
P

Petroz

Hi Brian,

Yeah, judging from the other posts, I think it's better to call the
destructor before placement new. You just have to be careful that you
don't destruct something which hasn't yet been constructed. If it's on
the stack then that is probably unlikely.

There are probably hairy edge cases as well, what if you destruct,
then the constructor throws, the next time it hits your code it might
try to destruct something which didn't get fully constructed. I'm not
sure, but I think for general purpose use what you have there is safe.

With regard to the boost library, it seems quite powerful and to be
honest I haven't quite wrapped my head around it. From what I've read
it hasn't been used much (if at all) in for game AI.

After further consideration of the strategy pattern I can't think of a
good reason not to use that over what I'm attempting to do. Over the
weekend I'll try to nut out some use-cases and see what fits best.

Thanks for the help everyone!
-Pete
 
J

James Kanze

Would it be better to say trivial destruction rather than a
trivial destructor, since the class could be derived from a
class with a non-trivial destructor?

In which case, it doesn't have a trivial destructor. The
standard uses the words "trivial destructor" in this context,
and defines "trivial destructor"; the basic effects of the
meaning is that a "trivial destructor" is a no-op. (The
standard language is, of course, a lot more complex: the
destructor is trivial if it is not user defined, all of the
bases and members have trvial destructors, there are no virtual
functions, and perhaps some other conditions I've forgotten.)
Currently I'm not calling any destructor when I use
placement new:
template <typename B>
void
Receive(B* buf, File& abt1)
{
new (&abt1) File(buf);
}
I guess it would be safer to make that:
template <typename B>
void
Receive(B* buf, File& abt1)
{
abt1.~File();
new (&abt1) File(buf);
}

Yes and no. What happens if an exception is raised in "new"?
What happens in the calling code?

My advice is to just forget this sort of thing. It's just too
error prone, and will come back and bite you in the end.
 
B

Brian

In which case, it doesn't have a trivial destructor. The
standard uses the words "trivial destructor" in this context,
and defines "trivial destructor"; the basic effects of the
meaning is that a "trivial destructor" is a no-op. (The
standard language is, of course, a lot more complex: the
destructor is trivial if it is not user defined, all of the
bases and members have trvial destructors, there are no virtual
functions, and perhaps some other conditions I've forgotten.)

I wondered about that briefly. Thanks for clarifying.

Yes and no. What happens if an exception is raised in "new"?
What happens in the calling code?


The alternative is to pass a pointer:

template <typename B>
void
Receive(B* buf, File* abt1)
{
abt1 = new File(buf);
}

And the caller is responsible for deleting the object.
I guess the benefit of that is exception safety.


Brian Wood
 
B

Brian

I wondered about that briefly.  Thanks for clarifying.







The alternative is to pass a pointer:

  template <typename B>
  void
  Receive(B* buf, File* abt1)

That should be:

Receive(B* buf, File*& abt1) ...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top