2010-10-18 4 views
0

Можно ли хранить шаблонный класс какмагазин Templated объект в контейнере

template <typename rtn, typename arg> 
class BufferAccessor { 
    public: 
    int ThreadID; 
    virtual rtn do_work(arg) = 0; 
}; 

BufferAccessor<void,int> access1; 
BufferAccessor<int,void> access2; 

в том же контейнере, как вектор или список

редактировать: Цель для этого я пытаюсь сделать круговой буфер, где объекты, которые хотят использовать буфер, должны регистрироваться в буфере. Буфер будет хранить boost :: shared_ptr для объектов-аксессуаров и генерировать обратный вызов там функций, которые будут толкать или вытаскивать данные в/из буфера. Обратный вызов будет использоваться в общей рабочей функции потока, которую я создал аналогично пулу потоков с тем фактом, что им нужно получить доступ к общему объекту памяти. Ниже приведен код, я отпечатал, которые могли бы помочь проиллюстрировать то, что я пытаюсь сделать, но он не был скомпилирован еще и это тоже мой первый раз с помощью связывания, функции многопоточной

typedef boost::function<BUF_QObj (void)> CallbackT_pro; 
     typedef boost::function<void (BUF_QObj)> CallbackT_con; 
     typedef boost::shared_ptr<BufferAccessor> buf_ptr; 

     // Register the worker object 
      int register_consumer(BufferAccesser &accessor) { 
       mRegCons[mNumConsumers] = buf_ptr(accessor); 
       return ++mNumConsumers; 
      } 

      int register_producer(BufferAccesser &accessor) { 
       mRegPros[mNumProducers] = buf_ptr(accessor); 
       return ++mNumProducers; 
      } 
       // Dispatch consumer threads 
       for(;x<mNumConsumers; ++x) { 
        CallBack_Tcon callback_con = boost::bind(&BufferAccessor::do_work, mRegCons[x]); 
        tw = new boost:thread(boost::bind(&RT_ActiveCircularBuffer::consumerWorker, this, callback_con)); 
        consumers.add(tw); 
       } 

       // Dispatch producer threads 
       for(x=0;x<mNumProducers; ++x) { 
        CallBack_Tpro callback_pro = boost::bind(&BufferAccessor::do_work, mRegPros[x], _1); 
        tw = new boost:thread(boost::bind(&RT_ActiveCircularBuffer::producerWorker, this, callback_pro)); 
        producers.add(tw); 
       } 
     // Thread Template Workers - Consumer 
      void consumerWorker(CallbackT_con worker) { 
       struct BUF_QObj *qData; 

       while(!mRun) 
        cond.wait(mLock); 

       while(!mTerminate) { 
        // Set interruption point so that thread can be interrupted 
        boost::thread::interruption_point(); 
        { // Code Block 
         boost::mutex::scoped_lock lock(mLock); 
         if(buf.empty()) { 
          cond.wait(mLock) 

         qData = mBuf.front(); 
         mBuf.pop_front(); // remove the front element 
        } // End Code Block 

        worker(qData); // Process data 

        // Sleep that thread for 1 uSec 
        boost::thread::sleep(boost::posix_time::nanoseconds(1000)); 
       } // End of while loop 
      } 

      // Thread Template Workers - Producer 
      void producerWorker(CallbackT_pro worker) { 
       struct BUF_QObj *qData; 
       boost::thread::sleep(boost::posix_time::nanoseconds(1000)); 

       while(!mRun) 
        cond.wait(mLock); 

       while(!mTerminate) { 
        // Set interruption point so that thread can be interrupted 
        boost::thread::interruption_point(); 

        qData = worker(); // get data to be processed 

        { // Code Block 
         boost::mutex::scoped_lock lock(mLock); 
         buf.push_back(qData); 
         cond.notify_one(mLock); 
        } // End Code Block 

        // Sleep that thread for 1 uSec 
        boost::thread::sleep(boost::posix_time::nanoseconds(1000)); 
       } // End of while loop 
      } 
+2

Как вы хотите называть 'do_work' *, если * возможно? – kennytm

+0

Точка этого класса предназначена для того, чтобы объекты регистрировались с помощью циклического буфера. после регистрации в качестве производителя или потребителя буферный объект создаст обратный вызов функции do_work и передаст это в функцию рабочего потока, чтобы буфер мог быть заполнен и потреблен. – Talguy

+0

Я не уверен, что я следую, но похоже, что вы ищете 'std :: function' /' boost :: function', а также 'std :: bind' или' boost: bind'. – GManNickG

ответ

3

Нет, это не так, потому что контейнеры STL однородны, а access1 и access2 имеют совершенно разные несвязанные типы. Но вы могли бы сделать класс BufferAccessor нешаблонном один, а элемент сделай работу в качестве шаблона, например:

class BufferAccessor 
{ 
    template<class R, class A> 
    R doWork(A arg) {...} 
}; 

В этом случае вы можете хранить BufferAccessors в контейнере, но вы не можете сделать член функция шаблона виртуальная.

+0

Каков наилучший способ наследования этого класса при определении возврата void и возврата какого-либо объекта для функции dowork? – Talguy

+0

@Talguy: Боюсь, вам придется перефразировать ваш вопрос. Я этого не понял, извините –

+0

Я хочу наследовать из класса BufferAccessor, чтобы объект был определен как производитель или потребитель для моего циркуляра. я просто оставлю функциональность в функции dowork базового класса пустым, а затем определим функциональность в производных классах. или я должен написать некоторый код наполнителя для базового класса, например cout << «Hello world». – Talguy

0

Да, вы можете использовать vector<BufferAccessor<void,int> > для хранения BufferAccessor<void,int> объектов и vector<BufferAccessor<int,void> > для хранения BufferAccessor<int,void> объектов.

Что вы не можете сделать, это использовать тот же вектор для хранения как BufferAccessor<int,void> и BufferAccessor<void,int> объект Причина это не работает потому, что BufferAccessor<void,int> и BufferAccessor<int,void> два разных класса

Note: можно использовать тот же вектор для хранения оба BufferAccessor<int,void> и BufferAccessor<void,int>, но вам нужно будет либо хранить их как void *, используя shared_ptr<void>. Или еще лучше, но вы можете использовать boost::variant

Смежные вопросы