/// <summary>
        /// Removes all items from the concurrent weak dictionary
        /// </summary>
        /// <returns>An array of all the key/value pairs removed</returns>
        public KeyValuePair <TKey, TValue>[] RemoveAll()
        {               //****************************************
            var    MyValues = new List <KeyValuePair <TKey, TValue> >(_Dictionary.Count);
            TValue?MyValue;

            //****************************************

            while (!_Dictionary.IsEmpty)
            {
                foreach (var MyKey in _Dictionary.Keys)
                {
                    if (!_Dictionary.TryRemove(MyKey, out var MyHandle))
                    {
                        continue;
                    }

                    MyValue = (TValue?)MyHandle.Target;

                    if (MyValue != null)
                    {
                        MyValues.Add(new KeyValuePair <TKey, TValue>(MyKey, MyValue));
                    }

                    MyHandle.Dispose();
                }
            }

            return(MyValues.ToArray());
        }
        //****************************************

        /// <summary>
        /// Adds a new pair to the dictionary
        /// </summary>
        /// <param name="key">The key of the item to add</param>
        /// <param name="value">The value that will be weakly referenced</param>
        /// <exception cref="ArgumentNullException">Value was null</exception>
        /// <exception cref="ArgumentException">Key already exists</exception>
        public void Add(TKey key, TValue value)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value), "Cannot add null to a Weak Dictionary");
            }

            // Is this key already in the dictionary?
            if (_Dictionary.TryGetValue(key, out var MyHandle))
            {
                // Yes, is the object available?
                if (MyHandle.IsAlive)
                {
                    throw new ArgumentException("Key already exists in the Weak Dictionary");
                }

                // No, free the handle and replace it
                MyHandle.Dispose();

                _Dictionary[key] = new GCReference(value, _HandleType);
            }
            else
            {
                // Not in the dictionary, add it
                _Dictionary.Add(key, new GCReference(value, _HandleType));
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Removes all elements from the collection
        /// </summary>
        public void Clear()
        {
            foreach (var MyHandle in _Values)
            {
                MyHandle.Dispose();
            }

            _Values.Clear();
        }
        /// <summary>
        /// Removes all elements from the collection
        /// </summary>
        public void Clear()
        {
            foreach (var MyHandle in _Dictionary.Values)
            {
                MyHandle.Dispose();
            }

            _Dictionary.Clear();
        }
 /// <summary>
 /// Removes all elements from the collection
 /// </summary>
 public void Clear()
 {
     foreach (var MyPair in _Dictionary)
     {
         if (_Dictionary.TryRemove(MyPair.Key, out var MyHandle))
         {
             MyHandle.Dispose();
         }
     }
 }
        /// <summary>
        /// Adds an item to the dictionary
        /// </summary>
        /// <param name="key">The key of the item to add</param>
        /// <param name="value">The value of the item to add</param>
        /// <returns>True if the item was added, otherwise false</returns>
        /// <remarks>Will add if the key is not set, and replace if the value is no longer available</remarks>
        public bool TryAdd(TKey key, TValue value)
        {               //****************************************
            GCReference NewHandle;

            //****************************************

            if (value == null)
            {
                throw new InvalidOperationException("Cannot add null to a Weak Dictionary");
            }

            for (; ;)
            {
                // Is this key already in the dictionary?
                if (!_Dictionary.TryGetValue(key, out var MyHandle))
                {
                    // Key not found, so let's try and add it
                    // Create a GC Handle to reference the object
                    NewHandle = new GCReference(value, _HandleType);

                    // Try and add it to the dictionary
                    if (_Dictionary.TryAdd(key, NewHandle))
                    {
                        return(true);                        // Success, return the result
                    }
                    // Key was added concurrently, free the handle we no longer need
                    NewHandle.Dispose();

                    return(false);
                }

                // Key found, is the weak reference still valid?
                if (MyHandle.IsAlive)
                {
                    return(false);                    // Yes, can't add
                }
                // Target reference has vanished, we can replace it with the new value
                NewHandle = new GCReference(value, _HandleType);

                // Try and update the dictionary with the replacement value
                if (_Dictionary.TryUpdate(key, NewHandle, MyHandle))
                {
                    // Success, now we can safely expire the old handle
                    MyHandle.Dispose();

                    return(true);
                }

                // Key was updated elsewhere. Could have been removed or simply updated with a valid value elsewhere
                // Ditch the updated value and try again
                NewHandle.Dispose();
            }
        }
        /// <summary>
        /// Removes the value associated with the specified key
        /// </summary>
        /// <param name="key">The key to remove</param>
        /// <returns>True if the key was found and still referenced, otherwise false</returns>
        public bool Remove(TKey key)
        {
            if (!_Dictionary.TryRemove(key, out var MyHandle))
            {
                return(false);
            }

            var IsValid = MyHandle.IsAlive;

            MyHandle.Dispose();

            return(IsValid);
        }
Ejemplo n.º 8
0
	public static int test_0_safehandle_ref ()
	{
		MyHandle m = new MyHandle ((IntPtr) 0xdead);

		mono_safe_handle_ref (ref m);
		
		if (m.DangerousGetHandle () != (IntPtr) 0x800d){
			Console.WriteLine ("test_0_safehandle_ref: fail; Expected 0x800d, got: {0:x}", m.DangerousGetHandle ());
			return 1;
		}
		Console.WriteLine ("test_0_safehandle_ref: pass");
		return 0;
	}
Ejemplo n.º 9
0
    public static int test_0_safehandle_ref()
    {
        MyHandle m = new MyHandle((IntPtr)0xdead);

        mono_safe_handle_ref(ref m);

        if (m.DangerousGetHandle() != (IntPtr)0x800d)
        {
            Console.WriteLine("test_0_safehandle_ref: fail; Expected 0x800d, got: {0:x}", m.DangerousGetHandle());
            return(1);
        }
        Console.WriteLine("test_0_safehandle_ref: pass");
        return(0);
    }
        public void TryTakeNoMaxTime()
        {               //****************************************
            var MyLock = new AsyncSemaphore();

            //****************************************

            Assert.True(MyLock.TryTake(out var MyHandle, TimeSpan.FromMilliseconds(50)), "Lock not taken");

            MyHandle.Dispose();

            //****************************************

            Assert.AreEqual(0, MyLock.WaitingCount, "Still waiting for Semaphore");
            Assert.AreEqual(MyLock.MaxCount, MyLock.CurrentCount, "Semaphore still held");
        }
        /// <summary>
        /// Removes the value associated with the specified key
        /// </summary>
        /// <param name="key">The key to remove</param>
        /// <param name="value">The value to remove, if still referenced. Null if the key was not found or was found but the reference expired</param>
        /// <returns>True if the key was found and still referenced, otherwise false</returns>
        public bool TryRemove(TKey key,
#if !NETSTANDARD2_0 && !NET40
                              [MaybeNullWhen(false)]
#endif
                              out TValue value)
        {
            if (_Dictionary.TryRemove(key, out var MyHandle))
            {
                value = (TValue?)MyHandle.Target !;

                MyHandle.Dispose();

                return(value != null);
            }

            value = null !;

            return(false);
        }
        /// <summary>
        /// Removes the specified key/value pair
        /// </summary>
        /// <param name="key">The key to remove</param>
        /// <param name="value">The value to remove</param>
        /// <returns>True if the key was found with the expected value, otherwise false</returns>
        public bool Remove(TKey key, TValue value)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value), "Cannot have a null in a Weak Dictionary");
            }

            // Is this key in the dictionary?
            if (!_Dictionary.TryGetValue(key, out var MyHandle))
            {
                return(false);
            }

            try
            {
                var MyValue = (TValue?)MyHandle.Target;

                // Is the referenced value as expected?
                if (MyValue != value)
                {
                    return(false);
                }
            }
            catch (InvalidOperationException)
            {
                // The GCHandle was disposed, so someone concurrently removed it
                return(false);
            }

            // Yes, try and remove this key/GCReference pair
            if (!((IDictionary <TKey, GCReference>)_Dictionary).Remove(new KeyValuePair <TKey, GCReference>(key, MyHandle)))
            {
                return(false);
            }

            // Success, free the handle
            MyHandle.Dispose();

            return(true);
        }
        public async Task TryTakeLock()
        {               //****************************************
            var MyLock = new AsyncSemaphore();

            //****************************************

            Assert.True(MyLock.TryTake(out var MyHandle), "Lock not taken");

            var MyWait = MyLock.Take();

            Assert.IsFalse(MyWait.IsCompleted, "Nested lock taken");

            MyHandle.Dispose();

            MyHandle = await MyWait;

            MyHandle.Dispose();

            //****************************************

            Assert.AreEqual(0, MyLock.WaitingCount, "Still waiting for Semaphore");
            Assert.AreEqual(MyLock.MaxCount, MyLock.CurrentCount, "Semaphore still held");
        }
Ejemplo n.º 14
0
 public static extern void mono_safe_handle_ref(ref MyHandle handle);
Ejemplo n.º 15
0
 public static extern void UseResource(MyHandle resource);
Ejemplo n.º 16
0
 public Resource(int id, string name)
 {
     ptr = OpenResource(id, name);
 }
        /// <summary>
        /// Adds or updates a key/value pair
        /// </summary>
        /// <param name="key">The key to add or replace</param>
        /// <param name="valueCallback">A callback providing the new value</param>
        /// <param name="updateCallback">A callback updating an existing value</param>
        /// <returns>The added or updated value</returns>
        public TValue AddOrUpdate(TKey key, Func <TKey, TValue> valueCallback, Func <TKey, TValue, TValue> updateCallback)
        {               //****************************************
            GCReference NewHandle;

            TValue?OldValue;
            TValue NewValue;

            //****************************************

            for (; ;)
            {
                // Is this key already in the dictionary?
                if (_Dictionary.TryGetValue(key, out var MyHandle))
                {
                    try
                    {
                        OldValue = (TValue?)MyHandle.Target;
                    }
                    catch (InvalidOperationException)
                    {
                        // The GCHandle was disposed, try again
                        continue;
                    }

                    // Yes, does the target still exist?
                    if (OldValue != null)
                    {
                        // Yes, let's try and update it
                        NewValue = updateCallback(key, OldValue);

                        // If the reference is the same, no need to change anything
                        if (object.ReferenceEquals(OldValue, NewValue))
                        {
                            return(NewValue);
                        }
                    }
                    else
                    {
                        // Target reference has vanished, replace it with the new value
                        NewValue = valueCallback(key);

                        if (NewValue == null)
                        {
                            throw new InvalidOperationException("Cannot add null to a Weak Dictionary");
                        }
                    }

                    // Reference has changed, create a new GCReference
                    NewHandle = new GCReference(NewValue, _HandleType);

                    // Try and update the dictionary with the replacement value
                    if (_Dictionary.TryUpdate(key, NewHandle, MyHandle))
                    {
                        // Success, now we can safely expire the old handle
                        MyHandle.Dispose();

                        return(NewValue);
                    }

                    // Key was updated elsewhere, ditch the updated value and try again
                    NewHandle.Dispose();

                    continue;
                }

                // Key not found, so let's try and add it
                NewValue = valueCallback(key);

                if (NewValue == null)
                {
                    throw new InvalidOperationException("Cannot add null to a Weak Dictionary");
                }

                // Create a GC Handle to reference the object
                NewHandle = new GCReference(NewValue, _HandleType);

                // Try and add it to the dictionary
                if (_Dictionary.TryAdd(key, NewHandle))
                {
                    return(NewValue);                    // Success, return the result
                }
                // Key was added concurrently, free the handle we no longer need
                NewHandle.Dispose();

                // Loop back and try again
            }
        }
        /// <summary>
        /// Adds or retrieves a value based on the key
        /// </summary>
        /// <param name="key">The key to add or retrieve</param>
        /// <param name="value">A value to associate if the key doesn't exist</param>
        /// <param name="wasAdded">Receives whether the value was added or simply retrieved</param>
        /// <returns>The new or existing value</returns>
        public TValue GetOrAdd(TKey key, TValue value, out bool wasAdded)
        {         //****************************************
            GCReference NewHandle;

            //****************************************

            if (value == null)
            {
                throw new InvalidOperationException("Cannot add null to a Weak Dictionary");
            }

            for (; ;)
            {
                // Is this key already in the dictionary?
                if (_Dictionary.TryGetValue(key, out var MyHandle))
                {
                    try
                    {
                        var MyValue = (TValue?)MyHandle.Target;

                        // Yes, does the target still exist?
                        if (MyValue != null)
                        {
                            wasAdded = false;

                            return(MyValue);                            // Yes, return it
                        }
                    }
                    catch (InvalidOperationException)
                    {
                        // The GCHandle was disposed, try again
                        continue;
                    }

                    // Target reference has vanished, replace it with the new value
                    NewHandle = new GCReference(value, _HandleType);

                    // Try and update the dictionary with the replacement value
                    if (_Dictionary.TryUpdate(key, NewHandle, MyHandle))
                    {
                        // Success, now we can safely expire the old handle
                        MyHandle.Dispose();

                        wasAdded = true;

                        return(value);
                    }

                    // Key was updated elsewhere, ditch the updated value and try again
                    NewHandle.Dispose();

                    continue;
                }

                // Key not found, so let's try and add it
                // Create a GC Handle to reference the object
                NewHandle = new GCReference(value, _HandleType);

                // Try and add it to the dictionary
                if (_Dictionary.TryAdd(key, NewHandle))
                {
                    wasAdded = true;

                    return(value);                    // Success, return the result
                }

                // Key was added concurrently, free the handle we no longer need
                NewHandle.Dispose();

                // Loop back and try again
            }
        }
        //****************************************

        /// <summary>
        /// Adds or replaces a key/value pair
        /// </summary>
        /// <param name="key">The key to add or replace</param>
        /// <param name="value">The value to associate with the key</param>
        public void AddOrReplace(TKey key, TValue value)
        {               //****************************************
            GCReference NewHandle;

            //****************************************

            if (value == null)
            {
                throw new InvalidOperationException("Cannot add null to a Weak Dictionary");
            }

            for (; ;)
            {
                // Is this key already in the dictionary?
                if (_Dictionary.TryGetValue(key, out var MyHandle))
                {
                    try
                    {
                        var OldValue = (TValue?)MyHandle.Target;

                        // Yes. If the reference is the same, no need to change anything
                        if (object.ReferenceEquals(OldValue, value))
                        {
                            return;
                        }
                    }
                    catch (InvalidOperationException)
                    {
                        // The GCHandle was disposed, try again
                        continue;
                    }

                    // Reference has changed, create a new GCReference
                    NewHandle = new GCReference(value, _HandleType);

                    // Try and update the dictionary with the replacement value
                    if (_Dictionary.TryUpdate(key, NewHandle, MyHandle))
                    {
                        // Success, now we can safely expire the old handle
                        MyHandle.Dispose();

                        return;
                    }

                    // Key was updated elsewhere, ditch the updated value and try again
                    NewHandle.Dispose();

                    continue;
                }

                // Create a GC Handle to reference the object
                NewHandle = new GCReference(value, _HandleType);

                // Try and add it to the dictionary
                if (_Dictionary.TryAdd(key, NewHandle))
                {
                    return;                     // Success, return the result
                }
                // Key was added concurrently, free the handle we no longer need
                NewHandle.Dispose();

                // Loop back and try again
            }
        }
        /// <summary>
        /// Updates an item in the dictionary
        /// </summary>
        /// <param name="key">The key of the item to update</param>
        /// <param name="newValue">The new value of the item</param>
        /// <param name="oldValue">The old value we expect to replace</param>
        /// <returns>True if the key exists and old value was replaced with new value, otherwise false</returns>
        /// <remarks>Will return false if the reference has expired</remarks>
        public bool TryUpdate(TKey key, TValue newValue, TValue oldValue)
        {               //****************************************
            GCReference NewHandle;

            TValue?OldValue;

            //****************************************

            if (newValue == null)
            {
                throw new ArgumentNullException(nameof(newValue), "Cannot add null to a Weak Dictionary");
            }

            if (oldValue == null)
            {
                throw new ArgumentNullException(nameof(oldValue), "Cannot have a null in a Weak Dictionary");
            }

            for (; ;)
            {
                // Is this key already in the dictionary?
                if (!_Dictionary.TryGetValue(key, out var MyHandle))
                {
                    return(false);                    // No, update fails
                }
                try
                {
                    OldValue = (TValue?)MyHandle.Target;
                }
                catch (InvalidOperationException)
                {
                    // The GCHandle was disposed, try again
                    continue;
                }

                // Yes, is it what we expected?
                if (!object.ReferenceEquals(oldValue, OldValue))
                {
                    return(false);                    // No, update fails
                }
                // Yes. If the old and new references are the same, no need to change anything
                // Check now, rather than earlier, so we can return true if it was 'updated' correctly
                if (object.ReferenceEquals(OldValue, newValue))
                {
                    return(true);
                }

                // Reference has changed, create a new GCReference
                NewHandle = new GCReference(newValue, _HandleType);

                // Try and update the dictionary with the replacement value
                if (_Dictionary.TryUpdate(key, NewHandle, MyHandle))
                {
                    // Success, now we can safely expire the old handle
                    MyHandle.Dispose();

                    return(true);
                }

                // Key was updated elsewhere, ditch the updated value and try again
                NewHandle.Dispose();
            }
        }
Ejemplo n.º 21
0
 public Resource(int id, string name)
 {
     ptr = OpenResource(id, name);
 }
Ejemplo n.º 22
0
	public static extern void mono_safe_handle_ref (ref MyHandle handle);
        /// <summary>
        /// Updates an item if it exists in the dictionary
        /// </summary>
        /// <param name="key">The key of the item to update</param>
        /// <param name="updateCallback">A callback that performs the update</param>
        /// <param name="newValue">Receives the new value if the dictionary was updated</param>
        /// <returns>True if the item was updated, False if it does not exist or the reference expired</returns>
        public bool TryUpdate(TKey key, Func <TKey, TValue, TValue> updateCallback,
#if !NETSTANDARD2_0 && !NET40
                              [MaybeNullWhen(false)]
#endif
                              out TValue newValue)
        {               //****************************************
            GCReference NewHandle;

            TValue?OldValue;
            TValue NewValue;

            //****************************************

            for (; ;)
            {
                // Is this key already in the dictionary?
                if (!_Dictionary.TryGetValue(key, out var MyHandle))
                {
                    newValue = null !;

                    return(false);                    // No, update fails
                }

                try
                {
                    OldValue = (TValue?)MyHandle.Target;
                }
                catch (InvalidOperationException)
                {
                    // The GCHandle was disposed, try again
                    continue;
                }

                // Yes, is the reference still valid?
                if (OldValue == null)
                {
                    newValue = null !;

                    return(false);                    // No, update fails
                }

                // Yes, update it
                NewValue = updateCallback(key, OldValue);

                if (NewValue == null)
                {
                    throw new InvalidOperationException("Cannot add null to a Weak Dictionary");
                }

                // Yes. If the old and new references are the same, no need to change anything
                // Check now, rather than earlier, so we can return true if it was 'updated' correctly
                if (object.ReferenceEquals(OldValue, NewValue))
                {
                    newValue = NewValue;

                    return(true);
                }

                // Reference has changed, create a new GCReference
                NewHandle = new GCReference(NewValue, _HandleType);

                // Try and update the dictionary with the replacement value
                if (_Dictionary.TryUpdate(key, NewHandle, MyHandle))
                {
                    // Success, now we can safely expire the old handle
                    MyHandle.Dispose();

                    newValue = NewValue;

                    return(true);
                }

                // Key was updated elsewhere, ditch the updated value and try again
                NewHandle.Dispose();
            }
        }
Ejemplo n.º 24
0
 public static extern void UseResource(MyHandle resource);