예제 #1
0
            internal static void AddEventHandler <T>(Func <T, EventRegistrationToken> addMethod,
                                                     Action <EventRegistrationToken> removeMethod,
                                                     T handler)
            {
                Debug.Assert(addMethod != null);
                Debug.Assert(removeMethod != null);

                // Add the method, and make a note of the token -> delegate mapping.
                object instance = removeMethod.Target;

#if !RHTESTCL
                Debug.Assert(instance != null && !(instance is __ComObject));
#endif
                System.Collections.Generic.Internal.Dictionary <object, EventRegistrationTokenList> registrationTokens = GetEventRegistrationTokenTable(instance, removeMethod);

                EventRegistrationToken token = addMethod(handler);

                try
                {
                    registrationTokens.LockAcquire();

                    EventRegistrationTokenList tokens;

                    if (!registrationTokens.TryGetValue(handler, out tokens))
                    {
                        tokens = new EventRegistrationTokenList(token);
                        registrationTokens[handler] = tokens;
                    }
                    else
                    {
                        bool needCopy = tokens.Push(token);

                        // You need to copy back this list into the dictionary (so that you don't lose change outside dictionary)
                        if (needCopy)
                        {
                            registrationTokens[handler] = tokens;
                        }
                    }
#if false
                    BCLDebug.Log("INTEROP", "[WinRT_Eventing] Event subscribed for managed instance = " + instance + ", handler = " + handler + "\n");
#endif
                }
                finally
                {
                    registrationTokens.LockRelease();
                }
            }
예제 #2
0
            internal static void RemoveAllEventHandlers(Action <EventRegistrationToken> removeMethod)
            {
                Debug.Assert(removeMethod != null);

                object instance = removeMethod.Target;

                System.Collections.Generic.Internal.Dictionary <object, EventRegistrationTokenList> registrationTokens = GetEventRegistrationTokenTable(instance, removeMethod);

                System.Collections.Generic.Internal.List <EventRegistrationToken> tokensToRemove = new System.Collections.Generic.Internal.List <EventRegistrationToken>();

                try
                {
                    registrationTokens.LockAcquire();

                    // Copy all tokens to tokensToRemove array which later we'll call removeMethod on
                    // outside this lock
                    foreach (EventRegistrationTokenList tokens in registrationTokens.Values)
                    {
                        tokens.CopyTo(tokensToRemove);
                    }

                    // Clear the dictionary - at this point all event handlers are no longer in the cache
                    // but they are not removed yet
                    registrationTokens.Clear();
#if false
                    BCLDebug.Log("INTEROP", "[WinRT_Eventing] Cache cleared for managed instance = " + instance + "\n");
#endif
                }
                finally
                {
                    registrationTokens.LockRelease();
                }

                //
                // Remove all handlers outside the lock
                //
#if false
                BCLDebug.Log("INTEROP", "[WinRT_Eventing] Start removing all events for instance = " + instance + "\n");
#endif
                CallRemoveMethods(removeMethod, tokensToRemove);
#if false
                BCLDebug.Log("INTEROP", "[WinRT_Eventing] Finished removing all events for instance = " + instance + "\n");
#endif
            }
예제 #3
0
        internal static CCWTemplateInfo GetCCWTemplateDataInfoFromTypeHandle(RuntimeTypeHandle typeHnd)
        {
            CCWTemplateInfo ccwTemplateInfo;

            try
            {
                s_runtimeTypeHandleToCCWTemplateInfoMap.LockAcquire();
                if (!s_runtimeTypeHandleToCCWTemplateInfoMap.TryGetValue(typeHnd, out ccwTemplateInfo))
                {
                    ccwTemplateInfo = GetCCWTemplateDataInfoFromTypeHandleInternal(typeHnd);
                    s_runtimeTypeHandleToCCWTemplateInfoMap.Add(typeHnd, ccwTemplateInfo);
                }
            }
            finally
            {
                s_runtimeTypeHandleToCCWTemplateInfoMap.LockRelease();
            }

            return(ccwTemplateInfo);
        }
예제 #4
0
        internal static McgInterfaceInfo GetInterfaceInfoByHandle(RuntimeTypeHandle typeHnd)
        {
            McgInterfaceInfo interfaceInfo;

            try
            {
                s_runtimeTypeHandleToMcgInterfaceInfoMap.LockAcquire();
                if (!s_runtimeTypeHandleToMcgInterfaceInfoMap.TryGetValue(typeHnd, out interfaceInfo))
                {
                    interfaceInfo = GetInterfaceInfoByHandleInternal(typeHnd);
                    s_runtimeTypeHandleToMcgInterfaceInfoMap.Add(typeHnd, interfaceInfo);
                }
            }
            finally
            {
                s_runtimeTypeHandleToMcgInterfaceInfoMap.LockRelease();
            }

            return(interfaceInfo);
        }
예제 #5
0
            internal static void RemoveEventHandler <T>(Action <EventRegistrationToken> removeMethod, T handler)
            {
                Debug.Assert(removeMethod != null);

                object instance = removeMethod.Target;

                //
                // Temporary static event support - this is bad for a couple of reasons:
                // 1. This will leak the event delegates. Our real implementation fixes that
                // 2. We need the type itself, but we don't have delegate.Method.DeclaringType (
                // but I don't know what is the best replacement). Perhaps this isn't too bad
                // 3. Unsubscription doesn't work due to ConditionalWeakTable work on reference equality.
                // I can fix this but I figured it is easier to keep this broken so that we know we'll fix
                // this (rather than using the slower value equality version which we might forget to fix
                // later
                // @TODO - Remove this and replace with real static support (that was #ifdef-ed out)
                //
                if (instance == null)
                {
                    // Because this code only operates for delegates to static methods, the output typehandle of GetFunctionPointer is not used
                    RuntimeTypeHandle thDummy;
                    instance = removeMethod.GetFunctionPointer(out thDummy);
                }

                System.Collections.Generic.Internal.Dictionary <object, EventRegistrationTokenList> registrationTokens = GetEventRegistrationTokenTable(instance, removeMethod);
                EventRegistrationToken token;

                try
                {
                    registrationTokens.LockAcquire();

                    EventRegistrationTokenList tokens;

                    // Failure to find a registration for a token is not an error - it's simply a no-op.
                    if (!registrationTokens.TryGetValue(handler, out tokens))
                    {
#if false
                        BCLDebug.Log("INTEROP", "[WinRT_Eventing] no registrationTokens found for instance=" + instance + ", handler= " + handler + "\n");
#endif

                        return;
                    }

                    // Select a registration token to unregister
                    // We don't care which one but I'm returning the last registered token to be consistent
                    // with native event registration implementation
                    bool moreItems = tokens.Pop(out token);
                    if (!moreItems)
                    {
                        // Remove it from cache if this list become empty
                        // This must be done because EventRegistrationTokenList now becomes invalid
                        // (mostly because there is no safe default value for EventRegistrationToken to express 'no token')
                        // NOTE: We should try to remove registrationTokens itself from cache if it is empty, otherwise
                        // we could run into a race condition where one thread removes it from cache and another thread adds
                        // into the empty registrationToken table
                        registrationTokens.Remove(handler);
                    }
                }
                finally
                {
                    registrationTokens.LockRelease();
                }

                removeMethod(token);
#if false
                BCLDebug.Log("INTEROP", "[WinRT_Eventing] Event unsubscribed for managed instance = " + instance + ", handler = " + handler + ", token = " + token.m_value + "\n");
#endif
            }