Search code examples
c++socketsevent-driveninteractive-brokers

Is acknowledgement critical in TWS c++ API


My question

In the Interactive Brokers TWS c++ API, (or in event-driven programming in general) when is it critical to change the state/mode (this is m_state in TWS API) to a state of "acknowledgement?" Depending on the state of this variable, different class methods are called. Towards the end of the definition of one of these methods, the state is changed back to an acknowledgement state, which appears to allow messages to be received by the host. Can I change m_state to something else, and skip the acknowledgement process altogether?

Some background information for those who don't know the TWS API

(feel free to ignore this section)

Interactive Brokers' TWS C++ API has tens of thousands of lines of code, so let me try to describe what I think the essential functionality is.

My programs entry point in Main.cpp instantiates a client object, and then repeatedly calls its void TestCppClient::processMessages() method over and over again in every iteration of a while loop.

On the one hand, there are a bunch of methods that get triggered by the broker whenever the broker decides to call them, and you, as a client, may or may not take advantage of the provided information.

But on the other hand, there are a bunch of methods that get triggered by my client code. Depending on the value of m_state, a different class method is triggered. In the sample code provided by IB, that is, in my TestCppClient class, most of these functions have some helpful demonstration code provided, and more to the point of my question, most of these functions have the last line setting the value of m_state to something ending in _ACK (which, I believe, is a socket programming convention that is short for "acknowledgement.")

For example, when m_state is equal to ST_REUTERSFUNDAMENTALS, TestCppClient::processMessages()'s switch statement will trigger TestCppClient::reutersFundamentals(). The last line of this method's definition is

m_state = ST_REUTERSFUNDAMENTALS_ACK;

The next time void TestCppClient::processMessages() is triggered, (and it gets triggered all the time by the while loop, if you recall) the switch statement is skipped due to there only being a break statement:

...
case ST_REUTERSFUNDAMENTALS:
    reutersFundamentals();
    break;
case ST_REUTERSFUNDAMENTALS_ACK:
    break;
...

This switch statement code makes up the majority of the code in this function's definition, but there is a little at the end outside of the switch statement. The only code that runs in TestCppClient::procesMessages() in this case is at the very end, which is

m_pReader->checkClient();
m_osSignal.waitForSignal();
m_pReader->processMsgs();

These lines apparently handle some low-level socket programming stuff.

Reiterating my question

So, if I didn't change the state to an acknowledgement state, these last three lines wouldn't run. But would that be a bad thing? Does anyone have experience with this? Any anecdotal pieces of information?


Solution

  • The TestCppClient example is fairly complicated as IB/C++ applications go, but those three lines are important. m_pReader is an instance of the EReader class, which reads incoming data and produces messages. Because it runs in its own thread, it needs special handling.

    The checkClient function tells the EReader to package incoming data into an EMessage and store the message in the message queue. But the application can't access the queue until the waitForSignal function returns. Afterward, processMsgs reads the EMessage and calls the appropriate callback function.

    Dealing with the EReader is a pain, but once you get an application working, you can copy and paste the code into further applications.