第3月第2天 find symbolicatecrash 生产者-消费者 ice 引用计数

1.linux find export

find /Applications/Xcode.app/ -name symbolicatecrash -type f

export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"

 

2.symbolicatecrash

http://www.cnblogs.com/ningxu-ios/p/4141783.html

3.AURenderCallbackStruct

        AURenderCallbackStruct callbackStruct;
        callbackStruct.inputProc = AudioPlayUnit_context::playbackCallback;
        callbackStruct.inputProcRefCon = this;

4.生产者-消费者

1)缓冲区,缓冲区写满需等待,消费者消费后需通知

class BytesBuffer : public IceUtil::Shared
{
public:
    BytesBuffer(size_t bufferSize);
    void feed(size_t size, BufferChunkRef cbChunk);
    void eat(size_t size, BufferChunkRef cbChunk);

等待 

void BytesBuffer_context::feed(size_t size, BufferChunkRef cbChunk)
{
    {
        Monitor<RecMutex>::Lock lock(_monitor);
        if (_feedTerminated) return;
        
        while( size > _feedCapacity && !_eatTerminated) {
            _currentFeedRequestSize = size;
            //            SP::printf("
wait feeding, eatting %s
", _eatTerminated ? "terminated" : "not terminated");
            _monitor.wait();
        }
        _currentFeedRequestSize = 0;
    }

通知

        Monitor<RecMutex>::Lock lock(_monitor);
        //check and notify, if _feedTerminated then _currentFeedRequestSize=0,  verify already included
        if (_feedCapacity < _currentFeedRequestSize && _feedCapacity + size >= _currentFeedRequestSize)
            _monitor.notify();

  

2)生产者

DecoderFileThread::DecoderFileThread(const char* path, BytesBufferPtr buffer)
: filepath(path)
, _buffer(buffer)
, _destroy(false)
, _decodeState(0)

, file(0)
{
    _cbChunk._userData = this;
    _cbChunk._callback = DecoderFileThread::feedCallback;
}

void DecoderFileThread::run()
{
    _decodeState = Decoder_Interface_init();
    file = fopen(filepath.c_str(), "rb");
    fseek(file, 6, 0);
    do {
        _buffer->feed(160*2, &_cbChunk);
    } while (!_destroy);
    Decoder_Interface_exit(_decodeState);
    fclose(file);
    //SP::printf("
finish decode file
");
}

3)消费者

OSStatus AudioPlayUnit_context::playbackCallback(void *inRefCon,
                                                 AudioUnitRenderActionFlags *ioActionFlags,
                                                 const AudioTimeStamp *inTimeStamp,
                                                 UInt32 inBusNumber,
                                                 UInt32 inNumberFrames,
                                                 AudioBufferList *ioData) {
#if !TEST
    // Notes: ioData contains buffers (may be more than one!)
    // Fill them up as much as you can. Remember to set the size value in each buffer to match how
    // much data is in the buffer.
    AudioPlayUnit_context* This = (AudioPlayUnit_context*)inRefCon;
    
    
    RenderChunk cbchunk = {0};
    cbchunk.inRefCon = This;
    cbchunk.ioActionFlags = ioActionFlags;
    cbchunk.inTimeStamp = inTimeStamp;
    cbchunk.inBusNumber = inBusNumber;
    cbchunk.inNumberFrames = inNumberFrames;
    cbchunk.ioData = ioData;
    
    BufferChunk chunk;
    chunk._callback = AudioPlayUnit_context::eatCallback;
    chunk._userData = &cbchunk;
    This->_buffer->eat(inNumberFrames*This->_audioFormat.mBytesPerFrame, &chunk);
    
    static size_t expired = 0;
    static IceUtil::Time lasttime;
    if(This->_renderstartTimestamp == 0)
    {
        This->_renderstartTimestamp = IceUtil::Time::now().toMilliSeconds();
        expired = 0;
    }
    else
        expired = IceUtil::Time::now().toMilliSeconds() - This->_renderstartTimestamp;
    
    if (This->_listenerPtr.get()) This->_listenerPtr->progress(This->_listenerPtr->userData, expired);
    return noErr;
#else
    
    AudioPlayUnit_context* This = (AudioPlayUnit_context*)inRefCon;
    static size_t pos = 0;
    ioData->mBuffers[0].mData = This->_filebuffer + pos;
    pos += inNumberFrames*2;
    //bytes2HexS((unsigned char*)ioData->mBuffers[0].mData, inNumberFrames*2);
    return noErr;
#endif
}

 5.ice

unix网络编程(卷2)7.3小节描述了生产者-消费者问题,7.5小节描述了条件变量

iceutil的monitor就是cpp的封装实现。

//
// This monitor implements the Mesa monitor semantics. That is any
// calls to notify() or notifyAll() are delayed until the monitor is
// unlocked.
//
template <class T>
class Monitor
{

 6.引用计数

objective-c的引用计数很好理解,[[xx alloc] init]引用计数为1,retain引用计数加1,release引用计数减1,当引用计数为0时销毁内存。

ice的IceUtil::Shared包含了引用计数加1减1,但IceUtil::Shared在构造函数和析构函数并不会改变引用计数。使用时是使用IceUtil::Handle对象,IceUtil::Handle包含一个_ptr,构造函数如果参数为空,_prt置为null。如果构造函数的参数不为空,就会将_prt的引用计数加1,this->_ptr->__incRef(),析构函数会将_ptr的引用计数减1,this->_ptr->__decRef()。decRef函数判断引用计数为0时销毁内存。

IceUtril::Handle的拷贝构造函数和赋值函数也是将_ptr引用计数加1.因此有多个IceHandle包含同一个IceUtil::Shared,将IceUtil::Shared的引用计数加加减减。

IceUtil::Shared是用户自己new出来的,默认的引用计数为0,使用IceUtil::Handle时才会改变_ptr引用计数的值。

ace的ACE_Refcounted_Auto_Ptr_Rep包含了引用计数,内部包括一个auto_ptr的ptr_对象,构造函数会创建ptr_对象,析构时ptr_对象也会自动销毁,auto_ptr对象销毁时会释放new出来的内存。通过static函数attach,detach将引用计数加1减1,detach函数判断引用计数为0时销毁ACE_Refcounted_Auto_Ptr_Rep对象。

ace使用时是使用 ACE_Refcounted_Auto_Ptr,ACE_Refcounted_Auto_Ptr对象构造函数会创建ACE_Refcounted_Auto_Ptr_Rep对象rep_,析构函数会调用detach函数将rep_的引用计数减1.ACE_Refcounted_Auto_Ptr对象的拷贝构造函数和赋值函数也是将rep_引用计数加1.

因此有多个ACE_Refcounted_Auto_Ptr包含同一个ACE_Refcounted_Auto_Ptr_Rep,将ACE_Refcounted_Auto_Ptr_Rep的引用计数加加减减。

ACE_Refcounted_Auto_Ptr_Rep对象是ACE_Refcounted_Auto_Ptr对象构造函数创建的。使用ACE_Refcounted_Auto_Ptr时会改变rep_引用计数的值。

总结:

ace的ACE_Refcounted_Auto_Ptr不是很好理解,因为X *p并没有引用计数,所以需要封装一个ACE_Refcounted_Auto_Ptr_Rep对象,但ACE_Refcounted_Auto_Ptr_Rep对象又不是用户自己创建的,是构造函数自己创建的。 而构造函数中又没有通过ACE_Refcounted_Auto_Ptr_Rep对象来创建,这样就隐藏了ACE_Refcounted_Auto_Ptr_Rep对象的存在,让人不好理解。

第一步,创建ACE_Refcounted_Auto_Ptr_Rep对象,第二步使用ACE_Refcounted_Auto_Ptr。ace不让用户一步步完成。构造函数是通过X *p创建ACE_Refcounted_Auto_Ptr_Rep对象,拷贝构造函数和赋值函数是通过const ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> &r的rep_引用计数加1。

而ice 因此如果需要将一个对象申明智能指针,必须让其继承至IceUtil::Shared,就好理解一点。

iceutil::Shared

class ICE_UTIL_API Shared
{
public:

    Shared();
    Shared(const Shared&);

    virtual ~Shared()
    {
    }

    Shared& operator=(const Shared&)
    {
        return *this;
    }

    virtual void __incRef();
    virtual void __decRef();
    virtual int __getRef() const;
    virtual void __setNoDelete(bool);

protected:

#if defined(_WIN32)
    LONG _ref;
#elif defined(ICE_HAS_ATOMIC_FUNCTIONS) || defined(ICE_HAS_GCC_BUILTINS)
    volatile int _ref;
#else
    int _ref;
    Mutex _mutex;
#endif
    bool _noDelete;
};

}

ace

template <class X, class ACE_LOCK> inline
ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::ACE_Refcounted_Auto_Ptr (X *p)
  : rep_ (AUTO_REFCOUNTED_PTR_REP::create (p))
{
}

template <class X, class ACE_LOCK> inline
ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::ACE_Refcounted_Auto_Ptr (const ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> &r)
  : rep_ (AUTO_REFCOUNTED_PTR_REP::attach (((ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> &) r).rep_))
{
}

template <class X, class ACE_LOCK> inline void
ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::operator = (const ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> &rhs)
{
  //  bind <this> to the same <ACE_Refcounted_Auto_Ptr_Rep> as <r>.
  AUTO_REFCOUNTED_PTR_REP *old_rep = this->rep_;
  if (rhs.rep_ != 0)
    {
      this->rep_ = AUTO_REFCOUNTED_PTR_REP::attach
        (const_cast<ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>& > (rhs).rep_);
      if (this->rep_ != 0)
        AUTO_REFCOUNTED_PTR_REP::detach (old_rep);
    }
  else    // Assign a 0 rep to this
    {
      AUTO_REFCOUNTED_PTR_REP::detach (old_rep);
      this->rep_ = 0;
    }
}

template <class X, class ACE_LOCK>
ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::~ACE_Refcounted_Auto_Ptr (void)
{
  AUTO_REFCOUNTED_PTR_REP::detach (rep_);
}

7.书籍

http://bestcbooks.com/recommended-cpp-books/

原文地址:https://www.cnblogs.com/javastart/p/6124653.html