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.

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

mercurial