0

I have problem with storing templates class in the base of two objects.

Say I have generalized class named ObjectManager Defined as:

template<typename T>
class ObjectManager
{}

And I have a base class like:

class MediaSample
{
public:
    MediaSample(ObjectManager<?>* manager){}
private:
    ObjectManager<?> mMediaSampleManager;
}

Now I declare another two drived class from MediaSample, say:

class AudioSample : public MediaSample
{
public:
    AudioSample() : MediaSample(new ObjectManager<AudioSample>()){}
    //...
}
public class VideoSample : public MediaSample
{
public:
    VideoSample() : MediaSample(new ObjectManager<VideoSample>())
    //...
}

My problem is type of manager, input parameter of MediaSample class.

Which type must be place instead of question mark character? (Audio, Video or what?)

for more clarification i posted complete source of ObjectManager note that object manager is a poll of media sample objects and media sample can be audio or video

class BaseMediaSampleManager
{
public:
    ~BaseMediaSampleManager(){}

    virtual INT initialize(INT objectCount) = 0;

protected:
private:
};

template<typename T>
class MediaSamppleManager : public BaseMediaSampleMnager //(based on user2079303 advise)
{
protected:
    MediaSamppleManager(void);

    MediaSamppleManager(const MediaSamppleManager& manager);

    MediaSamppleManager& operator = (const MediaSamppleManager& rhs);

public: 

    virtual ~MediaSamppleManager(void);

    static MediaSamppleManager<T>* instance();

    INT initialize(INT objectCount);

    // take existing object from object pool and return that object
    INT aquireObject(T** object);

    // take back in use object to object pool
    INT release(T* object);

private:
    std::list<T*> mPooledSamples;
    INT32 mPooledObjectCount;
    INT32 mInUseObjects;
    Mutex mPooledSamplesMutex;
    static Mutex mSampleManagerObjectMutex;
    static MediaSamppleManager<T>* mSampleManagerObject;
};

template<typename T>
Mutex MediaSamppleManager<T>::mSampleManagerObjectMutex;

template<typename T>
MediaSamppleManager<T>* MediaSamppleManager<T>::mSampleManagerObject = NULL;

template<typename T>
MediaSamppleManager<T>* MediaSamppleManager<T>::instance()
{
    if (mSampleManagerObject == NULL)
    {
        ScopedLock<Mutex> guard(mSampleManagerObjectMutex);
        if (mSampleManagerObject == NULL)
        {
            MediaSamppleManager<T>* temp = new MediaSamppleManager<T>();
            mSampleManagerObject = temp;
        }
    }
    return mSampleManagerObject;
}

template<typename T>
MediaSamppleManager<T>& MediaSamppleManager<T>::operator=(const MediaSamppleManager<T>& rhs)
{

}

template<typename T>
MediaSamppleManager<T>::MediaSamppleManager(const MediaSamppleManager<T>& manager)
{

}

template<typename T>
INT MediaSamppleManager<T>::release(T* object)
{
    ScopedLock<Mutex> guard(mPooledSamplesMutex);
    mPooledSamples.push_back(object);
    mInUseObjects--;
}

template<typename T>
INT MediaSamppleManager<T>::aquireObject(T** object)
{
    ScopedLock<Mutex> guard(mPooledSamplesMutex);
    if (mInUseObjects == mPooledObjectCount)
    {
        // do we need waiting until new sample become available? or 
        // is it required to create new sample when no free sample exist in pool? 
        return 2;
    } 
    else
    {
        T* temp = 0;
        temp = mPooledSamples.front();
        *object = temp;
        mPooledSamples.pop_front();
        mInUseObjects++;
    }
    return 1;
}

template<typename T>
INT MediaSamppleManager<T>::initialize(INT objectCount)
{
    if (objectCount<=0)
    {
        return -1;
    }
    mPooledObjectCount = objectCount;
    mPooledSamples.resize(objectCount);
    for (int i = 0 ; i< objectCount ; i++)
    {
        T* temp = new T(this);
        mPooledSamples.push_back(temp);
    }
    return 1;
}

template<typename T>
MediaSamppleManager<T>::~MediaSamppleManager(void)
{
    std::cout << "MediaSampleManager Destroyed \n";
}

template<typename T>
MediaSamppleManager<T>::MediaSamppleManager(void)
    :mPooledObjectCount(0)
    ,mInUseObjects(0)
{

}

class MediaSample :

class MediaSample
{
public:
    // create empty media sample
    MediaSample(BaseMediaSampleManager* manager);

    virtual ~MediaSample(void);

    virtual INT32 rate() = 0;

    virtual double frameSize() = 0;

    // data size of media sample
    virtual INT size();

    UINT* data();

    ULONG samplingTime();

    INT32 addRef();

    INT32 release();    

private:
    UINT8* mMediaSampleBuffer;
    // The time sample captured
    ULONG mTimestamp;
    // length of data
    INT mDataLength;

    INT mRefCount;

    BaseMediaSampleManager* mMediaSampleManager;
};

class AudioSample :

class PMCAPI AudioSample 
    :public MediaSample/*<AudioSample>*/
{
public:
    AudioSample(MediaSamppleManager<AudioSample>* manager);

    ~AudioSample();

    virtual INT32 rate();

    virtual double frameSize();

    virtual INT size();

protected:
private:
    // in 8,16 KHZ
    INT32 mSampleRate;
    // Mono or Stereo
    INT mChannels;
    // Used format ex: PCM,G729,G723,G711A,G711U
    INT mCodec;
    // ex : 8 bit , 16 bit
    INT mBitsPerSample;
};
Benyamin Jane
  • 407
  • 2
  • 5
  • 16
  • How `MediaSample`, `ObjectManger` and `XxxSample` are supposed to interact with each other? Is `MediaSample`supposed to 'aquire/contruct' `XxxSample` with `mMediaSampleManager`? – Gall Jul 31 '14 at 12:04
  • NO,when client need new MediaSample , request it from MediaSampleManager.
    MediaSampleManager* amsm = MediaSampleManager::instanse();
    AudioSample* asample = NULL;
    amsm.aquireObject(&asample);
    this way we get Media(audio/video)Sample from pool. for releasing it we call amsm.release(asample);
    – Benyamin Jane Jul 31 '14 at 12:09
  • I see, what about the first question? – Gall Jul 31 '14 at 12:15
  • Because I don't see the need for `ObjectManager` in `MediaSample` right now. – Gall Jul 31 '14 at 12:18
  • MediaSample need to reference it's manager because when client down with MediaSample object , release it.by releasing, MediaSample Object request from manager to take it back to the pool(this down in destructor of MediaSample) – Benyamin Jane Jul 31 '14 at 12:24
  • @Gall MediaSample is base class of Audio and Video Sample. MediaSample class is ref counted object.like Microsoft Directshow whenever a filter use MediaSample must call addRef(somthing like ref counted object) and whenever a filter done with media sample deRef it. when ref count reaches zero , we detect this in the destructor of MediaSample object, MediaSample object request from manager to take it back to ready to use pool. – Benyamin Jane Jul 31 '14 at 12:31

3 Answers3

2

It's can get pretty difficult to mix compile time (templates) and runtime polymorphism (inheritance). What you can do:

a) Make the base class a template

template <class T>
class MediaSample {
    ObjectManager<T> mMediaSampleManager;
};

class AudioSample : public MediaSample<AudioSample>

In this case AudioSample and VideoSample will not have a common base class, which may not be what you want. Alternatively, you can

b) Give ObjectManager a non-template base class (an interface)

class BaseManager{
    virtual ~BaseManager(){}
    // pure virtual functions that ObjectManager implements
};

template<typename T>
class ObjectManager: public BaseManager{
    // implementation
};

class MediaSample {
    BaseManager mMediaSampleManager;
    // ...
};

class AudioSample: public MediaSample {
public:
    AudioSample() : MediaSample(new ObjectManager<AudioSample>()){}

Also, note that if your MediaSample constructor accepts a pointer to newly constructed ObjectManager and you presumably copy that to the member object, you must remember to delete the pointer or it'll leak. You should probably pass by value instead.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • i test first way but i see no media object constructed. and about second way i am going to test it now – Benyamin Jane Jul 31 '14 at 11:38
  • What is "media object"? If you mean `MediaSample`, an instance is constructed as a parent of `AudioSample` – eerorika Jul 31 '14 at 11:43
  • i mean initialize method could not create object of type T. even when i try to break into the constructor of type T(that is AudioSample or VideoSample class) VS says that source changed – Benyamin Jane Jul 31 '14 at 12:20
  • `VS says that source changed` Is that a compilation error message? Sounds weird, I don't use VS. `break into the constructor` What does that mean? Anyway, your `initialize` method constructs `T`'s by passing `this` to the constructor but you've only shown that `AudioSample` etc has a constructor with no parameters. Did you forget to add the constructor which has a `ObjectManager*` as a parameter? (I'm assuming that `MediaSamppleManager` is the same as `ObjectManager`. Please, try to stay consistent) – eerorika Jul 31 '14 at 12:36
  • YES ,both are equivelant i add defnitions of AudioSample and MediaSample classes – Benyamin Jane Jul 31 '14 at 12:43
  • i found that initialize work perfectly but i don't know what happen when we return from initialize method.after returning from this method none of the created objects are valid!!! – Benyamin Jane Jul 31 '14 at 12:50
  • initialize creates `objectCount` number of uninitialized pointers in the list when you call `resize`. You add the pointers to the constructed objects after the uninitialized pointers. – eerorika Jul 31 '14 at 12:53
  • Okey,Thank u so much , by removing resize every thing work correctly – Benyamin Jane Jul 31 '14 at 13:01
0

How about making MediaSample a template:

template <typename T>
class MediaSample
{
public:
    MediaSample(ObjectManager<T>* manager){}
private:
    ObjectManager<T> mMediaSampleManager;
};

This way you can have different kinds of MediaSample without the neeed of having derived classes AudioSample and VideoSample.

0

In this case MediaSampleneeds to be a template

template<typename T>
class MediaSample
{
public:
    MediaSample(ObjectManager<T>* manager): mMediaSampleManager(manager) {}
private:
    ObjectManager<T>* mMediaSampleManager;
}

and XxxSample has to inherit from the specialized MediaSample

class AudioSample : public MediaSample<AudioSample>
{
public:
    AudioSample() : MediaSample(new ObjectManager<AudioSample>()){}
    ...
}
Gall
  • 1,595
  • 1
  • 14
  • 22
  • in this case we fall into The **Curiously Recurring Template Pattern (CRTP)** when we drive AudioSample from MediaSample no objects of type AudioSample constructed. AudioSample is our final type – Benyamin Jane Jul 31 '14 at 11:34
  • @BenyaminJane I don't get what you mean, can you edit your question with the intented behavior you are looking for then ? – Gall Jul 31 '14 at 11:42
  • mi mean inheriting AdudioSample from MediaSample is not correct way as i tested this way before – Benyamin Jane Jul 31 '14 at 11:48
  • This changes the class hierarchy. Presumably there is a reason for the two classes inheriting from the same base. – D Drmmr Jul 31 '14 at 11:49