2010-10-18 10 views
0

Est-il possible de stocker une classe basé sur des modèles commemagasin basé sur des modèles d'objets dans le conteneur

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

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

dans le même récipient comme un vecteur ou d'une liste

modifier: Le but de cela est que je suis en train de faire un tampon circulaire où les objets qui veulent utiliser le tampon doivent s'inscrire avec le tampon. Le buffer stockera un boost :: shared_ptr aux objets accesseur et générera un callback à ses fonctions qui vont pousser ou tirer des données vers/depuis le buffer. Le rappel sera utilisé dans une fonction générique de thread worker que j'ai créée de la même manière qu'un pool de threads avec le fait qu'ils doivent accéder à un objet de mémoire partagée. Voici un code que je l'ai tapé qui pourrait aider à illustrer ce que je suis en train de faire, mais il n'a pas été compilé encore et c'est aussi ma première fois en utilisant bind, fonction, multi-threading

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

Comment voulez-vous appeler 'do_work' * si * c'est possible? – kennytm

+0

Le but de cette classe est d'autoriser les objets à s'inscrire avec le tampon circulaire. une fois enregistré en tant que producteur ou consommateur, l'objet tampon va créer un rappel de la fonction do_work et le passer dans la fonction de thread worker afin que le buffer puisse être rempli et consommé. – Talguy

+0

Je ne suis pas sûr de suivre, mais il semble que vous cherchiez peut-être 'std :: function' /' boost :: function', avec 'std :: bind' ou' boost: bind'. – GManNickG

Répondre

3

Non, ce n'est pas le cas, car les conteneurs STL sont homogènes, et access1 et access2 ont des types complètement différents. Mais vous pourriez faire la classe BufferAccessor non-modèle, mais un membre do travail comme modèle, comme ceci:

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

Dans ce cas, vous pouvez stocker BufferAccessors dans un récipient, mais vous ne pouvez pas faire un membre fonction de template virtuelle.

+0

Quelle est la meilleure façon d'hériter de cette classe lors de la définition d'un retour vide et d'une sorte de retour d'objet pour la fonction dowork? – Talguy

+0

@Talguy: Je crains que vous n'ayez à reformuler votre question. Je ne l'ai pas compris, désolé –

+0

Je veux hériter de la classe BufferAccessor pour qu'un objet soit défini en tant que producteur ou consommateur pour ma circulaire. devrais-je simplement laisser la fonctionnalité dans la fonction dowork de la classe de base vide, puis définir la fonctionnalité dans les classes dérivées. ou devrais-je écrire un code de remplissage pour la classe de base comme cout << << Hello world ". – Talguy

0

Oui, vous pouvez utiliser vector<BufferAccessor<void,int> > pour stocker des objets BufferAccessor<void,int> et vector<BufferAccessor<int,void> > pour stocker des objets BufferAccessor<int,void>.

Ce que vous ne pouvez pas faire est d'utiliser un même vecteur pour stocker à la fois BufferAccessor<int,void> et BufferAccessor<void,int> objet La raison pour laquelle cela ne fonctionne pas parce que BufferAccessor<void,int> et BufferAccessor<int,void> sont deux classes différentes

Note: il est possible d'utiliser le même vecteur pour stocker à la fois BufferAccessor<int,void> et BufferAccessor<void,int> mais vous devrez soit les stocker comme void * en utilisant shared_ptr<void>. Ou mieux encore, vous pouvez utiliser un boost::variant