输入时输出

时间:2014-06-28 08:00:01

标签: c++ c++11

我希望能够在输入时输出信息。 例如:每秒打印一行,但也取消用户输入......

我试过了:

#include <iostream>
#include <thread>
#include <string>
#include <unistd.h>
using namespace std;

void foo()
{
    while(1)
    {
        usleep(1000000);
        cout << "Cake\n";
    }
}

int main()
{
    thread t1(foo);
    t1.join();
    string x;
    while(1)
    {
        cin >> x;
        cout << x << "\n";
    }
    return 0;
}

哪个输出:

  

蛋糕
  蛋糕
  蛋糕

然后我开始输入:

  

hiCake

当我希望它是:

  

蛋糕
  喜

&#39; hi&#39;仍然在输入

如果这不可能,在输入文字时,至少有一种方法可以暂停输出吗?

我在Windows 7上使用C ++ 11,使用CygWin作为Unix库

MUTEX TESTS

输出循环锁定:

#include <iostream>
#include <thread>
#include <string>
#include <unistd.h>
#include <mutex>
using namespace std;

mutex mtx;

void foo()
{
    mtx.lock();
    while(1)
    {
        usleep(1000000);
        cout << "Cake\n";
    }
    mtx.unlock();
}

int main()
{
    thread t1(foo);
    t1.join();
    string x;
    while(1)
    {
        cin >> x;
        cout << x << "\n";
    }
    return 0;
}

输入循环锁定:

#include <iostream>
#include <thread>
#include <string>
#include <unistd.h>
#include <mutex>
using namespace std;

mutex mtx;

void foo()
{
    while(1)
    {
        usleep(1000000);
        cout << "Cake\n";
    }
}

int main()
{
    thread t1(foo);
    t1.join();
    string x;
    mtx.lock();
    while(1)
    {
        cin >> x;
        cout << x << "\n";
    }
    mtx.unlock();
    return 0;
}

纯输出锁定:

#include <iostream>
#include <thread>
#include <string>
#include <unistd.h>
#include <mutex>
using namespace std;

mutex mtx;

void foo()
{
    while(1)
    {
        mtx.lock();
        usleep(1000000);
        cout << "Cake\n";
        mtx.unlock();
    }
}

int main()
{
    thread t1(foo);
    t1.join();
    string x;
    while(1)
    {
        cin >> x;
        cout << x << "\n";
    }
    return 0;
}

纯输入锁定:

#include <iostream>
#include <thread>
#include <string>
#include <unistd.h>
#include <mutex>
using namespace std;

mutex mtx;

void foo()
{
    while(1)
    {
        usleep(1000000);
        cout << "Cake\n";
    }
}

int main()
{
    thread t1(foo);
    t1.join();
    string x;
    while(1)
    {
        mtx.lock();
        cin >> x;
        mtx.unlock();
        cout << x << "\n";
    }
    return 0;
}

为了节省空间,我不会粘贴更多代码;我做了其他测试,我做了mutex mtx2并试图锁定输入(mtx)和输出(mtx2)(纯和循环)。我也尝试用mtx(再次,纯粹和循环)

来锁定

5 个答案:

答案 0 :(得分:2)

使用互斥锁保护代码的关键部分 - 请参阅http://www.cplusplus.com/reference/mutex/mutex/

答案 1 :(得分:1)

使用pure output locked的代码几乎是正确的解决方案。需要做的是使用互斥锁保护“cout”语句并在std::thread::join中移动while main循环,否则永远不会执行:

using namespace std;

mutex mtx;

void foo()
{
    while(1)
    {
        usleep(1000000);
        mtx.lock(); // we want mutex to be held only for time of cout, not time of wait
        cout << "Cake\n";
        mtx.unlock();
    }
}

int main()
{
    thread t1(foo);
    string x;
    while(1)
    {
        mtx.lock(); // we lock second occurence of cout and cin not to get interrupted by foo
        cin >> x;
        cout << x << "\n";
        mtx.unlock(); 
    }
    t1.join(); // thread join stops the calling thread until called thread is finished
    // so we join the thread just before our program finishes
    return 0;
}

通过这种方式,您将获得如下输出:

Cake
Hi
Hi

为什么我们在foo()的时间内没有锁定usleep?因为它会锁定互斥锁的时间超过必要的时间。

为什么我选择不在mtx之前锁定cin?因为cin的时间非常不确定。如果foo()正在执行任何重要操作,则可能会暂停很长时间。

我个人建议你阅读Anthony Williams的书C++ Concurrency in Action。我认为很好看。

答案 2 :(得分:0)

使用&#34;打印&#34;同步对cout的访问权限的对象:

struct SyncCOUT{
  SyncCOUT(): m_mutex() {}
  std::mutex m_mutex;
  std::ostream & operator<<(const char * _str)
  {
    m_mutex.lock();
    cout << _str;
    m_mutex.unlock();
    return cout;
  }
};

SyncCOUT g_scout;

// and then in both threads use this global synchronized "cout" wrapper like this:
// g_scout << "Hello, world!\n";

答案 3 :(得分:0)

为此,您需要做一些事情:

  1. 创建两个线程,一个将在标准输出上写入文本,另一个将从标准输入中读取文本。

  2. 在写入之前使输出线程锁定mutex,并在写入后将其解锁。此写作操作将是您的关键部分&#34;。

  3. read 线程内,直接从终端读取字符数据。在Unix上,您可以使用curses库来完成此任务(可能是getch()函数),在Windows上,您可能会在从ReadFile获取的句柄上使用GetStdHandle(STD_INPUT_HANDLE)

  4. 然后您可以创建一个简单的状态机:如果用户按下不是enter的密钥,请尝试锁定mutex。如果用户按下enter键,请解锁mutex

  5. 这样,只有在用户按下enter键后, write 线程才能输出文本。当用户处于输入文本的中间时(即按<{1}}键之前的),enter将阻止写入操作,直到用户按下{{1密钥。

    可能需要扩展此方法以处理按mutex键。

答案 4 :(得分:0)

您可能需要通过调用std :: cout.flush()显式同步std :: cout。

这似乎是您正在运行的控制台的实现问题。某些控制台(如cmd.exe和powershell)在std :: cout上每次插入(&lt;&lt;&lt;&lt;&lt;)操作后都执行了隐式flush()同步。我担心我测试的线程代码有并发问题,直到我发现它在cmd.exe和powershell下正常工作,但不在MINGW64 / MSYS2下(Git for Windows部署)。

没有刷新调用我的两个线程没有按预期交错字符,实际上直到工作线程是.join()编辑时才输出字符,直到我添加了显式的std :: cout.flush()。在添加之后,所有三个控制台都具有相同的行为。