Queue of function calls

R

Richard Berg

Hello,

I need implementation advice:
I am writing a program that should call some API functions in a
specific order. The APIs are for another application, not Windows
APIs. The order and type of the calls is determined at runtime. There
are a couple of hundred of those APIs that can be called, and they all
take different parameters. What I need is somehow queue the calls with
their parameters and then dequeue and execute them one by one... Now I
really have no idea on how to acomplish anything like this. Could
someone please advice me? I can provide more details if needed.

Please reply to the group.

Thank you!
 
V

Victor Bazarov

Richard Berg said:
I need implementation advice:
I am writing a program that should call some API functions in a
specific order. The APIs are for another application, not Windows
APIs. The order and type of the calls is determined at runtime. There
are a couple of hundred of those APIs that can be called, and they all
take different parameters. What I need is somehow queue the calls with
their parameters and then dequeue and execute them one by one... Now I
really have no idea on how to acomplish anything like this. Could
someone please advice me? I can provide more details if needed.

Wrap the queuing part and dequeuing into some kind of interpreter
of strings -- basically a mechanism that would read a given string
and extract the name of the function to call and values of the args
for that function. Then it would call it. If the function throws
or returns an error, you'll need some mechanism to account for that.

To create a queue, the user would call your "queue stuffer" with
a string, something like

Queue.add("myfunction_1, 123, 3.14, 'a'");
Queue.add("myfunction_2, \"string\", 42"); // need to use \"

then

Queue.execute();

which would go through the strings and execute them one by one.
You can add "syntax" checking to the 'add' method.

Honestly, I don't see any language issue here. Perhaps you should
try comp.programming for more advice on interpreters.

Victor
 
S

Samuele Armondi

Samuele Armondi said:
I'm not sure if this is the best solution or indeed what you are asking for,
but here goes... create an Argument base class, and derive all your argument
classes from it. using polymorphism, you will be able to treat all these
arguments the same, even thought they will be of different types (provided
of course you pass them around by pointer or reference).
Now create an class to hold the arguments (say, ArgumentContainer). This
class will hold the number of arguments and an array of _pointers_ to these
arguments (otherwise polymorphism goes through the window). Then wrap your
api functions so that they take your ArgumentContainer as an argument, and
store them in a map, like this:
typedef bool (*ApiPointer)(ArgumentContainer)
std::map <std::string, ApiPointer> FunctionMap;
where the string is the function name. now you can use a std::queue
or std::deque<string> to queue these calls up and then look them up by name
in the map.
I hope it makes sense!
HTH,
S. Armondi
BTW, I have got some code that does something like what I set out above if
you want to take a look
S
 
R

Richard Berg

Samuele Armondi said:
BTW, I have got some code that does something like what I set out above if
you want to take a look
S

Thanks for your reply. I was thinking along the same lines... What I
don't really understand is how to call the API function once I have
its name (as string) and a list of arguments (wrapped in classes). Of
course I could make a gigantic if-statement like:

if(strcmp(name, "DoSomething")) {
DoSomething();
}
else if(strcmp(name, "DoOther")) {
DoOther();
}

but this would be terribly ugly when I have hundreds of
possibilities...
Do you see what I mean?

Thanks!
 
A

Alf P. Steinbach

Richard said:
I am writing a program that should call some API functions in a
specific order. The APIs are for another application, not Windows
APIs. The order and type of the calls is determined at runtime. There
are a couple of hundred of those APIs that can be called, and they all
take different parameters. What I need is somehow queue the calls with
their parameters and then dequeue and execute them one by one...

Check out the functor object implementation(s) in Andrei Alexandrescu's
book "Modern C++ Design"; I'm suggesting here a "Command object"-based
implementation using templated functor objects, which you'll find at least
one example of in the book.

The drawback of that type-safe method is that you'll need to define one
functor class for each distinct function signature. Whether to define each
functor class once or e.g. via some template mechanism at each usage point
is one design decision you'll need to address. Probably a combination of
predefined functors + support for ad-hoc definitions would be best.

If you're actually going to use all those API-functions then the
"Command object" solution is probably not too much work in comparision with
other methods and in comparision with the client code.
 
T

tom_usenet

Hello,

I need implementation advice:
I am writing a program that should call some API functions in a
specific order. The APIs are for another application, not Windows
APIs. The order and type of the calls is determined at runtime. There
are a couple of hundred of those APIs that can be called, and they all
take different parameters. What I need is somehow queue the calls with
their parameters and then dequeue and execute them one by one... Now I
really have no idea on how to acomplish anything like this. Could
someone please advice me? I can provide more details if needed.

Please reply to the group.

Download boost from www.boost.org. Then:

#include <boost/function.hpp>
#include <boost/bind.hpp>

typedef boost::function<void()> void_function_t;

std::deque<void_function_t> queue;

void execute_queue()
{
for(std::deque<void_function_t>::iterator i = queue.begin(),
end = queue.end();
i != end;
++i)
{
(*i)();
}
queue.clear();
}

Then to add a call to the queue, just do:

queue.push_back(boost::bind(myapifunction, param1, param2, param3));

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
 
S

Samuele Armondi

Richard Berg said:
"Samuele Armondi" <[email protected]> wrote in message
[SNIP]
Thanks!

Ok, I'll go through how i did it...I didn't use polymorphism since I did not
need it, but the bare bones is here.

This is your abstract base class, from which all the argument types will
inherit.
class ArgBase
{
//whatever
}

This is the class that holds all the arguments for a function
class FunctionArguments
{
private:
int NumArgs;
ArgBase *Args; //This could be a std::vector rather than an array
const ArgTypes operator [] (const int) const;
public:
FunctionArguments();
FunctionArguments(int);
FunctionArguments(const FunctionArguments&); // throws
MemCopyError
~FunctionArguments();
FunctionArguments& operator = (const FunctionArguments&); // Need to
be defined because the class allocates memory

const int GetNumArgs() const;
// all the functions to set/retrieve the argument values
};

typedef bool (*FunctionPointer) (const FunctionArguments&);

This class holds the information about a function, such as its name, how
many arguments it takes, ecc. I used a string to represent the argument
sequence, for example a string "ii" meant that a function expected two
integer arguments, "fs" meant float and string, ecc...
class FunctionRecord
{
private:
std::string FunctionName;
std::string ArgumentSequence;
FunctionPointer Function; // Pointer to the actual function
int NumArgs;

bool CheckArgSequence(std::string&);
public:
FunctionRecord(std::string, std::string, int, FunctionPointer);
//throws InvalidArgSequence exception
FunctionRecord();
//This function executes the API call. It inderects FunctionPointer
and passes all the arguments to the actual API call
bool Do(const FunctionArguments&) const;
const std::string& GetArgSequence() const;
const std::string& GetFunctionName() const;
const int GetArgNum() const;
};

Then, you can hold everything in a map:
typedef std::map<std::string, FunctionRecord> FunctionMap;

I added most of the functions at compile time, but I did also make it
possible to add them at runtime. This code comes from the bare bones for an
in-game console I wrote for a friend, but it can very easily be adapted to
your needs.

Once you have the name of the function, you can look it up in the map and
call FunctionMap::second.Do(Arguments) to execute the call.
HTH!!
S. Armondi
 

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,159
Messages
2,570,879
Members
47,413
Latest member
ReeceDorri

Latest Threads

Top