#include <pthread.h>

class TThread{
    public:
        int start();
        int lock();
        int unlock();
        int wait();
        int cont();
        int detach();
        int join();
        int lockNwait();
        bool isWait;

        virtual void run(){}

        //char   msg[LEN_MSG+1];
        //struct sockaddr_in addr;
        //int addrlen;

    private:
    pthread_t       mvThr;
    pthread_cond_t  mvCond;
    pthread_mutex_t mvMutex;
};

extern "C" void* threadLauncher( void* ) ;
int TThread::start()
{
    int ret;
    isWait = false;
    ret = pthread_cond_init ( &mvCond,  NULL);
    ret = pthread_mutex_init( &mvMutex, NULL);
    ret = pthread_create( &mvThr, NULL, &threadLauncher, this ) ;

    return ret;
}

extern "C" void* threadLauncher( void* t ) {
  ((TThread*)t)->run() ;
  return NULL ;
}

int TThread::join()
{
    int ret;
    ret = pthread_join( (mvThr), NULL );
    return ret;
}
int TThread::detach()
{
    int ret;
    ret = pthread_detach( (mvThr) );
    return ret;
}

int TThread::wait()
{
    int ret;
    ret = pthread_cond_wait(&mvCond, &mvMutex);
    return ret;
}
int TThread::cont()
{
    int ret;
    ret = pthread_cond_signal( &mvCond ) ;
    return ret;
}
int TThread::lock()
{
    int ret;
    ret = pthread_mutex_lock(&mvMutex);
    return ret;
}
int TThread::unlock()
{
    int ret;
    ret = pthread_mutex_unlock(&mvMutex);
    return ret;
}

int TThread::lockNwait()
{
    lock();
    isWait = true;
    wait();
    isWait = false;
    unlock();
}


#include <iostream>
#include <vector>
using namespace std;
class TT:public TThread{
};

typedef vector<TT*> testThrVec;
testThrVec t_thrVec;
// -------------------------------------- Ttest
class Ttest : public TT{
    public:
    Ttest(int i);
    void run();
    int i;
    int no;
};
Ttest::Ttest(int x){
    i = 0;
    no = x;
}
void Ttest::run(){
  while(1){
      t_thrVec[no]->lockNwait();
      cerr<<"start"<<no<<endl;
      sleep(2);
      cerr<<"           end"<<no<<endl;
      if(i++ > 2) break;
  }
      cerr<<"---------- return"<<no<<endl;
}

// -------------------------------------- Tinput
class Tinput : public TT {
    public:
    void run();
};

void Tinput::run(){
    begin:
      for(int i = 0; i<t_thrVec.size() ;i++){
        getc(stdin);
        if( !t_thrVec[i]->isWait ) { cerr<<"       busy:"<<i<<endl; continue; }
        cerr<<"       cond_signal:"<<i<<endl; 
        t_thrVec[i]->cont();
      }
    goto begin;
}


int main(){
    int ret;

    Tinput *inputThr = new Tinput();
        inputThr->start();
        ret = inputThr->detach();


    for(int i=0;i<9000;i++) {
        t_thrVec.push_back( new Ttest(i) ); 
        ret = t_thrVec[i]->start();
        if(ret!=0) {
            delete( t_thrVec[i] ); 
            t_thrVec.erase( t_thrVec.end()-1 );
            break;
        }
    }

	cout<< "thread " << t_thrVec.size() << "created " << endl;

    for(int i=0;i<t_thrVec.size();i++){
        t_thrVec[i]->join();
    }
}