ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Producer / Customer
    Operations Dev/Producer 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
Designed by Tistory.