Skip to content

Commit

Permalink
Bug 1647536 - Support ref counted pointers in nsDeque r=froydnj
Browse files Browse the repository at this point in the history
Adds a new specialization of nsDeque, nsRefPtrDeque for use with
reference counted pointers.

Differential Revision: https://phabricator.services.mozilla.com/D84766
  • Loading branch information
Chris Fronk committed Aug 14, 2020
1 parent 3c8ea64 commit 8770c8a
Show file tree
Hide file tree
Showing 10 changed files with 347 additions and 155 deletions.
6 changes: 2 additions & 4 deletions dom/media/MediaDecoderStateMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3958,8 +3958,7 @@ class VideoQueueMemoryFunctor : public nsDequeFunctor<VideoData> {
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf);

virtual void operator()(VideoData* aObject) override {
const VideoData* v = aObject;
mSize += v->SizeOfIncludingThis(MallocSizeOf);
mSize += aObject->SizeOfIncludingThis(MallocSizeOf);
}

size_t mSize;
Expand All @@ -3972,8 +3971,7 @@ class AudioQueueMemoryFunctor : public nsDequeFunctor<AudioData> {
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf);

virtual void operator()(AudioData* aObject) override {
const AudioData* audioData = aObject;
mSize += audioData->SizeOfIncludingThis(MallocSizeOf);
mSize += aObject->SizeOfIncludingThis(MallocSizeOf);
}

size_t mSize;
Expand Down
47 changes: 19 additions & 28 deletions dom/media/MediaQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,41 +19,35 @@ namespace mozilla {

class AudioData;

// Thread and type safe wrapper around nsDeque.
template <class T>
class MediaQueueDeallocator : public nsDequeFunctor<T> {
virtual void operator()(T* aObject) override {
RefPtr<T> releaseMe = dont_AddRef(aObject);
}
};

template <class T>
class MediaQueue : private nsDeque<T> {
class MediaQueue : private nsRefPtrDeque<T> {
public:
MediaQueue()
: nsDeque<T>(new MediaQueueDeallocator<T>()),
: nsRefPtrDeque<T>(),
mRecursiveMutex("mediaqueue"),
mEndOfStream(false) {}

~MediaQueue() { Reset(); }

inline size_t GetSize() const {
RecursiveMutexAutoLock lock(mRecursiveMutex);
return nsDeque<T>::GetSize();
return nsRefPtrDeque<T>::GetSize();
}

inline void Push(T* aItem) {
MOZ_DIAGNOSTIC_ASSERT(aItem);
Push(do_AddRef(aItem));
nsRefPtrDeque<T>::Push(aItem);
}

inline void Push(already_AddRefed<T> aItem) {
RecursiveMutexAutoLock lock(mRecursiveMutex);
T* item = aItem.take();

MOZ_DIAGNOSTIC_ASSERT(item);
MOZ_DIAGNOSTIC_ASSERT(item->GetEndTime() >= item->mTime);
nsDeque<T>::Push(item);
nsRefPtrDeque<T>::Push(dont_AddRef(item));
mPushEvent.Notify(RefPtr<T>(item));

// Pushing new data after queue has ended means that the stream is active
// again, so we should not mark it as ended.
if (mEndOfStream) {
Expand All @@ -63,7 +57,7 @@ class MediaQueue : private nsDeque<T> {

inline already_AddRefed<T> PopFront() {
RecursiveMutexAutoLock lock(mRecursiveMutex);
RefPtr<T> rv = dont_AddRef(nsDeque<T>::PopFront());
RefPtr<T> rv = nsRefPtrDeque<T>::PopFront();
if (rv) {
MOZ_DIAGNOSTIC_ASSERT(rv->GetEndTime() >= rv->mTime);
mPopFrontEvent.Notify(rv);
Expand All @@ -73,25 +67,22 @@ class MediaQueue : private nsDeque<T> {

inline already_AddRefed<T> PopBack() {
RecursiveMutexAutoLock lock(mRecursiveMutex);
RefPtr<T> rv = dont_AddRef(nsDeque<T>::Pop());
return rv.forget();
return nsRefPtrDeque<T>::Pop();
}

inline RefPtr<T> PeekFront() const {
RecursiveMutexAutoLock lock(mRecursiveMutex);
return nsDeque<T>::PeekFront();
return nsRefPtrDeque<T>::PeekFront();
}

inline RefPtr<T> PeekBack() const {
RecursiveMutexAutoLock lock(mRecursiveMutex);
return nsDeque<T>::Peek();
return nsRefPtrDeque<T>::Peek();
}

void Reset() {
RecursiveMutexAutoLock lock(mRecursiveMutex);
while (GetSize() > 0) {
RefPtr<T> x = dont_AddRef(nsDeque<T>::PopFront());
}
nsRefPtrDeque<T>::Erase();
mEndOfStream = false;
}

Expand Down Expand Up @@ -123,14 +114,14 @@ class MediaQueue : private nsDeque<T> {
if (GetSize() == 0) {
return 0;
}
T* last = nsDeque<T>::Peek();
T* first = nsDeque<T>::PeekFront();
T* last = nsRefPtrDeque<T>::Peek();
T* first = nsRefPtrDeque<T>::PeekFront();
return (last->GetEndTime() - first->mTime).ToMicroseconds();
}

void LockedForEach(nsDequeFunctor<T>& aFunctor) const {
RecursiveMutexAutoLock lock(mRecursiveMutex);
nsDeque<T>::ForEach(aFunctor);
nsRefPtrDeque<T>::ForEach(aFunctor);
}

// Extracts elements from the queue into aResult, in order.
Expand All @@ -140,13 +131,13 @@ class MediaQueue : private nsDeque<T> {
if (GetSize() == 0) return;
size_t i;
for (i = GetSize() - 1; i > 0; --i) {
T* v = nsDeque<T>::ObjectAt(i);
T* v = nsRefPtrDeque<T>::ObjectAt(i);
if (v->GetEndTime().ToMicroseconds() < aTime) break;
}
// Elements less than i have a end time before aTime. It's also possible
// that the element at i has a end time before aTime, but that's OK.
for (; i < GetSize(); ++i) {
RefPtr<T> elem = nsDeque<T>::ObjectAt(i);
RefPtr<T> elem = nsRefPtrDeque<T>::ObjectAt(i);
aResult->AppendElement(elem);
}
}
Expand All @@ -159,7 +150,7 @@ class MediaQueue : private nsDeque<T> {
void GetFirstElements(uint32_t aMaxElements, nsTArray<RefPtr<T>>* aResult) {
RecursiveMutexAutoLock lock(mRecursiveMutex);
for (size_t i = 0; i < aMaxElements && i < GetSize(); ++i) {
*aResult->AppendElement() = nsDeque<T>::ObjectAt(i);
*aResult->AppendElement() = nsRefPtrDeque<T>::ObjectAt(i);
}
}

Expand All @@ -169,7 +160,7 @@ class MediaQueue : private nsDeque<T> {
RecursiveMutexAutoLock lock(mRecursiveMutex);
uint32_t frames = 0;
for (size_t i = 0; i < GetSize(); ++i) {
T* v = nsDeque<T>::ObjectAt(i);
T* v = nsRefPtrDeque<T>::ObjectAt(i);
frames += v->Frames();
}
return frames;
Expand Down
43 changes: 10 additions & 33 deletions editor/txmgr/TransactionStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,60 +14,37 @@

namespace mozilla {

class TransactionStackDeallocator final
: public nsDequeFunctor<TransactionItem> {
virtual void operator()(TransactionItem* aObject) override {
RefPtr<TransactionItem> releaseMe = dont_AddRef(aObject);
}
};

TransactionStack::TransactionStack(Type aType)
: nsDeque<TransactionItem>(new TransactionStackDeallocator()),
mType(aType) {}
: nsRefPtrDeque<TransactionItem>(), mType(aType) {}

TransactionStack::~TransactionStack() { Clear(); }

void TransactionStack::Push(TransactionItem* aTransactionItem) {
if (NS_WARN_IF(!aTransactionItem)) {
return;
}

RefPtr<TransactionItem> item(aTransactionItem);
Push(item.forget());
nsRefPtrDeque<TransactionItem>::Push(aTransactionItem);
}

void TransactionStack::Push(
already_AddRefed<TransactionItem> aTransactionItem) {
RefPtr<TransactionItem> transactionItem(aTransactionItem);
if (NS_WARN_IF(!transactionItem)) {
return;
}

nsDeque<TransactionItem>::Push(transactionItem.forget().take());
nsRefPtrDeque<TransactionItem>::Push(std::move(aTransactionItem));
}

already_AddRefed<TransactionItem> TransactionStack::Pop() {
RefPtr<TransactionItem> item = dont_AddRef(nsDeque<TransactionItem>::Pop());
return item.forget();
return nsRefPtrDeque<TransactionItem>::Pop();
}

already_AddRefed<TransactionItem> TransactionStack::PopBottom() {
RefPtr<TransactionItem> item =
dont_AddRef(nsDeque<TransactionItem>::PopFront());
return item.forget();
return nsRefPtrDeque<TransactionItem>::PopFront();
}

already_AddRefed<TransactionItem> TransactionStack::Peek() {
RefPtr<TransactionItem> item = nsDeque<TransactionItem>::Peek();
already_AddRefed<TransactionItem> TransactionStack::Peek() const {
RefPtr<TransactionItem> item = nsRefPtrDeque<TransactionItem>::Peek();
return item.forget();
}

already_AddRefed<TransactionItem> TransactionStack::GetItemAt(
size_t aIndex) const {
if (NS_WARN_IF(aIndex >= nsDeque<TransactionItem>::GetSize())) {
return nullptr;
}
RefPtr<TransactionItem> item = nsDeque<TransactionItem>::ObjectAt(aIndex);
RefPtr<TransactionItem> item =
nsRefPtrDeque<TransactionItem>::ObjectAt(aIndex);
return item.forget();
}

Expand All @@ -80,7 +57,7 @@ void TransactionStack::Clear() {
void TransactionStack::DoTraverse(nsCycleCollectionTraversalCallback& cb) {
size_t size = GetSize();
for (size_t i = 0; i < size; ++i) {
TransactionItem* item = nsDeque<TransactionItem>::ObjectAt(i);
auto* item = nsRefPtrDeque<TransactionItem>::ObjectAt(i);
if (item) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "transaction stack mDeque[i]");
cb.NoteNativeChild(item,
Expand Down
6 changes: 3 additions & 3 deletions editor/txmgr/TransactionStack.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace mozilla {

class TransactionItem;

class TransactionStack : private nsDeque<TransactionItem> {
class TransactionStack : private nsRefPtrDeque<TransactionItem> {
public:
enum Type { FOR_UNDO, FOR_REDO };

Expand All @@ -26,10 +26,10 @@ class TransactionStack : private nsDeque<TransactionItem> {
void Push(already_AddRefed<TransactionItem> aTransactionItem);
already_AddRefed<TransactionItem> Pop();
already_AddRefed<TransactionItem> PopBottom();
already_AddRefed<TransactionItem> Peek();
already_AddRefed<TransactionItem> Peek() const;
already_AddRefed<TransactionItem> GetItemAt(size_t aIndex) const;
void Clear();
size_t GetSize() const { return nsDeque::GetSize(); }
size_t GetSize() const { return nsRefPtrDeque<TransactionItem>::GetSize(); }
bool IsEmpty() const { return GetSize() == 0; }

void DoUnlink() { Clear(); }
Expand Down
8 changes: 4 additions & 4 deletions netwerk/base/EventTokenBucket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ EventTokenBucket::~EventTokenBucket() {

// Complete any queued events to prevent hangs
while (mEvents.GetSize()) {
RefPtr<TokenBucketCancelable> cancelable = dont_AddRef(mEvents.PopFront());
RefPtr<TokenBucketCancelable> cancelable = mEvents.PopFront();
cancelable->Fire();
}
}
Expand Down Expand Up @@ -196,7 +196,7 @@ void EventTokenBucket::Stop() {

// Complete any queued events to prevent hangs
while (mEvents.GetSize()) {
RefPtr<TokenBucketCancelable> cancelable = dont_AddRef(mEvents.PopFront());
RefPtr<TokenBucketCancelable> cancelable = mEvents.PopFront();
cancelable->Fire();
}
}
Expand All @@ -219,7 +219,7 @@ nsresult EventTokenBucket::SubmitEvent(ATokenBucketEvent* event,
if (mPaused || !TryImmediateDispatch(cancelEvent.get())) {
// queue it
SOCKET_LOG((" queued\n"));
mEvents.Push(cancelEvent.forget().take());
mEvents.Push(cancelEvent.forget());
UpdateTimer();
} else {
SOCKET_LOG((" dispatched synchronously\n"));
Expand All @@ -242,7 +242,7 @@ void EventTokenBucket::DispatchEvents() {
if (mPaused || mStopped) return;

while (mEvents.GetSize() && mUnitCost <= mCredit) {
RefPtr<TokenBucketCancelable> cancelable = dont_AddRef(mEvents.PopFront());
RefPtr<TokenBucketCancelable> cancelable = mEvents.PopFront();
if (cancelable->mEvent) {
SOCKET_LOG(
("EventTokenBucket::DispachEvents [%p] "
Expand Down
2 changes: 1 addition & 1 deletion netwerk/base/EventTokenBucket.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class EventTokenBucket : public nsITimerCallback,

bool mPaused;
bool mStopped;
nsDeque<TokenBucketCancelable> mEvents;
nsRefPtrDeque<TokenBucketCancelable> mEvents;
bool mTimerArmed;
TimeStamp mLastUpdate;

Expand Down
18 changes: 7 additions & 11 deletions netwerk/sctp/datachannel/DataChannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -904,16 +904,15 @@ void DataChannelConnection::ProcessQueuedOpens() {

// Can't copy nsDeque's. Move into temp array since any that fail will
// go back to mPending
nsDeque<DataChannel> temp;
DataChannel* temp_channel; // really already_AddRefed<>
nsRefPtrDeque<DataChannel> temp;
RefPtr<DataChannel> temp_channel;
while (nullptr != (temp_channel = mPending.PopFront())) {
temp.Push(temp_channel);
temp.Push(temp_channel.forget());
}

RefPtr<DataChannel> channel;
// All these entries have an AddRef(); make that explicit now via the
// dont_AddRef()
while (nullptr != (channel = dont_AddRef(temp.PopFront()))) {

while (nullptr != (channel = temp.PopFront())) {
if (channel->mFlags & DATA_CHANNEL_FLAGS_FINISH_OPEN) {
DC_DEBUG(("Processing queued open for %p (%u)", channel.get(),
channel->mStream));
Expand Down Expand Up @@ -2506,10 +2505,7 @@ already_AddRefed<DataChannel> DataChannelConnection::OpenFinish(
DC_DEBUG(("Queuing channel %p (%u) to finish open", channel.get(), stream));
// Also serves to mark we told the app
channel->mFlags |= DATA_CHANNEL_FLAGS_FINISH_OPEN;
// we need a ref for the nsDeQue and one to return
DataChannel* rawChannel = channel;
rawChannel->AddRef();
mPending.Push(rawChannel);
mPending.Push(channel);
return channel.forget();
}

Expand Down Expand Up @@ -3055,7 +3051,7 @@ void DataChannelConnection::CloseAll() {

// Clean up any pending opens for channels
RefPtr<DataChannel> channel;
while (nullptr != (channel = dont_AddRef(mPending.PopFront()))) {
while (nullptr != (channel = mPending.PopFront())) {
DC_DEBUG(("closing pending channel %p, stream %u", channel.get(),
channel->mStream));
channel->Close(); // also releases the ref on each iteration
Expand Down
2 changes: 1 addition & 1 deletion netwerk/sctp/datachannel/DataChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ class DataChannelConnection final : public net::NeckoTargetHolder
Channels mChannels;
// STS only
uint32_t mCurrentStream = 0;
nsDeque<DataChannel> mPending; // Holds addref'ed DataChannel's -- careful!
nsRefPtrDeque<DataChannel> mPending;
// STS and main
size_t mNegotiatedIdLimit = 0; // GUARDED_BY(mConnection->mLock)
uint8_t mPendingType = PENDING_NONE;
Expand Down
Loading

0 comments on commit 8770c8a

Please sign in to comment.