Ref-counted rewrite of ChannelManager.
The complexity of the last ChannelManager and potentially usage of it as well caused race conditions and deadlocks in loopback voe_auto_test. This ref-counted solution takes no long-term locks, uses less locks overall and is significantly easier to understand. ScopedChannel has been split up into a ChannelOwner with a reference to a channel and an Iterator over ChannelManager. Previous code was really used for both things. ChannelOwner is used as a shared pointer to a channel object, while an Iterator should work as expected. BUG=2081 R=tommi@webrtc.org, xians@webrtc.org Review URL: https://webrtc-codereview.appspot.com/1802004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@4502 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@ -11,79 +11,108 @@
|
||||
#ifndef WEBRTC_VOICE_ENGINE_CHANNEL_MANAGER_H
|
||||
#define WEBRTC_VOICE_ENGINE_CHANNEL_MANAGER_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/atomic32.h"
|
||||
#include "webrtc/system_wrappers/interface/constructor_magic.h"
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
#include "webrtc/voice_engine/channel_manager_base.h"
|
||||
|
||||
namespace webrtc
|
||||
{
|
||||
namespace webrtc {
|
||||
namespace voe {
|
||||
|
||||
namespace voe
|
||||
{
|
||||
|
||||
class ScopedChannel;
|
||||
class Channel;
|
||||
|
||||
class ChannelManager: private ChannelManagerBase
|
||||
{
|
||||
friend class ScopedChannel;
|
||||
// Shared-pointer implementation for keeping track of Channels. The underlying
|
||||
// shared instance will be dropped when no more ChannelOwners point to it.
|
||||
//
|
||||
// One common source of ChannelOwner instances are
|
||||
// ChannelManager::CreateChannel() and ChannelManager::GetChannel(...).
|
||||
// It has a similar use case to shared_ptr in C++11. Should this move to C++11
|
||||
// in the future, this class should be replaced by exactly that.
|
||||
//
|
||||
// To access the underlying Channel, use .channel().
|
||||
// IsValid() implements a convenience method as an alternative for checking
|
||||
// whether the underlying pointer is NULL or not.
|
||||
//
|
||||
// Channel channel_owner = channel_manager.GetChannel(channel_id);
|
||||
// if (channel_owner.IsValid())
|
||||
// channel_owner.channel()->...;
|
||||
//
|
||||
class ChannelOwner {
|
||||
public:
|
||||
explicit ChannelOwner(Channel* channel);
|
||||
ChannelOwner(const ChannelOwner& channel_owner);
|
||||
|
||||
public:
|
||||
bool CreateChannel(int32_t& channelId);
|
||||
~ChannelOwner();
|
||||
|
||||
int32_t DestroyChannel(int32_t channelId);
|
||||
ChannelOwner& operator=(const ChannelOwner& other);
|
||||
|
||||
int32_t MaxNumOfChannels() const;
|
||||
Channel* channel() { return channel_ref_->channel.get(); }
|
||||
bool IsValid() { return channel_ref_->channel.get() != NULL; }
|
||||
private:
|
||||
// Shared instance of a Channel. Copying ChannelOwners increase the reference
|
||||
// count and destroying ChannelOwners decrease references. Channels are
|
||||
// deleted when no references to them are held.
|
||||
struct ChannelRef {
|
||||
ChannelRef(Channel* channel);
|
||||
const scoped_ptr<Channel> channel;
|
||||
Atomic32 ref_count;
|
||||
};
|
||||
|
||||
int32_t NumOfChannels() const;
|
||||
|
||||
void GetChannelIds(int32_t* channelsArray,
|
||||
int32_t& numOfChannels) const;
|
||||
|
||||
ChannelManager(uint32_t instanceId);
|
||||
|
||||
~ChannelManager();
|
||||
|
||||
private:
|
||||
ChannelManager(const ChannelManager&);
|
||||
|
||||
ChannelManager& operator=(const ChannelManager&);
|
||||
|
||||
Channel* GetChannel(int32_t channelId) const;
|
||||
|
||||
void GetChannels(MapWrapper& channels) const;
|
||||
|
||||
void ReleaseChannel();
|
||||
|
||||
virtual void* NewItem(int32_t itemID);
|
||||
|
||||
virtual void DeleteItem(void* item);
|
||||
|
||||
uint32_t _instanceId;
|
||||
ChannelRef* channel_ref_;
|
||||
};
|
||||
|
||||
class ScopedChannel
|
||||
{
|
||||
public:
|
||||
// Can only be created by the channel manager
|
||||
ScopedChannel(ChannelManager& chManager);
|
||||
class ChannelManager {
|
||||
public:
|
||||
ChannelManager(uint32_t instance_id);
|
||||
|
||||
ScopedChannel(ChannelManager& chManager, int32_t channelId);
|
||||
// Upon construction of an Iterator it will grab a copy of the channel list of
|
||||
// the ChannelManager. The iteration will then occur over this state, not the
|
||||
// current one of the ChannelManager. As the Iterator holds its own references
|
||||
// to the Channels, they will remain valid even if they are removed from the
|
||||
// ChannelManager.
|
||||
class Iterator {
|
||||
public:
|
||||
explicit Iterator(ChannelManager* channel_manager);
|
||||
|
||||
Channel* ChannelPtr();
|
||||
Channel* GetChannel();
|
||||
bool IsValid();
|
||||
|
||||
Channel* GetFirstChannel(void*& iterator) const;
|
||||
void Increment();
|
||||
|
||||
Channel* GetNextChannel(void*& iterator) const;
|
||||
private:
|
||||
size_t iterator_pos_;
|
||||
std::vector<ChannelOwner> channels_;
|
||||
|
||||
~ScopedChannel();
|
||||
private:
|
||||
ChannelManager& _chManager;
|
||||
Channel* _channelPtr;
|
||||
MapWrapper _channels;
|
||||
DISALLOW_COPY_AND_ASSIGN(Iterator);
|
||||
};
|
||||
|
||||
// CreateChannel will always return a valid ChannelOwner instance.
|
||||
ChannelOwner CreateChannel();
|
||||
|
||||
// ChannelOwner.channel() will be NULL if channel_id is invalid or no longer
|
||||
// exists. This should be checked with ChannelOwner::IsValid().
|
||||
ChannelOwner GetChannel(int32_t channel_id);
|
||||
void GetAllChannels(std::vector<ChannelOwner>* channels);
|
||||
|
||||
void DestroyChannel(int32_t channel_id);
|
||||
void DestroyAllChannels();
|
||||
|
||||
size_t NumOfChannels() const;
|
||||
|
||||
private:
|
||||
uint32_t instance_id_;
|
||||
|
||||
Atomic32 last_channel_id_;
|
||||
|
||||
scoped_ptr<CriticalSectionWrapper> lock_;
|
||||
std::vector<ChannelOwner> channels_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ChannelManager);
|
||||
};
|
||||
|
||||
} // namespace voe
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_VOICE_ENGINE_CHANNEL_MANAGER_H
|
||||
|
Reference in New Issue
Block a user