media/webrtc/signaling/src/common/Wrapper.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #pragma once
michael@0 6
michael@0 7 /*
michael@0 8 * Wrapper - Helper class for wrapper objects.
michael@0 9 *
michael@0 10 * This helps to construct a shared_ptr object which wraps access to an underlying handle.
michael@0 11 * (The handle could be a pointer to some low-level type, a conventional C handle, an int ID, a GUID, etc.)
michael@0 12 *
michael@0 13 * Usage:
michael@0 14 * To obtain a FooPtr from a foo_handle_t, call FooPtr Foo::wrap(foo_handle_t);
michael@0 15 *
michael@0 16 * To implement Foo using Wrapper, Foo needs to include this macro in its class definition:
michael@0 17 * CSF_DECLARE_WRAP(Foo, foo_handle_t);
michael@0 18 * It also needs to include this in the cpp file, to provide the wrap() implementation and define the static Wrapper.
michael@0 19 * CSF_IMPLEMENT_WRAP(Foo, foo_handle_t);
michael@0 20 * These are all declared in common/Wrapper.h - Foo.h needs to include this too.
michael@0 21 * The client needs to declare Foo(foo_handle_t) as private, and provide a suitable implementation, as well as
michael@0 22 * implementing wrappers for any other functions to be exposed.
michael@0 23 * The client needs to implement ~Foo() to perform any cleanup as usual.
michael@0 24 *
michael@0 25 * wrap() will always return the same FooPtr for a given foo_handle_t, it will not construct additional objects
michael@0 26 * if a suitable one already exists.
michael@0 27 * changeHandle() is used in rare cases where the underlying handle is changed, but the wrapper object is intended
michael@0 28 * to remain. This is the case for the "fake" CC_DPCall generated on CC_DPLine::CreateCall(), where
michael@0 29 * the correct IDPCall* is provided later.
michael@0 30 * reset() is a cleanup step to wipe the handle map and allow memory to be reclaimed.
michael@0 31 *
michael@0 32 * Future enhancements:
michael@0 33 * - For now, objects remain in the map forever. Better would be to add a releaseHandle() function which would
michael@0 34 * allow the map to be emptied as underlying handles expired. While we can't force the client to give up its
michael@0 35 * shared_ptr<Foo> objects, we can remove our own copy, for instance on a call ended event.
michael@0 36 */
michael@0 37
michael@0 38 #include <map>
michael@0 39 #include "prlock.h"
michael@0 40 #include "mozilla/Assertions.h"
michael@0 41
michael@0 42 /*
michael@0 43 * Wrapper has its own autolock class because the instances are declared
michael@0 44 * statically and mozilla::Mutex will not work properly when instantiated
michael@0 45 * in a static constructor.
michael@0 46 */
michael@0 47
michael@0 48 class LockNSPR {
michael@0 49 public:
michael@0 50 LockNSPR() : lock_(nullptr) {
michael@0 51 lock_ = PR_NewLock();
michael@0 52 MOZ_ASSERT(lock_);
michael@0 53 }
michael@0 54 ~LockNSPR() {
michael@0 55 PR_DestroyLock(lock_);
michael@0 56 }
michael@0 57
michael@0 58 void Acquire() {
michael@0 59 PR_Lock(lock_);
michael@0 60 }
michael@0 61
michael@0 62 void Release() {
michael@0 63 PR_Unlock(lock_);
michael@0 64 }
michael@0 65
michael@0 66 private:
michael@0 67 PRLock *lock_;
michael@0 68 };
michael@0 69
michael@0 70 class AutoLockNSPR {
michael@0 71 public:
michael@0 72 AutoLockNSPR(LockNSPR& lock) : lock_(lock) {
michael@0 73 lock_.Acquire();
michael@0 74 }
michael@0 75 ~AutoLockNSPR() {
michael@0 76 lock_.Release();
michael@0 77 }
michael@0 78
michael@0 79 private:
michael@0 80 LockNSPR& lock_;
michael@0 81 };
michael@0 82
michael@0 83 template <class T>
michael@0 84 class Wrapper
michael@0 85 {
michael@0 86 private:
michael@0 87 typedef std::map<typename T::Handle, typename T::Ptr> HandleMapType;
michael@0 88 HandleMapType handleMap;
michael@0 89 LockNSPR handleMapMutex;
michael@0 90
michael@0 91 public:
michael@0 92 Wrapper() {}
michael@0 93
michael@0 94 typename T::Ptr wrap(typename T::Handle handle)
michael@0 95 {
michael@0 96 AutoLockNSPR lock(handleMapMutex);
michael@0 97 typename HandleMapType::iterator it = handleMap.find(handle);
michael@0 98 if(it != handleMap.end())
michael@0 99 {
michael@0 100 return it->second;
michael@0 101 }
michael@0 102 else
michael@0 103 {
michael@0 104 typename T::Ptr p(new T(handle));
michael@0 105 handleMap[handle] = p;
michael@0 106 return p;
michael@0 107 }
michael@0 108 }
michael@0 109
michael@0 110 bool changeHandle(typename T::Handle oldHandle, typename T::Handle newHandle)
michael@0 111 {
michael@0 112 AutoLockNSPR lock(handleMapMutex);
michael@0 113 typename HandleMapType::iterator it = handleMap.find(oldHandle);
michael@0 114 if(it != handleMap.end())
michael@0 115 {
michael@0 116 typename T::Ptr p = it->second;
michael@0 117 handleMap.erase(it);
michael@0 118 handleMap[newHandle] = p;
michael@0 119 return true;
michael@0 120 }
michael@0 121 else
michael@0 122 {
michael@0 123 return false;
michael@0 124 }
michael@0 125 }
michael@0 126
michael@0 127 bool release(typename T::Handle handle)
michael@0 128 {
michael@0 129 AutoLockNSPR lock(handleMapMutex);
michael@0 130 typename HandleMapType::iterator it = handleMap.find(handle);
michael@0 131 if(it != handleMap.end())
michael@0 132 {
michael@0 133 handleMap.erase(it);
michael@0 134 return true;
michael@0 135 }
michael@0 136 else
michael@0 137 {
michael@0 138 return false;
michael@0 139 }
michael@0 140 }
michael@0 141
michael@0 142 void reset()
michael@0 143 {
michael@0 144 AutoLockNSPR lock(handleMapMutex);
michael@0 145 handleMap.clear();
michael@0 146 }
michael@0 147 };
michael@0 148
michael@0 149 #define CSF_DECLARE_WRAP(classname, handletype) \
michael@0 150 public: \
michael@0 151 static classname ## Ptr wrap(handletype handle); \
michael@0 152 static void reset(); \
michael@0 153 static void release(handletype handle); \
michael@0 154 private: \
michael@0 155 friend class Wrapper<classname>; \
michael@0 156 typedef classname ## Ptr Ptr; \
michael@0 157 typedef handletype Handle; \
michael@0 158 static Wrapper<classname>& getWrapper() { \
michael@0 159 static Wrapper<classname> wrapper; \
michael@0 160 return wrapper; \
michael@0 161 }
michael@0 162
michael@0 163 #define CSF_IMPLEMENT_WRAP(classname, handletype) \
michael@0 164 classname ## Ptr classname::wrap(handletype handle) \
michael@0 165 { \
michael@0 166 return getWrapper().wrap(handle); \
michael@0 167 } \
michael@0 168 void classname::reset() \
michael@0 169 { \
michael@0 170 getWrapper().reset(); \
michael@0 171 } \
michael@0 172 void classname::release(handletype handle) \
michael@0 173 { \
michael@0 174 getWrapper().release(handle); \
michael@0 175 }

mercurial