組み込みシステム インターフェイスの場合、シリアル ポートを読み取るための最大 8 つの読み取りモード (以下のコードでは、FREERUN と BLOCKRUN の 2 つだけが示されています) を持つクラスを実装しています。このリーダーの単純化された ReaderTest() 関数は次のようになります。
void CSerialBoost::ReaderTest()
{
while (RUNflag)
switch (RUNstate) {
case FREERUN:
port.async_read_some(asio::buffer(TextIn, SZTXT),
boost::bind(&CSerialBoost::OnReadFree, this, asio::placeholders::error, asio::placeholders::bytes_transferred));
server.reset();
server.run(error); // it calls OnReadBlock() here
break;
case BLOCKRUN:
port.async_read_some(asio::buffer(TextIn, SZTXT),
boost::bind(&CSerialBoost::OnReadBlock, this, asio::placeholders::error, asio::placeholders::bytes_transferred));
server.reset();
server.run(error); // it calls OnReadFree() here
break;
default: break;
}
port.cancel(error); // cancel all IO operations
}
クラス CSerialBoost には、次のメンバーがあります。
asio::io_service server;
asio::serial_port port;
asio::error_code error;
volatile int RUNstate; // reader mode
volatile int RUNflag; // start/stop flag
あるモードから別のモードに切り替えると、予期しない動作が発生します。着信データがなく、コードが FREERUN で実行されていると仮定すると、別のスレッドから BLOCKRUN に切り替えるために、次のようにします。
RUNstate = BLOCKRUN;
server.stop(); // unblock the event loop
操作は、当然のことながら BLOCKRUN に切り替わり、BLOCKRUN ケースの server.run(error) 行に到達すると、エラー operation_aborted で CSerialBoost::OnReadFree() 関数が呼び出されます。FREERUN に戻すときも同じことが起こります。FREERUN の場合、server.run(error) に到達すると、CSerialBoost::OnReadBlock() が呼び出されます。
これは、常に別のモードの関数を呼び出すため、非常に誤解を招きます。IO サービスを停止/キャンセルすると、各ケースで独自の関数が呼び出される (または何も呼び出されない) ことが予想されます。期待しすぎですか、それともこれは正常な動作ですか? 私は何か間違ったことをしていますか?この問題をどのように処理できるかについてのヒントを教えてください。(私はboost:asio 1-5-3をWin XPおよびWin 7、Visual Studio 2010で使用していますが、ブーストは初めてです)
ありがとう、MA。