取消阻止调用外部进程的线程

时间:2014-10-04 03:48:14

标签: c++ multithreading c++11 blocking nonblocking

我有以下完整的,可编译的示例(也可用作gist),它产生少量线程(echo pass)和另一个(echo block; sleep 1; echo unblock)。第二个是这样的名字,因为当我在输出中看到block时,即使其他“通过”线程应该在此之前完成 long ,循环也会旋转它的轮子。我希望它输出pass多次,散布checking(因为主线程在这一点上循环)然后在最后unblock

如何获得预期的行为?

我意识到这很可能是使用system的一个症状,但我一直在使用它来建立一个多线程解决方案,因为我还没有收到工作替代方案。我注意到一些我应该改变的事情,但我仍在研究这些解决方案。但它们也可能是这个bug的来源。

// -*- compile-command: "g++ -std=c++0x main.cpp;./a.out" -*-
#include <iostream>
#include <thread>
#include <map>
#include <unistd.h>

typedef char status_t;

/**
 * I know I'm not supposed to be using system, but I don't know what
 * else to use in this context.  The program I'm starting is,
 * theoretically, arbitrary.
 *
 * @param command a shell command to run, such as "pdflatex file.tex"
 * @param running a sentinal boolean for whether this thread is still
 *                running
 * @param exit_code_buf a buffer for the exit code
 *
 * @todo use std::{atomic,future,promise} appropriately...
 */
void run(std::string command, bool *running, status_t *exit_code_buf)
{
  // TODO: add std::chrono::duration timeout
  *running = true;
  *exit_code_buf = system(command.c_str());
  *running = false;
}


class ProcessGroup
{
  std::map<std::pair<std::thread *, bool *>, status_t *> threads;
public:
  void Add(std::string);
  void Join();
};

/**
 * Starts a process in a new thread and adds it to the map
 *
 * @param command a command to start
 *
 * @todo use std::{atomic,future,promise} appropriately...
 */
void
ProcessGroup::Add(std::string command)
{
  status_t *status = new status_t(0);
  bool *running = new bool(false);
  std::thread *t = new std::thread(&run, command, running, status);
  threads.insert(std::make_pair(std::make_pair(t, running), status));
}

/**
 * Periodically checks all threads to see if they are still running.
 * If one of them is, sleep for a small amount of time and check
 * again.
 */
void
ProcessGroup::Join()
{
  bool still_running;
  do {
    still_running = false;
    for (auto it = threads.cbegin(); it != threads.cend(); ++it) {
      still_running |= *it->first.second;
    }
    std::cout << "checking" << std::endl;
    if (still_running) usleep (100000);
  } while (still_running);
}

int main()
{
  std::cout << "Program start." << std::endl;
  ProcessGroup pg;
  std::string
    block("echo block; sleep 1; echo unblock"),
    pass("echo pass");

  pg.Add(block);
  std::cout << "here" << std::endl;
  for (int i = 0; i<10; i++) {
    pg.Add(pass);
  }

  std::cout << "Joining threads..." << std::endl;
  pg.Join();
  std::cout << "Program end." << std::endl;
  return 0;
}

...编译

$ g++ -std=c++0x main.cpp; ./a.out 
Program start.
here
Joining threads...
checking
block
checking
checking
checking
checking
checking
checking
checking
checking
checking
unblock
pass
pass
checking
pass
pass
pass
pass
pass
pass
pass
pass
checking
Program end.

Compilation finished at Fri Oct  3 23:49:45

0 个答案:

没有答案