posted by Kyleslab 2010. 12. 10. 23:45


Producer.h

#pragma once

#include <queue>
#include <string>

#include "Concurrency\Thread.h"
#include "Customer.h"
#include "Concurrency\Timer.h"
#include "Concurrency\SpinLock.h"

class Producer
{
public:
 Producer(float frequency);
 ~Producer();


public:
 void
  beginService();
 bool
  tryPop( std::string * product);
 
private:
 void service();

private:
 Thread * _thread;
 std::queue< std::string > _products;//경쟁관계에 있는 녀석
 Timer _timer;
 float _frequency;
 unsigned int _count;
 volatile bool _isEnd;
 SpinLock mylock;
};


Produce.cpp

#include "StdAfx.h"
#include "Producer.h"

#include <Windows.h>


Producer::Producer(float frequency)//인자를 갖지 않는 생성자를 호출한다 기입하지 않으면, 파라미터를 받는 생성자를 만들었다면 기본생성자는 호출되지않는다.
 : _count( 0 ),
 _isEnd(false),
 _frequency(frequency)
{
 
}

void Producer::beginService()
{
 _thread = new Thread( std::bind(&Producer::service, this));
}

Producer::~Producer(void)
{
 _isEnd = true;
 ::WaitForSingleObject( ( HANDLE )( _thread ), INFINITE); //반드시해주어야함 모든 자식 스레드를 종료해주기 위해 메인스레드가 종료하면 소멸자를
 delete _thread;

 // 메인스레드가 종료될때 소멸자 호출,. 그러나 지금 스레드가 작동중이라면???
 

}

bool Producer::tryPop( std::string * product)
{
 mylock.lock();
 bool result = false;

 if( !_products.empty())
 {
  *product = _products.front();
  _products.pop();
  result = true;
 }
 mylock.unlock();
 return result;

}

 

void Producer::service()

 _timer.start();
 
 while( !_isEnd )
 {
   
  if(_timer.elapsedSeconds() >= _frequency)
  {
   
   char number[100];
   itoa( _count, number, 10 );
   
   std::string product = "product";
   product += number;
   ++_count;
   _timer.stop();
   _timer.start();
   mylock.lock();
   _products.push( product );
   mylock.unlock();
  }
  
  ::Sleep(0); //원래는 블록큐로 가나, 0이니까 준비큐로가고 1초가 아닐때 다른작업할거있음 하라고 양보하는 것이다.
 }
 
}

Customer.h
#pragma once

#include "Concurrency\Thread.h"
#include "Concurrency\Timer.h"
#include "Concurrency\MutexLock.h"

class Producer;

class Customer
{
public:
 Customer( Producer * producer, // 포인터 타입으로 갖고 있게 한다. 인스턴스를 선언하지 않고, 클래스실체를 선언하지 않고 사용하는법
        float frequency);
 ~Customer();

public:
 void
  beginService();

private:
 void service();//백그라운드에서
 
 private:
 Thread * _thread;
 Producer * _producer;
 Timer _timer;
 float _frequency;
 volatile bool _isEnd;


};


Customer.cpp
#include "StdAfx.h"
#include <concrt.h>
#include <Windows.h>


#include "Customer.h"

 

#include "Producer.h"//헤더에서 그냥 선언만해놓고 여기서 추가해주면 사용할수 있다.


Customer::Customer( Producer * producer,
 float frequency)
 : _producer( producer ),
 _frequency( frequency ),
 _isEnd(false)
{

}


Customer::~Customer(void)
{
 _isEnd = true;
 ::WaitForSingleObject( ( HANDLE )( _thread ), INFINITE);
 delete _thread;
}


void Customer::beginService()
{
 _thread = new Thread( std::bind(&Customer::service, this));
}


void
 Customer::service()
{
 _timer.start();

 while( !_isEnd)
 {
  if(_timer.elapsedSeconds() >= _frequency )
  {
   std::string product;

   if( _producer->tryPop(&product)) // 커스토머 쓰레드 호출되는 곳의 쓰레드이다.
   {
 
    printf( "%s\n", product.c_str() );

    _timer.stop();
    _timer.start();
   }

  }
  ::Sleep( _frequency * 250 );
 }
}


ServiceThread.cpp
// ServiceThread.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//

#include "stdafx.h"

#include<Windows.h>

#include "Customer.h"
#include "Producer.h"
int _tmain(int argc, _TCHAR* argv[])
{
 Producer p(0.01f);
 Customer c1( &p, 0.008);
 Customer c2( &p, 0.005 );

 p.beginService();
 ::Sleep( 2000 );
 c1.beginService();
 c2.beginService();

 Timer timer;
 timer.start();
 while( timer.elapsedSeconds() < 20);

 return 0;
}

 

'Operations Dev > Producer' 카테고리의 다른 글

종료  (0) 2010.12.11