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("\nwait feeding, eatting %s\n", _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("\nfinish decode file\n"); }
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/