0

ファイルが変更されたときにイベントを取得するために、関数poll() (POSIX の一部であると思いますか?) を C++ クラスで使用しています。これは問題なく動作するようですが、スレッドを閉じる必要があるときに関数をすぐに終了できるようにしたいと考えています。

私はこれを調査し、試してみたいくつかのアイデアを思いつきました-信号を送信しようとするなど、これを機能させる方法を理解できませんでした.

以下のコード (100% 完全ではありませんが、問題を説明するのに十分なはずです) には、コンストラクターからスレッドを開始し、そのスレッドをデストラクターでクリーンアップしたい C++ クラスがあります。スレッドは、ファイルが変更されたときに返されるpoll()を呼び出し、デリゲート オブジェクトに通知します。監視スレッドは、FileMonitorオブジェクトが (bool を返すメソッドを使用して) 終了できることを示すまでループします。

デストラクタでやりたいことは、bool を反転させてから、poll()をすぐに終了させる何かを実行してから、*pthread_join()* を呼び出すことです。では、 poll()をすぐに終了させる方法についてのアイデアはありますか?

このコードは Linux (特に debian) を対象としていますが、Mac でも作業しています。poll() API が基本的に同じように機能することが理想的です。

void * manage_fm(void *arg)
{
    FileMonitor * theFileMonitor = (FileMonitor*)arg;
    FileMonitorDelegate * delegate;

    unsigned char c;
    int fd = open(theFileMonitor->filepath2monitor(), O_RDWR);

    int count;

    ioctl(fd, FIONREAD, &count);
    for (int i=0;i<count;++i) {
       read(fd, &c, 1);
    }

    struct pollfd poller;
    poller.fd = fd;
    poller.events = POLLPRI;


    while (theFileMonitor->continue_managing_thread()) {
        delegate = theFileMonitor->delegate;
        if (poll(&poller, 1, -1) > 0) {
            (void) read(fd, &c, 1);
            if (delegate) {
                delegate->fileChanged();
            }
        }
    }
}

FileMonitor::FileMonitor( )
{
    pthread_mutex_init(&mon_mutex, NULL);

    manage_thread = true;

    pthread_mutex_lock (&mon_mutex);

    pthread_create(&thread_id, NULL, manage_fm, this);

    pthread_mutex_unlock(&pin_mutex);

}

FileMonitor::~FileMonitor()
{
    manage_thread = false;

    // I would like to do something here to force the "poll" function to return immediately.

    pthread_join(thread_id, NULL);
}

bool FileMonitor::continue_managing_thread()
{
    return manage_thread;
}

const char * FileMonitor::filepath2monitor()
{
    return "/some/example/file";
}
4

2 に答える 2

3

ファイル監視クラスにパイプを追加し、ポーリングを切り替えて、元のファイル記述子とパイプの読み取り記述子の両方をポーリングに使用します。終了を確認するためにファイル モニター クラスをウェイクアップする場合は、パイプの書き込み記述子を介してバイトを送信します。これにより、スレッドがウェイクアップします。

これらのファイル モニターが多数ある場合、プロセスのファイル記述子の最大数に達する可能性があります (詳細については、 Linux で特定のプロセスのオープン FD 制限を確認するを参照してください。私のシステムでは、1024 ソフト、4096 です)。難しい)。複数のモニター クラスが 1 つのパイプを共有するようにすることもできますが、それらがすべて一度に起動して終了インジケーターを確認することを気にしない場合です。

于 2014-09-05T19:21:15.330 に答える
-2

-ing ループ内 (およびその直前) でpthread条件変数を使用し、他のスレッドでpthread_cond_signalを呼び出す必要があります。poll

pipe(7) to self トリックを検討することもできます(たとえば、あるスレッドが、同じパイプをread(2)する別のスレッドによって、おそらくpthread_cond_signalの直前に- パイプpoll(2)に 1 バイトを write(2)される)。 . signal-safety(7)およびUnix シグナル ハンドラからの Qt 関数の呼び出しも参照してください。どちらもあなたにインスピレーションを与えることができます。

そのパイプから自己へのトリックで、pollそのパイプを読み取るために行うと仮定すると、pollが返されます。もちろん、他のスレッドが以前write同じパイプで a を実行した可能性があります。

Philippe Chaintreuil's answerも参照してください。彼は同様のアイデアを提案しています。

于 2014-03-03T06:21:42.013 に答える