μΉ΄ν…Œκ³ λ¦¬ 보관물: C++

C++

클래슀의 pthread ν•¨μˆ˜ *){ cout <<

λ‹€μŒκ³Ό 같은 μˆ˜μ—…μ΄ μžˆλ‹€κ³  κ°€μ • ν•΄ λ΄…μ‹œλ‹€.

class c {
    // ...
    void *print(void *){ cout << "Hello"; }
}

그리고 μ €λŠ” c의 벑터λ₯Ό κ°€μ§€κ³  μžˆμŠ΅λ‹ˆλ‹€.

vector<c> classes; pthread_t t1;
classes.push_back(c());
classes.push_back(c());

이제 μŠ€λ ˆλ“œλ₯Ό λ§Œλ“€κ³  μ‹ΆμŠ΅λ‹ˆλ‹€. c.print();

그리고 λ‹€μŒμ€ λ‚˜μ—κ²Œ μ•„λž˜ 문제λ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€. pthread_create(&t1, NULL, &c[0].print, NULL);

였λ₯˜ 좜λ ₯ : 인수 β€˜3’에 λŒ€ν•΄ β€˜void * (tree_item ::) (void )’λ₯Ό β€˜void * ( ) (void )’ 둜 λ³€ν™˜ ν•  수 μ—†μŠ΅λ‹ˆλ‹€. β€˜int pthread_create (pthread_t *, const pthread_attr_t *, void * ( ) (void ), 무효 *) β€˜



λ‹΅λ³€

C ++ 클래슀 멀버 ν•¨μˆ˜μ— μˆ¨κ²¨μ§„ this맀개 λ³€μˆ˜κ°€ 전달 λ˜μ—ˆκΈ° λ•Œλ¬Έμ— μž‘μ„±ν•œ λ°©μ‹λŒ€λ‘œ μˆ˜ν–‰ ν•  수 μ—†μŠ΅λ‹ˆλ‹€ . μ‚¬μš©ν•  pthread_create()값을 μ•Œμ§€ λͺ» thisν•˜λ―€λ‘œ λ©”μ†Œλ“œλ₯Ό ν•¨μˆ˜λ‘œ μΊμŠ€νŒ…ν•˜μ—¬ 컴파일러λ₯Ό μš°νšŒν•˜λ €κ³ ν•©λ‹ˆλ‹€. μ μ ˆν•œ μœ ν˜•μ˜ 포인터λ₯Ό μ‚¬μš©ν•˜λ©΄ segmetnation 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€. 정적 클래슀 λ©”μ„œλ“œ ( this맀개 λ³€μˆ˜ κ°€ μ—†μŒ ) λ˜λŠ” 일반 일반 ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 클래슀λ₯Ό λΆ€νŠΈ μŠ€νŠΈλž©ν•΄μ•Όν•©λ‹ˆλ‹€.

class C
{
public:
    void *hello(void)
    {
        std::cout << "Hello, world!" << std::endl;
        return 0;
    }

    static void *hello_helper(void *context)
    {
        return ((C *)context)->hello();
    }
};
...
C c;
pthread_t t;
pthread_create(&t, NULL, &C::hello_helper, &c);

λ‹΅λ³€

μŠ€λ ˆλ“œλ₯Ό μ²˜λ¦¬ν•˜λŠ” κ°€μž₯ 쒋은 방법은 μŠ€λ ˆλ“œλ₯Ό C ++ 객체 μ•ˆμ— μΊ‘μŠν™”ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 예λ₯Ό λ“€λ©΄ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

class MyThreadClass
{
public:
   MyThreadClass() {/* empty */}
   virtual ~MyThreadClass() {/* empty */}

   /** Returns true if the thread was successfully started, false if there was an error starting the thread */
   bool StartInternalThread()
   {
      return (pthread_create(&_thread, NULL, InternalThreadEntryFunc, this) == 0);
   }

   /** Will not return until the internal thread has exited. */
   void WaitForInternalThreadToExit()
   {
      (void) pthread_join(_thread, NULL);
   }

protected:
   /** Implement this method in your subclass with the code you want your thread to run. */
   virtual void InternalThreadEntry() = 0;

private:
   static void * InternalThreadEntryFunc(void * This) {((MyThreadClass *)This)->InternalThreadEntry(); return NULL;}

   pthread_t _thread;
};

이λ₯Ό μ‚¬μš©ν•˜λ €λ©΄ μŠ€λ ˆλ“œμ˜ 이벀트 루프λ₯Ό ν¬ν•¨ν•˜λ„λ‘ κ΅¬ν˜„ 된 InternalThreadEntry () λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ MyThreadClass의 ν•˜μœ„ 클래슀λ₯Ό λ§Œλ“­λ‹ˆλ‹€. λ¬Όλ‘  μŠ€λ ˆλ“œ 개체λ₯Ό μ‚­μ œν•˜κΈ° 전에 μŠ€λ ˆλ“œ κ°œμ²΄μ—μ„œ WaitForInternalThreadToExit ()λ₯Ό ν˜ΈμΆœν•΄μ•Όν•©λ‹ˆλ‹€ (그리고 μŠ€λ ˆλ“œκ°€ μ‹€μ œλ‘œ μ’…λ£Œλ˜λŠ”μ§€ ν™•μΈν•˜λŠ” λ©”μ»€λ‹ˆμ¦˜μ΄ μžˆμŠ΅λ‹ˆλ‹€. κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄ WaitForInternalThreadToExit ()κ°€ λ°˜ν™˜λ˜μ§€ μ•ŠμŒ)


λ‹΅λ³€

pthread_createμ°Ύκ³ μžˆλŠ” μ„œλͺ…κ³Ό μΌμΉ˜ν•˜λŠ” ν•¨μˆ˜ λ₯Ό μ œκ³΅ν•΄μ•Όν•©λ‹ˆλ‹€ . 당신이 μ „λ‹¬ν•˜λŠ” 것은 μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

μ›ν•˜λŠ” λͺ¨λ“  정적 ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•  수 있으며 μΈμŠ€ν„΄μŠ€λ₯Ό μ°Έμ‘° cν•˜κ³  μŠ€λ ˆλ“œμ—μ„œ μ›ν•˜λŠ” 것을 μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€. pthread_createν•¨μˆ˜ ν¬μΈν„°λΏλ§Œ μ•„λ‹ˆλΌ β€œμ»¨ν…μŠ€νŠΈβ€μ— λŒ€ν•œ 포인터λ₯Ό μ‚¬μš©ν•˜λ„λ‘ μ„€κ³„λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이 κ²½μš°μ—λŠ” μΈμŠ€ν„΄μŠ€μ— λŒ€ν•œ 포인터λ₯Ό μ „λ‹¬ν•˜κΈ° λ§Œν•˜λ©΄ cλ©λ‹ˆλ‹€.

예λ₯Ό λ“€λ©΄ :

static void* execute_print(void* ctx) {
    c* cptr = (c*)ctx;
    cptr->print();
    return NULL;
}


void func() {

    ...

    pthread_create(&t1, NULL, execute_print, &c[0]);

    ...
}

λ‹΅λ³€

μœ„μ˜ 닡변은 μ’‹μ§€λ§Œ 제 κ²½μš°μ—λŠ” ν•¨μˆ˜λ₯Ό μ •μ μœΌλ‘œ λ³€ν™˜ν•˜λŠ” 첫 번째 μ ‘κ·Ό 방식이 μž‘λ™ν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. μŠ€λ ˆλ“œ ν•¨μˆ˜λ‘œ μ΄λ™ν•˜κΈ° μœ„ν•΄ κΈ°μ‘΄ μ½”λ“œλ₯Ό λ³€ν™˜ν•˜λ €κ³  μ‹œλ„ν–ˆμ§€λ§Œ ν•΄λ‹Ή μ½”λ“œμ—λŠ” 이미 λΉ„ 정적 클래슀 멀버에 λŒ€ν•œ μ°Έμ‘°κ°€ 많이 μžˆμŠ΅λ‹ˆλ‹€. C ++ 객체둜 μΊ‘μŠν™”ν•˜λŠ” 두 번째 μ†”λ£¨μ…˜μ€ μž‘λ™ν•˜μ§€λ§Œ μŠ€λ ˆλ“œλ₯Ό μ‹€ν–‰ν•˜κΈ°μœ„ν•œ 3 단계 λž˜νΌκ°€ μžˆμŠ΅λ‹ˆλ‹€.

κΈ°μ‘΄ C ++ ꡬ쑰 인 β€˜μΉœκ΅¬β€™κΈ°λŠ₯을 μ‚¬μš©ν•˜λŠ” λŒ€μ²΄ μ†”λ£¨μ…˜μ΄ μžˆμ—ˆκ³  제 κ²½μš°μ—λŠ” μ™„λ²½ν•˜κ²Œ μž‘λ™ν–ˆμŠ΅λ‹ˆλ‹€. λ‚΄κ°€ β€˜μΉœκ΅¬β€™λ₯Ό μ‚¬μš©ν•œ λ°©λ²•μ˜ 예 (친ꡬλ₯Ό μ‚¬μš©ν•˜μ—¬ μ••μΆ• ν˜•μ‹μœΌλ‘œ λ³€ν™˜ν•˜λŠ” 방법을 λ³΄μ—¬μ£ΌλŠ” 이름에 μœ„μ˜ λ™μΌν•œ 예λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€)

    class MyThreadClass
    {
    public:
       MyThreadClass() {/* empty */}
       virtual ~MyThreadClass() {/* empty */}

       bool Init()
       {
          return (pthread_create(&_thread, NULL, &ThreadEntryFunc, this) == 0);
       }

       /** Will not return until the internal thread has exited. */
       void WaitForThreadToExit()
       {
          (void) pthread_join(_thread, NULL);
       }

    private:
       //our friend function that runs the thread task
       friend void* ThreadEntryFunc(void *);

       pthread_t _thread;
    };

    //friend is defined outside of class and without any qualifiers
    void* ThreadEntryFunc(void *obj_param) {
    MyThreadClass *thr  = ((MyThreadClass *)obj_param);

    //access all the members using thr->

    return NULL;
    }

λ¬Όλ‘ , μš°λ¦¬λŠ” boost :: threadλ₯Ό μ‚¬μš©ν•  수 있고 μ΄λŸ¬ν•œ λͺ¨λ“  것을 ν”Όν•  수 μžˆμ§€λ§Œ, μ €λŠ” boostλ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šλ„λ‘ C ++ μ½”λ“œλ₯Ό μˆ˜μ •ν•˜λ €κ³ ν–ˆμŠ΅λ‹ˆλ‹€ (μ½”λ“œλŠ” 단지이 λͺ©μ μ„ μœ„ν•΄ boost에 λŒ€ν•΄ λ§ν¬λ˜μ—ˆμŠ΅λ‹ˆλ‹€)


λ‹΅λ³€

λˆ„κ΅°κ°€μ—κ²Œ 유용 ν•  κ²ƒμ΄λΌλŠ” 희망의 첫 번째 λŒ€λ‹΅ : 이제 이것은 였래된 μ§ˆλ¬Έμ΄μ§€λ§Œ TcpServer 클래슀λ₯Ό μž‘μ„±ν•˜κ³  pthreadλ₯Ό μ‚¬μš©ν•˜λ €κ³  ν•  λ•Œ μœ„μ˜ 질문과 λ˜‘κ°™μ€ 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. λ‚˜λŠ”μ΄ μ§ˆλ¬Έμ„ λ°œκ²¬ν–ˆκ³  그것이 μ™œ 일어 λ‚¬λŠ”μ§€ 이제 μ΄ν•΄ν•©λ‹ˆλ‹€. λ‚˜λŠ” 이것을 λλ‚΄μ—ˆλ‹€.

#include <thread>

μŠ€λ ˆλ“œ μ‹€ν–‰ 방법-> void* TcpServer::sockethandler(void* lp) {/*code here*/}

그리고 λ‚˜λŠ” 그것을 λžŒλ‹€λ‘œ λΆ€λ₯Έλ‹€-> std::thread( [=] { sockethandler((void*)csock); } ).detach();

그것은 λ‚˜μ—κ²Œ κΉ¨λ—ν•œ μ ‘κ·Ό λ°©μ‹μœΌλ‘œ λ³΄μž…λ‹ˆλ‹€.


λ‹΅λ³€

λ‚˜λŠ” 당신이 μš”κ΅¬ν•˜λŠ” 것을 ν•΄κ²°ν•˜λŠ” 방법을 λ„ˆλ¬΄ 많이 μ°Ύμ•˜μŠ΅λ‹ˆλ‹€. 제 μƒκ°μ—λŠ” λ„ˆλ¬΄ λ³΅μž‘ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ μƒˆλ‘œμš΄ 클래슀 μœ ν˜•, 링크 라이브러리 등을 μ •μ˜ν•΄μ•Όν•©λ‹ˆλ‹€. κ·Έλž˜μ„œ μ΅œμ’… μ‚¬μš©μžκ°€ 기본적으둜 β€œvoid :: method (void)”λ₯Ό β€œμŠ€λ ˆλ“œ 화”할 수 μžˆλ„λ‘ λͺ‡ μ€„μ˜ μ½”λ“œλ₯Ό μž‘μ„±ν•˜κΈ°λ‘œ κ²°μ •ν–ˆμŠ΅λ‹ˆλ‹€. μ–΄λ–€ μˆ˜μ—…μ΄λ“ . λ‚΄κ°€ κ΅¬ν˜„ ν•œμ΄ μ†”λ£¨μ…˜μ„ ν™•μž₯ν•˜κ±°λ‚˜ κ°œμ„  ν•  수 μžˆλŠ”μ§€ ν™•μΈν•˜κΈ° μœ„ν•΄ 더 ꡬ체적인 λ°©λ²•μ΄λ‚˜ κΈ°λŠ₯이 ν•„μš”ν•˜λ©΄ μΆ”κ°€ν•˜κ³  κ³„μ†ν•΄μ„œ μ•Œλ €μ£Όμ„Έμš”.

λ‚΄κ°€ ν•œ 일을 λ³΄μ—¬μ£ΌλŠ” 3 개의 파일이 μžˆμŠ΅λ‹ˆλ‹€.

    // A basic mutex class, I called this file Mutex.h
#ifndef MUTEXCONDITION_H_
#define MUTEXCONDITION_H_

#include <pthread.h>
#include <stdio.h>

class MutexCondition
{
private:
    bool init() {
        //printf("MutexCondition::init called\n");
        pthread_mutex_init(&m_mut, NULL);
        pthread_cond_init(&m_con, NULL);
        return true;
    }

    bool destroy() {
        pthread_mutex_destroy(&m_mut);
        pthread_cond_destroy(&m_con);
        return true;
    }

public:
    pthread_mutex_t m_mut;
    pthread_cond_t m_con;

    MutexCondition() {
        init();
    }
    virtual ~MutexCondition() {
        destroy();
    }

    bool lock() {
        pthread_mutex_lock(&m_mut);
        return true;
    }

    bool unlock() {
        pthread_mutex_unlock(&m_mut);
        return true;
    }

    bool wait() {
        lock();
        pthread_cond_wait(&m_con, &m_mut);
        unlock();
        return true;
    }

    bool signal() {
        pthread_cond_signal(&m_con);
        return true;
    }
};
#endif
// End of Mutex.h

// λ©”μ„œλ“œλ₯Ό μŠ€λ ˆλ“œ ν™”ν•˜λŠ” λͺ¨λ“  μž‘μ—…μ„ μΊ‘μŠν™”ν•˜λŠ” 클래슀 (test.h) :

#ifndef __THREAD_HANDLER___
#define __THREAD_HANDLER___

#include <pthread.h>
#include <vector>
#include <iostream>
#include "Mutex.h"

using namespace std;

template <class T>
class CThreadInfo
{
  public:
    typedef void (T::*MHT_PTR) (void);
    vector<MHT_PTR> _threaded_methods;
    vector<bool> _status_flags;
    T *_data;
    MutexCondition _mutex;
    int _idx;
    bool _status;

    CThreadInfo(T* p1):_data(p1), _idx(0) {}
    void setThreadedMethods(vector<MHT_PTR> & pThreadedMethods)
    {
        _threaded_methods = pThreadedMethods;
      _status_flags.resize(_threaded_methods.size(), false);
    }
};

template <class T>
class CSThread {
  protected:
    typedef void (T::*MHT_PTR) (void);
    vector<MHT_PTR> _threaded_methods;
    vector<string> _thread_labels;
    MHT_PTR _stop_f_pt;
    vector<T*> _elements;
    vector<T*> _performDelete;
    vector<CThreadInfo<T>*> _threadlds;
    vector<pthread_t*> _threads;
    int _totalRunningThreads;

    static void * gencker_(void * pArg)
    {
      CThreadInfo<T>* vArg = (CThreadInfo<T> *) pArg;
      vArg->_mutex.lock();
      int vIndex = vArg->_idx++;
      vArg->_mutex.unlock();

      vArg->_status_flags[vIndex]=true;

      MHT_PTR mhtCalledOne = vArg->_threaded_methods[vIndex];
      (vArg->_data->*mhtCalledOne)();
      vArg->_status_flags[vIndex]=false;
        return NULL;
    }

  public:
    CSThread ():_stop_f_pt(NULL), _totalRunningThreads(0)  {}
    ~CSThread()
    {
      for (int i=_threads.size() -1; i >= 0; --i)
          pthread_detach(*_threads[i]);

      for (int i=_threadlds.size() -1; i >= 0; --i)
        delete _threadlds[i];

      for (int i=_elements.size() -1; i >= 0; --i)
         if (find (_performDelete.begin(), _performDelete.end(), _elements[i]) != _performDelete.end())
              delete _elements[i];
    }
    int  runningThreadsCount(void) {return _totalRunningThreads;}
    int  elementsCount()        {return _elements.size();}
    void addThread (MHT_PTR p, string pLabel="") { _threaded_methods.push_back(p); _thread_labels.push_back(pLabel);}
    void clearThreadedMethods() { _threaded_methods.clear(); }
    void getThreadedMethodsCount() { return _threaded_methods.size(); }
    void addStopMethod(MHT_PTR p)  { _stop_f_pt  = p; }
    string getStatusStr(unsigned int _elementIndex, unsigned int pMethodIndex)
    {
      char ch[99];

      if (getStatus(_elementIndex, pMethodIndex) == true)
        sprintf (ch, "[%s] - TRUE\n", _thread_labels[pMethodIndex].c_str());
      else
        sprintf (ch, "[%s] - FALSE\n", _thread_labels[pMethodIndex].c_str());

      return ch;
    }
    bool getStatus(unsigned int _elementIndex, unsigned int pMethodIndex)
    {
      if (_elementIndex > _elements.size()) return false;
      return _threadlds[_elementIndex]->_status_flags[pMethodIndex];
    }

    bool run(unsigned int pIdx)
    {
      T * myElem = _elements[pIdx];
      _threadlds.push_back(new CThreadInfo<T>(myElem));
      _threadlds[_threadlds.size()-1]->setThreadedMethods(_threaded_methods);

      int vStart = _threads.size();
      for (int hhh=0; hhh<_threaded_methods.size(); ++hhh)
          _threads.push_back(new pthread_t);

      for (int currentCount =0; currentCount < _threaded_methods.size(); ++vStart, ++currentCount)
      {
                if (pthread_create(_threads[vStart], NULL, gencker_, (void*) _threadlds[_threadlds.size()-1]) != 0)
        {
                // cout <<"\t\tThread " << currentCount << " creation FAILED for element: " << pIdx << endl;
                    return false;
                }
        else
        {
            ++_totalRunningThreads;
             // cout <<"\t\tThread " << currentCount << " creation SUCCEDED for element: " << pIdx << endl;
                }
      }
      return true;
    }

    bool run()
    {
            for (int vI = 0; vI < _elements.size(); ++vI)
            if (run(vI) == false) return false;
          // cout <<"Number of currently running threads: " << _totalRunningThreads << endl;
        return true;
    }

    T * addElement(void)
    {
      int vId=-1;
      return addElement(vId);
    }

    T * addElement(int & pIdx)
    {
      T * myElem = new T();
      _elements.push_back(myElem);
      pIdx = _elements.size()-1;
      _performDelete.push_back(myElem);
      return _elements[pIdx];
    }

    T * addElement(T *pElem)
    {
      int vId=-1;
      return addElement(pElem, vId);
    }

    T * addElement(T *pElem, int & pIdx)
    {
      _elements.push_back(pElem);
      pIdx = _elements.size()-1;
      return pElem;
    }

    T * getElement(int pId) { return _elements[pId]; }

    void stopThread(int i)
    {
      if (_stop_f_pt != NULL)
      {
         ( _elements[i]->*_stop_f_pt)() ;
      }
      pthread_detach(*_threads[i]);
      --_totalRunningThreads;
    }

    void stopAll()
    {
      if (_stop_f_pt != NULL)
        for (int i=0; i<_elements.size(); ++i)
        {
          ( _elements[i]->*_stop_f_pt)() ;
        }
      _totalRunningThreads=0;
    }
};
#endif
// end of test.h

// Linuxμ—μ„œ 컴파일 ν•œ μ‚¬μš© 예제 파일 β€œtest.ccβ€λ©”μ„œλ“œλ₯Ό μŠ€λ ˆλ“œ ν™”ν•˜λŠ” λͺ¨λ“  μž‘μ—…μ„ μΊ‘μŠν™”ν•˜λŠ” 클래슀 : g ++ -o mytest.exe test.cc -I. -lpthread -lstdc ++

#include <test.h>
#include <vector>
#include <iostream>
#include <Mutex.h>

using namespace std;

// Just a class for which I need to "thread-ize" a some methods
// Given that with OOP the objecs include both "functions" (methods)
// and data (attributes), then there is no need to use function arguments,
// just a "void xxx (void)" method.
// 
class TPuck
{
  public:
   bool _go;
   TPuck(int pVal):_go(true)
   {
     Value = pVal;
   }
   TPuck():_go(true)
   {
   }
   int Value;
   int vc;

   void setValue(int p){Value = p; }

   void super()
   {
     while (_go)
     {
      cout <<"super " << vc << endl;
            sleep(2);
         }
      cout <<"end of super " << vc << endl;
   }

   void vusss()
   {
     while (_go)
     {
      cout <<"vusss " << vc << endl;
      sleep(2);
     }
      cout <<"end of vusss " << vc << endl;
   }

   void fazz()
   {
     static int vcount =0;
     vc = vcount++;
     cout <<"Puck create instance: " << vc << endl;
     while (_go)
     {
       cout <<"fazz " << vc << endl;
       sleep(2);
     }
     cout <<"Completed TPuck..fazz instance "<<  vc << endl;
   }

   void stop()
   {
      _go=false;
      cout << endl << "Stopping TPuck...." << vc << endl;
   }
};


int main(int argc, char* argv[])
{
  // just a number of instances of the class I need to make threads
  int vN = 3;

  // This object will be your threads maker.
  // Just declare an instance for each class
  // you need to create method threads
  //
  CSThread<TPuck> PuckThreadMaker;
  //
  // Hera I'm telling which methods should be threaded
  PuckThreadMaker.addThread(&TPuck::fazz, "fazz1");
  PuckThreadMaker.addThread(&TPuck::fazz, "fazz2");
  PuckThreadMaker.addThread(&TPuck::fazz, "fazz3");
  PuckThreadMaker.addThread(&TPuck::vusss, "vusss");
  PuckThreadMaker.addThread(&TPuck::super, "super");

  PuckThreadMaker.addStopMethod(&TPuck::stop);

  for (int ii=0; ii<vN; ++ii)
  {
    // Creating instances of the class that I need to run threads.
    // If you already have your instances, then just pass them as a
    // parameter such "mythreadmaker.addElement(&myinstance);"
    TPuck * vOne = PuckThreadMaker.addElement();
  }

  if (PuckThreadMaker.run() == true)
  {
    cout <<"All running!" << endl;
  }
  else
  {
    cout <<"Error: not all threads running!" << endl;
  }

  sleep(1);
  cout <<"Totale threads creati: " << PuckThreadMaker.runningThreadsCount()  << endl;
  for (unsigned int ii=0; ii<vN; ++ii)
  {
    unsigned int kk=0;
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
  }

  sleep(2);
  PuckThreadMaker.stopAll();
  cout <<"\n\nAfter the stop!!!!" << endl;
  sleep(2);

  for (int ii=0; ii<vN; ++ii)
  {
    int kk=0;
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
    cout <<"status for element " << ii << " is " << PuckThreadMaker.getStatusStr(ii, kk++) << endl;
  }

  sleep(5);
  return 0;
}

// End of test.cc

λ‹΅λ³€

이것은 μ•½κ°„ 였래된 μ§ˆλ¬Έμ΄μ§€λ§Œ λ§Žμ€ μ‚¬λžŒλ“€μ΄ μ§λ©΄ν•˜λŠ” 맀우 일반적인 λ¬Έμ œμž…λ‹ˆλ‹€. λ‹€μŒμ€ std :: threadλ₯Ό μ‚¬μš©ν•˜μ—¬μ΄λ₯Ό μ²˜λ¦¬ν•˜λŠ” κ°„λ‹¨ν•˜κ³  μš°μ•„ν•œ λ°©λ²•μž…λ‹ˆλ‹€.

#include <iostream>
#include <utility>
#include <thread>
#include <chrono>

class foo
{
    public:
        void bar(int j)
        {
            n = j;
            for (int i = 0; i < 5; ++i) {
                std::cout << "Child thread executing\n";
                ++n;
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
            }
        }
        int n = 0;
};

int main()
{
    int n = 5;
    foo f;
    std::thread class_thread(&foo::bar, &f, n); // t5 runs foo::bar() on object f
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
    std::cout << "Main Thread running as usual";
    class_thread.join();
    std::cout << "Final value of foo::n is " << f.n << '\n';
}

μœ„μ˜ μ½”λ“œλŠ” μŠ€λ ˆλ“œ ν•¨μˆ˜μ— 인수λ₯Ό μ „λ‹¬ν•˜λŠ” μž‘μ—…λ„ μ²˜λ¦¬ν•©λ‹ˆλ‹€.

μžμ„Έν•œ λ‚΄μš©μ€ std :: thread λ¬Έμ„œλ₯Ό μ°Έμ‘°ν•˜μ‹­μ‹œμ˜€.


이 글은 C++ μΉ΄ν…Œκ³ λ¦¬λ‘œ λΆ„λ₯˜λ˜μ—ˆκ³  λ‹˜μ— μ˜ν•΄ 에 μž‘μ„±λμŠ΅λ‹ˆλ‹€.