C++ windows c++;等待队列数据推送的线程

C++ windows c++;等待队列数据推送的线程,c++,windows,multithreading,events,queue,C++,Windows,Multithreading,Events,Queue,我的程序设置如下: 有一个线程安全的队列类,一个线程在无限循环中向其推送数据,另一个线程在无限循环中弹出数据。我试图想出一种方法,使用windows事件或其他机制使线程_1(如下)在无限while循环中等待,并且仅在队列深度大于或等于1时迭代 class thread-safe_Queue { public: push(); pop(); }; DWORD thread_1() { while(1) { // wait for thread-safe queue to hav

我的程序设置如下:
有一个线程安全的队列类,一个线程在无限循环中向其推送数据,另一个线程在无限循环中弹出数据。我试图想出一种方法,使用windows事件或其他机制使线程_1(如下)在无限while循环中等待,并且仅在队列深度大于或等于1时迭代

class thread-safe_Queue
{
 public:
  push();
  pop();
};

DWORD thread_1()
{
 while(1)
 {
  // wait for thread-safe queue to have data on it
  // pop data off
  // process data
 }
}

DWORD thread_2()
{
 while(1)
 {
  // when data becomes available, push data onto thread-safe queue
 }
}
这个怎么样(我想您熟悉事件机制)

一,

二,

三,。线程_1只是尝试弹出对象并处理它。当推送某物时,事件被启用,因此可以成功调用
pop
。否则它将在
pop
内等待。实际上,在本例中,您可以使用其他同步对象,如互斥对象或关键部分,而不是事件

更新。外部事件: 线程1:

void thread_1()
  {
  while(1)
    {
    WaitForSingleObject(notification);
    if (!pop(object))  // pop should return if there are any objects left in queue
      SetEvent(notification);    
    }
  }
螺纹2

void thread_2()
  {
  while(1)
    {
    // push the object and than signal event
    ResetEvent(notification)
    }
  }

您可以使用命名事件。每个线程将以相同的名称调用CreateEvent传递。然后使用WaitForMultipleObjects等待队列相关事件或结束程序事件。pop线程将等待队列\u有\u数据和结束\u程序事件。推送线程将等待数据可用并结束程序事件,并在将某些内容放入队列时设置队列has data事件。

我认为这可能会奏效。派生类事件并重载Process()函数

#include <process.h> // Along with all the normal windows includes

//*********************************************
using namespace os;

Mutex globalQueueMutex;

class QueueReader : public Event
{
public:
    virtual void Process()
    {
      // Lock the queue
      Locker l(globalQueueMutex);
      // pop data off
      // process data
      return; // queue will automatically unlock
    }
};

QueueReader myQueueReader;

//*********************************************
// The queue writer would have functions like :
void StartQueueReader()
{
    Thread(QueueReader::StartEventHandler, &myQueueReader);
}
void WriteToQueue()
{
    Locker l(globalQueueMutex);
    // write to the queue
    myQueueReader.SignalProcess(); // tell reader to wake up
}
// When want to shutdown
void Shutdown()
{
    myQueueReader.SignalShutdown();
}

我希望事件在类之外,在线程入口点函数内部。原因是线程也在等待第二个事件。这时,用户希望结束程序,从而结束无限while循环。发生这种情况时,用户将发送命令关闭程序,推送线程将停止侦听数据并关闭,推送线程将停止等待线程中包含数据,并将关闭。您可以对外部事件执行同样的操作。我更新了上面的答案。您的意思是线程1调用重置,线程2调用外部版本中的设置吗?另外,在这个场景中如何避免死锁:1。thread1无法弹出。2.thread2调用set。3.thread1调用reset。
void thread_2()
  {
  while(1)
    {
    // push the object and than signal event
    ResetEvent(notification)
    }
  }
#include <process.h> // Along with all the normal windows includes

//*********************************************
using namespace os;

Mutex globalQueueMutex;

class QueueReader : public Event
{
public:
    virtual void Process()
    {
      // Lock the queue
      Locker l(globalQueueMutex);
      // pop data off
      // process data
      return; // queue will automatically unlock
    }
};

QueueReader myQueueReader;

//*********************************************
// The queue writer would have functions like :
void StartQueueReader()
{
    Thread(QueueReader::StartEventHandler, &myQueueReader);
}
void WriteToQueue()
{
    Locker l(globalQueueMutex);
    // write to the queue
    myQueueReader.SignalProcess(); // tell reader to wake up
}
// When want to shutdown
void Shutdown()
{
    myQueueReader.SignalShutdown();
}
namespace os {

// **********************************************************************
/// Windows implementation to spawn a thread.
static uintptr_t Thread (void (*StartAddress)(void *), void *ArgList)
{
  return _beginthread(StartAddress, 0, ArgList);
}

// **********************************************************************
/// Windows implementation of a critical section.
class Mutex
{
public:
  // Initialize section on construction
  Mutex() { InitializeCriticalSection( &cs_ ); }
  // Delete section on destruction
  ~Mutex() { DeleteCriticalSection( &cs_ ); }
  // Lock it
  void lock() { EnterCriticalSection( &cs_ ); }
  // Unlock it
  void unlock() { LeaveCriticalSection( &cs_ ); }

private:
  CRITICAL_SECTION cs_;
}; // class Mutex

/// Locks/Unlocks a mutex
class Locker
{
public:
  // Lock the mutex on construction
  Locker( Mutex& mutex ): mutex_( mutex ) { mutex_.lock(); }
  // Unlock on destruction
  ~Locker() { mutex_.unlock(); }
private:
  Mutex& mutex_;
}; // class Locker

// **********************************************************************
// Windows implementation of event handler
#define ProcessEvent  hEvents[0]
#define SetTimerEvent hEvents[1]
#define ShutdownEvent hEvents[2]

/// Windows implementation of events
class Event
{
  /// Flag set when shutdown is complete
  bool Shutdown;
  /// Max time to wait for events
  DWORD Timer;
  /// The three events  - process, reset timer, and shutdown
  HANDLE hEvents[3];

public:
  /// Timeout is disabled by default and Events assigned
  Event( DWORD timer = INFINITE) : Timer(timer)
  {
    Shutdown = false;
    ProcessEvent = CreateEvent( NULL,TRUE,FALSE,NULL );
    SetTimerEvent = CreateEvent( NULL,TRUE,FALSE,NULL );
    ShutdownEvent = CreateEvent( NULL,TRUE,FALSE,NULL );
  }

  /// Close the event handles
  virtual ~Event()
  {
    CloseHandle(ProcessEvent);
    CloseHandle(SetTimerEvent);
    CloseHandle(ShutdownEvent);
  }

  /// os::Thread calls this to start the Event handler
  static void StartEventHandler(void *pMyInstance)
    { ((Event *)pMyInstance)->EventHandler(); }
  /// Call here to Change/Reset the timeout timer
  void ResetTimer(DWORD timer)  { Timer = timer; SetEvent(SetTimerEvent); }
  /// Set the signal to shutdown the worker thread processing events
  void SignalShutdown() { SetEvent(ShutdownEvent); while (!Shutdown) Sleep(30);}
  /// Set the signal to run the process
  void SignalProcess() { SetEvent(ProcessEvent); }

protected:
  /// Overload in derived class to process events with worker thread
  virtual void Process(){}
  /// Override to process timeout- return true to terminate thread
  virtual bool Timeout(){ return true;}

  /// Monitor thread events
  void EventHandler()
  {
    DWORD WaitEvents;
    while (!Shutdown)
    {
      // Wait here, looking to be signaled what to do next
      WaitEvents = WaitForMultipleObjects(3, hEvents, FALSE, Timer);

      switch (WaitEvents)
      {
        // Process event - process event then reset for the next one
        case WAIT_OBJECT_0 + 0:
          Process();
          ResetEvent(ProcessEvent);
          break;

        // Change timer event - see ResetTimer(DWORD timer)
        case WAIT_OBJECT_0 + 1:
          ResetEvent(SetTimerEvent);
          continue;

        // Shutdown requested so exit this thread
        case WAIT_OBJECT_0 + 2:
          Shutdown = true;
          break;

        // Timed out waiting for an event
        case WAIT_TIMEOUT:
          Shutdown = Timeout();
          break;

        // Failed - should never happen
        case WAIT_FAILED:
          break;

        default:
          break;
      }
    }
  }


};

} // namespace os