-1

I'm trying to create specific object pool in c# . I have two basic methods, getObject and putObject and one thread-safe collection - concurrentDictionary (because of requiment to have some keys to identify objects in pool).

But when I remove and return object from dictionary, I need to reorganize this collection, and also when I want to put new object to collection, I want to auto-increment key. Is there any solution to achieve this ? Or any other collection, which can help me to achive same effect and which can help me to create object pool ? (I have two pools, one to create objects, but objects can contain data, so i have also some "data pool" and "data" should be object with some non-constant size , I need this solution for "data pool" ).

Or maybe, do you have some know-how, how to make object pool (memory pool) with objects than can contain different data with different size ?

some example code

->Foreach is there because I want to find the closest match of size of "data objects" and then, if there is any suitable object, I want to return it. If not, I create new.

namespace MPool
{
    public class DataPool<T>
    {
        private ConcurrentDictionary<int,T> _objects;
        private Func<T> _objectGenerator;

        public DataPool(Func<T> objectGenerator)
        {
            if (objectGenerator == null)
                throw new ArgumentNullException("Chyba metoda objectGenerator");
            _objects = new ConcurrentDictionary<int,T>();
            _objectGenerator = objectGenerator;
        }

        public T GetObject(int size)
        {
            int diverse = Int32.MaxValue;
            T item = default(T);
            int key = -1;
            foreach (KeyValuePair<int,T> obj in _objects) {
                if (GetObjectSize(obj.Value) == size) {
                    //item = obj.Value;
                    key = obj.Key;
                    break;
                } else {
                    if (Math.Abs((GetObjectSize(obj.Value) - size)) < diverse) {
                        diverse = Math.Abs((GetObjectSize(obj.Value) - size));
                        if (diverse < (2 * GetObjectSize(obj.Value))) {
                            //item = obj.Value;
                            key = obj.Key;
                        }
                    }
                }
            }
            if (key==-1) {
                return _objectGenerator();
            } else {
                _objects.TryRemove(key, out item);
                return item;
            }
        }

        public void PutObject(T item)
        {
            //_objects.AddOrUpdate
        }

        public void Free()
        {
            while (!_objects.IsEmpty) {
                _objects.Clear();
            }
        }

        private int GetObjectSize(T TestObject)
        {
            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream ms = new MemoryStream();
            byte[] Array;
            bf.Serialize(ms, TestObject);
            Array = ms.ToArray();
            return Array.Length;
        }
    }
}
  • 4
    I have no clue what it is you're asking for. Can you provide some example code of what you have, or what sort of client code you'd like to work in the end? – millimoose Nov 05 '12 at 20:52
  • What is this "key" that you are auto incrementing? What do you mean by "reorganize" the collection when you return an object? Do you mean that if you had the keys "1, 2, 3, 4, 5" and then removed item with key "3", then items 4 and 5 would move up to 3 and 4 respectively thus having the keys now "1, 2, 3, 4" and the next key would be `5` as opposed to `6`? – pstrjds Nov 05 '12 at 20:55
  • 3
    Autoincrement the key and reorganize the collection? Isn't the List what you're looking for? It has indexes and it reorganizes itself when you remove an item. – Nikola Davidovic Nov 05 '12 at 20:55
  • pstrjds, exactly that is what i meant. I have some code but its maybe strange, because I do something like that for the first time. List can help but I thing It hasn't thread-safe alternative. – Martin Fedy Fedorko Nov 05 '12 at 21:02
  • So are these keys just used to tie between the object collection and the data that the object might be holding? Also, is the "data" that is non-const size a stream of bytes or something similar to that? – pstrjds Nov 05 '12 at 21:06
  • I dont need these keys but I havent found any other good solution, how to make these pools and return the correct amount of data (object with some size) according to the needs . So i write some code which do this with help of dictionary, I could use also any other concurrent collection, but I dont know , how to achieve this pooling with "memory chunks"and so on – Martin Fedy Fedorko Nov 05 '12 at 21:10
  • I have no idea what this is supposed to do, but if you need a thread safe list use `ConcurrentBag`. – FlyingStreudel Nov 05 '12 at 21:15
  • Can you explain the `else` part of your foreach loop (edit your post and add it there, not in the comments). It seems like if you don't find the exact size, but you find something that the difference between the object size and the size requested is less than 2 times the object size you will end up returning that item. Is the idea that you want to get as close to the size as you can if you don't have an exact match? – pstrjds Nov 05 '12 at 21:16
  • yes, Its just draft but I want to find closest match of size – Martin Fedy Fedorko Nov 05 '12 at 21:19
  • Are you trying to simulate a heap here or what? This seems a really strange way to do things. Perhaps if you explained the actual purpose of your "DataPool" rather than just its functionality... – JamieSee Nov 05 '12 at 21:33
  • Thank you, i know, but can you advice me some solution, how to make this kind of object pooling? :/ thank you for every answer – Martin Fedy Fedorko Nov 05 '12 at 21:34
  • You may want to look over http://stackoverflow.com/questions/102398/priority-queue-in-net – JamieSee Nov 05 '12 at 21:49
  • thank you very much for advice – Martin Fedy Fedorko Nov 05 '12 at 21:52

1 Answers1

0

I have a comment about the posted code that is not directly related to what you are trying to do (as I am still somewhat unsure as to what you want to do), but I feel like this should be addressed.

You are computing the size of the object potentially 4 times in each loop iteration. Since you are adding these objects to your collection at one time, I would suggest you make a helper class within this class that can store the object and its size and you compute it at the time of creation and then store these objects in the collection.

public DataPool<T>
{
        internal class DataStructHelper<T>
        {
            public T DataObject { get; private set; }
            public int Size { get; private set; }
            public DataStructHelper(T dataObject)
            {
                DataObject = dataObject;
                Size = GetObjectSize(dataObject);
            }

            private int GetObjectSize(T TestObject)
            {
                BinaryFormatter bf = new BinaryFormatter();
                using (MemoryStream ms = new MemoryStream())
                {
                    byte[] Array;
                    bf.Serialize(ms, TestObject);
                    return ms.ToArray().Length;
                }
            }
        }
    }
// Other code here
}

Not knowing how your class is going to be used and how many threads you plan on hitting this thing with, etc. I would consider just using a regular list and locking around access. You can store the items in sorted order and use BinarySearch to insert and search for items based on the size (you will need to provide the compare function).

pstrjds
  • 15,103
  • 6
  • 48
  • 60
  • Thank you, and what about creating new objects, when in collection isn't object with suitable size? – Martin Fedy Fedorko Nov 05 '12 at 21:36
  • This code should be called in your PutObject method that is putting data in the collection. When you are returning an object in GetObject you are removing from the collection so this structure won't be useful there. – pstrjds Nov 05 '12 at 21:45