Object-oriented jump table defined over multiple classes - c++

I am in the midst of refactoring a NMOS6502 emulator into multiple classes. I was wondering if there is an "object-oriented" way to define a function jump table. Basically, I have defined separate instruction classes to classify groups of related cpu operations- like "CStackInstHandler" or "CArithmeticInstHandler" which will have a reference to a cpu object. Each instruction class is derived from an abstract instruction class. Each derived instruction class has a set of functions which will use the cpu object's public interface to change the cpu state e.g:
uint8_t opcode = _memory->readMem(_cpu->getProgramCounter());
AInstructionHandler* _handler = _cpu->getInstHandler(opcode);
_handler->setCpu(&cpu);
_handler->setMemory(&memory);
_handler->execute(opcode);
The problem is that at runtime an instruction handler as well as the appropriate member function defined for that handler needs to be determined using an opcode.
So we have - opcode is read from memory, a table is used by the cpu to map opcode to instruction handler type, and then the same opcode is used by the instruction handler to select the correct function. Each instruction overrides an "execute" function e.g:
void CBranchInstHandler::execute() {
switch(_opcode) {
case 0x90:
this->BCC();
break;
case 0xb0:
this->BCS();
break;
case 0xf0:
this->BEQ();
break;
case 0x30:
this->BMI();
break;
case 0xd0:
this->BNE();
break;
case 0x10:
this->BPL();
break;
default:
break;
}
}
void CBranchInstHandler::BCC() {
uint16_t address = this->getAddress();
if(!_cpu->isCarry()) {
uint16_t pc = _cpu->getPC();
pc += address;
_cpu->setPC(pc);
}
}
/*more instruction specific functions...*/
I end up with two look-ups, one of which is redundant. One to select the handler, and another to select the handler function. I feel like this is the wrong way to accomplish this task, but I am not sure of an alternative that doesn't just devolve into groups of non-member functions.
I am wondering if anyone has insight into this problem. It basically boils down to wanting to refactor a class into smaller bites (cpu class with instruction member functions refactored to cpu class and instruction classes), but the all of the components are so interrelated that I end up having to repeat myself. Redundancy is introduced.
A non-object oriented solution would be to just have these instructions be non-member functions that accept a cpu reference. Then, a function jump table would be defined, instructions would be looked up and indexed by opcode and executed.
This doesn't really seem practical with objects. I could make all the instructions static or something but this seems to miss the point.
Any insight or information about even tangentially related problems would be super helpful.
Thanks.

I'm going to promote my comment to an answer: the object-oriented solution is, as you say, to give the child classes full responsibility for deciding which opcodes they respond to.
I'd suggest that the easiest way of doing that isn't to try to build a two-stage switch but simply to route every opcode to every child and let the child either contribute or not. That's the minimum viable solution.
If you need an optimisation then the easiest thing would be to reformulate:
void CBranchInstHandler::execute() {
switch(_opcode) {
case 0x90:
this->BCC();
break;
... etc ...
}
}
To:
FuncPtr CBranchInstHandler::execute() {
switch(_opcode) {
case 0x90:
return BCC;
... etc ...
}
return NULL;
}
So each execute returns whether it in fact handled that opcode.
Within the parent class you could then simply keep a table from opcode to function pointer. An array will do. The table will initially contain NULLs throughout.
When performing an opcode, look up the handler in the table. If the handler is there, call it and move on. If not then call execute on every child in turn until someone that returns a handler, then put them into the table and then call it. So you'll build it just-in-time, at runtime. The first run of each opcode will take slightly longer but you'll subsequently have what amounts to a jump table.
The advantage of that is that it allows the information about what a child handles to be tied closely to the actual handling of it syntactically, reducing code overhead and the probability of error.

If I understand, what you are doing is creating a class for each type of instruction (Branch, Arithmetic, Load, Store, etc) and then within those you are writing member functions for the individual instructions -- c.f. you have a "CBranchInstrHandler" which handles "branch on carry", "branch on zero" etc?
The fully Object Oriented approach is to extend your subclassing down to individual instructions.
class CBranchInstrHandler { virtual void execute() = 0; };
class CBranchOnCarryClear : public CBranchInstrHandler {
void execute() override {
...;
}
};
class CBranchOnCarrySet : public CBranchInstrHandler {
void execute() override {
...;
}
};
Now you can look your instructions up in one shot, but you'll need a one-to-one mapping of all of these.
switch (opCode) {
case 0x90: return .. CBranchOnCarryClear .. ;
case 0xB0: return .. CBranchOnCarrySet .. ;
}
The elipsis are there because I'm not sure how you are getting a pointer to your CBranchInstrHandler; I'm guessing that they are static and that you aren't newing them every instruction.
If they are dataless, you can return them as function objects by value:
struct Base { virtual void execute() { /* noop */ } };
struct Derived { void execute(override) { ... } };
Base getHandler(opcode_t opcode) {
if (opcode == 1) { return Derived(); }
}
but I suspect you probably want to take parameters and store state, in which case return by value here could result in slicing.
Of course, if you are using C++11 you could use lambdas:
switch (opCode) {
case 0x90: return [this] () {
... implement BCC execute here ...
};
case 0xB0: return [this] () {
... implement BCS execute here ...
}
}

You could use pointer to class member function/method:
void (CBranchHandlerBase::*)();
Using for store the pointers to the methods which should be invoked for given _opcode.
map<uint8_t, void (CBranchHandlerBase::*)()> handlers;
handlers[0x90] = &BCC;
handlers[0xb0] = &BCS;
...
The code above should be provided in the initialize section/method inside your base class for the handlers. Of course BCC, BCS and so on must be declared as pure virtual methods to make the approach work.
Then instead of your switch:
void CBranchHandlerBase::execute() {
(this->*handlers[_opcode])();
}
Note that execute is defined in the base class (and it does not have to be virtual! as each Handler will have the same functionality of execute method).
Edit: The map actually can be replaced by the vector or array of size: 2^(8*sizeof(uint8_t)) for efficiency reasons

Related

Should I and how do I create progress reporting in computation demanding algorithms in c++

I am implementing some Deep Learning Neural Networks and existing code from Matlab normaly just prints out to the console such users have an idea of progress.
When I am doing my design for C++ and have put core parts of the algorithms into separate functions that I do not want to print stuff out to the console, are there ways or design principles for leaving a option to the users who use the algorithm to get some kind of progress indication?
Could one let a optional parameter be a function pointer that people could hook into, or how would I do this?
void my_heavy_algorithm(int * data, int n,...);
If you are exposing your algorithm as a collection of functions then the way to go would be to have one of the parameters be a function pointer with a signature like this:
void (*reportProgress)(void*, int)
But if you are designing your algorithm in C++ you should probably take advantage of encapsulation and create a class (or set of classes) for your algorithm. In this case you wouldn't want to add the function pointer as a parameter to the individual functions.
Rather you might make the function pointer a member of your class. And have accessor methods to get/set it. Or even better, provide an abstract class for reporting progress.
class ProgressReporter
{
public:
virtual ~ProgressReporter() = 0;
virtual void notifyProgressChanged(void* source, int progressValue) = 0;
}
class Algo
{
private:
ProgressReporter* _userProvidedReporter = NULL;
public:
void set_ProgressReporter(ProgressReporter*); // set accessor
ProgressReporter* get_ProgressReporter(); // get accessor
void my_heavy_algorithm(int*, int, ...); // your algo. implementation fn.
}
void Algo::set_ProgressReporter(ProgressReporter* reporter){
_userProvidedReporter = reporter;
}
ProgressReporter* Algo::get_ProgressReporter(){
return _userProvidedReporter;
}
void Algo::my_heavy_algorithm(int * data, int n,...){
// do stuff
if(_userProvidedReporter != NULL)
_userProvidedReporter->notifyProgressChanged((void*)this, currentProgress);
// do more stuff
if(_userProvidedReporter != NULL)
_userProvidedReporter->notifyProgressChanged((void*)this, currentProgress);
// so on and so forth..
}
Of course the above is a pretty simplistic example. If you expect your algorithms to support concurrency you should synchronize access to the internal user reporter and you might consider creating a base class for your algorithm and provide concrete derived implementations..
STL style functors may help you. This would also allow yor algorithm be used withoud any progress indicator.
For example, let's say you'd like to give a percent progress indicator.
// disclaimer - I didn't compile this code
class NoProgressFeedback; // see below
void my_heavy_algorithm(int * data, int n, ProgressFeedback giveFeedback = NoProgressFeedback() {
int percentProgress = 0;
giveFeedback(percentProgress);
/* start calculations, do stuff */
percentProgress++;
giveFeedback(percentProgress);
/* continue over and repeat percentProgress updates and giveFeedback calls */
}
/* NoProgressFeedback will do no progress feedback */
class NoProgressFeedback {
public:
operator()(int percent) {}
}
If user code wants feedback, then it should pass your my_heavy_algorithm function a different progress indicator, that sould look like this:
class GetProgressFeedback {
public:
void operator()(int percent) { std::cout << "percent advance: " << percent; }
}
Take a look at Dependancy Injection.
You can pass an object that implements an IProgress interface. A NullProgress object could just have the stubs but does no real work for objects you aren't interested in monitoring.
The usual way is to run your computationally heavy work in seperate thread and use that to update a section of memory via a lock. The UI thread then reads periodically from this memory location and updates the screen accordingly.
To report proper progress, you need three things:
An estimate of the total work to be done.
An estimate of how much work has been done so far.
A source of time.
You also need some way for your "heavy math" function to "report in". One way to do that is to have some sort of function that you call in the "start of function", "progress so far" and "end of function". The start of function also sets "total amount of work to do". Progress so far reports "how much is done now", and "end of function" says "I'm complete".
In a C++ class environment, this could be done as:
class Progress
{
Progress() { };
virtual void Start(int todo) = 0;
virtual void Done(int doneSoFar) = 0;
virtual void Finish();
};
This provides an interface that other classes can be derived from.
Of course, you still need to find a useful pace to put your "Done()" - if you put it too deep inside some tight loop, it will impact performance, but you need to do it often enough that it shows some useful progress too.

Creating new object with parameter

void ChangeState(int newState)
{
nextState = newState;
//Change the state
switch( nextState ) ///the change still will have a case for everything
{
case STATE_INTRO:
{
vec.pop_back();
state ptr(new CIntroState);
vec.push_back(ptr);
break;
}
case STATE_MENU:
{
vec.pop_back();
state ptr(new CMainMState);
vec.push_back(ptr);
break;
}
}
}
I have this function that allows me to change my current state; however, I thought about it and this is going to be a huge switch statement by the time I am finished. Currently, it already has about 10 states in it, this is just some sample code. I am trying to do something a little different, but I am not sure how to go about it.
void ChangeState(something)
{
vec.pop_back();
state ptr(new something);
vec.push_back(ptr)
}
If I could bring it in this way, I could completely avoid the use of the switch statement and get the same end result. Does anyone know how to go about this? Any help would be greatly appreciated.
You need to link compile-time polymorphism (i.e., templates) and run-time polymorphism, as ryanbwork suggests. The challenge here is to try to avoid transforming your current form of repetitive code (the big switch) into a similarly verbose but more declarative form of repetitive code.
As another popular Stack Overflow question reveals, clone methods are usually the way one creates new instances of dynamically determined types at run-time. Cloning is really a specialization of the more general factory pattern, and you could create a set of factories for your types whose definition would be only a little more verbose than your current enumeration presumably is:
template <class T>
class factory {
public:
T* operator()() {return new T;}
};
factory<CIntroState> IntroState;
factory<CMainState> MainState;
// etc...
template <class Fac>
void ChangeState(Fac newStateFactory)
{
vec.pop_back();
vec.push_back(newStateFactory());
}
It looks like you need a combination of templates and polymorphism. With templates, you don't need to enumerate all the different types that you may pass into a function, as this will be done for you during compilation. To store all of these different types in the same vector, you'll need to have them all sub class some super-type which then allows you to store them side by side in a vector of super-type.

A proper way to restrict access to an interface?

Let's say I have a class that represents a printing job: CPrintingJob. It knows nothing of the document being printed, just the job state - whether the job was queued, rejected, carried on etc.
The idea is an object of this class is instantiated whenever some printing needs to be done, then passed to the printing module along with other data, then the job's creator checks its state to see how printing is going.
Suppose CPrintingJob inherits two interfaces:
class IPrintingJob // this one is to check the job state
{
virtual TState GetState() const = 0;
// ... some other state-inquiring methods
class ICallback // job's owner is notified of state changes via this one
{
virtual void OnStateChange( const IPrintingJob& Job ) = 0;
};
};
and
class IPrintingJobControl // this one is for printing module to update the state
{
virtual void SetState( const TState& NewState ) = 0;
// ... some other state-changing methods
};
Problem is, the class that creates a CPrintingJob object shouldn't have access to the IPrintingJobControl, but the printing module CPrintingJob is being passed to must be able to change its state and, therefore, have access to that interface.
I suppose this is exactly the case where friends should be used but I have always avoided them as an inherently flawed mechanic and consequently have no idea of how to use them properly.
So, how do I do it properly?
Use a factory and have the factory return an instance of IPrintingJob (best wrapped inside a smart_ptr). e.g.:
struct PrintingFactory {
static auto create() -> std::unique_ptr<IPrintingJob> {
return std::unique_ptr<IPrintingJob>(new CPrintingJob());//as there is currently no std::make_unique..
}
}
Once you have to use the JobControl you can simply cast the pointer via std::dynamic_pointer_cast.
After some deliberation I've decided that:
This whole thing is definitely more trouble than it's worth;
(A slightly modified) version of MFH's answer above is the only, hence the best, way to go.
Thanks everyone for the input, it certainly has been enlightening.

How to write an elegant collision handling mechanism?

I'm in a bit of a pickle: say I'm making a simple, 2D, Zelda-like game.
When two Objects collide, each should have a resulting action. However, when the main character collides with something, his reaction depends solely on the type of the object with which he collided. If it's a monster, he should bounce back, if it's a wall, nothing should happen, if it's a magical blue box with ribbons, he should heal, etc. (these are just examples).
I should also note that BOTH things are part of the collision, that is, collision events should happen for both the character AND the monster, not just one or the other.
How would you write code like this? I can think of a number of incredibly inelegant ways, for instance, having virtual functions in the global WorldObject class, to identify attributes - for instance, a GetObjectType() function (returns ints, char*s, anything that identifies the object as Monster, Box, or Wall), then in classes with more attributes, say Monster, there could be more virtual functions, say GetSpecies().
However, this becomes annoying to maintain, and leads to a large cascading switch (or If) statement in the collision handler
MainCharacter::Handler(Object& obj)
{
switch(obj.GetType())
{
case MONSTER:
switch((*(Monster*)&obj)->GetSpecies())
{
case EVILSCARYDOG:
...
...
}
...
}
}
There's also the option of using files, and the files would have things like:
Object=Monster
Species=EvilScaryDog
Subspecies=Boss
And then the code can retrieve the attributes without the need for virtual functions cluttering everything up. This doesn't solve the cascading If problem, however.
And THEN there's the option of having a function for each case, say CollideWall(), CollideMonster(), CollideHealingThingy(). This is personally my least favourite (although they're all far from likeable), because it seems the most cumbersome to maintain.
Could somebody please give some insight into more elegant solutions to this problem?
Thanks for any and all help!
I would do it vice versa - because if the character collides with an object, an object collides with the character as well. Thus you can have a base class Object, like this:
class Object {
virtual void collideWithCharacter(MainCharacter&) = 0;
};
class Monster : public Object {
virtual void collideWithCharacter(MainCharacter&) { /* Monster collision handler */ }
};
// etc. for each object
Generally in OOP design virtual functions are the only "correct" solution for cases like this:
switch (obj.getType()) {
case A: /* ... */ break;
case B: /* ... */ break;
}
EDIT:
After your clarification, you will need to adjust the above a bit. The MainCharacter should have overloaded methods for each of the objects it can collide with:
class MainCharacter {
void collideWith(Monster&) { /* ... */ }
void collideWith(EvilScaryDog&) { /* ... */ }
void collideWith(Boss&) { /* ... */ }
/* etc. for each object */
};
class Object {
virtual void collideWithCharacter(MainCharacter&) = 0;
};
class Monster : public Object {
virtual void collideWithCharacter(MainCharacter& c)
{
c.collideWith(*this); // Tell the main character it collided with us
/* ... */
}
};
/* So on for each object */
This way you notify the main character about the collision and it can take appropriate actions. Also if you need an object that should not notify the main character about the collision, you can just remove the notification call in that particular class.
This approach is called a double dispatch.
I would also consider making the MainCharacter itself an Object, move the overloads to Object and use collideWith instead of collideWithCharacter.
How about deriving all collidable objects from one common abstract class (let's call it Collidable). That class could contain all properties that can be changed by a collission and one HandleCollision function. When two objects collide, you just call HandleCollision on each object with the other object as the argument. Each object manipulates the other to handle the collision. Neither object needs to know what other object type it just bounced into and you have no big switch statements.
Make all colidable entities implement an interface (lets say "Collidable") with a collideWith(Collidable) method.
Then, on you collision detection algorithm, if you detect that A collides with B, you would call:
A->collideWith((Collidable)B);
B->collideWith((Collidable)A);
Assume that A is the MainCharacter and B a monster and both implement the Collidable interface.
A->collideWith(B);
Would call the following:
MainCharacter::collideWith(Collidable& obj)
{
//switch(obj.GetType()){
// case MONSTER:
// ...
//instead of this switch you were doing, dispatch it to another function
obj->collideWith(this); //Note that "this", in this context is evaluated to the
//something of type MainCharacter.
}
This would in turn call the Monster::collideWith(MainCharacter) method and you can implement all monster-character behaviour there:
Monster::CollideWith(MainCharacter mc){
//take the life of character and make it bounce back
mc->takeDamage(this.attackPower);
mc->bounceBack(20/*e.g.*/);
}
More info: Single Dispatch
Hope it helps.
What you call "an annoying switch statement" i would call "a great game" so you are on the right track.
Having a function for every interaction/game rule is exactly what I would suggest. It makes it easy to find, debug, change and add new functionality:
void PlayerCollidesWithWall(player, wall) {
player.velocity = 0;
}
void PlayerCollidesWithHPPotion(player, hpPoition) {
player.hp = player.maxHp;
Destroy(hpPoition);
}
...
So the question is really how to detect each of these cases. Assuming you have some sort of collision detection that results in X and Y collide (as simple as N^2 overlap tests (hey, it works for plants vs zombies, and that's got a lot going on!) or as complicated as sweep and prune + gjk)
void DoCollision(x, y) {
if (x.IsPlayer() && y.IsWall()) { // need reverse too, y.IsPlayer, x.IsWall
PlayerCollidesWithWall(x, y); // unless you have somehow sorted them...
return;
}
if (x.IsPlayer() && y.IsPotion() { ... }
...
This style, while verbose is
easy to debug
easy to add cases
shows you when you have
logical/design inconsistencies or
omissions "oh what if a X is both a
player and a wall due to the
"PosessWall" ability, what then!?!"
(and then lets you simply add cases
to handle those)
Spore's cell stage uses exactly this style and has approximately 100 checks resulting in about 70 different outcomes (not counting the param reversals). It's only a ten minute game, that's 1 new interaction every 6 seconds for the whole stage - now that's gameplay value!
If I am getting your problem correctly, I would sth like
Class EventManager {
// some members/methods
handleCollisionEvent(ObjectType1 o1, ObjectType2 o2);
// and do overloading for every type of unique behavior with different type of objects.
// can have default behavior as well for unhandled object types
}

Reconciling classes, inheritance, and C callbacks

In my C++ project, I've chosen to use a C library. In my zeal to have a well-abstracted and simple design, I've ended up doing a bit of a kludge. Part of my design requirement is that I can easily support multiple APIs and libraries for a given task (due, primarily, to my requirement for cross-platform support). So, I chose to create an abstract base class which would uniformly handle a given selection of libraries.
Consider this simplification of my design:
class BaseClass
{
public:
BaseClass() {}
~BaseClass() {}
bool init() { return doInit(); }
bool run() { return doWork(); }
void shutdown() { destroy(); }
private:
virtual bool doInit() = 0;
virtual bool doWork() = 0;
virtual void destroy() = 0;
};
And a class that inherits from it:
class LibrarySupportClass : public BaseClass
{
public:
LibrarySupportClass()
: BaseClass(), state_manager(new SomeOtherClass()) {}
int callbackA(int a, int b);
private:
virtual bool doInit();
virtual bool doWork();
virtual void destroy();
SomeOtherClass* state_manager;
};
// LSC.cpp:
bool LibrarySupportClass::doInit()
{
if (!libraryInit()) return false;
// the issue is that I can't do this:
libraryCallbackA(&LibrarySupportClass::callbackA);
return true;
}
// ... and so on
The problem I've run into is that because this is a C library, I'm required to provide a C-compatible callback of the form int (*)(int, int), but the library doesn't support an extra userdata pointer for these callbacks. I would prefer doing all of these callbacks within the class because the class carries a state object.
What I ended up doing is...
static LibrarySupportClass* _inst_ptr = NULL;
static int callbackADispatch(int a, int b)
{
_inst_ptr->callbackA(a, b);
}
bool LibrarySupportClass::doInit()
{
_inst_ptr = this;
if (!libraryInit()) return false;
// the issue is that I can't do this:
libraryCallbackA(&callbackADispatch);
return true;
}
This will clearly do Bad Things(TM) if LibrarySupportClass is instantiated more than once, so I considered using the singleton design, but for this one reason, I can't justify that choice.
Is there a better way?
You can justify that choice: your justification is that the C library only supports one callback instance.
Singletons scare me: It's not clear how to correctly destroy a singleton, and inheritance just complicates matters. I'll take another look at this approach.
Here's how I'd do it.
LibrarySupportClass.h
class LibrarySupportClass : public BaseClass
{
public:
LibrarySupportClass();
~LibrarySupportClass();
static int static_callbackA(int a, int b);
int callbackA(int a, int b);
private:
//copy and assignment are rivate and not implemented
LibrarySupportClass(const LibrarySupportClass&);
LibrarySupportClass& operator=(const LibrarySupportClass&);
private:
static LibrarySupportClass* singleton_instance;
};
LibrarySupportClass.cpp
LibrarySupportClass* LibrarySupportClass::singleton_instance = 0;
int LibrarySupportClass::static_callbackA(int a, int b)
{
if (!singleton_instance)
{
WHAT? unexpected callback while no instance exists
}
else
{
return singleton_instance->callback(a, b);
}
}
LibrarySupportClass::LibrarySupportClass()
{
if (singleton_instance)
{
WHAT? unexpected creation of a second concurrent instance
throw some kind of exception here
}
singleton_instance = this;
}
LibrarySupportClass::~LibrarySupportClass()
{
singleton_instance = 0;
}
My point is that you don't need to give it the external interface of a canonical 'singleton' (which e.g. makes it difficult to destroy).
Instead, the fact that there is only one of it can be a private implementation detail, and enforced by a private implementation detail (e.g. by the throw statement in the constructor) ... assuming that the application code is already such that it will not try to create more than one instance of this class.
Having an API like this (instead of the more canonical 'singleton' API) means that you can for example create an instance of this class on the stack if you want to (provided you don't try to create more than one of it).
The external constraint of the c library dictates that when your callback is called you don't have the identification of the "owning" instance of the callback. Therefore I think that your approach is correct.
I would suggest to declare the callbackDispatch method a static member of the class, and make the class itself a singleton (there are lots of examples of how to implement a singleton). This will let you implement similar classes for other libraries.
Dani beat me to the answer, but one other idea is that you could have a messaging system where the call back function dispatch the results to all or some of the instances of your class. If there isn't a clean way to figure out which instance is supposed to get the results, then just let the ones that don't need it ignore the results.
Of course this has the problem of performance if you have a lot of instances, and you have to iterate through the entire list.
The problem the way I see it is that because your method is not static, you can very easily end up having an internal state in a function that isn't supposed to have one, which, because there's a single instance on the top of the file, can be carried over between invocations, which is a -really- bad thing (tm). At the very least, as Dani suggested above, whatever methods you're calling from inside your C callback would have to be static so that you guarantee no residual state is left from an invocation of your callback.
The above assumes you have static LibrarySupportClass* _inst_ptr declared at the very top. As an alternative, consider having a factory function which will create working copies of your LibrarySupportClass on demand from a pool. These copies can then return to the pool after you're done with them and be recycled, so that you don't go around creating an instance every time you need that functionality.
This way you can have your objects keep state during a single callback invocation, since there's going to be a clear point where your instance is released and gets a green light to be reused. You will also be in a much better position for a multi-threaded environment, in which case each thread gets its own LibrarySupportClass instance.
The problem I've run into is that because this is a C library, I'm required to provide a C-compatible callback of the form int (*)(int, int), but the library doesn't support an extra userdata pointer for these callbacks
Can you elaborate? Is choosing a callback type based on userdata a problem?
Could your callback choose an instance based on a and/or b? If so, then register your library support classes in a global/static map and then have callbackADispatch() look up the correct instance in the map.
Serializing access to the map with a mutex would be a reasonable way to make this thread-safe, but beware: if the library holds any locks when it invokes your callback, then you may have to do something more clever to avoid deadlocks, depending on your lock hierarchy.